Settings page ux refactor (#1242)

Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
This commit is contained in:
Prakash Senthil Vel
2021-11-20 04:57:18 +05:30
committed by GitHub
parent 575bf2927d
commit f56b4905c9
10 changed files with 155 additions and 63 deletions

View File

@@ -146,6 +146,7 @@ const CSVMultiSelector = ({
<InputBoxWrapper
id={`${name}-${index.toString()}`}
label={""}
classes={classes}
name={`${name}-${index.toString()}`}
value={currentElements[index]}
onChange={onChangeElement}

View File

@@ -148,7 +148,9 @@ const InputBoxWrapper = ({
<React.Fragment>
<Grid
container
className={` ${error !== "" ? classes.errorInField : ""}`}
className={` ${
error !== "" ? classes.errorInField : classes.inputBoxContainer
}`}
>
{label !== "" && (
<InputLabel

View File

@@ -388,8 +388,7 @@ export const settingsCommon = {
margin: "15px 38px 27px",
},
settingsFormContainer: {
height: "calc(100vh - 421px)",
padding: "15px 38px",
padding: 38,
overflowY: "auto" as const,
scrollbarWidth: "none" as const,
"&::-webkit-scrollbar": {
@@ -397,7 +396,6 @@ export const settingsCommon = {
},
},
settingsButtonContainer: {
borderTop: "1px solid #EAEAEA",
padding: "15px 38px",
textAlign: "right" as const,
},

View File

@@ -24,6 +24,7 @@ const styles = (theme: Theme) =>
tabsContainer: {
display: "flex",
height: "100%",
width: "100%",
},
tabsHeaderContainer: {
width: "300px",
@@ -39,11 +40,9 @@ const styles = (theme: Theme) =>
alignItems: "center",
justifyContent: "flex-start",
borderBottom: "1px solid #EAEAEA",
"& .min-icon": {
marginRight: ".3rem",
"& .MuiSvgIcon-root": {
marginRight: 8,
marginBottom: 0,
height: ".8rem",
width: ".8rem",
},
"&.Mui-selected": {
background: "#E5E5E5",

View File

@@ -18,15 +18,13 @@ 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";
const ConfigurationMain = () => {
return (
<Router history={history}>
<Switch>
<Route path="/settings" exact component={ConfigurationOptions} />
<Route path="/settings/:option" component={ConfigurationForm} />
<Route path="/settings" component={ConfigurationOptions} />
<Route component={NotFoundPage} />
</Switch>
</Router>

View File

@@ -14,7 +14,7 @@
// 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 React from "react";
import get from "lodash/get";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
@@ -28,8 +28,6 @@ import {
searchField,
settingsCommon,
} from "../../Common/FormComponents/common/styleLibrary";
import BackLink from "../../../../common/BackLink";
import PageHeader from "../../Common/PageHeader/PageHeader";
interface IListConfiguration {
classes: any;
@@ -65,36 +63,27 @@ const styles = (theme: Theme) =>
},
});
const ConfigurationsList = ({
classes,
match,
history,
}: IListConfiguration) => {
const configurationName = get(match, "params.option", "");
const ConfigurationsList = ({ match, history }: IListConfiguration) => {
const activeConfRoute = get(match, "url", "");
const findConfiguration = configurationElements.find(
(element) => element.configuration_id === configurationName
const configName = activeConfRoute.substring(
activeConfRoute.lastIndexOf("/") + 1
);
const validActiveConfig = configurationElements.find(
(element) => element.configuration_id === configName
);
const containerClassName = `${configName}`;
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>
<Grid item xs={12}>
{validActiveConfig && (
<EditConfiguration
className={`${containerClassName}`}
selectedConfiguration={validActiveConfig}
history={history}
/>
)}
</Grid>
);
};

View File

@@ -27,12 +27,19 @@ import {
searchField,
} from "../../Common/FormComponents/common/styleLibrary";
import PageHeader from "../../Common/PageHeader/PageHeader";
import SettingsCard from "../../Common/SettingsCard/SettingsCard";
import HelpBox from "../../../../common/HelpBox";
import { SettingsIcon } from "../../../../icons";
import { Link, Redirect, Route, Router, Switch } from "react-router-dom";
import ConfigurationForm from "./ConfigurationForm";
import history from "../../../../history";
import VerticalTabs from "../../Common/VerticalTabs/VerticalTabs";
import PageLayout from "../../Common/Layout/PageLayout";
import get from "lodash/get";
import ScreenTitle from "../../Common/ScreenTitle/ScreenTitle";
interface IConfigurationOptions {
classes: any;
match: any;
}
const styles = (theme: Theme) =>
@@ -60,7 +67,6 @@ const styles = (theme: Theme) =>
flexWrap: "wrap" as const,
border: "#E5E5E5 1px solid",
borderRadius: 2,
padding: 5,
backgroundColor: "#fff",
},
configurationLink: {
@@ -76,20 +82,63 @@ const styles = (theme: Theme) =>
...containerForHeader(theme.spacing(4)),
});
const ConfigurationOptions = ({ classes }: IConfigurationOptions) => {
const getRoutePath = (path: string) => {
return `/settings/${path}`;
};
const ConfigurationOptions = ({ classes, match }: IConfigurationOptions) => {
const configurationName = get(match, "url", "");
let selConfigTab = configurationName.substring(
configurationName.lastIndexOf("/") + 1
);
selConfigTab = selConfigTab === "settings" ? "region" : selConfigTab;
return (
<Fragment>
<PageHeader label={"Settings"} />
<Grid container className={classes.container}>
<PageLayout>
<Grid item xs={12}>
<Grid item xs={12}>
<div className={classes.settingsOptionsContainer}>
{configurationElements.map((element) => (
<SettingsCard
configuration={element}
key={`configItem-${element.configuration_label}`}
/>
))}
<ScreenTitle icon={<SettingsIcon />} title={"Configuration:"} />
<VerticalTabs
selectedTab={selConfigTab}
isRouteTabs
routes={
<div className={classes.contentSpacer}>
<Router history={history}>
<Switch>
{configurationElements.map((element) => (
<Route
exact
key={`configItem-${element.configuration_label}`}
path={`/settings/${element.configuration_id}`}
component={ConfigurationForm}
/>
))}
<Route exact path="/settings">
<Redirect to="/settings/region" />
</Route>
</Switch>
</Router>
</div>
}
>
{configurationElements.map((element) => {
const { configuration_id, configuration_label, icon } =
element;
return {
tabConfig: {
label: configuration_label,
value: configuration_id,
icon: icon,
component: Link,
to: getRoutePath(configuration_id),
},
};
})}
</VerticalTabs>
</div>
</Grid>
</Grid>
@@ -116,7 +165,7 @@ const ConfigurationOptions = ({ classes }: IConfigurationOptions) => {
}
/>
</Grid>
</Grid>
</PageLayout>
</Fragment>
);
};

View File

@@ -86,6 +86,7 @@ const IconsScreen = React.lazy(() => import("./Common/IconsScreen"));
const Speedtest = React.lazy(() => import("./Speedtest/Speedtest"));
const drawerWidth = 245;
const Buckets = React.lazy(() => import("./Buckets/Buckets"));
@@ -102,6 +103,7 @@ const TenantDetails = React.lazy(
() => import("./Tenants/TenantDetails/TenantDetails")
);
const License = React.lazy(() => import("./License/License"));
const ConfigurationOptions = React.lazy(() => import("./Configurations/ConfigurationPanels/ConfigurationOptions"));
const styles = (theme: Theme) =>
createStyles({
@@ -341,11 +343,11 @@ const Console = ({
path: "/tools",
},
{
component: ConfigurationMain,
component: ConfigurationOptions,
path: "/settings",
},
{
component: ConfigurationMain,
component: ConfigurationOptions,
path: "/settings/:option",
},
{

View File

@@ -14,13 +14,17 @@
// 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, { useEffect, useState, Fragment } from "react";
import React, { 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, KVField } from "../Configurations/types";
import { modalBasic } from "../Common/FormComponents/common/styleLibrary";
import {
fieldBasic,
formFieldStyles,
modalBasic,
} from "../Common/FormComponents/common/styleLibrary";
import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import CSVMultiSelector from "../Common/FormComponents/CSVMultiSelector/CSVMultiSelector";
import CommentBoxWrapper from "../Common/FormComponents/CommentBoxWrapper/CommentBoxWrapper";
@@ -35,6 +39,52 @@ interface IConfGenericProps {
const styles = (theme: Theme) =>
createStyles({
...formFieldStyles,
formFieldRow: {
...formFieldStyles.formFieldRow,
},
inputBoxContainer: {
marginBottom: 7,
"& .MuiInputLabel-root": {
minWidth: 200,
"& svg": {
width: 16,
height: 16,
},
},
"& div[class|='InputBoxWrapper-textBoxContainer']": {
display: "flex",
},
},
overlayAction: {
top: 0,
right: 0,
position: "relative",
marginLeft: 10,
display: "flex",
alignItems: "center",
"& button": {
background: "#EAEAEA",
},
},
fieldContainer: {
"& .MuiInputLabel-root": {
flex: 1,
minWidth: 200,
},
"& div[class|='CommentBoxWrapper-textBoxContainer']": {
flexGrow: 1,
width: "100%",
},
},
tooltipContainer: {
...fieldBasic.tooltipContainer,
"& svg": {
width: 16,
height: 16,
},
},
...modalBasic,
});
@@ -102,6 +152,7 @@ const ConfTargetGeneric = ({
return (
<FormSwitchWrapper
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.checked ? "true" : "false";
setValueElement(field.name, value, item);
@@ -117,6 +168,7 @@ const ConfTargetGeneric = ({
case "csv":
return (
<CSVMultiSelector
classes={classes}
elements={valueHolder[item] ? valueHolder[item].value : ""}
label={field.label}
name={field.name}
@@ -125,12 +177,13 @@ const ConfTargetGeneric = ({
}
tooltip={field.tooltip}
commonPlaceholder={field.placeholder}
withBorder={!!field.withBorder}
withBorder={true}
/>
);
case "comment":
return (
<CommentBoxWrapper
classes={classes}
id={field.name}
name={field.name}
label={field.label}
@@ -145,6 +198,7 @@ const ConfTargetGeneric = ({
default:
return (
<InputBoxWrapper
classes={classes}
id={field.name}
name={field.name}
label={field.label}
@@ -162,13 +216,11 @@ const ConfTargetGeneric = ({
return (
<Grid container>
<Grid xs={12} item>
<Grid xs={12} item className={classes.fieldBox}>
{fieldsElements.map((field, item) => (
<Fragment key={field.name}>
<Grid item xs={12}>
{fieldDefinition(field, item)}
</Grid>
</Fragment>
<Grid item xs={12} key={field.name} className={classes.formFieldRow}>
{fieldDefinition(field, item)}
</Grid>
))}
</Grid>
</Grid>

View File

@@ -68,6 +68,7 @@ interface IAddNotificationEndpointProps {
selectedConfiguration: IConfigurationElement;
classes: any;
history: any;
className?: string;
}
const EditConfiguration = ({
@@ -76,6 +77,7 @@ const EditConfiguration = ({
setErrorSnackMessage,
classes,
history,
className = "",
}: IAddNotificationEndpointProps) => {
//Local States
const [valuesObj, setValueObj] = useState<IElementValue[]>([]);
@@ -147,7 +149,7 @@ const EditConfiguration = ({
return (
<Fragment>
<form noValidate onSubmit={submitForm}>
<form noValidate onSubmit={submitForm} className={className}>
<Grid item xs={12} className={classes.settingsFormContainer}>
{loadingConfig && (
<Grid item xs={12}>