Restructured settings page to use URL navigation (#1138)

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
Alex
2021-10-22 12:49:39 -05:00
committed by GitHub
parent 3fabfb96c9
commit a4de76c3e2
23 changed files with 387 additions and 306 deletions

View File

@@ -23,6 +23,7 @@ import (
// endpoints definition
var (
configuration = "/settings"
configurationItem = "/settings/:option"
notificationEndpoints = "/notification-endpoints"
notificationEndpointsAddAny = "/notification-endpoints/add/:service"
notificationEndpointsAdd = "/notification-endpoints/add"
@@ -294,6 +295,7 @@ 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,
configurationItem: configurationActionSet,
notificationEndpoints: configurationActionSet,
notificationEndpointsAdd: configurationActionSet,
notificationEndpointsAddAny: configurationActionSet,

View File

@@ -70,7 +70,7 @@ func TestGetAuthorizedEndpoints(t *testing.T) {
"admin:*",
},
},
want: 29,
want: 30,
},
{
name: "all s3 endpoints",
@@ -89,7 +89,7 @@ func TestGetAuthorizedEndpoints(t *testing.T) {
"s3:*",
},
},
want: 31,
want: 32,
},
{
name: "Console User - default endpoints",

View File

@@ -1,23 +1,23 @@
{
"files": {
"main.css": "./static/css/main.e33a67ba.chunk.css",
"main.js": "./static/js/main.7937d4e3.chunk.js",
"main.js.map": "./static/js/main.7937d4e3.chunk.js.map",
"main.js": "./static/js/main.368c5d1e.chunk.js",
"main.js.map": "./static/js/main.368c5d1e.chunk.js.map",
"runtime-main.js": "./static/js/runtime-main.30f8243a.js",
"runtime-main.js.map": "./static/js/runtime-main.30f8243a.js.map",
"static/css/2.f324abd6.chunk.css": "./static/css/2.f324abd6.chunk.css",
"static/js/2.332af55f.chunk.js": "./static/js/2.332af55f.chunk.js",
"static/js/2.332af55f.chunk.js.map": "./static/js/2.332af55f.chunk.js.map",
"static/js/2.97faa37d.chunk.js": "./static/js/2.97faa37d.chunk.js",
"static/js/2.97faa37d.chunk.js.map": "./static/js/2.97faa37d.chunk.js.map",
"index.html": "./index.html",
"static/css/2.f324abd6.chunk.css.map": "./static/css/2.f324abd6.chunk.css.map",
"static/css/main.e33a67ba.chunk.css.map": "./static/css/main.e33a67ba.chunk.css.map",
"static/js/2.332af55f.chunk.js.LICENSE.txt": "./static/js/2.332af55f.chunk.js.LICENSE.txt"
"static/js/2.97faa37d.chunk.js.LICENSE.txt": "./static/js/2.97faa37d.chunk.js.LICENSE.txt"
},
"entrypoints": [
"static/js/runtime-main.30f8243a.js",
"static/css/2.f324abd6.chunk.css",
"static/js/2.332af55f.chunk.js",
"static/js/2.97faa37d.chunk.js",
"static/css/main.e33a67ba.chunk.css",
"static/js/main.7937d4e3.chunk.js"
"static/js/main.368c5d1e.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="#081C42" media="(prefers-color-scheme: light)"/><meta name="theme-color" content="#081C42" media="(prefers-color-scheme: dark)"/><meta name="description" content="MinIO Console"/><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.f324abd6.chunk.css" rel="stylesheet"><link href="./static/css/main.e33a67ba.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.332af55f.chunk.js"></script><script src="./static/js/main.7937d4e3.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="#081C42" media="(prefers-color-scheme: light)"/><meta name="theme-color" content="#081C42" media="(prefers-color-scheme: dark)"/><meta name="description" content="MinIO Console"/><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.f324abd6.chunk.css" rel="stylesheet"><link href="./static/css/main.e33a67ba.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.97faa37d.chunk.js"></script><script src="./static/js/main.368c5d1e.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

@@ -0,0 +1,70 @@
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { Link } from "react-router-dom";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { IElement } from "../../Configurations/types";
interface ISettingsCard {
classes: any;
configuration: IElement;
}
const styles = (theme: Theme) =>
createStyles({
configurationLink: {
border: "#E5E5E5 1px solid",
borderRadius: 2,
padding: 20,
width: 190,
maxWidth: 190,
height: 80,
margin: 14,
display: "flex",
alignItems: "center",
color: "#072C4F",
fontSize: 14,
fontWeight: 700,
textDecoration: "none",
overflow: "hidden",
textOverflow: "ellipsis",
lineClamp: 2,
"& svg": {
fontSize: 35,
marginRight: 15,
},
"&:hover": {
backgroundColor: "#FBFAFA",
},
},
});
const SettingsCard = ({ classes, configuration }: ISettingsCard) => {
return (
<Link
to={`/settings/${configuration.configuration_id}`}
className={classes.configurationLink}
>
{configuration.icon}
{configuration.configuration_label}
</Link>
);
};
export default withStyles(styles)(SettingsCard);

View File

@@ -14,46 +14,23 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment } from "react";
import PageHeader from "../Common/PageHeader/PageHeader";
import { Grid } from "@mui/material";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { containerForHeader } from "../Common/FormComponents/common/styleLibrary";
import ConfigurationsList from "./ConfigurationPanels/ConfigurationsList";
import { ISessionResponse } from "../types";
import React from "react";
import { Route, Router, Switch } from "react-router-dom";
import history from "../../../history";
import ConfigurationOptions from "./ConfigurationPanels/ConfigurationOptions";
import ConfigurationForm from "./ConfigurationPanels/ConfigurationForm";
import NotFoundPage from "../../NotFoundPage";
interface IConfigurationMain {
classes: any;
session: ISessionResponse;
distributedSetup: boolean;
}
const styles = (theme: Theme) =>
createStyles({
headerLabel: {
fontSize: 22,
fontWeight: 600,
color: "#000",
marginTop: 4,
},
...containerForHeader(theme.spacing(4)),
});
const ConfigurationMain = ({ classes }: IConfigurationMain) => {
const ConfigurationMain = () => {
return (
<Fragment>
<PageHeader label="Settings" />
<Grid container className={classes.container}>
<Grid item xs={12}>
<Grid item xs={12}>
<ConfigurationsList />
</Grid>
</Grid>
</Grid>
</Fragment>
<Router history={history}>
<Switch>
<Route path="/settings" exact component={ConfigurationOptions} />
<Route path="/settings/:option" component={ConfigurationForm} />
<Route component={NotFoundPage} />
</Switch>
</Router>
);
};
export default withStyles(styles)(ConfigurationMain);
export default ConfigurationMain;

View File

@@ -0,0 +1,101 @@
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment } from "react";
import get from "lodash/get";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import Grid from "@mui/material/Grid";
import { configurationElements } from "../utils";
import EditConfiguration from "../../NotificationEndpoints/CustomForms/EditConfiguration";
import {
actionsTray,
containerForHeader,
searchField,
settingsCommon,
} from "../../Common/FormComponents/common/styleLibrary";
import BackLink from "../../../../common/BackLink";
import PageHeader from "../../Common/PageHeader/PageHeader";
interface IListConfiguration {
classes: any;
match: any;
history: any;
}
const styles = (theme: Theme) =>
createStyles({
...searchField,
...actionsTray,
...settingsCommon,
...containerForHeader(theme.spacing(4)),
strongText: {
fontWeight: 700,
},
keyName: {
marginLeft: 5,
},
iconText: {
lineHeight: "24px",
},
customConfigurationPage: {
height: "calc(100vh - 324px)",
scrollbarWidth: "none" as const,
"&::-webkit-scrollbar": {
display: "none",
},
},
mainCont: {
...settingsCommon.mainCont,
maxWidth: 1180,
},
});
const ConfigurationsList = ({
classes,
match,
history,
}: IListConfiguration) => {
const configurationName = get(match, "params.option", "");
const findConfiguration = configurationElements.find(
(element) => element.configuration_id === configurationName
);
return (
<Fragment>
<PageHeader
label={`${findConfiguration?.configuration_label} Settings`}
/>
<Grid container className={classes.container}>
<Grid item xs={12} className={classes.mainTitle}>
<BackLink to="/settings" label="Return to Settings" />
</Grid>
<Grid item xs={12}>
{findConfiguration && (
<EditConfiguration
selectedConfiguration={findConfiguration}
history={history}
/>
)}
</Grid>
</Grid>
</Fragment>
);
};
export default withStyles(styles)(ConfigurationsList);

View File

@@ -0,0 +1,99 @@
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment } from "react";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import Grid from "@mui/material/Grid";
import { configurationElements } from "../utils";
import {
actionsTray,
containerForHeader,
searchField,
} from "../../Common/FormComponents/common/styleLibrary";
import PageHeader from "../../Common/PageHeader/PageHeader";
import SettingsCard from "../../Common/SettingsCard/SettingsCard";
interface IConfigurationOptions {
classes: any;
}
const styles = (theme: Theme) =>
createStyles({
strongText: {
fontWeight: 700,
},
keyName: {
marginLeft: 5,
},
iconText: {
lineHeight: "24px",
},
customConfigurationPage: {
height: "calc(100vh - 324px)",
scrollbarWidth: "none" as const,
"&::-webkit-scrollbar": {
display: "none",
},
},
settingsOptionsContainer: {
display: "flex" as const,
flexDirection: "row" as const,
justifyContent: "flex-start" as const,
flexWrap: "wrap" as const,
border: "#E5E5E5 1px solid",
borderRadius: 2,
padding: 5,
backgroundColor: "#fff",
},
configurationLink: {
border: "#E5E5E5 1px solid",
borderRadius: 2,
padding: 20,
width: 190,
height: 80,
margin: 15,
},
...searchField,
...actionsTray,
...containerForHeader(theme.spacing(4)),
});
const ConfigurationOptions = ({ classes }: IConfigurationOptions) => {
return (
<Fragment>
<PageHeader label={"Settings"} />
<Grid container className={classes.container}>
<Grid item xs={12}>
<Grid item xs={12}>
<div className={classes.settingsOptionsContainer}>
{configurationElements.map((element) => (
<SettingsCard
configuration={element}
key={`configItem-${element.configuration_label}`}
/>
))}
</div>
</Grid>
</Grid>
</Grid>
</Fragment>
);
};
export default withStyles(styles)(ConfigurationOptions);

View File

@@ -36,6 +36,7 @@ import BackSettingsIcon from "../../../../icons/BackSettingsIcon";
interface IListConfiguration {
classes: any;
history: any;
}
const styles = (theme: Theme) =>
@@ -67,7 +68,7 @@ const initialConfiguration = {
configuration_label: "",
};
const ConfigurationsList = ({ classes }: IListConfiguration) => {
const ConfigurationsList = ({ classes, history }: IListConfiguration) => {
const [selectedConfiguration, setSelectedConfiguration] =
useState(initialConfiguration);
const [currentConfiguration, setCurrentConfiguration] = useState<number>(0);
@@ -131,9 +132,7 @@ const ConfigurationsList = ({ classes }: IListConfiguration) => {
<Grid item xs={12}>
{currentConfiguration === 1 ? (
<EditConfiguration
closeModalAndRefresh={() => {
setCurrentConfiguration(0);
}}
history={history}
selectedConfiguration={selectedConfiguration}
/>
) : null}

View File

@@ -1,187 +0,0 @@
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useState } from "react";
import get from "lodash/get";
import Grid from "@mui/material/Grid";
import Typography from "@mui/material/Typography";
import { Button, TextField } from "@mui/material";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import InputAdornment from "@mui/material/InputAdornment";
import AddIcon from "@mui/icons-material/Add";
import TableWrapper from "../../Common/TableWrapper/TableWrapper";
import EditConfiguration from "../../NotificationEndpoints/CustomForms/EditConfiguration";
import SearchIcon from "../../../../icons/SearchIcon";
interface IMatchParams {
isExact: boolean;
params: any;
path: string;
}
interface IWebhookPanel {
match: IMatchParams;
classes: any;
}
interface IWebhook {
name: string;
}
const styles = (theme: Theme) =>
createStyles({
strongText: {
fontWeight: 700,
},
keyName: {
marginLeft: 5,
},
actionsTray: {
textAlign: "right",
"& button": {
marginLeft: 10,
},
},
searchField: {
background: "#FFFFFF",
padding: 12,
borderRadius: 5,
boxShadow: "0px 3px 6px #00000012",
},
iconText: {
lineHeight: "24px",
},
});
const panels = {
logger: {
main: "logger",
title: "Logger Webhook Configuration",
modalTitle: "Logger Webhook",
apiURL: "",
configuration: {
configuration_id: "logger_webhook",
configuration_label: "Logger Webhook",
},
},
audit: {
main: "audit",
title: "Audit Webhook Configuration",
modalTitle: "Audit Webhook",
apiURL: "",
configuration: {
configuration_id: "audit_webhook",
configuration_label: "Audit Webhook",
},
},
};
const WebhookPanel = ({ match, classes }: IWebhookPanel) => {
const [addWebhookOpen, setAddWebhookOpen] = useState<boolean>(false);
const [filter, setFilter] = useState<string>("");
const [isLoading, setIsLoading] = useState<boolean>(false);
// const [webhooks, setWebhooks] = useState<IWebhook[]>([]);
const pathIn = get(match, "path", "");
const panelToDisplay = pathIn.split("/");
const panelData = get(panels, panelToDisplay[2], false);
if (!panelData) {
return null;
}
const webhooks: IWebhook[] = [];
const filteredRecords: IWebhook[] = webhooks.filter((elementItem) =>
elementItem.name.toLocaleLowerCase().includes(filter.toLocaleLowerCase())
);
const tableActions = [
{
type: "edit",
onClick: () => {},
},
];
return (
<React.Fragment>
{addWebhookOpen && (
<EditConfiguration
closeModalAndRefresh={() => {
setIsLoading(true);
setAddWebhookOpen(false);
}}
selectedConfiguration={panelData.configuration}
/>
)}
<Grid container>
<Grid item xs={12}>
<Typography variant="h6">{panelData.title}</Typography>
</Grid>
<Grid item xs={12}>
<br />
</Grid>
<Grid item xs={12} className={classes.actionsTray}>
<TextField
placeholder="Filter"
className={classes.searchField}
id="search-resource"
label=""
onChange={(event) => {
setFilter(event.target.value);
}}
InputProps={{
disableUnderline: true,
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
),
}}
variant="standard"
/>
<Button
variant="contained"
color="primary"
startIcon={<AddIcon />}
onClick={() => {
setAddWebhookOpen(true);
}}
>
Add Webhook Configuration
</Button>
</Grid>
<Grid item xs={12}>
<br />
</Grid>
<Grid item xs={12}>
<TableWrapper
itemActions={tableActions}
columns={[{ label: "Name", elementKey: "name" }]}
isLoading={isLoading}
records={filteredRecords}
entityName="Webhook Configurations"
idField="name"
/>
</Grid>
</Grid>
</React.Fragment>
);
};
export default withStyles(styles)(WebhookPanel);

View File

@@ -90,7 +90,7 @@ const TierTypeSelector = ({ classes, history }: ITypeTiersConfig) => {
<Grid container className={classes.mainCont}>
<Grid item xs={12}>
<Grid item xs={12} className={classes.mainTitle}>
<BackLink to="/tiers" label="Pick an object store" />
<BackLink to="/tiers" label="Return to Configured Tiers" />
</Grid>
<Grid item xs={12}>
<Grid item xs={12}>

View File

@@ -53,3 +53,9 @@ export interface IElementValue {
key: string;
value: string;
}
export interface IElement {
configuration_id: string;
configuration_label: string;
icon?: any;
}

View File

@@ -13,49 +13,75 @@
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import { IConfigurationElement, IElementValue } from "./types";
import React from "react";
import PublicIcon from "@mui/icons-material/Public";
import SdStorageIcon from "@mui/icons-material/SdStorage";
import CompressIcon from "@mui/icons-material/Compress";
import CodeIcon from "@mui/icons-material/Code";
import LocalHospitalIcon from "@mui/icons-material/LocalHospital";
import FindReplaceIcon from "@mui/icons-material/FindReplace";
import VpnKeyIcon from "@mui/icons-material/VpnKey";
import LockOpenIcon from "@mui/icons-material/LockOpen";
import LoginIcon from "@mui/icons-material/Login";
import PendingActionsIcon from "@mui/icons-material/PendingActions";
import CallToActionIcon from "@mui/icons-material/CallToAction";
import { IElement, IElementValue } from "./types";
export const configurationElements: IConfigurationElement[] = [
export const configurationElements: IElement[] = [
{
icon: <PublicIcon />,
configuration_id: "region",
configuration_label: "Edit Region Configuration",
configuration_label: "Region",
},
{
icon: <SdStorageIcon />,
configuration_id: "cache",
configuration_label: "Edit Cache Configuration",
configuration_label: "Cache",
},
{
icon: <CompressIcon />,
configuration_id: "compression",
configuration_label: "Edit Compression Configuration",
configuration_label: "Compression",
},
{
icon: <CodeIcon />,
configuration_id: "api",
configuration_label: "Edit API Configuration",
configuration_label: "API",
},
{
icon: <LocalHospitalIcon />,
configuration_id: "heal",
configuration_label: "Edit Heal Configuration",
configuration_label: "Heal",
},
{
icon: <FindReplaceIcon />,
configuration_id: "scanner",
configuration_label: "Edit Scanner Configuration",
configuration_label: "Scanner",
},
{ configuration_id: "etcd", configuration_label: "Edit Etcd Configuration" },
{
icon: <VpnKeyIcon />,
configuration_id: "etcd",
configuration_label: "Etcd",
},
{
icon: <LockOpenIcon />,
configuration_id: "identity_openid",
configuration_label: "Edit Identity Openid Configuration",
configuration_label: "Identity Openid",
},
{
icon: <LoginIcon />,
configuration_id: "identity_ldap",
configuration_label: "Edit Identity LDAP Configuration",
configuration_label: "Identity LDAP",
},
{
icon: <CallToActionIcon />,
configuration_id: "logger_webhook",
configuration_label: "Edit Logger Webhook Configuration",
configuration_label: "Logger Webhook",
},
{
icon: <PendingActionsIcon />,
configuration_id: "audit_webhook",
configuration_label: "Edit Audit Webhook Configuration",
configuration_label: "Audit Webhook",
},
];

View File

@@ -44,7 +44,6 @@ import Account from "./Account/Account";
import Users from "./Users/Users";
import Groups from "./Groups/Groups";
import ConfigurationMain from "./Configurations/ConfigurationMain";
import WebhookPanel from "./Configurations/ConfigurationPanels/WebhookPanel";
import TenantsMain from "./Tenants/TenantsMain";
import TenantDetails from "./Tenants/TenantDetails/TenantDetails";
import License from "./License/License";
@@ -286,6 +285,10 @@ const Console = ({
component: ConfigurationMain,
path: "/settings",
},
{
component: ConfigurationMain,
path: "/settings/:option",
},
{
component: AddNotificationEndpoint,
path: "/notification-endpoints/add/:service",
@@ -317,14 +320,6 @@ const Console = ({
changePassword: session.pages.includes("/account/change-password"),
},
},
{
component: WebhookPanel,
path: "/webhook/logger",
},
{
component: WebhookPanel,
path: "/webhook/audit",
},
{
component: TenantsMain,
path: "/tenants",

View File

@@ -63,19 +63,19 @@ const styles = (theme: Theme) =>
});
interface IAddNotificationEndpointProps {
closeModalAndRefresh: any;
serverNeedsRestart: typeof serverNeedsRestart;
setErrorSnackMessage: typeof setErrorSnackMessage;
selectedConfiguration: IConfigurationElement;
classes: any;
history: any;
}
const EditConfiguration = ({
closeModalAndRefresh,
serverNeedsRestart,
selectedConfiguration,
setErrorSnackMessage,
classes,
history,
}: IAddNotificationEndpointProps) => {
//Local States
const [valuesObj, setValueObj] = useState<IElementValue[]>([]);
@@ -116,7 +116,7 @@ const EditConfiguration = ({
setSaving(false);
serverNeedsRestart(true);
closeModalAndRefresh();
history.push("/settings");
})
.catch((err: ErrorResponseHandler) => {
setSaving(false);
@@ -125,10 +125,10 @@ const EditConfiguration = ({
}
}, [
saving,
history,
serverNeedsRestart,
selectedConfiguration,
valuesObj,
closeModalAndRefresh,
setErrorSnackMessage,
]);
@@ -147,39 +147,32 @@ const EditConfiguration = ({
return (
<Fragment>
<Grid item xs={12} className={classes.customTitle}>
{selectedConfiguration.configuration_label}
</Grid>
<Fragment>
<form noValidate onSubmit={submitForm}>
<Grid item xs={12} className={classes.settingsFormContainer}>
{loadingConfig && (
<Grid item xs={12}>
<LinearProgress />
</Grid>
)}
<ConfTargetGeneric
fields={
fieldsConfigurations[selectedConfiguration.configuration_id]
}
onChange={onValueChange}
defaultVals={configValues}
/>
</Grid>
<Grid item xs={12} className={classes.settingsButtonContainer}>
<Grid item xs={12} className={classes.innerSettingsButtonContainer}>
<Button
type="submit"
variant="contained"
color="primary"
disabled={saving}
>
Save
</Button>
<form noValidate onSubmit={submitForm}>
<Grid item xs={12} className={classes.settingsFormContainer}>
{loadingConfig && (
<Grid item xs={12}>
<LinearProgress />
</Grid>
</Grid>
</form>
</Fragment>
)}
<ConfTargetGeneric
fields={
fieldsConfigurations[selectedConfiguration.configuration_id]
}
onChange={onValueChange}
defaultVals={configValues}
/>
</Grid>
<Grid item xs={12} className={classes.settingsButtonContainer}>
<Button
type="submit"
variant="contained"
color="primary"
disabled={saving}
>
Save
</Button>
</Grid>
</form>
</Fragment>
);
};

View File

@@ -56,7 +56,7 @@ const NotificationTypeSelector = ({ classes }: INotificationTypeSelector) => {
<Grid item xs={12} className={classes.mainTitle}>
<BackLink
to="/notification-endpoints"
label="Pick a supported service"
label="Return to Configured Endpoints"
/>
</Grid>
<Grid item xs={12} className={classes.centerElements}>