Update Settings Page components (#2986)

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
Alex
2023-08-09 18:30:42 -06:00
committed by GitHub
parent 93bd0d65e2
commit 72bb9d0ca1
10 changed files with 189 additions and 404 deletions

View File

@@ -1,181 +0,0 @@
import React, { useEffect, useState } from "react";
import { Box, Tab, TabProps } from "@mui/material";
import { TabContext, TabList, TabPanel } from "@mui/lab";
import withStyles from "@mui/styles/withStyles";
import { Theme, useTheme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import useMediaQuery from "@mui/material/useMediaQuery";
import { useLocation } from "react-router-dom";
export type TabItemProps = {
tabConfig: TabProps | any;
content?: JSX.Element | JSX.Element[];
};
type VerticalTabsProps = {
classes: any;
children: TabItemProps[];
selectedTab?: string;
routes?: any;
isRouteTabs?: boolean;
};
const styles = (theme: Theme) =>
createStyles({
tabsContainer: {
display: "flex",
height: "100%",
width: "100%",
},
tabsHeaderContainer: {
width: "300px",
background: "#F8F8F8",
borderRight: "1px solid #EAEAEA",
"& .MuiTabs-root": {
"& .MuiTabs-indicator": {
display: "none",
},
"& .MuiTab-root": {
display: "flex",
flexFlow: "row",
alignItems: "center",
justifyContent: "flex-start",
borderBottom: "1px solid #EAEAEA",
"& .MuiSvgIcon-root": {
marginRight: 8,
marginBottom: 0,
},
"&.Mui-selected": {
background: "#E5E5E5",
fontWeight: 600,
},
},
"&. MuiTabs-scroller": {
display: "none",
},
},
},
tabContentContainer: {
width: "100%",
"& .MuiTabPanel-root": {
height: "100%",
},
},
tabPanel: {
height: "100%",
},
/*Below md breakpoint make it horizontal and style it for scrolling tabs*/
"@media (max-width: 900px)": {
tabsContainer: {
flexFlow: "column",
flexDirection: "column",
},
tabsHeaderContainer: {
width: "100%",
borderBottom: " 1px solid #EAEAEA",
"& .MuiTabs-root .MuiTabs-scroller .MuiButtonBase-root": {
borderBottom: " 0px",
},
},
},
});
const tabStripStyle = {
minHeight: 60,
};
const VerticalTabs = ({
children,
classes,
selectedTab = "0",
routes,
isRouteTabs,
}: VerticalTabsProps) => {
const theme = useTheme();
const { pathname = "" } = useLocation();
const isSmallScreen = useMediaQuery(theme.breakpoints.down("md"));
const [value, setValue] = useState(selectedTab);
const headerList: TabProps[] = [];
const contentList: React.ReactNode[] = [];
useEffect(() => {
if (isRouteTabs) {
const tabConfigElement = children.find(
(item) => item.tabConfig.to === pathname,
);
if (tabConfigElement) {
setValue(tabConfigElement.tabConfig.value);
}
}
}, [isRouteTabs, children, pathname]);
if (!children) return null;
children.forEach((child) => {
headerList.push(child.tabConfig);
contentList.push(child.content);
});
const handleChange = (event: React.SyntheticEvent, newValue: string) => {
setValue(newValue);
};
return (
<TabContext value={`${value}`}>
<Box className={classes.tabsContainer}>
<Box className={classes.tabsHeaderContainer}>
<TabList
onChange={handleChange}
orientation={isSmallScreen ? "horizontal" : "vertical"}
variant={isSmallScreen ? "scrollable" : "standard"}
scrollButtons="auto"
className={classes.tabList}
>
{headerList.map((item, index) => {
if (item) {
return (
<Tab
className={classes.tabHeader}
key={`v-tab-${index}`}
value={`${index}`}
style={tabStripStyle}
{...item}
disableRipple
disableTouchRipple
focusRipple={true}
/>
);
}
return null;
})}
</TabList>
</Box>
<Box className={classes.tabContentContainer}>
{!isRouteTabs
? contentList.map((item, index) => {
return (
<TabPanel
classes={{ ...classes.tabPanel }}
key={`v-tab-p-${index}`}
value={`${index}`}
>
{item ? item : null}
</TabPanel>
);
})
: null}
{isRouteTabs ? (
<div className={classes.tabPanel}>{routes}</div>
) : null}
</Box>
</Box>
</TabContext>
);
};
export default withStyles(styles)(VerticalTabs);

View File

@@ -15,27 +15,31 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment, useCallback, useEffect, useState } from "react"; import React, { Fragment, useCallback, useEffect, useState } from "react";
import { Theme } from "@mui/material/styles"; import {
import createStyles from "@mui/styles/createStyles"; Box,
import withStyles from "@mui/styles/withStyles"; Grid,
import Grid from "@mui/material/Grid"; HelpBox,
PageLayout,
ScreenTitle,
SettingsIcon,
Tabs,
} from "mds";
import { configurationElements } from "../utils"; import { configurationElements } from "../utils";
import { import {
actionsTray, Navigate,
containerForHeader, Route,
searchField, Routes,
} from "../../Common/FormComponents/common/styleLibrary"; useLocation,
import { HelpBox, PageLayout, SettingsIcon } from "mds"; useNavigate,
import { Link, Navigate, Route, Routes, useLocation } from "react-router-dom"; } from "react-router-dom";
import VerticalTabs from "../../Common/VerticalTabs/VerticalTabs";
import ScreenTitle from "../../Common/ScreenTitle/ScreenTitle";
import ConfigurationForm from "./ConfigurationForm"; import ConfigurationForm from "./ConfigurationForm";
import { IAM_PAGES } from "../../../../common/SecureComponent/permissions"; import { IAM_PAGES } from "../../../../common/SecureComponent/permissions";
import PageHeaderWrapper from "../../Common/PageHeaderWrapper/PageHeaderWrapper"; import PageHeaderWrapper from "../../Common/PageHeaderWrapper/PageHeaderWrapper";
import ExportConfigButton from "./ExportConfigButton"; import ExportConfigButton from "./ExportConfigButton";
import ImportConfigButton from "./ImportConfigButton"; import ImportConfigButton from "./ImportConfigButton";
import { Box } from "@mui/material";
import HelpMenu from "../../HelpMenu"; import HelpMenu from "../../HelpMenu";
import { setErrorSnackMessage, setHelpName } from "../../../../systemSlice"; import { setErrorSnackMessage, setHelpName } from "../../../../systemSlice";
import { useAppDispatch } from "../../../../store"; import { useAppDispatch } from "../../../../store";
@@ -43,26 +47,6 @@ import { api } from "../../../../api";
import { IElement } from "../types"; import { IElement } from "../types";
import { errorToHandler } from "../../../../api/errors"; import { errorToHandler } from "../../../../api/errors";
interface IConfigurationOptions {
classes: any;
}
const styles = (theme: Theme) =>
createStyles({
settingsOptionsContainer: {
display: "flex" as const,
flexDirection: "row" as const,
justifyContent: "flex-start" as const,
flexWrap: "wrap" as const,
border: "#E5E5E5 1px solid",
borderRadius: 2,
backgroundColor: "#fff",
},
...searchField,
...actionsTray,
...containerForHeader,
});
const getRoutePath = (path: string) => { const getRoutePath = (path: string) => {
return `${IAM_PAGES.SETTINGS}/${path}`; return `${IAM_PAGES.SETTINGS}/${path}`;
}; };
@@ -71,9 +55,10 @@ const getRoutePath = (path: string) => {
const NON_SUB_SYS_CONFIG_ITEMS = ["region"]; const NON_SUB_SYS_CONFIG_ITEMS = ["region"];
const IGNORED_CONFIG_SUB_SYS = ["cache"]; // cache config is not supported. const IGNORED_CONFIG_SUB_SYS = ["cache"]; // cache config is not supported.
const ConfigurationOptions = ({ classes }: IConfigurationOptions) => { const ConfigurationOptions = () => {
const { pathname = "" } = useLocation(); const { pathname = "" } = useLocation();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const navigate = useNavigate();
const [configSubSysList, setConfigSubSysList] = useState<string[]>([]); const [configSubSysList, setConfigSubSysList] = useState<string[]>([]);
const fetchConfigSubSysList = useCallback(async () => { const fetchConfigSubSysList = useCallback(async () => {
@@ -99,8 +84,6 @@ const ConfigurationOptions = ({ classes }: IConfigurationOptions) => {
}); });
}, [dispatch]); }, [dispatch]);
let selConfigTab = pathname.substring(pathname.lastIndexOf("/") + 1);
selConfigTab = selConfigTab === "settings" ? "region" : selConfigTab;
useEffect(() => { useEffect(() => {
fetchConfigSubSysList(); fetchConfigSubSysList();
dispatch(setHelpName("settings_Region")); dispatch(setHelpName("settings_Region"));
@@ -121,59 +104,57 @@ const ConfigurationOptions = ({ classes }: IConfigurationOptions) => {
<Fragment> <Fragment>
<PageHeaderWrapper label={"Settings"} actions={<HelpMenu />} /> <PageHeaderWrapper label={"Settings"} actions={<HelpMenu />} />
<PageLayout> <PageLayout>
<Grid item xs={12}> <Grid item xs={12} id={"settings-container"}>
<div <ScreenTitle
id="settings-container" icon={<SettingsIcon />}
className={classes.settingsOptionsContainer} title={"MinIO Configuration:"}
> actions={
<ScreenTitle <Box
icon={<SettingsIcon />} sx={{
title={"MinIO Configuration:"} display: "flex",
actions={ gap: 10,
<Box }}
sx={{ >
display: "flex", <ImportConfigButton />
gap: 2, <ExportConfigButton />
}} </Box>
> }
<ImportConfigButton /> sx={{ marginBottom: 15 }}
<ExportConfigButton /> />
</Box> <Tabs
} currentTabOrPath={pathname}
/> onTabClick={(path) => {
<VerticalTabs navigate(path);
selectedTab={selConfigTab} }}
isRouteTabs useRouteTabs
routes={ options={availableConfigSubSys.map((element) => {
<Routes> const { configuration_id, configuration_label, icon } = element;
{availableConfigSubSys.map((element) => ( return {
<Route tabConfig: {
key={`configItem-${element.configuration_label}`} id: `settings-tab-${configuration_label}`,
path={`${element.configuration_id}`} label: configuration_label,
element={<ConfigurationForm />} value: configuration_id,
/> icon: icon,
))} to: getRoutePath(configuration_id),
},
};
})}
routes={
<Routes>
{availableConfigSubSys.map((element) => (
<Route <Route
path={"/"} key={`configItem-${element.configuration_label}`}
element={<Navigate to={`${IAM_PAGES.SETTINGS}/region`} />} path={`${element.configuration_id}`}
element={<ConfigurationForm />}
/> />
</Routes> ))}
} <Route
> path={"/"}
{availableConfigSubSys.map((element) => { element={<Navigate to={`${IAM_PAGES.SETTINGS}/region`} />}
const { configuration_id, configuration_label, icon } = element; />
return { </Routes>
tabConfig: { }
label: configuration_label, />
value: configuration_id,
icon: icon,
component: Link,
to: getRoutePath(configuration_id),
},
};
})}
</VerticalTabs>
</div>
</Grid> </Grid>
<Grid item xs={12} sx={{ paddingTop: "15px" }}> <Grid item xs={12} sx={{ paddingTop: "15px" }}>
<HelpBox <HelpBox
@@ -203,4 +184,4 @@ const ConfigurationOptions = ({ classes }: IConfigurationOptions) => {
); );
}; };
export default withStyles(styles)(ConfigurationOptions); export default ConfigurationOptions;

View File

@@ -1,3 +1,19 @@
// 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 React from "react";
import { Button, UploadIcon } from "mds"; import { Button, UploadIcon } from "mds";
import useApi from "../../Common/Hooks/useApi"; import useApi from "../../Common/Hooks/useApi";

View File

@@ -1,3 +1,19 @@
// 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, useEffect, useRef, useState } from "react"; import React, { Fragment, useEffect, useRef, useState } from "react";
import { Button, DownloadIcon } from "mds"; import { Button, DownloadIcon } from "mds";
import useApi from "../../Common/Hooks/useApi"; import useApi from "../../Common/Hooks/useApi";

View File

@@ -14,38 +14,27 @@
// You should have received a copy of the GNU Affero General Public License // 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/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useEffect, useState } from "react"; import React, { Fragment, useEffect, useState } 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 { IElementValue, IOverrideEnv, KVField } from "../Configurations/types";
import { import {
formFieldStyles, CommentBox,
modalBasic, ConsoleIcon,
} from "../Common/FormComponents/common/styleLibrary"; FormLayout,
Grid,
InputBox,
ReadBox,
Switch,
Tooltip,
} from "mds";
import { IElementValue, IOverrideEnv, KVField } from "../Configurations/types";
import CSVMultiSelector from "../Common/FormComponents/CSVMultiSelector/CSVMultiSelector"; import CSVMultiSelector from "../Common/FormComponents/CSVMultiSelector/CSVMultiSelector";
import CommentBoxWrapper from "../Common/FormComponents/CommentBoxWrapper/CommentBoxWrapper";
import PredefinedList from "../Common/FormComponents/PredefinedList/PredefinedList";
import { ConsoleIcon, InputBox, Switch, Tooltip } from "mds";
interface IConfGenericProps { interface IConfGenericProps {
onChange: (newValue: IElementValue[]) => void; onChange: (newValue: IElementValue[]) => void;
fields: KVField[]; fields: KVField[];
defaultVals?: IElementValue[]; defaultVals?: IElementValue[];
overrideEnv?: IOverrideEnv; overrideEnv?: IOverrideEnv;
classes: any;
} }
const styles = (theme: Theme) =>
createStyles({
...formFieldStyles,
formFieldRow: {
...formFieldStyles.formFieldRow,
},
...modalBasic,
});
// Function to get defined values, // Function to get defined values,
//we make this because the backed sometimes don't return all the keys when there is an initial configuration //we make this because the backed sometimes don't return all the keys when there is an initial configuration
export const valueDef = ( export const valueDef = (
@@ -71,7 +60,6 @@ const ConfTargetGeneric = ({
fields, fields,
defaultVals, defaultVals,
overrideEnv, overrideEnv,
classes,
}: IConfGenericProps) => { }: IConfGenericProps) => {
const [valueHolder, setValueHolder] = useState<IElementValue[]>([]); const [valueHolder, setValueHolder] = useState<IElementValue[]>([]);
const fieldsElements = !fields ? [] : fields; const fieldsElements = !fields ? [] : fields;
@@ -113,9 +101,8 @@ const ConfTargetGeneric = ({
if (override) { if (override) {
return ( return (
<PredefinedList <ReadBox
label={field.label} label={field.label}
content={override.value}
actionButton={ actionButton={
<Grid <Grid
item item
@@ -133,7 +120,10 @@ const ConfTargetGeneric = ({
</Tooltip> </Tooltip>
</Grid> </Grid>
} }
/> sx={{ width: "100%" }}
>
{override.value}
</ReadBox>
); );
} }
} }
@@ -180,15 +170,13 @@ const ConfTargetGeneric = ({
); );
case "comment": case "comment":
return ( return (
<CommentBoxWrapper <CommentBox
id={field.name} id={field.name}
name={field.name} name={field.name}
label={field.label} label={field.label}
tooltip={field.tooltip} tooltip={field.tooltip}
value={holderItem ? holderItem.value : ""} value={holderItem ? holderItem.value : ""}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => onChange={(e) => setValueElement(field.name, e.target.value, item)}
setValueElement(field.name, e.target.value, item)
}
placeholder={field.placeholder} placeholder={field.placeholder}
/> />
); );
@@ -210,16 +198,12 @@ const ConfTargetGeneric = ({
}; };
return ( return (
<Grid container> <FormLayout withBorders={false} containerPadding={false}>
<Grid xs={12} item className={classes.fieldBox}> {fieldsElements.map((field, item) => (
{fieldsElements.map((field, item) => ( <Fragment key={field.name}>{fieldDefinition(field, item)}</Fragment>
<Grid item xs={12} key={field.name} className={classes.formFieldRow}> ))}
{fieldDefinition(field, item)} </FormLayout>
</Grid>
))}
</Grid>
</Grid>
); );
}; };
export default withStyles(styles)(ConfTargetGeneric); export default ConfTargetGeneric;

View File

@@ -15,20 +15,13 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment, useCallback, useEffect, useState } from "react"; import React, { Fragment, useCallback, useEffect, useState } from "react";
import { Button, Loader } from "mds";
import { useLocation, useNavigate } from "react-router-dom";
import get from "lodash/get"; import get from "lodash/get";
import { Theme } from "@mui/material/styles"; import { Box, Button, Grid, Loader } from "mds";
import createStyles from "@mui/styles/createStyles"; import { useLocation, useNavigate } from "react-router-dom";
import withStyles from "@mui/styles/withStyles"; import { useSelector } from "react-redux";
import { Box } from "@mui/material"; import { api } from "api";
import Grid from "@mui/material/Grid"; import { Configuration, ConfigurationKV } from "api/consoleApi";
import ConfTargetGeneric from "../ConfTargetGeneric"; import { errorToHandler } from "api/errors";
import {
fieldBasic,
settingsCommon,
} from "../../Common/FormComponents/common/styleLibrary";
import { import {
fieldsConfigurations, fieldsConfigurations,
overrideFields, overrideFields,
@@ -40,7 +33,6 @@ import {
IOverrideEnv, IOverrideEnv,
KVField, KVField,
} from "../../Configurations/types"; } from "../../Configurations/types";
import ResetConfigurationModal from "./ResetConfigurationModal";
import { import {
configurationIsLoading, configurationIsLoading,
setErrorSnackMessage, setErrorSnackMessage,
@@ -50,31 +42,16 @@ import {
} from "../../../../systemSlice"; } from "../../../../systemSlice";
import { AppState, useAppDispatch } from "../../../../store"; import { AppState, useAppDispatch } from "../../../../store";
import WebhookSettings from "../WebhookSettings/WebhookSettings"; import WebhookSettings from "../WebhookSettings/WebhookSettings";
import { useSelector } from "react-redux"; import ConfTargetGeneric from "../ConfTargetGeneric";
import { api } from "api"; import ResetConfigurationModal from "./ResetConfigurationModal";
import { Configuration, ConfigurationKV } from "api/consoleApi";
import { errorToHandler } from "api/errors";
const styles = (theme: Theme) =>
createStyles({
...fieldBasic,
...settingsCommon,
settingsFormContainer: {
display: "grid",
gridTemplateColumns: "1fr",
gridGap: "10px",
},
});
interface IAddNotificationEndpointProps { interface IAddNotificationEndpointProps {
selectedConfiguration: IConfigurationElement; selectedConfiguration: IConfigurationElement;
classes: any;
className?: string; className?: string;
} }
const EditConfiguration = ({ const EditConfiguration = ({
selectedConfiguration, selectedConfiguration,
classes,
className = "", className = "",
}: IAddNotificationEndpointProps) => { }: IAddNotificationEndpointProps) => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@@ -238,7 +215,15 @@ const EditConfiguration = ({
flexFlow: "column", flexFlow: "column",
}} }}
> >
<Grid item xs={12} className={classes.settingsFormContainer}> <Grid
item
xs={12}
sx={{
display: "grid",
gridTemplateColumns: "1fr",
gap: "10px",
}}
>
<ConfTargetGeneric <ConfTargetGeneric
fields={ fields={
fieldsConfigurations[ fieldsConfigurations[
@@ -263,6 +248,7 @@ const EditConfiguration = ({
}} }}
> >
<Button <Button
type={"button"}
id={"restore-defaults"} id={"restore-defaults"}
variant="secondary" variant="secondary"
onClick={resetConfigurationMOpen} onClick={resetConfigurationMOpen}
@@ -287,4 +273,4 @@ const EditConfiguration = ({
); );
}; };
export default withStyles(styles)(EditConfiguration); export default EditConfiguration;

View File

@@ -15,11 +15,11 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment, useState } from "react"; import React, { Fragment, useState } from "react";
import { Button, Grid } from "mds"; import { Button, FormLayout, Grid, InputBox } from "mds";
import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; import { api } from "api";
import { errorToHandler } from "api/errors";
import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper"; import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper";
import { Webhook } from "@mui/icons-material"; import { Webhook } from "@mui/icons-material";
import { formFieldStyles } from "../../Common/FormComponents/common/styleLibrary";
import CallToActionIcon from "@mui/icons-material/CallToAction"; import CallToActionIcon from "@mui/icons-material/CallToAction";
import PendingActionsIcon from "@mui/icons-material/PendingActions"; import PendingActionsIcon from "@mui/icons-material/PendingActions";
import { import {
@@ -30,8 +30,7 @@ import {
} from "../../../../systemSlice"; } from "../../../../systemSlice";
import { useAppDispatch } from "../../../../store"; import { useAppDispatch } from "../../../../store";
import { LinearProgress } from "@mui/material"; import { LinearProgress } from "@mui/material";
import { api } from "api"; import { modalStyleUtils } from "../../Common/FormComponents/common/styleLibrary";
import { errorToHandler } from "api/errors";
interface IEndpointModal { interface IEndpointModal {
open: boolean; open: boolean;
@@ -148,8 +147,8 @@ const AddEndpointModal = ({ open, type, onCloseEndpoint }: IEndpointModal) => {
onClose={onCloseEndpoint} onClose={onCloseEndpoint}
titleIcon={icon} titleIcon={icon}
> >
<Grid item xs={12} sx={{ ...formFieldStyles.formFieldRow }}> <FormLayout containerPadding={false} withBorders={false}>
<InputBoxWrapper <InputBox
id="name" id="name"
name="name" name="name"
onChange={(event: React.ChangeEvent<HTMLInputElement>) => { onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
@@ -167,9 +166,7 @@ const AddEndpointModal = ({ open, type, onCloseEndpoint }: IEndpointModal) => {
pattern={"^(?=.*[a-zA-Z0-9]).{1,}$"} pattern={"^(?=.*[a-zA-Z0-9]).{1,}$"}
required required
/> />
</Grid> <InputBox
<Grid item xs={12} sx={{ ...formFieldStyles.formFieldRow }}>
<InputBoxWrapper
id="endpoint" id="endpoint"
name="endpoint" name="endpoint"
onChange={(event: React.ChangeEvent<HTMLInputElement>) => { onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
@@ -190,9 +187,7 @@ const AddEndpointModal = ({ open, type, onCloseEndpoint }: IEndpointModal) => {
} }
required required
/> />
</Grid> <InputBox
<Grid item xs={12} sx={{ ...formFieldStyles.formFieldRow }}>
<InputBoxWrapper
id="auth-token" id="auth-token"
name="auth-token" name="auth-token"
onChange={(event: React.ChangeEvent<HTMLInputElement>) => { onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
@@ -202,7 +197,7 @@ const AddEndpointModal = ({ open, type, onCloseEndpoint }: IEndpointModal) => {
label="Auth Token" label="Auth Token"
value={authToken} value={authToken}
/> />
</Grid> </FormLayout>
{saving && ( {saving && (
<Grid <Grid
item item
@@ -214,14 +209,7 @@ const AddEndpointModal = ({ open, type, onCloseEndpoint }: IEndpointModal) => {
<LinearProgress /> <LinearProgress />
</Grid> </Grid>
)} )}
<Grid <Grid item xs={12} sx={modalStyleUtils.modalButtonBar}>
item
xs={12}
sx={{
display: "flex",
justifyContent: "flex-end",
}}
>
<Button <Button
id={"reset"} id={"reset"}
type="button" type="button"

View File

@@ -14,9 +14,10 @@
// You should have received a copy of the GNU Affero General Public License // 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/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useEffect, useState } from "react"; import React, { useEffect, useState, Fragment } from "react";
import { ConfirmDeleteIcon } from "mds"; import { ConfirmDeleteIcon } from "mds";
import { DialogContentText } from "@mui/material"; import { api } from "api";
import { errorToHandler } from "api/errors";
import ConfirmDialog from "../../Common/ModalWrapper/ConfirmDialog"; import ConfirmDialog from "../../Common/ModalWrapper/ConfirmDialog";
import { import {
configurationIsLoading, configurationIsLoading,
@@ -24,8 +25,6 @@ import {
setServerNeedsRestart, setServerNeedsRestart,
} from "../../../../systemSlice"; } from "../../../../systemSlice";
import { useAppDispatch } from "../../../../store"; import { useAppDispatch } from "../../../../store";
import { api } from "api";
import { errorToHandler } from "api/errors";
interface IDeleteWebhookEndpoint { interface IDeleteWebhookEndpoint {
modalOpen: boolean; modalOpen: boolean;
@@ -38,7 +37,6 @@ const DeleteWebhookEndpoint = ({
modalOpen, modalOpen,
onClose, onClose,
selectedARN, selectedARN,
type,
}: IDeleteWebhookEndpoint) => { }: IDeleteWebhookEndpoint) => {
const [deleteLoading, setDeleteLoading] = useState<boolean>(false); const [deleteLoading, setDeleteLoading] = useState<boolean>(false);
@@ -84,10 +82,10 @@ const DeleteWebhookEndpoint = ({
titleIcon={<ConfirmDeleteIcon />} titleIcon={<ConfirmDeleteIcon />}
onClose={onClose} onClose={onClose}
confirmationContent={ confirmationContent={
<DialogContentText> <Fragment>
{`${message} `} {`${message} `}
<strong>{selectedARN}</strong>? <strong>{selectedARN}</strong>?
</DialogContentText> </Fragment>
} }
/> />
); );

View File

@@ -43,11 +43,10 @@ test("All vertical tab items exist", async (t) => {
const settingsHealTabExists = elements.settingsHealTab.exists; const settingsHealTabExists = elements.settingsHealTab.exists;
const settingsScannerTabExists = elements.settingsScannerTab.exists; const settingsScannerTabExists = elements.settingsScannerTab.exists;
const settingsEtcdTabExists = elements.settingsEtcdTab.exists; const settingsEtcdTabExists = elements.settingsEtcdTab.exists;
const settingsOpenIdTabExists = elements.settingsOpenIdTab.exists;
const settingsLdapTabExists = elements.settingsLdapTab.exists;
const settingsLoggerWebhookTabExists = const settingsLoggerWebhookTabExists =
elements.settingsLoggerWebhookTab.exists; elements.settingsLoggerWebhookTab.exists;
const settingsAuditWebhookTabExists = elements.settingsAuditWebhookTab.exists; const settingsAuditWebhookTabExists = elements.settingsAuditWebhookTab.exists;
const settingsAuditKafkaTabExists = elements.settingsAuditKafkaTab.exists;
await t await t
.navigateTo("http://localhost:9090/settings/configurations") .navigateTo("http://localhost:9090/settings/configurations")
.expect(settingsRegionTabExists) .expect(settingsRegionTabExists)
@@ -65,5 +64,7 @@ test("All vertical tab items exist", async (t) => {
.expect(settingsLoggerWebhookTabExists) .expect(settingsLoggerWebhookTabExists)
.ok() .ok()
.expect(settingsAuditWebhookTabExists) .expect(settingsAuditWebhookTabExists)
.ok()
.expect(settingsAuditKafkaTabExists)
.ok(); .ok();
}); });

View File

@@ -123,45 +123,41 @@ export const settingsWindow = Selector("#settings-container");
//---------------------------------------------------- //----------------------------------------------------
// Settings page vertical tabs // Settings page vertical tabs
//---------------------------------------------------- //----------------------------------------------------
export const settingsRegionTab = Selector(".MuiTab-root").withAttribute( export const settingsRegionTab = Selector("button").withAttribute(
"href", "id",
"/settings/configurations/region", "settings-tab-Region",
); );
export const settingsCompressionTab = Selector(".MuiTab-root").withAttribute( export const settingsCompressionTab = Selector("button").withAttribute(
"href", "id",
"/settings/configurations/compression", "settings-tab-Compression",
); );
export const settingsApiTab = Selector(".MuiTab-root").withAttribute( export const settingsApiTab = Selector("button").withAttribute(
"href", "id",
"/settings/configurations/api", "settings-tab-API",
); );
export const settingsHealTab = Selector(".MuiTab-root").withAttribute( export const settingsHealTab = Selector("button").withAttribute(
"href", "id",
"/settings/configurations/heal", "settings-tab-Heal",
); );
export const settingsScannerTab = Selector(".MuiTab-root").withAttribute( export const settingsScannerTab = Selector("button").withAttribute(
"href", "id",
"/settings/configurations/scanner", "settings-tab-Scanner",
); );
export const settingsEtcdTab = Selector(".MuiTab-root").withAttribute( export const settingsEtcdTab = Selector("button").withAttribute(
"href", "id",
"/settings/configurations/etcd", "settings-tab-Etcd",
); );
export const settingsOpenIdTab = Selector(".MuiTab-root").withAttribute( export const settingsLoggerWebhookTab = Selector("button").withAttribute(
"href", "id",
"/settings/configurations/identity_openid", "settings-tab-Logger Webhook",
); );
export const settingsLdapTab = Selector(".MuiTab-root").withAttribute( export const settingsAuditWebhookTab = Selector("button").withAttribute(
"href", "id",
"/settings/configurations/identity_ldap", "settings-tab-Audit Webhook",
); );
export const settingsLoggerWebhookTab = Selector(".MuiTab-root").withAttribute( export const settingsAuditKafkaTab = Selector("button").withAttribute(
"href", "id",
"/settings/configurations/logger_webhook", "settings-tab-Audit Kafka",
);
export const settingsAuditWebhookTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/configurations/audit_webhook",
); );
//---------------------------------------------------- //----------------------------------------------------