Tabs to Lists for Configurations, Policy (#913)

* Tabs to Lists for Configurations, Policy

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* Fix Tests

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* Logs

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
This commit is contained in:
Daniel Valdivia
2021-07-30 17:01:55 -07:00
committed by GitHub
parent ac7cefde39
commit 0c78359832
23 changed files with 360 additions and 357 deletions

View File

@@ -22,50 +22,43 @@ import (
// endpoints definition
var (
configuration = "/settings"
users = "/users"
usersDetail = "/users/:userName+"
groups = "/groups"
iamPolicies = "/policies"
policiesDetail = "/policies/:policyName"
dashboard = "/dashboard"
metrics = "/metrics"
profiling = "/profiling"
buckets = "/buckets"
bucketsDetail = "/buckets/:bucketName"
bucketsDetailSummary = "/buckets/:bucketName/summary"
bucketsDetailEvents = "/buckets/:bucketName/events"
bucketsDetailReplication = "/buckets/:bucketName/replication"
bucketsDetailLifecycle = "/buckets/:bucketName/lifecycle"
bucketsDetailAccess = "/buckets/:bucketName/access"
bucketsDetailAccessPolicies = "/buckets/:bucketName/access/policies"
bucketsDetailAccessUsers = "/buckets/:bucketName/access/users"
serviceAccounts = "/account"
changePassword = "/account/change-password"
tenants = "/tenants"
tenantsDetail = "/namespaces/:tenantNamespace/tenants/:tenantName"
tenantHop = "/namespaces/:tenantNamespace/tenants/:tenantName/hop"
podsDetail = "/namespaces/:tenantNamespace/tenants/:tenantName/pods/:podName"
tenantsDetailSummary = "/namespaces/:tenantNamespace/tenants/:tenantName/summary"
tenantsDetailMetrics = "/namespaces/:tenantNamespace/tenants/:tenantName/metrics"
tenantsDetailPods = "/namespaces/:tenantNamespace/tenants/:tenantName/pods"
tenantsDetailPools = "/namespaces/:tenantNamespace/tenants/:tenantName/pools"
tenantsDetailLicense = "/namespaces/:tenantNamespace/tenants/:tenantName/license"
tenantsDetailSecurity = "/namespaces/:tenantNamespace/tenants/:tenantName/security"
storage = "/storage"
storageVolumes = "/storage/volumes"
storageDrives = "/storage/drives"
remoteBuckets = "/remote-buckets"
replication = "/replication"
objectBrowser = "/object-browser/:bucket/*"
objectBrowserBucket = "/object-browser/:bucket"
mainObjectBrowser = "/object-browser"
license = "/license"
watch = "/watch"
heal = "/heal"
trace = "/trace"
logs = "/logs"
healthInfo = "/health-info"
configuration = "/settings"
users = "/users"
usersDetail = "/users/:userName+"
groups = "/groups"
iamPolicies = "/policies"
policiesDetail = "/policies/:policyName"
dashboard = "/dashboard"
metrics = "/metrics"
profiling = "/profiling"
buckets = "/buckets"
bucketsDetail = "/buckets/*"
serviceAccounts = "/account"
changePassword = "/account/change-password"
tenants = "/tenants"
tenantsDetail = "/namespaces/:tenantNamespace/tenants/:tenantName"
tenantHop = "/namespaces/:tenantNamespace/tenants/:tenantName/hop"
podsDetail = "/namespaces/:tenantNamespace/tenants/:tenantName/pods/:podName"
tenantsDetailSummary = "/namespaces/:tenantNamespace/tenants/:tenantName/summary"
tenantsDetailMetrics = "/namespaces/:tenantNamespace/tenants/:tenantName/metrics"
tenantsDetailPods = "/namespaces/:tenantNamespace/tenants/:tenantName/pods"
tenantsDetailPools = "/namespaces/:tenantNamespace/tenants/:tenantName/pools"
tenantsDetailLicense = "/namespaces/:tenantNamespace/tenants/:tenantName/license"
tenantsDetailSecurity = "/namespaces/:tenantNamespace/tenants/:tenantName/security"
storage = "/storage"
storageVolumes = "/storage/volumes"
storageDrives = "/storage/drives"
remoteBuckets = "/remote-buckets"
replication = "/replication"
objectBrowser = "/object-browser/:bucket/*"
objectBrowserBucket = "/object-browser/:bucket"
mainObjectBrowser = "/object-browser"
license = "/license"
watch = "/watch"
heal = "/heal"
trace = "/trace"
logs = "/logs"
healthInfo = "/health-info"
)
type ConfigurationActionSet struct {
@@ -288,37 +281,30 @@ var displayRules = map[string]func() bool{
// endpointRules contains the mapping between endpoints and ActionSets, additional rules can be added here
var endpointRules = map[string]ConfigurationActionSet{
configuration: configurationActionSet,
users: usersActionSet,
usersDetail: usersActionSet,
groups: groupsActionSet,
iamPolicies: iamPoliciesActionSet,
policiesDetail: iamPoliciesActionSet,
dashboard: dashboardActionSet,
metrics: dashboardActionSet,
profiling: profilingActionSet,
buckets: bucketsActionSet,
bucketsDetail: bucketsActionSet,
bucketsDetailSummary: bucketsActionSet,
bucketsDetailEvents: bucketsActionSet,
bucketsDetailReplication: bucketsActionSet,
bucketsDetailLifecycle: bucketsActionSet,
bucketsDetailAccess: bucketsActionSet,
bucketsDetailAccessPolicies: bucketsActionSet,
bucketsDetailAccessUsers: bucketsActionSet,
serviceAccounts: serviceAccountsActionSet,
changePassword: changePasswordActionSet,
remoteBuckets: remoteBucketsActionSet,
replication: replicationActionSet,
objectBrowser: objectBrowserActionSet,
mainObjectBrowser: objectBrowserActionSet,
objectBrowserBucket: objectBrowserActionSet,
license: licenseActionSet,
watch: watchActionSet,
heal: healActionSet,
trace: traceActionSet,
logs: logsActionSet,
healthInfo: healthInfoActionSet,
configuration: configurationActionSet,
users: usersActionSet,
usersDetail: usersActionSet,
groups: groupsActionSet,
iamPolicies: iamPoliciesActionSet,
policiesDetail: iamPoliciesActionSet,
dashboard: dashboardActionSet,
metrics: dashboardActionSet,
profiling: profilingActionSet,
buckets: bucketsActionSet,
bucketsDetail: bucketsActionSet,
serviceAccounts: serviceAccountsActionSet,
changePassword: changePasswordActionSet,
remoteBuckets: remoteBucketsActionSet,
replication: replicationActionSet,
objectBrowser: objectBrowserActionSet,
mainObjectBrowser: objectBrowserActionSet,
objectBrowserBucket: objectBrowserActionSet,
license: licenseActionSet,
watch: watchActionSet,
heal: healActionSet,
trace: traceActionSet,
logs: logsActionSet,
healthInfo: healthInfoActionSet,
}
// operatorRules contains the mapping between endpoints and ActionSets for operator only mode

View File

@@ -81,7 +81,7 @@ func TestGetAuthorizedEndpoints(t *testing.T) {
"s3:*",
},
},
want: 15,
want: 8,
},
{
name: "all admin and s3 endpoints",
@@ -91,7 +91,7 @@ func TestGetAuthorizedEndpoints(t *testing.T) {
"s3:*",
},
},
want: 31,
want: 24,
},
{
name: "Console User - default endpoints",

View File

@@ -1,25 +1,25 @@
{
"files": {
"main.css": "/static/css/main.8cfac526.chunk.css",
"main.js": "/static/js/main.2d317177.chunk.js",
"main.js.map": "/static/js/main.2d317177.chunk.js.map",
"main.js": "/static/js/main.94e52666.chunk.js",
"main.js.map": "/static/js/main.94e52666.chunk.js.map",
"runtime-main.js": "/static/js/runtime-main.43a31377.js",
"runtime-main.js.map": "/static/js/runtime-main.43a31377.js.map",
"static/css/2.60e04a19.chunk.css": "/static/css/2.60e04a19.chunk.css",
"static/js/2.e135a1be.chunk.js": "/static/js/2.e135a1be.chunk.js",
"static/js/2.e135a1be.chunk.js.map": "/static/js/2.e135a1be.chunk.js.map",
"static/js/2.c24beecf.chunk.js": "/static/js/2.c24beecf.chunk.js",
"static/js/2.c24beecf.chunk.js.map": "/static/js/2.c24beecf.chunk.js.map",
"index.html": "/index.html",
"static/css/2.60e04a19.chunk.css.map": "/static/css/2.60e04a19.chunk.css.map",
"static/css/main.8cfac526.chunk.css.map": "/static/css/main.8cfac526.chunk.css.map",
"static/js/2.e135a1be.chunk.js.LICENSE.txt": "/static/js/2.e135a1be.chunk.js.LICENSE.txt",
"static/js/2.c24beecf.chunk.js.LICENSE.txt": "/static/js/2.c24beecf.chunk.js.LICENSE.txt",
"static/media/minio_console_logo.0837460e.svg": "/static/media/minio_console_logo.0837460e.svg",
"static/media/minio_operator_logo.1312b7c9.svg": "/static/media/minio_operator_logo.1312b7c9.svg"
},
"entrypoints": [
"static/js/runtime-main.43a31377.js",
"static/css/2.60e04a19.chunk.css",
"static/js/2.e135a1be.chunk.js",
"static/js/2.c24beecf.chunk.js",
"static/css/main.8cfac526.chunk.css",
"static/js/main.2d317177.chunk.js"
"static/js/main.94e52666.chunk.js"
]
}

View File

@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="MinIO Console"/><link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;500;700;900&display=swap" rel="stylesheet"/><link href="/styles/root-styles.css" rel="stylesheet"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png"/><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/><link rel="manifest" href="/manifest.json"/><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#3a4e54"/><title>MinIO Console</title><link href="/static/css/2.60e04a19.chunk.css" rel="stylesheet"><link href="/static/css/main.8cfac526.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"><div id="loader-block"><svg class="loader-svg-container" viewBox="22 22 44 44"><circle class="loader-style MuiCircularProgress-circle MuiCircularProgress-circleIndeterminate" cx="44" cy="44" r="20.2" fill="none" stroke-width="3.6"></circle></svg></div></div><script>!function(e){function r(r){for(var n,l,i=r[0],a=r[1],p=r[2],c=0,s=[];c<i.length;c++)l=i[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(f&&f(r);s.length;)s.shift()();return u.push.apply(u,p||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var a=t[i];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={1:0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/";var i=this["webpackJsonpportal-ui"]=this["webpackJsonpportal-ui"]||[],a=i.push.bind(i);i.push=r,i=i.slice();for(var p=0;p<i.length;p++)r(i[p]);var f=a;t()}([])</script><script src="/static/js/2.e135a1be.chunk.js"></script><script src="/static/js/main.2d317177.chunk.js"></script></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="MinIO Console"/><link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;500;700;900&display=swap" rel="stylesheet"/><link href="/styles/root-styles.css" rel="stylesheet"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png"/><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/><link rel="manifest" href="/manifest.json"/><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#3a4e54"/><title>MinIO Console</title><link href="/static/css/2.60e04a19.chunk.css" rel="stylesheet"><link href="/static/css/main.8cfac526.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"><div id="loader-block"><svg class="loader-svg-container" viewBox="22 22 44 44"><circle class="loader-style MuiCircularProgress-circle MuiCircularProgress-circleIndeterminate" cx="44" cy="44" r="20.2" fill="none" stroke-width="3.6"></circle></svg></div></div><script>!function(e){function r(r){for(var n,l,i=r[0],a=r[1],p=r[2],c=0,s=[];c<i.length;c++)l=i[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(f&&f(r);s.length;)s.shift()();return u.push.apply(u,p||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var a=t[i];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={1:0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/";var i=this["webpackJsonpportal-ui"]=this["webpackJsonpportal-ui"]||[],a=i.push.bind(i);i.push=r,i=i.slice();for(var p=0;p<i.length;p++)r(i[p]);var f=a;t()}([])</script><script src="/static/js/2.c24beecf.chunk.js"></script><script src="/static/js/main.94e52666.chunk.js"></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -119,6 +119,7 @@ const AccessDetails = ({
return (
<Fragment>
<h1 className={classes.sectionTitle}>Access Audit</h1>
<Tabs
value={curTab}
onChange={(e: React.ChangeEvent<{}>, newValue: number) => {

View File

@@ -282,17 +282,16 @@ const BucketDetails = ({
>
<ListItemText primary="Events" />
</ListItem>
{canGetReplication && (
<ListItem
button
selected={selectedTab === "replication"}
onClick={() => {
changeRoute("replication");
}}
>
<ListItemText primary="Replication" />
</ListItem>
)}
<ListItem
button
disabled={!canGetReplication}
selected={selectedTab === "replication"}
onClick={() => {
changeRoute("replication");
}}
>
<ListItemText primary="Replication" />
</ListItem>
<ListItem
button
@@ -310,7 +309,7 @@ const BucketDetails = ({
changeRoute("access");
}}
>
<ListItemText primary="Audit Access" />
<ListItemText primary="Access Audit" />
</ListItem>
</List>
</Grid>

View File

@@ -121,7 +121,7 @@ const BucketEventsPanel = ({
<Grid container>
<Grid item xs={12} className={classes.actionsTray}>
<h1 style={{ padding: "0px", margin: "0px" }}>Events</h1>
<h1 className={classes.sectionTitle}>Events</h1>
<Button
variant="contained"
color="primary"

View File

@@ -169,7 +169,7 @@ const BucketLifecyclePanel = ({
)}
<Grid container>
<Grid item xs={12} className={classes.actionsTray}>
<h1 style={{ padding: "0px", margin: "0px" }}>Lifecycle Rules</h1>
<h1 className={classes.sectionTitle}>Lifecycle Rules</h1>
<Button
variant="contained"
color="primary"

View File

@@ -137,10 +137,6 @@ const BucketReplicationPanel = ({
}
}, [loadingReplication, setErrorSnackMessage, bucketName]);
if (!canGetReplication) {
return null;
}
const closeAddReplication = () => {
setOpenReplicationOpen(false);
setLoadingReplication(true);
@@ -199,21 +195,19 @@ const BucketReplicationPanel = ({
)}
<Grid container>
<Grid item xs={12} className={classes.actionsTray}>
<h1 style={{ padding: "0px", margin: "0px" }}>Replication</h1>
{canPutReplication && (
<Button
variant="contained"
color="primary"
startIcon={<CreateIcon />}
size="medium"
onClick={() => {
setOpenReplicationOpen(true);
}}
>
Add Replication Rule
</Button>
)}
<h1 className={classes.sectionTitle}>Replication</h1>
<Button
variant="contained"
color="primary"
disabled={!canPutReplication}
startIcon={<CreateIcon />}
size="medium"
onClick={() => {
setOpenReplicationOpen(true);
}}
>
Add Replication Rule
</Button>
</Grid>
<Grid item xs={12}>
<br />

View File

@@ -393,7 +393,7 @@ const BucketSummary = ({
)}
<Grid container>
<Grid item xs={12} className={classes.actionsTray}>
<h1 style={{ padding: "0px", margin: "0px" }}>Summary</h1>
<h1 className={classes.sectionTitle}>Summary</h1>
</Grid>
<Grid item xs={12}>
<br />

View File

@@ -138,6 +138,10 @@ export const containerForHeader = (bottomSpacing: any) => ({
},
},
},
sectionTitle: {
padding: "0px",
margin: "0px",
},
topSpacer: {
height: "8px",
},

View File

@@ -27,6 +27,9 @@ import ListTiersConfiguration from "./TiersConfiguration/ListTiersConfiguration"
import { AppState } from "../../../store";
import { connect } from "react-redux";
import { ISessionResponse } from "../types";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemText from "@material-ui/core/ListItemText";
interface IConfigurationMain {
classes: any;
@@ -55,40 +58,57 @@ const ConfigurationMain = ({
return (
<Fragment>
<PageHeader label="Settings" />
<Grid container>
<Grid item xs={12} className={classes.container}>
<Tabs
value={selectedTab}
indicatorColor="primary"
textColor="primary"
onChange={(_, newValue: number) => {
setSelectedTab(newValue);
}}
aria-label="tenant-tabs"
variant="scrollable"
scrollButtons="auto"
>
<Tab label="Configurations" />
<Tab label="Lambda Notifications" />
<Tab label="Tiers" disabled={!distributedSetup} />
</Tabs>
<Grid item xs={12}>
{selectedTab === 0 && (
<Grid item xs={12}>
<ConfigurationsList />
</Grid>
)}
{selectedTab === 1 && (
<Grid item xs={12}>
<ListNotificationEndpoints />
</Grid>
)}
{selectedTab === 2 && distributedSetup && (
<Grid item xs={12}>
<ListTiersConfiguration />
</Grid>
)}
</Grid>
<Grid container className={classes.container}>
<Grid item xs={2}>
<List component="nav" dense={true}>
<ListItem
button
selected={selectedTab === 0}
onClick={() => {
setSelectedTab(0);
}}
>
<ListItemText primary="Configurations" />
</ListItem>
<ListItem
button
selected={selectedTab === 1}
onClick={() => {
setSelectedTab(1);
}}
>
<ListItemText primary="Lambda Notifications" />
</ListItem>
<ListItem
button
selected={selectedTab === 2}
onClick={() => {
setSelectedTab(2);
}}
>
<ListItemText primary="Tiers" />
</ListItem>
</List>
</Grid>
<Grid item xs={10}>
{selectedTab === 0 && (
<Grid item xs={12}>
<h1 className={classes.sectionTitle}>Configurations</h1>
<ConfigurationsList />
</Grid>
)}
{selectedTab === 1 && (
<Grid item xs={12}>
<h1 className={classes.sectionTitle}>Lambda Notifications</h1>
<ListNotificationEndpoints />
</Grid>
)}
{selectedTab === 2 && distributedSetup && (
<Grid item xs={12}>
<h1 className={classes.sectionTitle}>Tiers</h1>
<ListTiersConfiguration />
</Grid>
)}
</Grid>
</Grid>
</Fragment>

View File

@@ -237,39 +237,7 @@ const Console = ({
},
{
component: Buckets,
path: "/buckets/:bucketName",
},
{
component: Buckets,
path: "/buckets/:bucketName/summary",
},
{
component: Buckets,
path: "/buckets/:bucketName/events",
},
{
component: Buckets,
path: "/buckets/:bucketName/replication",
},
{
component: Buckets,
path: "/buckets/:bucketName/lifecycle",
},
{
component: Buckets,
path: "/buckets/:bucketName/access",
},
{
component: Buckets,
path: "/buckets/:bucketName/access",
},
{
component: Buckets,
path: "/buckets/:bucketName/access/policies",
},
{
component: Buckets,
path: "/buckets/:bucketName/access/users",
path: "/buckets/*",
},
{
component: ObjectBrowser,

View File

@@ -17,7 +17,7 @@
import React, { Fragment, useState } from "react";
import { connect } from "react-redux";
import PageHeader from "../Common/PageHeader/PageHeader";
import { Grid } from "@material-ui/core";
import { Grid, List, ListItem, ListItemText } from "@material-ui/core";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import Tab from "@material-ui/core/Tab";
import Tabs from "@material-ui/core/Tabs";
@@ -50,39 +50,43 @@ const LogsMain = ({ classes, features }: ILogsMainProps) => {
return (
<Fragment>
<PageHeader label="Logs" />
<Grid container>
<Grid item xs={12} className={classes.container}>
<Fragment>
<Grid item xs={12} className={classes.headerLabel}>
All Logs
</Grid>
<Tabs
value={currentTab}
onChange={(e: React.ChangeEvent<{}>, newValue: number) => {
setCurrentTab(newValue);
<Grid container className={classes.container}>
<Grid item xs={2}>
<List component="nav" dense={true}>
<ListItem
button
selected={currentTab === 0}
onClick={() => {
setCurrentTab(0);
}}
indicatorColor="primary"
textColor="primary"
aria-label="cluster-tabs"
variant="scrollable"
scrollButtons="auto"
>
<Tab label="Error Logs" />
{logSearchEnabled && <Tab label="Logs Search" />}
</Tabs>
<Grid item xs={12}>
{currentTab === 0 && (
<Grid item xs={12}>
<ErrorLogs />
</Grid>
)}
{currentTab === 1 && logSearchEnabled && (
<Grid item xs={12}>
<LogsSearchMain />
</Grid>
)}
</Grid>
</Fragment>
<ListItemText primary="Error Logs" />
</ListItem>
<ListItem
button
selected={currentTab === 1}
disabled={!logSearchEnabled}
onClick={() => {
setCurrentTab(1);
}}
>
<ListItemText primary="Audit Logs" />
</ListItem>
</List>
</Grid>
<Grid item xs={10}>
{currentTab === 0 && (
<Fragment>
<h1 className={classes.sectionTitle}>Error Logs</h1>
<ErrorLogs />
</Fragment>
)}
{currentTab === 1 && logSearchEnabled && (
<Fragment>
<h1 className={classes.sectionTitle}>Audit Logs</h1>
<LogsSearchMain />
</Fragment>
)}
</Grid>
</Grid>
</Fragment>

View File

@@ -41,6 +41,9 @@ import {
searchField,
} from "../Common/FormComponents/common/styleLibrary";
import TextField from "@material-ui/core/TextField";
import ListItem from "@material-ui/core/ListItem";
import ListItemText from "@material-ui/core/ListItemText";
import List from "@material-ui/core/List";
interface IPolicyDetailsProps {
classes: any;
@@ -300,141 +303,167 @@ const PolicyDetails = ({
</Fragment>
}
/>
<Grid item xs={12} className={classes.container}>
<Grid item xs={12}>
<Tabs
value={selectedTab}
indicatorColor="primary"
textColor="primary"
onChange={(_, newValue: number) => {
setSelectedTab(newValue);
}}
aria-label="policy-tabs"
>
<Tab label="Details" />
<Tab label="Users" />
<Tab label="Groups" />
</Tabs>
</Grid>
{selectedTab === 0 && (
<Paper className={classes.paperContainer}>
<form
noValidate
autoComplete="off"
onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
saveRecord(e);
<Grid container className={classes.container}>
<Grid item xs={2}>
<List component="nav" dense={true}>
<ListItem
button
selected={selectedTab === 0}
onClick={() => {
setSelectedTab(0);
}}
>
<ListItemText primary="Details" />
</ListItem>
<ListItem
button
selected={selectedTab === 1}
onClick={() => {
setSelectedTab(1);
}}
>
<ListItemText primary="Users" />
</ListItem>
<ListItem
button
selected={selectedTab === 2}
onClick={() => {
setSelectedTab(2);
}}
>
<ListItemText primary="Groups" />
</ListItem>
</List>
</Grid>
<Grid item xs={10}>
{selectedTab === 0 && (
<Fragment>
<h1 className={classes.sectionTitle}>Edit Policy</h1>
<Paper className={classes.paperContainer}>
<form
noValidate
autoComplete="off"
onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
saveRecord(e);
}}
>
<Grid container>
<Grid item xs={12} className={classes.formScrollable}>
<CodeMirrorWrapper
value={policyDefinition}
onBeforeChange={(editor, data, value) => {
setPolicyDefinition(value);
}}
/>
</Grid>
<Grid item xs={12} className={classes.buttonContainer}>
{!policy && (
<button
type="button"
color="primary"
className={classes.clearButton}
onClick={() => {
resetForm();
}}
>
Clear
</button>
)}
<Button
type="submit"
variant="contained"
color="primary"
disabled={addLoading || !validSave}
>
Save
</Button>
</Grid>
{addLoading && (
<Grid item xs={12}>
<LinearProgress />
</Grid>
)}
</Grid>
</form>
</Paper>
</Fragment>
)}
{selectedTab === 1 && (
<Fragment>
<h1 className={classes.sectionTitle}>Users</h1>
<Grid container>
<Grid item xs={12} className={classes.formScrollable}>
<CodeMirrorWrapper
label={`${policy ? "Edit" : "Write"} Policy`}
value={policyDefinition}
onBeforeChange={(editor, data, value) => {
setPolicyDefinition(value);
<Grid item xs={12} className={classes.actionsTray}>
<TextField
placeholder="Search Users"
className={classes.searchField}
id="search-resource"
label=""
onChange={(val) => {
setFilterUsers(val.target.value);
}}
InputProps={{
disableUnderline: true,
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
),
}}
/>
</Grid>
<Grid item xs={12} className={classes.buttonContainer}>
{!policy && (
<button
type="button"
color="primary"
className={classes.clearButton}
onClick={() => {
resetForm();
}}
>
Clear
</button>
)}
<Button
type="submit"
variant="contained"
color="primary"
disabled={addLoading || !validSave}
>
Save
</Button>
<Grid item xs={12} className={classes.actionsTray}>
<br />
</Grid>
{addLoading && (
<Grid item xs={12}>
<LinearProgress />
</Grid>
)}
<TableWrapper
itemActions={userTableActions}
columns={[{ label: "Name", elementKey: "name" }]}
isLoading={loadingUsers}
records={filteredUsers}
entityName="Users"
idField="name"
/>
</Grid>
</form>
</Paper>
)}
{selectedTab === 1 && (
<Grid container>
<Grid item xs={12} className={classes.actionsTray}>
<TextField
placeholder="Search Users"
className={classes.searchField}
id="search-resource"
label=""
onChange={(val) => {
setFilterUsers(val.target.value);
}}
InputProps={{
disableUnderline: true,
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
),
}}
/>
</Grid>
<Grid item xs={12} className={classes.actionsTray}>
<br />
</Grid>
<TableWrapper
itemActions={userTableActions}
columns={[{ label: "Name", elementKey: "name" }]}
isLoading={loadingUsers}
records={filteredUsers}
entityName="Users"
idField="name"
/>
</Grid>
)}
{selectedTab === 2 && (
<Grid container>
<Grid item xs={12} className={classes.actionsTray}>
<TextField
placeholder="Search Groups"
className={classes.searchField}
id="search-resource"
label=""
onChange={(val) => {
setFilterGroups(val.target.value);
}}
InputProps={{
disableUnderline: true,
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
),
}}
/>
</Grid>
<Grid item xs={12} className={classes.actionsTray}>
<br />
</Grid>
<TableWrapper
itemActions={[]}
columns={[{ label: "Name", elementKey: "name" }]}
isLoading={loadingGroups}
records={filteredGroups}
entityName="Groups"
idField="name"
/>
</Grid>
)}
</Fragment>
)}
{selectedTab === 2 && (
<Fragment>
<h1 className={classes.sectionTitle}>Groups</h1>
<Grid container>
<Grid item xs={12} className={classes.actionsTray}>
<TextField
placeholder="Search Groups"
className={classes.searchField}
id="search-resource"
label=""
onChange={(val) => {
setFilterGroups(val.target.value);
}}
InputProps={{
disableUnderline: true,
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
),
}}
/>
</Grid>
<Grid item xs={12} className={classes.actionsTray}>
<br />
</Grid>
<TableWrapper
itemActions={[]}
columns={[{ label: "Name", elementKey: "name" }]}
isLoading={loadingGroups}
records={filteredGroups}
entityName="Groups"
idField="name"
/>
</Grid>
</Fragment>
)}
</Grid>
</Grid>
</React.Fragment>
);

View File

@@ -339,7 +339,7 @@ const UserDetails = ({ classes, match }: IUserDetailsProps) => {
<Grid item xs={12}>
<TabPanel index={0} value={curTab}>
<div className={classes.actionsTray}>
<h1 style={{ padding: "0px", margin: "0px" }}>Groups</h1>
<h1 className={classes.sectionTitle}>Groups</h1>
<Button
variant="contained"
color="primary"
@@ -364,9 +364,7 @@ const UserDetails = ({ classes, match }: IUserDetailsProps) => {
</TabPanel>
<TabPanel index={1} value={curTab}>
<div className={classes.actionsTray}>
<h1 style={{ padding: "0px", margin: "0px" }}>
Service Accounts
</h1>
<h1 className={classes.sectionTitle}>Service Accounts</h1>
<Button
variant="contained"
color="primary"
@@ -384,7 +382,7 @@ const UserDetails = ({ classes, match }: IUserDetailsProps) => {
</TabPanel>
<TabPanel index={2} value={curTab}>
<div className={classes.actionsTray}>
<h1 style={{ padding: "0px", margin: "0px" }}>Policies</h1>
<h1 className={classes.sectionTitle}>Policies</h1>
<Button
variant="contained"
color="primary"