From 67299b90840497e710914ffa1ef88e0b91977226 Mon Sep 17 00:00:00 2001 From: Benjamin Perez Date: Fri, 17 Nov 2023 14:47:11 -0600 Subject: [PATCH] Updated Create tenant screens to use mds components Signed-off-by: Benjamin Perez --- .../FormComponents/common/styleLibrary.ts | 65 -- .../src/screens/Console/Common/H3Section.tsx | 11 +- .../src/screens/Console/Common/SectionH1.tsx | 31 - .../TolerationSelector/TolerationSelector.tsx | 266 +++-- .../Console/Tenants/AddTenant/AddTenant.tsx | 71 +- .../Tenants/AddTenant/Steps/Affinity.tsx | 591 ++++++----- .../Tenants/AddTenant/Steps/Configure.tsx | 780 +++++++-------- .../Tenants/AddTenant/Steps/Encryption.tsx | 916 +++++++++--------- .../AddTenant/Steps/Encryption/AWSKMSAdd.tsx | 164 ++-- .../Steps/Encryption/AzureKMSAdd.tsx | 128 +-- .../AddTenant/Steps/Encryption/GCPKMSAdd.tsx | 150 ++- .../Steps/Encryption/GemaltoKMSAdd.tsx | 140 +-- .../Steps/Encryption/VaultKMSAdd.tsx | 249 ++--- .../AddTenant/Steps/IdentityProvider.tsx | 74 +- .../IdentityProvider/IDPActiveDirectory.tsx | 556 +++++------ .../Steps/IdentityProvider/IDPBuiltIn.tsx | 151 ++- .../Steps/IdentityProvider/IDPOpenID.tsx | 174 ++-- .../Tenants/AddTenant/Steps/Images.tsx | 198 ++-- .../Tenants/AddTenant/Steps/Security.tsx | 539 +++++------ .../Tenants/AddTenant/Steps/SizePreview.tsx | 113 +-- .../Steps/TenantResources/NameTenantMain.tsx | 159 ++- .../TenantResources/NamespaceSelector.tsx | 12 +- .../Steps/TenantResources/TenantSize.tsx | 200 ++-- .../TenantResources/TenantSizeResources.tsx | 350 +++---- .../Steps/helpers/AddNamespaceModal.tsx | 48 +- .../Tenants/AddTenant/createTenantSlice.ts | 2 +- .../Console/Tenants/HelpBox/TLSHelpBox.tsx | 15 +- .../Console/Tenants/LogoComponents.tsx | 51 - .../TenantDetails/TenantIdentityProvider.tsx | 31 +- web-app/src/screens/Console/Tenants/types.ts | 2 +- 30 files changed, 2676 insertions(+), 3561 deletions(-) delete mode 100644 web-app/src/screens/Console/Common/SectionH1.tsx delete mode 100644 web-app/src/screens/Console/Tenants/LogoComponents.tsx diff --git a/web-app/src/screens/Console/Common/FormComponents/common/styleLibrary.ts b/web-app/src/screens/Console/Common/FormComponents/common/styleLibrary.ts index 4870f20f4db..70b3dd21541 100644 --- a/web-app/src/screens/Console/Common/FormComponents/common/styleLibrary.ts +++ b/web-app/src/screens/Console/Common/FormComponents/common/styleLibrary.ts @@ -207,32 +207,6 @@ export const searchField = { }, }; -// ** According to W3 spec, default minimum values for flex width flex-grow is "auto" (https://drafts.csswg.org/css-flexbox/#min-size-auto). So in this case we need to enforce the use of an absolute width. -// "The preferred width of a box element child containing text content is currently the text without line breaks, leading to very unintuitive width and flex calculations → declare a width on a box element child with more than a few words (ever wonder why flexbox demos are all “1,2,3”?)" - -export const settingsCommon: any = { - settingsFormContainer: { - padding: 38, - overflowY: "auto" as const, - scrollbarWidth: "none" as const, - "&::-webkit-scrollbar": { - display: "none", - }, - }, - settingsButtonContainer: { - padding: "15px 38px", - display: "flex", - justifyContent: "flex-end", - }, - settingsOptionsContainer: { - height: "calc(100vh - 244px)", - backgroundColor: "#fff", - border: "#EAEDEE 1px solid", - borderRadius: 3, - marginTop: 15, - }, -}; - export const snackBarCommon = { snackBar: { backgroundColor: "#081F44", @@ -498,45 +472,6 @@ export const fileInputStyles = { }, }; -export const deleteDialogStyles: any = { - root: { - "& .MuiPaper-root": { - padding: "1rem 2rem 2rem 1rem", - }, - }, - title: { - display: "flex", - alignItems: "center", - justifyContent: "space-between", - }, - titleText: { - fontSize: 20, - fontWeight: 600, - display: "flex", - alignItems: "center", - "& svg": { - marginRight: 10, - }, - wordBreak: "break-all", - whiteSpace: "normal", - }, - closeContainer: { - "& .MuiIconButton-root": { - top: -20, - left: 30, - position: "relative", - padding: 1, - "&:focus, &:hover": { - background: "#EAEAEA", - }, - }, - "& .min-icon": { - height: 16, - width: 16, - }, - }, -}; - export const createTenantCommon: any = { fieldGroup: { border: "1px solid #EAEAEA", diff --git a/web-app/src/screens/Console/Common/H3Section.tsx b/web-app/src/screens/Console/Common/H3Section.tsx index 4790fcda8f6..6f31e62f464 100644 --- a/web-app/src/screens/Console/Common/H3Section.tsx +++ b/web-app/src/screens/Console/Common/H3Section.tsx @@ -14,9 +14,12 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import styled from "@emotion/styled"; +import styled from "styled-components"; +import get from "lodash/get"; + +const H3Section = styled.h3(({ theme }) => ({ + color: get(theme, "fontColor", "#000"), + margin: 0, +})); -const H3Section = styled("h3")` - margin: 0px; -`; export default H3Section; diff --git a/web-app/src/screens/Console/Common/SectionH1.tsx b/web-app/src/screens/Console/Common/SectionH1.tsx deleted file mode 100644 index eacf3f284eb..00000000000 --- a/web-app/src/screens/Console/Common/SectionH1.tsx +++ /dev/null @@ -1,31 +0,0 @@ -// This file is part of MinIO Operator -// Copyright (c) 2022 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 . - -import React from "react"; - -type Props = { - children: string; -}; - -const SectionH1: React.FC = ({ children }) => { - return ( -

- {children} -

- ); -}; - -export default SectionH1; diff --git a/web-app/src/screens/Console/Common/TolerationSelector/TolerationSelector.tsx b/web-app/src/screens/Console/Common/TolerationSelector/TolerationSelector.tsx index 8ed7d77a1ef..0fe66546ed9 100644 --- a/web-app/src/screens/Console/Common/TolerationSelector/TolerationSelector.tsx +++ b/web-app/src/screens/Console/Common/TolerationSelector/TolerationSelector.tsx @@ -15,19 +15,14 @@ // along with this program. If not, see . import React from "react"; +import { Grid, InputBox, Select, SelectorType } from "mds"; +import get from "lodash/get"; +import styled from "styled-components"; import { ITolerationEffect, ITolerationOperator, } from "../../../../common/types"; -import SelectWrapper, { - selectorTypes, -} from "../FormComponents/SelectWrapper/SelectWrapper"; -import { Grid, SelectChangeEvent } from "@mui/material"; -import InputBoxWrapper from "../FormComponents/InputBoxWrapper/InputBoxWrapper"; import InputUnitMenu from "../FormComponents/InputUnitMenu/InputUnitMenu"; -import withStyles from "@mui/styles/withStyles"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; interface ITolerationSelector { effect: ITolerationEffect; @@ -41,39 +36,33 @@ interface ITolerationSelector { tolerationSeconds?: number; onSecondsChange: (value: number) => void; index: number; - classes: any; } -const styles = (theme: Theme) => - createStyles({ - labelsStyle: { - fontSize: 18, - fontWeight: "bold", - color: "#AEAEAE", - display: "flex", - alignItems: "center", - justifyContent: "center", - maxWidth: 45, - marginRight: 10, - }, - fieldsetStyle: { - border: "1px solid #EAEAEA", - borderRadius: 2, - padding: 10, - marginBottom: 15, - }, - firstLevel: { - marginBottom: 10, - }, - fieldContainer: { - marginRight: 10, - }, - legendStyle: { - fontSize: 12, - color: "#696969", - fontWeight: "bold", - }, - }); +const TolerationBase = styled.div(({ theme }) => ({ + flexGrow: "1", + flexBasis: "100%", + width: "100%", + "& .labelsStyle": { + fontSize: 18, + fontWeight: "bold", + color: get(theme, "secondaryText", "#AEAEAE"), + display: "flex", + alignItems: "center", + justifyContent: "center", + maxWidth: 45, + marginRight: 10, + }, + "& .firstLevel": { + width: "100%", + marginBottom: 10, + }, + "& .secondLevel": { + width: "100%", + }, + "& .fieldContainer": { + marginRight: 10, + }, +})); const TolerationSelector = ({ effect, @@ -87,10 +76,9 @@ const TolerationSelector = ({ tolerationSeconds, onSecondsChange, index, - classes, }: ITolerationSelector) => { - const operatorOptions: selectorTypes[] = []; - const effectOptions: selectorTypes[] = []; + const operatorOptions: SelectorType[] = []; + const effectOptions: SelectorType[] = []; for (let operator in ITolerationOperator) { operatorOptions.push({ @@ -108,115 +96,117 @@ const TolerationSelector = ({ return ( -
- Toleration {index + 1} - - - - If - - - { - onTolerationKeyChange(e.target.value); - }} - index={index} - placeholder={"Toleration Key"} - /> - - {ITolerationOperator[operator] === ITolerationOperator.Equal && ( - - is - - )} - - ) => { - onOperatorChange( - ITolerationOperator[e.target.value as ITolerationOperator], - ); - }} - id={`operator-${index}`} - name="operator" - label={""} - value={ITolerationOperator[operator]} - options={operatorOptions} - /> - - {ITolerationOperator[operator] === ITolerationOperator.Equal && ( - - to +
+ Toleration {index + 1} + + + + + If - )} - {ITolerationOperator[operator] === ITolerationOperator.Equal && ( - - + { - onValueChange(e.target.value); + onTolerationKeyChange(e.target.value); }} index={index} - placeholder={"Toleration Value"} + placeholder={"Toleration Key"} /> - )} - - - - then - - - ) => { - onEffectChange( - ITolerationEffect[e.target.value as ITolerationEffect], - ); - }} - id={`effects-${index}`} - name="effects" - label={""} - value={ITolerationEffect[effect]} - options={effectOptions} - /> - - - after + {ITolerationOperator[operator] === ITolerationOperator.Equal && ( + + is + + )} + + { + onEffectChange( + ITolerationEffect[value as ITolerationEffect], + ); + }} + id={`effects-${index}`} + name="effects" + label={""} + value={ITolerationEffect[effect]} + options={effectOptions} + /> + + + after + + + { + if (e.target.validity.valid) { + onSecondsChange(parseInt(e.target.value)); + } + }} + index={index} + pattern={"[0-9]*"} + overlayObject={ + } - }} - index={index} - pattern={"[0-9]*"} - overlayObject={ - - } - /> + /> + - +
); }; -export default withStyles(styles)(TolerationSelector); +export default TolerationSelector; diff --git a/web-app/src/screens/Console/Tenants/AddTenant/AddTenant.tsx b/web-app/src/screens/Console/Tenants/AddTenant/AddTenant.tsx index 16711ca2f65..40f15a4d9be 100644 --- a/web-app/src/screens/Console/Tenants/AddTenant/AddTenant.tsx +++ b/web-app/src/screens/Console/Tenants/AddTenant/AddTenant.tsx @@ -16,17 +16,26 @@ import React, { Fragment, useEffect, useState } from "react"; import get from "lodash/get"; +import { + BackLink, + Box, + Grid, + HelpBox, + PageLayout, + ProgressBar, + StorageIcon, + Wizard, + WizardButton, + WizardElement, +} from "mds"; import { useSelector } from "react-redux"; -import Grid from "@mui/material/Grid"; -import { LinearProgress } from "@mui/material"; - -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; +import { useNavigate } from "react-router-dom"; import { - modalBasic, - settingsCommon, - wizardCommon, -} from "../../Common/FormComponents/common/styleLibrary"; + IMkEnvs, + resourcesConfigurations, +} from "./Steps/TenantResources/utils"; +import { selFeatures } from "../../consoleSlice"; +import { resetAddTenantForm } from "./createTenantSlice"; import { AppState, useAppDispatch } from "../../../../store"; import Configure from "./Steps/Configure"; import IdentityProvider from "./Steps/IdentityProvider"; @@ -34,44 +43,14 @@ import Security from "./Steps/Security"; import Encryption from "./Steps/Encryption"; import Affinity from "./Steps/Affinity"; import Images from "./Steps/Images"; - import TenantResources from "./Steps/TenantResources/TenantResources"; -import { - IMkEnvs, - resourcesConfigurations, -} from "./Steps/TenantResources/utils"; -import { - BackLink, - HelpBox, - StorageIcon, - PageLayout, - Wizard, - WizardElement, - WizardButton, -} from "mds"; -import { selFeatures } from "../../consoleSlice"; -import makeStyles from "@mui/styles/makeStyles"; -import { resetAddTenantForm } from "./createTenantSlice"; import CreateTenantButton from "./CreateTenantButton"; import NewTenantCredentials from "./NewTenantCredentials"; -import { useNavigate } from "react-router-dom"; import PageHeaderWrapper from "../../Common/PageHeaderWrapper/PageHeaderWrapper"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - pageBox: { - border: "1px solid #EAEAEA", - }, - ...modalBasic, - ...wizardCommon, - ...settingsCommon, - }), -); - const AddTenant = () => { const dispatch = useAppDispatch(); const navigate = useNavigate(); - const classes = useStyles(); const features = useSelector(selFeatures); @@ -159,8 +138,6 @@ const AddTenant = () => { }, ]; - let filteredWizardSteps = wizardSteps; - return ( @@ -179,12 +156,16 @@ const AddTenant = () => { {addSending && ( - + )} - - - + + + {formRender === IMkEnvs.aws && ( . import React, { Fragment, useCallback, useEffect, useState } from "react"; +import { + AddIcon, + RemoveIcon, + FormLayout, + Box, + InputLabel, + RadioGroup, + Switch, + Select, + InputBox, + IconButton, + Grid, +} from "mds"; import { useSelector } from "react-redux"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import withStyles from "@mui/styles/withStyles"; -import { Grid, IconButton, Paper, SelectChangeEvent } from "@mui/material"; +import styled from "styled-components"; import { AppState, useAppDispatch } from "../../../../../store"; - -import { - modalBasic, - wizardCommon, -} from "../../../Common/FormComponents/common/styleLibrary"; import { commonFormValidation, IValidation, } from "../../../../../utils/validationFunctions"; import { ErrorResponseHandler } from "../../../../../common/types"; import { LabelKeyPair } from "../../types"; -import RadioGroupSelector from "../../../Common/FormComponents/RadioGroupSelector/RadioGroupSelector"; -import FormSwitchWrapper from "../../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper"; -import api from "../../../../../common/api"; -import InputBoxWrapper from "../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; -import { AddIcon, RemoveIcon } from "mds"; -import SelectWrapper from "../../../Common/FormComponents/SelectWrapper/SelectWrapper"; -import TolerationSelector from "../../../Common/TolerationSelector/TolerationSelector"; import { setModalErrorSnackMessage } from "../../../../../systemSlice"; import { addNewToleration, @@ -48,74 +46,51 @@ import { setTolerationInfo, updateAddField, } from "../createTenantSlice"; +import api from "../../../../../common/api"; +import TolerationSelector from "../../../Common/TolerationSelector/TolerationSelector"; import H3Section from "../../../Common/H3Section"; -interface IAffinityProps { - classes: any; -} - -const styles = (theme: Theme) => - createStyles({ - overlayAction: { - marginLeft: 10, - display: "flex", - alignItems: "center", - "& svg": { - maxWidth: 15, - maxHeight: 15, - }, - "& button": { - background: "#EAEAEA", - }, - }, - affinityConfigField: { - display: "flex", - }, - affinityFieldLabel: { - display: "flex", - flexFlow: "column", - flex: 1, +const AffinityContainer = styled.div(() => ({ + "& .overlayAction": { + marginLeft: 10, + display: "flex", + alignItems: "center", + }, + "& .affinityConfigField": { + display: "flex", + }, + "& .affinityFieldLabel": { + display: "flex", + flexFlow: "column", + flex: 1, + }, + "& .affinityLabelKey": { + "& div:first-child": { + marginBottom: 0, }, - radioField: { - display: "flex", - alignItems: "flex-start", - marginTop: 10, - "& div:first-child": { - display: "flex", - flexFlow: "column", - alignItems: "baseline", - textAlign: "left !important", - }, + }, + "& .affinityLabelValue": { + marginLeft: 10, + "& div:first-child": { + marginBottom: 0, }, - affinityLabelKey: { - "& div:first-child": { - marginBottom: 0, - }, - }, - affinityLabelValue: { - marginLeft: 10, - "& div:first-child": { - marginBottom: 0, - }, - }, - rowActions: { - display: "flex", - alignItems: "center", - }, - affinityRow: { - marginBottom: 10, - display: "flex", - }, - ...modalBasic, - ...wizardCommon, - }); + }, + "& .rowActions": { + display: "flex", + alignItems: "center", + }, + "& .affinityRow": { + marginBottom: 10, + display: "flex", + }, +})); interface OptionPair { label: string; value: string; } -const Affinity = ({ classes }: IAffinityProps) => { +const Affinity = () => { const dispatch = useAppDispatch(); const podAffinity = useSelector( @@ -254,44 +229,38 @@ const Affinity = ({ classes }: IAffinityProps) => { }; return ( - -
- Pod Placement - - Configure how pods will be assigned to nodes - -
- - -
Type
-
- MinIO supports multiple configurations for Pod Affinity -
- - { - updateField("podAffinity", e.target.value); - }} - selectorOptions={[ - { label: "None", value: "none" }, - { label: "Default (Pod Anti-Affinity)", value: "default" }, - { label: "Node Selector", value: "nodeSelector" }, - ]} - /> - -
-
- {podAffinity === "nodeSelector" && ( - -
- - + + + Pod Placement + + Configure how pods will be assigned to nodes + + + + Type + + + MinIO supports multiple configurations for Pod Affinity + + { + updateField("podAffinity", e.target.value); + }} + selectorOptions={[ + { label: "None", value: "none" }, + { label: "Default (Pod Anti-Affinity)", value: "default" }, + { label: "Node Selector", value: "nodeSelector" }, + ]} + displayInColumn + /> + {podAffinity === "nodeSelector" && ( + + { }} label={"With Pod Anti-Affinity"} /> - - -

Labels

- {validationErrors["labels"]} + +

Labels

+ {validationErrors["labels"]} + + {keyValuePairs && + keyValuePairs.map((kvp, i) => { + return ( + + + {keyOptions.length > 0 && ( + { + const arrCp: LabelKeyPair[] = [ + ...keyValuePairs, + ]; + arrCp[i] = { + key: arrCp[i].key, + value: value, + }; + dispatch(setKeyValuePairs(arrCp)); + }} + id="select-access-policy" + name="select-access-policy" + label={""} + value={kvp.value} + options={ + keyValueMap[kvp.key] + ? keyValueMap[kvp.key].map((v) => { + return { label: v, value: v }; + }) + : [] + } + /> + )} + {keyOptions.length === 0 && ( + { + const arrCp: LabelKeyPair[] = [ + ...keyValuePairs, + ]; + arrCp[i] = { + key: arrCp[i].key, + value: e.target.value as string, + }; + dispatch(setKeyValuePairs(arrCp)); + }} + index={i} + placeholder={"value"} + /> + )} + + + + { + const arrCp = [...keyValuePairs]; + if (keyOptions.length > 0) { + arrCp.push({ + key: keyOptions[0].value, + value: keyValueMap[keyOptions[0].value][0], + }); + } else { + arrCp.push({ key: "", value: "" }); + } + + dispatch(setKeyValuePairs(arrCp)); + }} + disabled={i !== keyValuePairs.length - 1} + > + + + + + { + const arrCp = keyValuePairs.filter( + (item, index) => index !== i, + ); + dispatch(setKeyValuePairs(arrCp)); + }} + disabled={keyValuePairs.length <= 1} + > + + + + + + ); + })} + +
+
+ )} + + +

Tolerations

+ {validationErrors["tolerations"]} - {keyValuePairs && - keyValuePairs.map((kvp, i) => { + {tolerations && + tolerations.map((tol, i) => { return ( - - {keyOptions.length > 0 && ( - ) => { - const newKey = e.target.value as string; - const newLKP: LabelKeyPair = { - key: newKey, - value: keyValueMap[newKey][0], - }; - const arrCp: LabelKeyPair[] = [...keyValuePairs]; - arrCp[i] = newLKP; - dispatch(setKeyValuePairs(arrCp)); - }} - id="select-access-policy" - name="select-access-policy" - label={""} - value={kvp.key} - options={keyOptions} - /> - )} - {keyOptions.length === 0 && ( - { - const arrCp: LabelKeyPair[] = [...keyValuePairs]; - arrCp[i] = { - key: arrCp[i].key, - value: e.target.value as string, - }; - dispatch(setKeyValuePairs(arrCp)); - }} - index={i} - placeholder={"Key"} - /> - )} - - - {keyOptions.length > 0 && ( - ) => { - const arrCp: LabelKeyPair[] = [...keyValuePairs]; - arrCp[i] = { - key: arrCp[i].key, - value: e.target.value as string, - }; - dispatch(setKeyValuePairs(arrCp)); - }} - id="select-access-policy" - name="select-access-policy" - label={""} - value={kvp.value} - options={ - keyValueMap[kvp.key] - ? keyValueMap[kvp.key].map((v) => { - return { label: v, value: v }; - }) - : [] - } - /> - )} - {keyOptions.length === 0 && ( - { - const arrCp: LabelKeyPair[] = [...keyValuePairs]; - arrCp[i] = { - key: arrCp[i].key, - value: e.target.value as string, - }; - dispatch(setKeyValuePairs(arrCp)); - }} - index={i} - placeholder={"value"} - /> - )} - - -
- { - const arrCp = [...keyValuePairs]; - if (keyOptions.length > 0) { - arrCp.push({ - key: keyOptions[0].value, - value: keyValueMap[keyOptions[0].value][0], - }); - } else { - arrCp.push({ key: "", value: "" }); - } + { + updateToleration(i, "effect", value); + }} + tolerationKey={tol.key} + onTolerationKeyChange={(value) => { + updateToleration(i, "key", value); + }} + operator={tol.operator} + onOperatorChange={(value) => { + updateToleration(i, "operator", value); + }} + value={tol.value} + onValueChange={(value) => { + updateToleration(i, "value", value); + }} + tolerationSeconds={tol.tolerationSeconds?.seconds || 0} + onSecondsChange={(value) => { + updateToleration(i, "tolerationSeconds", { + seconds: value, + }); + }} + index={i} + /> + + { + dispatch(addNewToleration()); + }} + disabled={i !== tolerations.length - 1} + > + + + - dispatch(setKeyValuePairs(arrCp)); - }} - disabled={i !== keyValuePairs.length - 1} - > - - -
-
- { - const arrCp = keyValuePairs.filter( - (item, index) => index !== i, - ); - dispatch(setKeyValuePairs(arrCp)); - }} - disabled={keyValuePairs.length <= 1} - > - - -
-
+ + dispatch(removeToleration(i))} + disabled={tolerations.length <= 1} + > + + +
); })}
-
- )} - - -

Tolerations

- - {validationErrors["tolerations"]} - - - {tolerations && - tolerations.map((tol, i) => { - return ( - - { - updateToleration(i, "effect", value); - }} - tolerationKey={tol.key} - onTolerationKeyChange={(value) => { - updateToleration(i, "key", value); - }} - operator={tol.operator} - onOperatorChange={(value) => { - updateToleration(i, "operator", value); - }} - value={tol.value} - onValueChange={(value) => { - updateToleration(i, "value", value); - }} - tolerationSeconds={tol.tolerationSeconds?.seconds || 0} - onSecondsChange={(value) => { - updateToleration(i, "tolerationSeconds", { - seconds: value, - }); - }} - index={i} - /> -
- { - dispatch(addNewToleration()); - }} - disabled={i !== tolerations.length - 1} - > - - -
- -
- dispatch(removeToleration(i))} - disabled={tolerations.length <= 1} - > - - -
-
- ); - })} -
-
- + + ); }; -export default withStyles(styles)(Affinity); +export default Affinity; diff --git a/web-app/src/screens/Console/Tenants/AddTenant/Steps/Configure.tsx b/web-app/src/screens/Console/Tenants/AddTenant/Steps/Configure.tsx index b3f2caf16e0..04ecfa75a10 100644 --- a/web-app/src/screens/Console/Tenants/AddTenant/Steps/Configure.tsx +++ b/web-app/src/screens/Console/Tenants/AddTenant/Steps/Configure.tsx @@ -15,34 +15,25 @@ // along with this program. If not, see . import React, { useCallback, useEffect, useState } from "react"; -import { useSelector } from "react-redux"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import withStyles from "@mui/styles/withStyles"; import { - Divider, + Box, + FormLayout, Grid, IconButton, - Paper, - SelectChangeEvent, -} from "@mui/material"; -import { - createTenantCommon, - formFieldStyles, - modalBasic, - wizardCommon, -} from "../../../Common/FormComponents/common/styleLibrary"; - + InputBox, + RemoveIcon, + Select, + Switch, + AddIcon, +} from "mds"; +import { useSelector } from "react-redux"; +import styled from "styled-components"; import { AppState, useAppDispatch } from "../../../../../store"; import { clearValidationError } from "../../utils"; import { commonFormValidation, IValidation, } from "../../../../../utils/validationFunctions"; -import FormSwitchWrapper from "../../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper"; -import InputBoxWrapper from "../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; -import AddIcon from "@mui/icons-material/Add"; -import { RemoveIcon } from "mds"; import { addNewMinIODomain, isPageValid, @@ -50,100 +41,77 @@ import { setEnvVars, updateAddField, } from "../createTenantSlice"; -import SelectWrapper from "../../../Common/FormComponents/SelectWrapper/SelectWrapper"; import H3Section from "../../../Common/H3Section"; -interface IConfigureProps { - classes: any; -} - -const styles = (theme: Theme) => - createStyles({ - configSectionItem: { - marginRight: 15, - marginBottom: 15, - - "& .multiContainer": { - border: "1px solid red", +const ConfigureMain = styled.div(() => ({ + "& .configSectionItem": { + marginRight: 15, + marginBottom: 15, + }, + "& .containerItem": { + marginRight: 15, + }, + "& .responsiveSectionItem": { + "&.doubleElement": { + display: "flex", + "& div": { + flexGrow: 1, }, }, - tenantCustomizationFields: { - marginLeft: 30, // 2nd Level(15+15) - width: "88%", - margin: "auto", - }, - containerItem: { - marginRight: 15, - }, - fieldGroup: { - ...createTenantCommon.fieldGroup, - paddingTop: 15, - marginBottom: 25, - }, - responsiveSectionItem: { - "@media (max-width: 900px)": { - flexFlow: "column", - alignItems: "flex-start", + "@media (max-width: 900px)": { + flexFlow: "column", + alignItems: "flex-start", - "& div > div": { - marginBottom: 5, - marginRight: 0, - }, + "& div > div": { + marginBottom: 5, + marginRight: 0, }, }, - wrapperContainer: { - display: "flex", - marginBottom: 15, + }, + "& .wrapperContainer": { + display: "flex", + alignItems: "center", + }, + "& .envVarRow": { + display: "flex", + alignItems: "center", + justifyContent: "flex-start", + "&:last-child": { + borderBottom: 0, }, - envVarRow: { - display: "flex", - alignItems: "center", - justifyContent: "flex-start", - "&:last-child": { - borderBottom: 0, - }, - "@media (max-width: 900px)": { - flex: 1, + "@media (max-width: 900px)": { + flex: 1, - "& div label": { - minWidth: 50, - }, - }, - }, - fileItem: { - marginRight: 10, - display: "flex", "& div label": { minWidth: 50, }, - - "@media (max-width: 900px)": { - flexFlow: "column", - }, - }, - rowActions: { - display: "flex", - justifyContent: "flex-end", - "@media (max-width: 900px)": { - flex: 1, - }, }, - overlayAction: { - marginLeft: 10, - "& svg": { - maxWidth: 15, - maxHeight: 15, - }, - "& button": { - background: "#EAEAEA", - }, + }, + "& .fileItem": { + marginRight: 10, + display: "flex", + "& div label": { + minWidth: 50, }, - ...modalBasic, - ...wizardCommon, - ...formFieldStyles, - }); -const Configure = ({ classes }: IConfigureProps) => { + "@media (max-width: 900px)": { + flexFlow: "column", + }, + }, + "& .rowActions": { + display: "flex", + justifyContent: "flex-end", + "@media (max-width: 900px)": { + flex: 1, + }, + }, + "& .overlayAction": { + marginLeft: 10, + marginBottom: 15, + }, +})); + +const Configure = () => { const dispatch = useAppDispatch(); const exposeMinIO = useSelector( @@ -286,22 +254,22 @@ const Configure = ({ classes }: IConfigureProps) => { }; return ( - -
- Configure - - Basic configurations for tenant management - -
-
-

Services

- - Whether the tenant's services should request an external IP via - LoadBalancer service type. - -
- - + + + Configure + + Basic configurations for tenant management + + + +

Services

+ + Whether the tenant's services should request an external IP via + LoadBalancer service type. + +
+ { }} label={"Expose MinIO Service"} /> -
- - { }} label={"Expose Console Service"} /> - - - { }} label={"Expose SFTP Service"} /> - - - { }} label={"Set Custom Domains"} /> - - {setDomains && ( - -
- - Custom Domains for MinIO - - -
- ) => { - updateField("consoleDomain", e.target.value); - cleanValidation("tenant_securityContext_runAsUser"); - }} - label="Console Domain" - value={consoleDomain} - placeholder={ - "Eg. http://subdomain.domain:port/subpath1/subpath2" - } - error={validationErrors["console_domain"] || ""} - /> -
-
-

MinIO Domains

-
- {minioDomains.map((domain, index) => { - return ( -
- , - ) => { - updateMinIODomain(e.target.value, index); - }} - label={`MinIO Domain ${index + 1}`} - value={domain} - placeholder={"Eg. http://subdomain.domain"} - error={ - validationErrors[ - `minio-domain-${index.toString()}` - ] || "" - } - /> -
- dispatch(addNewMinIODomain())} - disabled={index !== minioDomains.length - 1} - > - - -
- -
- dispatch(removeMinIODomain(index))} - disabled={minioDomains.length <= 1} - > - - -
-
- ); - })} -
-
-
-
-
- )} + {setDomains && ( + +
+ Custom Domains for MinIO + + + ) => { + updateField("consoleDomain", e.target.value); + cleanValidation("tenant_securityContext_runAsUser"); + }} + label="Console Domain" + value={consoleDomain} + placeholder={ + "Eg. http://subdomain.domain:port/subpath1/subpath2" + } + error={validationErrors["console_domain"] || ""} + /> + + +

MinIO Domains

+ + {minioDomains.map((domain, index) => { + return ( + + , + ) => { + updateMinIODomain(e.target.value, index); + }} + label={`MinIO Domain ${index + 1}`} + value={domain} + placeholder={"Eg. http://subdomain.domain"} + error={ + validationErrors[ + `minio-domain-${index.toString()}` + ] || "" + } + /> + + dispatch(addNewMinIODomain())} + disabled={index !== minioDomains.length - 1} + > + + + + + + dispatch(removeMinIODomain(index))} + disabled={minioDomains.length <= 1} + > + + + + + ); + })} + +
+
+
+
+ )} - - { }} label={"Security Context"} /> - - {tenantCustom && ( - -
- - SecurityContext for MinIO - - -
-
- ) => { - updateField("tenantSecurityContext", { - ...tenantSecurityContext, - runAsUser: e.target.value, - }); - cleanValidation("tenant_securityContext_runAsUser"); - }} - label="Run As User" - value={tenantSecurityContext.runAsUser} - required - error={ - validationErrors["tenant_securityContext_runAsUser"] || "" - } - min="0" - /> -
-
- ) => { - updateField("tenantSecurityContext", { - ...tenantSecurityContext, - runAsGroup: e.target.value, - }); - cleanValidation("tenant_securityContext_runAsGroup"); - }} - label="Run As Group" - value={tenantSecurityContext.runAsGroup} - required - error={ - validationErrors["tenant_securityContext_runAsGroup"] || - "" - } - min="0" - /> -
-
-
-
- -
-
- ) => { - updateField("tenantSecurityContext", { - ...tenantSecurityContext, - fsGroup: e.target.value, - }); - cleanValidation("tenant_securityContext_fsGroup"); - }} - label="FsGroup" - value={tenantSecurityContext.fsGroup!} - required - error={ - validationErrors["tenant_securityContext_fsGroup"] || "" - } - min="0" - /> -
-
-
- +
+ Security Context for MinIO + + + + ) => { + updateField("tenantSecurityContext", { + ...tenantSecurityContext, + runAsUser: e.target.value, + }); + cleanValidation("tenant_securityContext_runAsUser"); + }} + label="Run As User" + value={tenantSecurityContext.runAsUser} + required + error={ + validationErrors["tenant_securityContext_runAsUser"] || + "" + } + min="0" + /> + + + ) => { + updateField("tenantSecurityContext", { + ...tenantSecurityContext, + runAsGroup: e.target.value, + }); + cleanValidation("tenant_securityContext_runAsGroup"); + }} + label="Run As Group" + value={tenantSecurityContext.runAsGroup} + required + error={ + validationErrors["tenant_securityContext_runAsGroup"] || + "" + } + min="0" + /> + + + +
+ + + + ) => { + updateField("tenantSecurityContext", { + ...tenantSecurityContext, + fsGroup: e.target.value, + }); + cleanValidation("tenant_securityContext_fsGroup"); + }} + label="FsGroup" + value={tenantSecurityContext.fsGroup!} + required + error={ + validationErrors["tenant_securityContext_fsGroup"] || "" + } + min="0" + /> + + + { + updateField("kesSecurityContext", { + ...kesSecurityContext, + fsGroupChangePolicy: value, + }); + }} + options={[ + { + label: "Always", + value: "Always", + }, + { + label: "OnRootMismatch", + value: "OnRootMismatch", + }, + ]} + /> +
+
- - )} - - +
+ { + const targetD = e.target; + const checked = targetD.checked; + updateField("kesSecurityContext", { + ...kesSecurityContext, + runAsNonRoot: checked, + }); + }} + label={"Do not run as Root"} + /> +
+ + )} + ); }; -export default withStyles(styles)(Encryption); +export default Encryption; diff --git a/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/AWSKMSAdd.tsx b/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/AWSKMSAdd.tsx index 5528f30429c..d7afdf21d72 100644 --- a/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/AWSKMSAdd.tsx +++ b/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/AWSKMSAdd.tsx @@ -15,19 +15,9 @@ // along with this program. If not, see . import React, { Fragment, useCallback, useEffect, useState } from "react"; -import Grid from "@mui/material/Grid"; -import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; +import { InputBox } from "mds"; import { useSelector } from "react-redux"; import { AppState, useAppDispatch } from "../../../../../../store"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import { - createTenantCommon, - formFieldStyles, - modalBasic, - wizardCommon, -} from "../../../../Common/FormComponents/common/styleLibrary"; -import makeStyles from "@mui/styles/makeStyles"; import { commonFormValidation, IValidation, @@ -35,18 +25,8 @@ import { import { isPageValid, updateAddField } from "../../createTenantSlice"; import { clearValidationError } from "../../../utils"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - ...createTenantCommon, - ...formFieldStyles, - ...modalBasic, - ...wizardCommon, - }), -); - const AWSKMSAdd = () => { const dispatch = useAppDispatch(); - const classes = useStyles(); const encryptionTab = useSelector( (state: AppState) => state.createTenant.fields.encryption.encryptionTab, @@ -136,95 +116,81 @@ const AWSKMSAdd = () => { return ( - - ) => { + updateField("awsEndpoint", e.target.value); + cleanValidation("aws_endpoint"); + }} + label="Endpoint" + tooltip="Endpoint is the AWS SecretsManager endpoint. AWS SecretsManager endpoints have the following schema: secrestmanager[-fips]..amanzonaws.com" + value={awsEndpoint} + error={validationErrors["aws_endpoint"] || ""} + required + /> + ) => { + updateField("awsRegion", e.target.value); + cleanValidation("aws_region"); + }} + label="Region" + tooltip="Region is the AWS region the SecretsManager is located" + value={awsRegion} + error={validationErrors["aws_region"] || ""} + required + /> + ) => { + updateField("awsKMSKey", e.target.value); + }} + label="KMS Key" + tooltip="KMSKey is the AWS-KMS key ID (CMK-ID) used to en/decrypt secrets managed by the SecretsManager. If empty, the default AWS KMS key is used" + value={awsKMSKey} + /> +
+ Credentials + ) => { - updateField("awsEndpoint", e.target.value); - cleanValidation("aws_endpoint"); + updateField("awsAccessKey", e.target.value); + cleanValidation("aws_accessKey"); }} - label="Endpoint" - tooltip="Endpoint is the AWS SecretsManager endpoint. AWS SecretsManager endpoints have the following schema: secrestmanager[-fips]..amanzonaws.com" - value={awsEndpoint} - error={validationErrors["aws_endpoint"] || ""} + label="Access Key" + tooltip="AccessKey is the access key for authenticating to AWS" + value={awsAccessKey} + error={validationErrors["aws_accessKey"] || ""} required /> - - - ) => { - updateField("awsRegion", e.target.value); - cleanValidation("aws_region"); + updateField("awsSecretKey", e.target.value); + cleanValidation("aws_secretKey"); }} - label="Region" - tooltip="Region is the AWS region the SecretsManager is located" - value={awsRegion} - error={validationErrors["aws_region"] || ""} + label="Secret Key" + tooltip="SecretKey is the secret key for authenticating to AWS" + value={awsSecretKey} + error={validationErrors["aws_secretKey"] || ""} required /> - - - ) => { - updateField("awsKMSKey", e.target.value); + updateField("awsToken", e.target.value); }} - label="KMS Key" - tooltip="KMSKey is the AWS-KMS key ID (CMK-ID) used to en/decrypt secrets managed by the SecretsManager. If empty, the default AWS KMS key is used" - value={awsKMSKey} + label="Token" + value={awsToken} /> - - -
- Credentials - - ) => { - updateField("awsAccessKey", e.target.value); - cleanValidation("aws_accessKey"); - }} - label="Access Key" - tooltip="AccessKey is the access key for authenticating to AWS" - value={awsAccessKey} - error={validationErrors["aws_accessKey"] || ""} - required - /> - - - ) => { - updateField("awsSecretKey", e.target.value); - cleanValidation("aws_secretKey"); - }} - label="Secret Key" - tooltip="SecretKey is the secret key for authenticating to AWS" - value={awsSecretKey} - error={validationErrors["aws_secretKey"] || ""} - required - /> - - - ) => { - updateField("awsToken", e.target.value); - }} - label="Token" - value={awsToken} - /> - -
-
+
); }; diff --git a/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/AzureKMSAdd.tsx b/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/AzureKMSAdd.tsx index a969eb12e38..4c301c6ec75 100644 --- a/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/AzureKMSAdd.tsx +++ b/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/AzureKMSAdd.tsx @@ -15,19 +15,9 @@ // along with this program. If not, see . import React, { Fragment, useCallback, useEffect, useState } from "react"; -import Grid from "@mui/material/Grid"; -import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; +import { InputBox } from "mds"; import { useSelector } from "react-redux"; import { AppState, useAppDispatch } from "../../../../../../store"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import { - createTenantCommon, - formFieldStyles, - modalBasic, - wizardCommon, -} from "../../../../Common/FormComponents/common/styleLibrary"; -import makeStyles from "@mui/styles/makeStyles"; import { commonFormValidation, IValidation, @@ -35,18 +25,8 @@ import { import { isPageValid, updateAddField } from "../../createTenantSlice"; import { clearValidationError } from "../../../utils"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - ...createTenantCommon, - ...formFieldStyles, - ...modalBasic, - ...wizardCommon, - }), -); - const AzureKMSAdd = () => { const dispatch = useAppDispatch(); - const classes = useStyles(); const encryptionTab = useSelector( (state: AppState) => state.createTenant.fields.encryption.encryptionTab, @@ -131,67 +111,57 @@ const AzureKMSAdd = () => { return ( - - ) => { + updateField("azureEndpoint", e.target.value); + cleanValidation("azure_endpoint"); + }} + label="Endpoint" + tooltip="Endpoint is the Azure KeyVault endpoint" + value={azureEndpoint} + error={validationErrors["azure_endpoint"] || ""} + /> +
+ Credentials + ) => { + updateField("azureTenantID", e.target.value); + cleanValidation("azure_tenant_id"); + }} + label="Tenant ID" + tooltip="TenantID is the ID of the Azure KeyVault tenant" + value={azureTenantID} + error={validationErrors["azure_tenant_id"] || ""} + /> + ) => { + updateField("azureClientID", e.target.value); + cleanValidation("azure_client_id"); + }} + label="Client ID" + tooltip="ClientID is the ID of the client accessing Azure KeyVault" + value={azureClientID} + error={validationErrors["azure_client_id"] || ""} + /> + ) => { - updateField("azureEndpoint", e.target.value); - cleanValidation("azure_endpoint"); + updateField("azureClientSecret", e.target.value); + cleanValidation("azure_client_secret"); }} - label="Endpoint" - tooltip="Endpoint is the Azure KeyVault endpoint" - value={azureEndpoint} - error={validationErrors["azure_endpoint"] || ""} + label="Client Secret" + tooltip="ClientSecret is the client secret accessing the Azure KeyVault" + value={azureClientSecret} + error={validationErrors["azure_client_secret"] || ""} /> - - -
- Credentials - - ) => { - updateField("azureTenantID", e.target.value); - cleanValidation("azure_tenant_id"); - }} - label="Tenant ID" - tooltip="TenantID is the ID of the Azure KeyVault tenant" - value={azureTenantID} - error={validationErrors["azure_tenant_id"] || ""} - /> - - - ) => { - updateField("azureClientID", e.target.value); - cleanValidation("azure_client_id"); - }} - label="Client ID" - tooltip="ClientID is the ID of the client accessing Azure KeyVault" - value={azureClientID} - error={validationErrors["azure_client_id"] || ""} - /> - - - ) => { - updateField("azureClientSecret", e.target.value); - cleanValidation("azure_client_secret"); - }} - label="Client Secret" - tooltip="ClientSecret is the client secret accessing the Azure KeyVault" - value={azureClientSecret} - error={validationErrors["azure_client_secret"] || ""} - /> - -
-
+
); }; diff --git a/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/GCPKMSAdd.tsx b/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/GCPKMSAdd.tsx index 58877ac5297..0d10be6971b 100644 --- a/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/GCPKMSAdd.tsx +++ b/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/GCPKMSAdd.tsx @@ -15,32 +15,12 @@ // along with this program. If not, see . import React, { Fragment, useCallback } from "react"; -import Grid from "@mui/material/Grid"; -import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; +import { InputBox } from "mds"; import { useSelector } from "react-redux"; import { AppState, useAppDispatch } from "../../../../../../store"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import { - createTenantCommon, - formFieldStyles, - modalBasic, - wizardCommon, -} from "../../../../Common/FormComponents/common/styleLibrary"; -import makeStyles from "@mui/styles/makeStyles"; import { updateAddField } from "../../createTenantSlice"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - ...createTenantCommon, - ...formFieldStyles, - ...modalBasic, - ...wizardCommon, - }), -); - const GCPKMSAdd = () => { - const classes = useStyles(); const dispatch = useAppDispatch(); const gcpProjectID = useSelector( @@ -74,83 +54,69 @@ const GCPKMSAdd = () => { return ( - - ) => { + updateField("gcpProjectID", e.target.value); + }} + label="Project ID" + tooltip="ProjectID is the GCP project ID." + value={gcpProjectID} + /> + ) => { + updateField("gcpEndpoint", e.target.value); + }} + label="Endpoint" + tooltip="Endpoint is the GCP project ID. If empty defaults to: secretmanager.googleapis.com:443" + value={gcpEndpoint} + /> +
+ Credentials + ) => { + updateField("gcpClientEmail", e.target.value); + }} + label="Client Email" + tooltip="Is the Client email of the GCP service account used to access the SecretManager" + value={gcpClientEmail} + /> + ) => { + updateField("gcpClientID", e.target.value); + }} + label="Client ID" + tooltip="Is the Client ID of the GCP service account used to access the SecretManager" + value={gcpClientID} + /> + ) => { - updateField("gcpProjectID", e.target.value); + updateField("gcpPrivateKeyID", e.target.value); }} - label="Project ID" - tooltip="ProjectID is the GCP project ID." - value={gcpProjectID} + label="Private Key ID" + tooltip="Is the private key ID of the GCP service account used to access the SecretManager" + value={gcpPrivateKeyID} /> - - - ) => { - updateField("gcpEndpoint", e.target.value); + updateField("gcpPrivateKey", e.target.value); }} - label="Endpoint" - tooltip="Endpoint is the GCP project ID. If empty defaults to: secretmanager.googleapis.com:443" - value={gcpEndpoint} + label="Private Key" + tooltip="Is the private key of the GCP service account used to access the SecretManager" + value={gcpPrivateKey} /> - - -
- Credentials - - ) => { - updateField("gcpClientEmail", e.target.value); - }} - label="Client Email" - tooltip="Is the Client email of the GCP service account used to access the SecretManager" - value={gcpClientEmail} - /> - - - ) => { - updateField("gcpClientID", e.target.value); - }} - label="Client ID" - tooltip="Is the Client ID of the GCP service account used to access the SecretManager" - value={gcpClientID} - /> - - - ) => { - updateField("gcpPrivateKeyID", e.target.value); - }} - label="Private Key ID" - tooltip="Is the private key ID of the GCP service account used to access the SecretManager" - value={gcpPrivateKeyID} - /> - - - ) => { - updateField("gcpPrivateKey", e.target.value); - }} - label="Private Key" - tooltip="Is the private key of the GCP service account used to access the SecretManager" - value={gcpPrivateKey} - /> - -
-
+
); }; diff --git a/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/GemaltoKMSAdd.tsx b/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/GemaltoKMSAdd.tsx index 0457fc78fd9..418ff4bc482 100644 --- a/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/GemaltoKMSAdd.tsx +++ b/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/GemaltoKMSAdd.tsx @@ -15,19 +15,9 @@ // along with this program. If not, see . import React, { Fragment, useCallback, useEffect, useState } from "react"; -import Grid from "@mui/material/Grid"; -import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; +import { InputBox } from "mds"; import { useSelector } from "react-redux"; import { AppState, useAppDispatch } from "../../../../../../store"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import { - createTenantCommon, - formFieldStyles, - modalBasic, - wizardCommon, -} from "../../../../Common/FormComponents/common/styleLibrary"; -import makeStyles from "@mui/styles/makeStyles"; import { isPageValid, updateAddField } from "../../createTenantSlice"; import { commonFormValidation, @@ -35,18 +25,8 @@ import { } from "../../../../../../utils/validationFunctions"; import { clearValidationError } from "../../../utils"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - ...createTenantCommon, - ...formFieldStyles, - ...modalBasic, - ...wizardCommon, - }), -); - const GemaltoKMSAdd = () => { const dispatch = useAppDispatch(); - const classes = useStyles(); const encryptionTab = useSelector( (state: AppState) => state.createTenant.fields.encryption.encryptionTab, @@ -133,77 +113,61 @@ const GemaltoKMSAdd = () => { return ( - - ) => { + updateField("gemaltoEndpoint", e.target.value); + cleanValidation("gemalto_endpoint"); + }} + label="Endpoint" + tooltip="Endpoint is the endpoint to the KeySecure server" + value={gemaltoEndpoint} + error={validationErrors["gemalto_endpoint"] || ""} + required + /> +
+ Credentials + ) => { - updateField("gemaltoEndpoint", e.target.value); - cleanValidation("gemalto_endpoint"); + updateField("gemaltoToken", e.target.value); + cleanValidation("gemalto_token"); }} - label="Endpoint" - tooltip="Endpoint is the endpoint to the KeySecure server" - value={gemaltoEndpoint} - error={validationErrors["gemalto_endpoint"] || ""} + label="Token" + tooltip="Token is the refresh authentication token to access the KeySecure server" + value={gemaltoToken} + error={validationErrors["gemalto_token"] || ""} required /> - - -
- Credentials - - ) => { - updateField("gemaltoToken", e.target.value); - cleanValidation("gemalto_token"); - }} - label="Token" - tooltip="Token is the refresh authentication token to access the KeySecure server" - value={gemaltoToken} - error={validationErrors["gemalto_token"] || ""} - required - /> - - - ) => { - updateField("gemaltoDomain", e.target.value); - cleanValidation("gemalto_domain"); - }} - label="Domain" - tooltip="Domain is the isolated namespace within the KeySecure server. If empty, defaults to the top-level / root domain" - value={gemaltoDomain} - error={validationErrors["gemalto_domain"] || ""} - required - /> - - - ) => { - updateField("gemaltoRetry", e.target.value); - cleanValidation("gemalto_retry"); - }} - label="Retry (seconds)" - value={gemaltoRetry} - error={validationErrors["gemalto_retry"] || ""} - /> - -
-
+ ) => { + updateField("gemaltoDomain", e.target.value); + cleanValidation("gemalto_domain"); + }} + label="Domain" + tooltip="Domain is the isolated namespace within the KeySecure server. If empty, defaults to the top-level / root domain" + value={gemaltoDomain} + error={validationErrors["gemalto_domain"] || ""} + required + /> + ) => { + updateField("gemaltoRetry", e.target.value); + cleanValidation("gemalto_retry"); + }} + label="Retry (seconds)" + value={gemaltoRetry} + error={validationErrors["gemalto_retry"] || ""} + /> +
); }; diff --git a/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/VaultKMSAdd.tsx b/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/VaultKMSAdd.tsx index 948009f872b..bfce98ba47b 100644 --- a/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/VaultKMSAdd.tsx +++ b/web-app/src/screens/Console/Tenants/AddTenant/Steps/Encryption/VaultKMSAdd.tsx @@ -15,39 +15,18 @@ // along with this program. If not, see . import React, { Fragment, useCallback, useEffect, useState } from "react"; -import Grid from "@mui/material/Grid"; -import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; - -import { isPageValid, updateAddField } from "../../createTenantSlice"; +import { InputBox } from "mds"; import { useSelector } from "react-redux"; +import { isPageValid, updateAddField } from "../../createTenantSlice"; import { AppState, useAppDispatch } from "../../../../../../store"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import { - createTenantCommon, - formFieldStyles, - modalBasic, - wizardCommon, -} from "../../../../Common/FormComponents/common/styleLibrary"; -import makeStyles from "@mui/styles/makeStyles"; import { commonFormValidation, IValidation, } from "../../../../../../utils/validationFunctions"; import { clearValidationError } from "../../../utils"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - ...createTenantCommon, - ...formFieldStyles, - ...modalBasic, - ...wizardCommon, - }), -); - const VaultKMSAdd = () => { const dispatch = useAppDispatch(); - const classes = useStyles(); const encryptionTab = useSelector( (state: AppState) => state.createTenant.fields.encryption.encryptionTab, @@ -159,144 +138,118 @@ const VaultKMSAdd = () => { return ( - - ) => { + updateField("vaultEndpoint", e.target.value); + cleanValidation("vault_endpoint"); + }} + label="Endpoint" + tooltip="Endpoint is the Hashicorp Vault endpoint" + value={vaultEndpoint} + error={validationErrors["vault_endpoint"] || ""} + required + /> + ) => { + updateField("vaultEngine", e.target.value); + cleanValidation("vault_engine"); + }} + label="Engine" + tooltip="Engine is the Hashicorp Vault K/V engine path. If empty, defaults to 'kv'" + value={vaultEngine} + /> + ) => { + updateField("vaultNamespace", e.target.value); + }} + label="Namespace" + tooltip="Namespace is an optional Hashicorp Vault namespace. An empty namespace means no particular namespace is used." + value={vaultNamespace} + /> + ) => { + updateField("vaultPrefix", e.target.value); + }} + label="Prefix" + tooltip="Prefix is an optional prefix / directory within the K/V engine. If empty, keys will be stored at the K/V engine top level" + value={vaultPrefix} + /> +
+ App Role + ) => { + updateField("vaultAppRoleEngine", e.target.value); + }} + label="Engine" + tooltip="AppRoleEngine is the AppRole authentication engine path. If empty, defaults to 'approle'" + value={vaultAppRoleEngine} + /> + ) => { - updateField("vaultEndpoint", e.target.value); - cleanValidation("vault_endpoint"); + updateField("vaultId", e.target.value); + cleanValidation("vault_id"); }} - label="Endpoint" - tooltip="Endpoint is the Hashicorp Vault endpoint" - value={vaultEndpoint} - error={validationErrors["vault_endpoint"] || ""} + label="AppRole ID" + tooltip="AppRoleSecret is the AppRole access secret for authenticating to Hashicorp Vault via the AppRole method" + value={vaultId} + error={validationErrors["vault_id"] || ""} required /> - - - ) => { - updateField("vaultEngine", e.target.value); - cleanValidation("vault_engine"); + updateField("vaultSecret", e.target.value); + cleanValidation("vault_secret"); }} - label="Engine" - tooltip="Engine is the Hashicorp Vault K/V engine path. If empty, defaults to 'kv'" - value={vaultEngine} + label="AppRole Secret" + tooltip="AppRoleSecret is the AppRole access secret for authenticating to Hashicorp Vault via the AppRole method" + value={vaultSecret} + error={validationErrors["vault_secret"] || ""} + required /> - - - ) => { - updateField("vaultNamespace", e.target.value); + updateField("vaultRetry", e.target.value); + cleanValidation("vault_retry"); }} - label="Namespace" - tooltip="Namespace is an optional Hashicorp Vault namespace. An empty namespace means no particular namespace is used." - value={vaultNamespace} + label="Retry (Seconds)" + value={vaultRetry} + error={validationErrors["vault_retry"] || ""} /> - - - +
+ Status + ) => { - updateField("vaultPrefix", e.target.value); + updateField("vaultPing", e.target.value); + cleanValidation("vault_ping"); }} - label="Prefix" - tooltip="Prefix is an optional prefix / directory within the K/V engine. If empty, keys will be stored at the K/V engine top level" - value={vaultPrefix} + label="Ping (Seconds)" + value={vaultPing} + error={validationErrors["vault_ping"] || ""} /> - - - -
- App Role - - ) => { - updateField("vaultAppRoleEngine", e.target.value); - }} - label="Engine" - tooltip="AppRoleEngine is the AppRole authentication engine path. If empty, defaults to 'approle'" - value={vaultAppRoleEngine} - /> - - - ) => { - updateField("vaultId", e.target.value); - cleanValidation("vault_id"); - }} - label="AppRole ID" - tooltip="AppRoleSecret is the AppRole access secret for authenticating to Hashicorp Vault via the AppRole method" - value={vaultId} - error={validationErrors["vault_id"] || ""} - required - /> - - - ) => { - updateField("vaultSecret", e.target.value); - cleanValidation("vault_secret"); - }} - label="AppRole Secret" - tooltip="AppRoleSecret is the AppRole access secret for authenticating to Hashicorp Vault via the AppRole method" - value={vaultSecret} - error={validationErrors["vault_secret"] || ""} - required - /> - - - ) => { - updateField("vaultRetry", e.target.value); - cleanValidation("vault_retry"); - }} - label="Retry (Seconds)" - value={vaultRetry} - error={validationErrors["vault_retry"] || ""} - /> - -
-
- -
- Status - ) => { - updateField("vaultPing", e.target.value); - cleanValidation("vault_ping"); - }} - label="Ping (Seconds)" - value={vaultPing} - error={validationErrors["vault_ping"] || ""} - /> -
-
+
); }; diff --git a/web-app/src/screens/Console/Tenants/AddTenant/Steps/IdentityProvider.tsx b/web-app/src/screens/Console/Tenants/AddTenant/Steps/IdentityProvider.tsx index 94d7dd3bdd7..be184937997 100644 --- a/web-app/src/screens/Console/Tenants/AddTenant/Steps/IdentityProvider.tsx +++ b/web-app/src/screens/Console/Tenants/AddTenant/Steps/IdentityProvider.tsx @@ -15,55 +15,25 @@ // along with this program. If not, see . import React from "react"; -import { useSelector } from "react-redux"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import { Grid, Paper } from "@mui/material"; import { - createTenantCommon, - modalBasic, - wizardCommon, -} from "../../../Common/FormComponents/common/styleLibrary"; + Box, + FormLayout, + Grid, + LDAPIcon, + OIDCIcon, + RadioGroup, + UsersIcon, +} from "mds"; +import { useSelector } from "react-redux"; import { AppState, useAppDispatch } from "../../../../../store"; -import RadioGroupSelector from "../../../Common/FormComponents/RadioGroupSelector/RadioGroupSelector"; import { setIDP } from "../createTenantSlice"; import IDPActiveDirectory from "./IdentityProvider/IDPActiveDirectory"; import IDPOpenID from "./IdentityProvider/IDPOpenID"; -import makeStyles from "@mui/styles/makeStyles"; import IDPBuiltIn from "./IdentityProvider/IDPBuiltIn"; -import { - BuiltInLogoElement, - LDAPLogoElement, - OIDCLogoElement, -} from "../../LogoComponents"; import H3Section from "../../../Common/H3Section"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - protocolRadioOptions: { - display: "flex", - flexFlow: "column", - marginBottom: 10, - - "& label": { - fontSize: 16, - fontWeight: 600, - }, - "& div": { - display: "flex", - flexFlow: "row", - alignItems: "top", - }, - }, - ...createTenantCommon, - ...modalBasic, - ...wizardCommon, - }), -); - const IdentityProvider = () => { const dispatch = useAppDispatch(); - const classes = useStyles(); const idpSelection = useSelector( (state: AppState) => @@ -71,17 +41,17 @@ const IdentityProvider = () => { ); return ( - -
+ + Identity Provider - + Access to the tenant can be controlled via an external Identity Manager. -
- - + + { dispatch(setIDP(e.target.value)); }} selectorOptions={[ - { label: , value: "Built-in" }, - { label: , value: "OpenID" }, - { label: , value: "AD" }, + { label: "Built-in", value: "Built-in", icon: }, + { label: "Open ID", value: "OpenID", icon: }, + { + label: "LDAP / Active Directory", + value: "AD", + icon: , + }, ]} /> {idpSelection === "Built-in" && } {idpSelection === "OpenID" && } {idpSelection === "AD" && } -
+ ); }; diff --git a/web-app/src/screens/Console/Tenants/AddTenant/Steps/IdentityProvider/IDPActiveDirectory.tsx b/web-app/src/screens/Console/Tenants/AddTenant/Steps/IdentityProvider/IDPActiveDirectory.tsx index 6a88dc2d0c4..bb099e815bc 100644 --- a/web-app/src/screens/Console/Tenants/AddTenant/Steps/IdentityProvider/IDPActiveDirectory.tsx +++ b/web-app/src/screens/Console/Tenants/AddTenant/Steps/IdentityProvider/IDPActiveDirectory.tsx @@ -14,19 +14,17 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import { Grid, IconButton, Tooltip, Typography } from "@mui/material"; -import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; import React, { Fragment, useCallback, useEffect, useState } from "react"; -import FormSwitchWrapper from "../../../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper"; -import makeStyles from "@mui/styles/makeStyles"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; import { - createTenantCommon, - formFieldStyles, - modalBasic, - wizardCommon, -} from "../../../../Common/FormComponents/common/styleLibrary"; + IconButton, + Tooltip, + InputBox, + Switch, + FormLayout, + Box, + AddIcon, + RemoveIcon, +} from "mds"; import { addIDPADGroupAtIndex, addIDPADUsrAtIndex, @@ -40,47 +38,13 @@ import { import { useSelector } from "react-redux"; import { clearValidationError } from "../../../utils"; import { AppState, useAppDispatch } from "../../../../../../store"; -import AddIcon from "@mui/icons-material/Add"; -import DeleteIcon from "@mui/icons-material/Delete"; import { commonFormValidation, IValidation, } from "../../../../../../utils/validationFunctions"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - adUserDnRows: { - display: "flex", - marginBottom: 10, - }, - buttonTray: { - marginLeft: 10, - display: "flex", - height: 38, - "& button": { - background: "#EAEAEA", - }, - }, - overlayAction: { - marginLeft: 10, - "& svg": { - maxWidth: 15, - maxHeight: 15, - }, - "& button": { - background: "#EAEAEA", - }, - }, - ...createTenantCommon, - ...formFieldStyles, - ...modalBasic, - ...wizardCommon, - }), -); - const IDPActiveDirectory = () => { const dispatch = useAppDispatch(); - const classes = useStyles(); const idpSelection = useSelector( (state: AppState) => @@ -192,275 +156,259 @@ const IDPActiveDirectory = () => { ]); return ( - - - ) => { - updateField("ADURL", e.target.value); - cleanValidation("AD_URL"); - }} - label="LDAP Server Address" - value={ADURL} - placeholder="ldap-server:636" - error={validationErrors["AD_URL"] || ""} - required - /> - - - { - const targetD = e.target; - const checked = targetD.checked; - updateField("ADSkipTLS", checked); - }} - label={"Skip TLS Verification"} - /> - - - { - const targetD = e.target; - const checked = targetD.checked; - updateField("ADServerInsecure", checked); - }} - label={"Server Insecure"} - /> - + + ) => { + updateField("ADURL", e.target.value); + cleanValidation("AD_URL"); + }} + label="LDAP Server Address" + value={ADURL} + placeholder="ldap-server:636" + error={validationErrors["AD_URL"] || ""} + required + /> + { + const targetD = e.target; + const checked = targetD.checked; + updateField("ADSkipTLS", checked); + }} + label={"Skip TLS Verification"} + /> + { + const targetD = e.target; + const checked = targetD.checked; + updateField("ADServerInsecure", checked); + }} + label={"Server Insecure"} + /> {ADServerInsecure ? ( - - + + Warning: All traffic with Active Directory will be unencrypted - +
-
+ ) : null} - - { - const targetD = e.target; - const checked = targetD.checked; - updateField("ADServerStartTLS", checked); - }} - label={"Start TLS connection to AD/LDAP server"} - /> - - - ) => { - updateField("ADLookupBindDN", e.target.value); - cleanValidation("ad_lookupBindDN"); - }} - label="Lookup Bind DN" - value={ADLookupBindDN} - placeholder="cn=admin,dc=min,dc=io" - error={validationErrors["ad_lookupBindDN"] || ""} - required - /> - - - ) => { - updateField("ADLookupBindPassword", e.target.value); - }} - label="Lookup Bind Password" - value={ADLookupBindPassword} - placeholder="admin" - /> - - - ) => { - updateField("ADUserDNSearchBaseDN", e.target.value); - }} - label="User DN Search Base DN" - value={ADUserDNSearchBaseDN} - placeholder="dc=min,dc=io" - /> - - - ) => { - updateField("ADUserDNSearchFilter", e.target.value); - }} - label="User DN Search Filter" - value={ADUserDNSearchFilter} - placeholder="(sAMAcountName=%s)" - /> - - - ) => { - updateField("ADGroupSearchBaseDN", e.target.value); - }} - label="Group Search Base DN" - value={ADGroupSearchBaseDN} - placeholder="ou=hwengg,dc=min,dc=io;ou=swengg,dc=min,dc=io" - /> - - - ) => { - updateField("ADGroupSearchFilter", e.target.value); - }} - label="Group Search Filter" - value={ADGroupSearchFilter} - placeholder="(&(objectclass=groupOfNames)(member=%s))" - /> - -
- + { + const targetD = e.target; + const checked = targetD.checked; + updateField("ADServerStartTLS", checked); + }} + label={"Start TLS connection to AD/LDAP server"} + /> + ) => { + updateField("ADLookupBindDN", e.target.value); + cleanValidation("ad_lookupBindDN"); + }} + label="Lookup Bind DN" + value={ADLookupBindDN} + placeholder="cn=admin,dc=min,dc=io" + error={validationErrors["ad_lookupBindDN"] || ""} + required + /> + ) => { + updateField("ADLookupBindPassword", e.target.value); + }} + label="Lookup Bind Password" + value={ADLookupBindPassword} + placeholder="admin" + /> + ) => { + updateField("ADUserDNSearchBaseDN", e.target.value); + }} + label="User DN Search Base DN" + value={ADUserDNSearchBaseDN} + placeholder="dc=min,dc=io" + /> + ) => { + updateField("ADUserDNSearchFilter", e.target.value); + }} + label="User DN Search Filter" + value={ADUserDNSearchFilter} + placeholder="(sAMAcountName=%s)" + /> + ) => { + updateField("ADGroupSearchBaseDN", e.target.value); + }} + label="Group Search Base DN" + value={ADGroupSearchBaseDN} + placeholder="ou=hwengg,dc=min,dc=io;ou=swengg,dc=min,dc=io" + /> + ) => { + updateField("ADGroupSearchFilter", e.target.value); + }} + label="Group Search Filter" + value={ADGroupSearchFilter} + placeholder="(&(objectclass=groupOfNames)(member=%s))" + /> +
+ List of user DNs (Distinguished Names) to be Tenant Administrators - - {ADUserDNs.map((_, index) => { - return ( - -
- ) => { - dispatch( - setIDPADUsrAtIndex({ - index: index, - userDN: e.target.value, - }), - ); - cleanValidation(`ad-userdn-${index.toString()}`); - }} - index={index} - key={`csv-ad-userdn-${index.toString()}`} - error={ - validationErrors[`ad-userdn-${index.toString()}`] || "" - } - /> -
- - { - dispatch(addIDPADUsrAtIndex()); - }} - > - - - - - { - if (ADUserDNs.length > 1) { - dispatch(removeIDPADUsrAtIndex(index)); - } - }} - > - - - -
-
-
- ); - })} -
+ {ADUserDNs.map((_, index) => { + return ( + + + ) => { + dispatch( + setIDPADUsrAtIndex({ + index: index, + userDN: e.target.value, + }), + ); + cleanValidation(`ad-userdn-${index.toString()}`); + }} + index={index} + key={`csv-ad-userdn-${index.toString()}`} + error={ + validationErrors[`ad-userdn-${index.toString()}`] || "" + } + /> + + + { + dispatch(addIDPADUsrAtIndex()); + }} + > + + + + + { + if (ADUserDNs.length > 1) { + dispatch(removeIDPADUsrAtIndex(index)); + } + }} + > + + + + + + + ); + })}
-
- +
+ List of group DNs (Distinguished Names) to be Tenant Administrators - - {ADGroupDNs.map((_, index) => { - return ( - -
- ) => { - dispatch( - setIDPADGroupAtIndex({ - index: index, - userDN: e.target.value, - }), - ); - cleanValidation(`ad-groupdn-${index.toString()}`); - }} - index={index} - key={`csv-ad-groupdn-${index.toString()}`} - error={ - validationErrors[`ad-groupdn-${index.toString()}`] || "" - } - /> -
- - { - dispatch(addIDPADGroupAtIndex()); - }} - > - - - - - { - if (ADGroupDNs.length > 1) { - dispatch(removeIDPADGroupAtIndex(index)); - } - }} - > - - - -
-
-
- ); - })} -
+ {ADGroupDNs.map((_, index) => { + return ( + + + ) => { + dispatch( + setIDPADGroupAtIndex({ + index: index, + userDN: e.target.value, + }), + ); + cleanValidation(`ad-groupdn-${index.toString()}`); + }} + index={index} + key={`csv-ad-groupdn-${index.toString()}`} + error={ + validationErrors[`ad-groupdn-${index.toString()}`] || "" + } + /> + + + { + dispatch(addIDPADGroupAtIndex()); + }} + > + + + + + { + if (ADGroupDNs.length > 1) { + dispatch(removeIDPADGroupAtIndex(index)); + } + }} + > + + + + + + + ); + })}
- + ); }; diff --git a/web-app/src/screens/Console/Tenants/AddTenant/Steps/IdentityProvider/IDPBuiltIn.tsx b/web-app/src/screens/Console/Tenants/AddTenant/Steps/IdentityProvider/IDPBuiltIn.tsx index dd57ee5f84e..eb6c7e9721e 100644 --- a/web-app/src/screens/Console/Tenants/AddTenant/Steps/IdentityProvider/IDPBuiltIn.tsx +++ b/web-app/src/screens/Console/Tenants/AddTenant/Steps/IdentityProvider/IDPBuiltIn.tsx @@ -15,7 +15,9 @@ // along with this program. If not, see . import React, { Fragment, useEffect, useState } from "react"; -import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; +import { IconButton, Tooltip, InputBox, AddIcon, RemoveIcon, Box } from "mds"; +import { useSelector } from "react-redux"; +import CasinoIcon from "@mui/icons-material/Casino"; // TODO: Implement this in mds import { addIDPNewKeyPair, isPageValid, @@ -23,66 +25,15 @@ import { setIDPPwdAtIndex, setIDPUsrAtIndex, } from "../../createTenantSlice"; -import { IconButton, Tooltip } from "@mui/material"; -import AddIcon from "@mui/icons-material/Add"; -import { RemoveIcon } from "mds"; import { clearValidationError, getRandomString } from "../../../utils"; -import CasinoIcon from "@mui/icons-material/Casino"; -import { useSelector } from "react-redux"; import { AppState, useAppDispatch } from "../../../../../../store"; -import makeStyles from "@mui/styles/makeStyles"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import { - createTenantCommon, - formFieldStyles, - modalBasic, - wizardCommon, -} from "../../../../Common/FormComponents/common/styleLibrary"; import { commonFormValidation, IValidation, } from "../../../../../../utils/validationFunctions"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - buttonTray: { - marginLeft: 10, - display: "flex", - height: 38, - "& button": { - background: "#EAEAEA", - }, - }, - overlayAction: { - marginLeft: 10, - "& svg": { - maxWidth: 15, - maxHeight: 15, - }, - "& button": { - background: "#EAEAEA", - }, - }, - shortened: { - gridTemplateColumns: "auto auto 50px 50px", - display: "grid", - gridGap: 15, - marginBottom: 10, - "& input": { - fontWeight: 400, - }, - }, - ...createTenantCommon, - ...formFieldStyles, - ...modalBasic, - ...wizardCommon, - }), -); - const IDPBuiltIn = () => { const dispatch = useAppDispatch(); - const classes = useStyles(); const idpSelection = useSelector( (state: AppState) => @@ -143,8 +94,15 @@ const IDPBuiltIn = () => { {accessKeys.map((_, index) => { return ( -
- + { key={`csv-accesskey-${index.toString()}`} error={validationErrors[`accesskey-${index.toString()}`] || ""} /> - { key={`csv-secretkey-${index.toString()}`} error={validationErrors[`secretkey-${index.toString()}`] || ""} /> -
-
+ + { + dispatch(addIDPNewKeyPair()); + }} + disabled={index !== accessKeys.length - 1} + > + + + { + dispatch(removeIDPKeyPairAtIndex(index)); + }} + disabled={accessKeys.length <= 1} + > + + + { - dispatch(addIDPNewKeyPair()); + dispatch( + setIDPUsrAtIndex({ + index, + accessKey: getRandomString(16), + }), + ); + dispatch( + setIDPPwdAtIndex({ + index, + secretKey: getRandomString(16), + }), + ); }} - disabled={index !== accessKeys.length - 1} - > - - -
-
- { - dispatch(removeIDPKeyPairAtIndex(index)); - }} - disabled={accessKeys.length <= 1} > - + -
- -
- { - dispatch( - setIDPUsrAtIndex({ - index, - accessKey: getRandomString(16), - }), - ); - dispatch( - setIDPPwdAtIndex({ - index, - secretKey: getRandomString(16), - }), - ); - }} - size={"small"} - > - - -
-
-
+ +
); })} diff --git a/web-app/src/screens/Console/Tenants/AddTenant/Steps/IdentityProvider/IDPOpenID.tsx b/web-app/src/screens/Console/Tenants/AddTenant/Steps/IdentityProvider/IDPOpenID.tsx index 1fe7d9ffffa..5c7f09201aa 100644 --- a/web-app/src/screens/Console/Tenants/AddTenant/Steps/IdentityProvider/IDPOpenID.tsx +++ b/web-app/src/screens/Console/Tenants/AddTenant/Steps/IdentityProvider/IDPOpenID.tsx @@ -14,18 +14,8 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import { Grid } from "@mui/material"; -import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; -import React, { Fragment, useCallback, useEffect, useState } from "react"; -import makeStyles from "@mui/styles/makeStyles"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import { - createTenantCommon, - formFieldStyles, - modalBasic, - wizardCommon, -} from "../../../../Common/FormComponents/common/styleLibrary"; +import React, { useCallback, useEffect, useState } from "react"; +import { FormLayout, InputBox } from "mds"; import { useSelector } from "react-redux"; import { AppState, useAppDispatch } from "../../../../../../store"; import { isPageValid, updateAddField } from "../../createTenantSlice"; @@ -35,36 +25,8 @@ import { IValidation, } from "../../../../../../utils/validationFunctions"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - buttonTray: { - marginLeft: 10, - display: "flex", - height: 38, - "& button": { - background: "#EAEAEA", - }, - }, - overlayAction: { - marginLeft: 10, - "& svg": { - maxWidth: 15, - maxHeight: 15, - }, - "& button": { - background: "#EAEAEA", - }, - }, - ...createTenantCommon, - ...formFieldStyles, - ...modalBasic, - ...wizardCommon, - }), -); - const IDPOpenID = () => { const dispatch = useAppDispatch(); - const classes = useStyles(); const idpSelection = useSelector( (state: AppState) => @@ -160,77 +122,67 @@ const IDPOpenID = () => { ]); return ( - - - ) => { - updateField("openIDConfigurationURL", e.target.value); - cleanValidation("openID_CONFIGURATION_URL"); - }} - label="Configuration URL" - value={openIDConfigurationURL} - placeholder="https://your-identity-provider.com/.well-known/openid-configuration" - error={validationErrors["openID_CONFIGURATION_URL"] || ""} - required - /> - - - ) => { - updateField("openIDClientID", e.target.value); - cleanValidation("openID_clientID"); - }} - label="Client ID" - value={openIDClientID} - error={validationErrors["openID_clientID"] || ""} - required - /> - - - ) => { - updateField("openIDSecretID", e.target.value); - cleanValidation("openID_secretID"); - }} - label="Secret ID" - value={openIDSecretID} - error={validationErrors["openID_secretID"] || ""} - required - /> - - - ) => { - updateField("openIDClaimName", e.target.value); - cleanValidation("openID_claimName"); - }} - label="Claim Name" - value={openIDClaimName} - placeholder="policy" - error={validationErrors["openID_claimName"] || ""} - /> - - - ) => { - updateField("openIDScopes", e.target.value); - cleanValidation("openID_scopes"); - }} - label="Scopes" - value={openIDScopes} - /> - - + + ) => { + updateField("openIDConfigurationURL", e.target.value); + cleanValidation("openID_CONFIGURATION_URL"); + }} + label="Configuration URL" + value={openIDConfigurationURL} + placeholder="https://your-identity-provider.com/.well-known/openid-configuration" + error={validationErrors["openID_CONFIGURATION_URL"] || ""} + required + /> + ) => { + updateField("openIDClientID", e.target.value); + cleanValidation("openID_clientID"); + }} + label="Client ID" + value={openIDClientID} + error={validationErrors["openID_clientID"] || ""} + required + /> + ) => { + updateField("openIDSecretID", e.target.value); + cleanValidation("openID_secretID"); + }} + label="Secret ID" + value={openIDSecretID} + error={validationErrors["openID_secretID"] || ""} + required + /> + ) => { + updateField("openIDClaimName", e.target.value); + cleanValidation("openID_claimName"); + }} + label="Claim Name" + value={openIDClaimName} + placeholder="policy" + error={validationErrors["openID_claimName"] || ""} + /> + ) => { + updateField("openIDScopes", e.target.value); + cleanValidation("openID_scopes"); + }} + label="Scopes" + value={openIDScopes} + /> + ); }; diff --git a/web-app/src/screens/Console/Tenants/AddTenant/Steps/Images.tsx b/web-app/src/screens/Console/Tenants/AddTenant/Steps/Images.tsx index 22c47445830..d5e49cdbcc9 100644 --- a/web-app/src/screens/Console/Tenants/AddTenant/Steps/Images.tsx +++ b/web-app/src/screens/Console/Tenants/AddTenant/Steps/Images.tsx @@ -16,36 +16,17 @@ import React, { Fragment, useCallback, useEffect, useState } from "react"; import { useSelector } from "react-redux"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import withStyles from "@mui/styles/withStyles"; -import { Grid, Paper } from "@mui/material"; -import { - formFieldStyles, - wizardCommon, -} from "../../../Common/FormComponents/common/styleLibrary"; +import { Box, FormLayout, InputBox, Switch } from "mds"; import { AppState, useAppDispatch } from "../../../../../store"; import { clearValidationError } from "../../utils"; import { commonFormValidation, IValidation, } from "../../../../../utils/validationFunctions"; -import FormSwitchWrapper from "../../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper"; -import InputBoxWrapper from "../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; import { isPageValid, updateAddField } from "../createTenantSlice"; import H3Section from "../../../Common/H3Section"; -interface IImagesProps { - classes: any; -} - -const styles = (theme: Theme) => - createStyles({ - ...formFieldStyles, - ...wizardCommon, - }); - -const Images = ({ classes }: IImagesProps) => { +const Images = () => { const dispatch = useAppDispatch(); const customImage = useSelector( @@ -160,114 +141,99 @@ const Images = ({ classes }: IImagesProps) => { }; return ( - -
+ + Container Images - + Specify the container images used by the Tenant and its features. -
- - - - ) => { - updateField("imageName", e.target.value); - cleanValidation("image"); - }} - label="MinIO" - value={imageName} - error={validationErrors["image"] || ""} - placeholder="minio/minio:RELEASE.2023-11-15T20-43-25Z" - /> - - - - ) => { - updateField("kesImage", e.target.value); - cleanValidation("kesImage"); - }} - label="KES" - value={kesImage} - error={validationErrors["kesImage"] || ""} - placeholder="minio/kes:2023-11-10T10-44-28Z" - /> - - + + + ) => { + updateField("imageName", e.target.value); + cleanValidation("image"); + }} + label="MinIO" + value={imageName} + error={validationErrors["image"] || ""} + placeholder="minio/minio:RELEASE.2023-11-15T20-43-25Z" + /> + ) => { + updateField("kesImage", e.target.value); + cleanValidation("kesImage"); + }} + label="KES" + value={kesImage} + error={validationErrors["kesImage"] || ""} + placeholder="minio/kes:2023-11-10T10-44-28Z" + /> {customImage && ( - +

Custom Container Registry

-
- - { - const targetD = e.target; - const checked = targetD.checked; - - updateField("customDockerhub", checked); - }} - label={"Use a private container registry"} - /> - + + { + const targetD = e.target; + const checked = targetD.checked; + + updateField("customDockerhub", checked); + }} + label={"Use a private container registry"} + />
)} {customDockerhub && ( - - ) => { - updateField("imageRegistry", e.target.value); - }} - label="Endpoint" - value={imageRegistry} - error={validationErrors["registry"] || ""} - placeholder="https://index.docker.io/v1/" - required - /> - - - ) => { - updateField("imageRegistryUsername", e.target.value); - }} - label="Username" - value={imageRegistryUsername} - error={validationErrors["registryUsername"] || ""} - required - /> - - - ) => { - updateField("imageRegistryPassword", e.target.value); - }} - label="Password" - value={imageRegistryPassword} - error={validationErrors["registryPassword"] || ""} - required - /> - + ) => { + updateField("imageRegistry", e.target.value); + }} + label="Endpoint" + value={imageRegistry} + error={validationErrors["registry"] || ""} + placeholder="https://index.docker.io/v1/" + required + /> + ) => { + updateField("imageRegistryUsername", e.target.value); + }} + label="Username" + value={imageRegistryUsername} + error={validationErrors["registryUsername"] || ""} + required + /> + ) => { + updateField("imageRegistryPassword", e.target.value); + }} + label="Password" + value={imageRegistryPassword} + error={validationErrors["registryPassword"] || ""} + required + /> )} -
+ ); }; -export default withStyles(styles)(Images); +export default Images; diff --git a/web-app/src/screens/Console/Tenants/AddTenant/Steps/Security.tsx b/web-app/src/screens/Console/Tenants/AddTenant/Steps/Security.tsx index d593fbe2fe2..54b35ed093c 100644 --- a/web-app/src/screens/Console/Tenants/AddTenant/Steps/Security.tsx +++ b/web-app/src/screens/Console/Tenants/AddTenant/Steps/Security.tsx @@ -15,23 +15,22 @@ // along with this program. If not, see . import React, { Fragment, useCallback, useEffect } from "react"; -import { useSelector } from "react-redux"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import withStyles from "@mui/styles/withStyles"; -import { Grid, IconButton, Paper } from "@mui/material"; import { - createTenantCommon, - modalBasic, - wizardCommon, -} from "../../../Common/FormComponents/common/styleLibrary"; - + AddIcon, + Box, + breakPoints, + FileSelector, + FormLayout, + Grid, + IconButton, + RemoveIcon, + Switch, +} from "mds"; +import { useSelector } from "react-redux"; +import get from "lodash/get"; +import styled from "styled-components"; import { AppState, useAppDispatch } from "../../../../../store"; import { KeyPair } from "../../ListTenants/utils"; -import FormSwitchWrapper from "../../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper"; -import FileSelector from "../../../Common/FormComponents/FileSelector/FileSelector"; -import AddIcon from "@mui/icons-material/Add"; -import { RemoveIcon } from "mds"; import { addCaCertificate, addClientKeyPair, @@ -48,79 +47,36 @@ import { import TLSHelpBox from "../../HelpBox/TLSHelpBox"; import H3Section from "../../../Common/H3Section"; -interface ISecurityProps { - classes: any; -} - -const styles = (theme: Theme) => - createStyles({ - minioCertificateRows: { - display: "flex", - alignItems: "center", - justifyContent: "flex-start", - borderBottom: "1px solid #EAEAEA", - "&:last-child": { - borderBottom: 0, - }, - "@media (max-width: 900px)": { - flex: 1, - }, - }, - fileItem: { - marginRight: 10, - display: "flex", - "& div label": { - minWidth: 50, - }, - - "@media (max-width: 900px)": { - flexFlow: "column", - }, - }, - minioCertsContainer: { - marginBottom: 15, +const CertificateRow = styled.div(({ theme }) => ({ + display: "flex", + alignItems: "center", + justifyContent: "flex-start", + padding: 8, + borderBottom: `1px solid ${get(theme, "borderColor", "#E2E2E2")}`, + "& .fileItem": { + display: "flex", + "& .inputItem:not(:last-of-type)": { + marginBottom: 0, }, - minioCACertsRow: { - display: "flex", - alignItems: "center", - justifyContent: "flex-start", - - borderBottom: "1px solid #EAEAEA", - "&:last-child": { - borderBottom: 0, - }, - "@media (max-width: 900px)": { - flex: 1, - - "& div label": { - minWidth: 50, - }, + [`@media (max-width: ${breakPoints.md}px)`]: { + flexFlow: "column", + "& .inputItem:not(:last-of-type)": { + marginBottom: 10, }, }, - rowActions: { - display: "flex", - justifyContent: "flex-end", - "@media (max-width: 900px)": { - flex: 1, - }, - }, - overlayAction: { - marginLeft: 10, - "& svg": { - maxWidth: 15, - maxHeight: 15, - }, - "& button": { - background: "#EAEAEA", - }, + }, + "& .rowActions": { + display: "flex", + justifyContent: "flex-end", + alignItems: "center", + gap: 10, + "@media (max-width: 900px)": { + flex: 1, }, + }, +})); - ...createTenantCommon, - ...modalBasic, - ...wizardCommon, - }); - -const Security = ({ classes }: ISecurityProps) => { +const Security = () => { const dispatch = useAppDispatch(); const enableTLS = useSelector( @@ -173,82 +129,68 @@ const Security = ({ classes }: ISecurityProps) => { }, [enableTLS, enableAutoCert, enableCustomCerts, dispatch]); return ( - -
+ + Security -
- - - + { + const targetD = e.target; + const checked = targetD.checked; + + updateField("enableTLS", checked); + }} + label={"TLS"} + description={ + "Securing all the traffic using TLS. This is required for Encryption Configuration" + } + /> + {enableTLS && ( + + { const targetD = e.target; const checked = targetD.checked; - - updateField("enableTLS", checked); + updateField("enableAutoCert", checked); }} - label={"TLS"} + label={"AutoCert"} description={ - "Securing all the traffic using TLS. This is required for Encryption Configuration" + "The internode certificates will be generated and managed by MinIO Operator" } /> - - {enableTLS && ( - - - { - const targetD = e.target; - const checked = targetD.checked; - updateField("enableAutoCert", checked); - }} - label={"AutoCert"} - description={ - "The internode certificates will be generated and managed by MinIO Operator" - } - /> - - - { - const targetD = e.target; - const checked = targetD.checked; - updateField("enableCustomCerts", checked); - }} - label={"Custom Certificates"} - description={"Certificates used to terminated TLS at MinIO"} - /> - - {enableCustomCerts && ( - - {!enableAutoCert && ( - - - - )} - -
MinIO Server Certificates
- {minioCertificates.map((keyPair: KeyPair, index) => ( - - - { + { + const targetD = e.target; + const checked = targetD.checked; + updateField("enableCustomCerts", checked); + }} + label={"Custom Certificates"} + description={"Certificates used to terminated TLS at MinIO"} + /> + {enableCustomCerts && ( + + {!enableAutoCert && } +
+ MinIO Server Certificates + + {minioCertificates.map((keyPair: KeyPair, index) => ( + + + { + if (encodedValue) { dispatch( addFileToKeyPair({ id: keyPair.id, @@ -257,15 +199,18 @@ const Security = ({ classes }: ISecurityProps) => { value: encodedValue, }), ); - }} - accept=".cer,.crt,.cert,.pem" - id="tlsCert" - name="tlsCert" - label="Cert" - value={keyPair.cert} - /> - { + } + }} + accept=".cer,.crt,.cert,.pem" + id="tlsCert" + name="tlsCert" + label="Cert" + value={keyPair.cert} + returnEncodedData + /> + { + if (encodedValue) { dispatch( addFileToKeyPair({ id: keyPair.id, @@ -274,54 +219,48 @@ const Security = ({ classes }: ISecurityProps) => { value: encodedValue, }), ); - }} - accept=".key,.pem" - id="tlsKey" - name="tlsKey" - label="Key" - value={keyPair.key} - /> - + } + }} + accept=".key,.pem" + id="tlsKey" + name="tlsKey" + label="Key" + value={keyPair.key} + returnEncodedData + /> + - -
- { - dispatch(addKeyPair()); - }} - disabled={index !== minioCertificates.length - 1} - > - - -
-
- { - dispatch(deleteKeyPair(keyPair.id)); - }} - disabled={minioCertificates.length <= 1} - > - - -
-
+ + { + dispatch(addKeyPair()); + }} + disabled={index !== minioCertificates.length - 1} + > + + + { + dispatch(deleteKeyPair(keyPair.id)); + }} + disabled={minioCertificates.length <= 1} + > + + - ))} - - -
MinIO Client Certificates
- {minioClientCertificates.map((keyPair: KeyPair, index) => ( - - - { +
+ ))} +
+
+ MinIO Client Certificates + {minioClientCertificates.map((keyPair: KeyPair, index) => ( + + + { + if (encodedValue) { dispatch( addFileToClientKeyPair({ id: keyPair.id, @@ -330,15 +269,18 @@ const Security = ({ classes }: ISecurityProps) => { value: encodedValue, }), ); - }} - accept=".cer,.crt,.cert,.pem" - id="tlsCert" - name="tlsCert" - label="Cert" - value={keyPair.cert} - /> - { + } + }} + accept=".cer,.crt,.cert,.pem" + id="tlsCert" + name="tlsCert" + label="Cert" + value={keyPair.cert} + returnEncodedData + /> + { + if (encodedValue) { dispatch( addFileToClientKeyPair({ id: keyPair.id, @@ -347,56 +289,48 @@ const Security = ({ classes }: ISecurityProps) => { value: encodedValue, }), ); - }} - accept=".key,.pem" - id="tlsKey" - name="tlsKey" - label="Key" - value={keyPair.key} - /> - + } + }} + accept=".key,.pem" + id="tlsKey" + name="tlsKey" + label="Key" + value={keyPair.key} + returnEncodedData + /> + - -
- { - dispatch(addClientKeyPair()); - }} - disabled={ - index !== minioClientCertificates.length - 1 - } - > - - -
-
- { - dispatch(deleteClientKeyPair(keyPair.id)); - }} - disabled={minioClientCertificates.length <= 1} - > - - -
-
+ + { + dispatch(addClientKeyPair()); + }} + disabled={index !== minioClientCertificates.length - 1} + > + + + { + dispatch(deleteClientKeyPair(keyPair.id)); + }} + disabled={minioClientCertificates.length <= 1} + > + + - ))} - - -
MinIO CA Certificates
- {caCertificates.map((keyPair: KeyPair, index) => ( - - - { +
+ ))} +
+
+ MinIO CA Certificates + {caCertificates.map((keyPair: KeyPair, index) => ( + + + { + if (encodedValue) { dispatch( addFileToCaCertificates({ id: keyPair.id, @@ -405,50 +339,47 @@ const Security = ({ classes }: ISecurityProps) => { value: encodedValue, }), ); + } + }} + accept=".cer,.crt,.cert,.pem" + id="tlsCert" + name="tlsCert" + label="Cert" + value={keyPair.cert} + returnEncodedData + /> + + +
+ { + dispatch(addCaCertificate()); + }} + disabled={index !== caCertificates.length - 1} + > + + + { + dispatch(deleteCaCertificate(keyPair.id)); }} - accept=".cer,.crt,.cert,.pem" - id="tlsCert" - name="tlsCert" - label="Cert" - value={keyPair.cert} - /> - - -
-
- { - dispatch(addCaCertificate()); - }} - disabled={index !== caCertificates.length - 1} - > - - -
-
- { - dispatch(deleteCaCertificate(keyPair.id)); - }} - disabled={caCertificates.length <= 1} - > - - -
-
-
+ disabled={caCertificates.length <= 1} + > + +
+
- ))} - - - )} - - )} - - +
+ ))} +
+
+ )} +
+ )} + ); }; -export default withStyles(styles)(Security); +export default Security; diff --git a/web-app/src/screens/Console/Tenants/AddTenant/Steps/SizePreview.tsx b/web-app/src/screens/Console/Tenants/AddTenant/Steps/SizePreview.tsx index 7c80365a97a..80d49411713 100644 --- a/web-app/src/screens/Console/Tenants/AddTenant/Steps/SizePreview.tsx +++ b/web-app/src/screens/Console/Tenants/AddTenant/Steps/SizePreview.tsx @@ -15,42 +15,12 @@ // along with this program. If not, see . import React, { Fragment } from "react"; +import { Box, SimpleHeader, Table, TableBody, TableCell, TableRow } from "mds"; import { useSelector } from "react-redux"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import withStyles from "@mui/styles/withStyles"; import { AppState } from "../../../../../store"; -import { - modalBasic, - wizardCommon, -} from "../../../Common/FormComponents/common/styleLibrary"; -import Table from "@mui/material/Table"; -import TableBody from "@mui/material/TableBody"; -import TableCell from "@mui/material/TableCell"; -import TableRow from "@mui/material/TableRow"; import { niceBytes } from "../../../../../common/utils"; -import { Divider } from "@mui/material"; - -interface ISizePreviewProps { - classes: any; -} - -const styles = (theme: Theme) => - createStyles({ - root: { - margin: 4, - }, - table: { - "& .MuiTableCell-root": { - fontSize: 13, - }, - }, - ...modalBasic, - ...wizardCommon, - }); - -const SizePreview = ({ classes }: ISizePreviewProps) => { +const SizePreview = () => { const nodes = useSelector( (state: AppState) => state.createTenant.fields.tenantSize.nodes, ); @@ -83,14 +53,18 @@ const SizePreview = ({ classes }: ISizePreviewProps) => { ); return ( -
-

Resource Allocation

- - + + +
Number of Servers - + {parseInt(nodes) > 0 ? nodes : "-"} @@ -99,13 +73,13 @@ const SizePreview = ({ classes }: ISizePreviewProps) => { Drives per Server - + {distribution ? distribution.disks : "-"} Drive Capacity - + {distribution ? niceBytes(distribution.pvSize) : "-"} @@ -114,7 +88,7 @@ const SizePreview = ({ classes }: ISizePreviewProps) => { Total Volumes - + {distribution ? distribution.persistentVolumes : "-"} @@ -123,13 +97,18 @@ const SizePreview = ({ classes }: ISizePreviewProps) => { Memory per Node - {memoryNode} Gi + + {memoryNode} Gi + CPU Selection - + {cpuToUse} @@ -139,29 +118,27 @@ const SizePreview = ({ classes }: ISizePreviewProps) => {
{ecParityCalc.error === 0 && usableInformation && ( -

Erasure Code Configuration

- - + +
EC Parity - + {ecParity !== "" ? ecParity : "-"} Raw Capacity - + {niceBytes(ecParityCalc.rawCapacity)} Usable Capacity - + {niceBytes(usableInformation.maxCapacity)} @@ -169,7 +146,10 @@ const SizePreview = ({ classes }: ISizePreviewProps) => { Server Failures Tolerated - + {distribution ? Math.floor( usableInformation.maxFailureTolerations / @@ -185,17 +165,15 @@ const SizePreview = ({ classes }: ISizePreviewProps) => { {integrationSelection.typeSelection !== "" && integrationSelection.storageClass !== "" && ( -

Single Instance Configuration

- -
+ +
CPU - + {integrationSelection.CPU !== 0 ? integrationSelection.CPU : "-"} @@ -203,7 +181,7 @@ const SizePreview = ({ classes }: ISizePreviewProps) => { Memory - + {integrationSelection.memory !== 0 ? `${integrationSelection.memory} Gi` : "-"} @@ -211,7 +189,7 @@ const SizePreview = ({ classes }: ISizePreviewProps) => { Drives per Server - + {integrationSelection.drivesPerServer !== 0 ? `${integrationSelection.drivesPerServer}` : "-"} @@ -221,7 +199,10 @@ const SizePreview = ({ classes }: ISizePreviewProps) => { Drive Size - + {integrationSelection.driveSize.driveSize} {integrationSelection.driveSize.sizeUnit} @@ -230,8 +211,8 @@ const SizePreview = ({ classes }: ISizePreviewProps) => {
)} -
+ ); }; -export default withStyles(styles)(SizePreview); +export default SizePreview; diff --git a/web-app/src/screens/Console/Tenants/AddTenant/Steps/TenantResources/NameTenantMain.tsx b/web-app/src/screens/Console/Tenants/AddTenant/Steps/TenantResources/NameTenantMain.tsx index d0e5d1e761a..6487ce67b07 100644 --- a/web-app/src/screens/Console/Tenants/AddTenant/Steps/TenantResources/NameTenantMain.tsx +++ b/web-app/src/screens/Console/Tenants/AddTenant/Steps/TenantResources/NameTenantMain.tsx @@ -16,22 +16,9 @@ import React, { Fragment, useCallback, useEffect } from "react"; import { useSelector } from "react-redux"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import withStyles from "@mui/styles/withStyles"; +import { Box, FormLayout, Grid, InputBox, Select } from "mds"; import get from "lodash/get"; -import Grid from "@mui/material/Grid"; -import { - formFieldStyles, - modalBasic, - wizardCommon, -} from "../../../../Common/FormComponents/common/styleLibrary"; import { AppState, useAppDispatch } from "../../../../../../store"; -import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; -import SelectWrapper from "../../../../Common/FormComponents/SelectWrapper/SelectWrapper"; -import SizePreview from "../SizePreview"; -import TenantSize from "./TenantSize"; -import { Paper, SelectChangeEvent } from "@mui/material"; import { IMkEnvs, mkPanelConfigurations } from "./utils"; import { isPageValid, @@ -40,23 +27,11 @@ import { updateAddField, } from "../../createTenantSlice"; import { selFeatures } from "../../../../consoleSlice"; +import SizePreview from "../SizePreview"; +import TenantSize from "./TenantSize"; import NamespaceSelector from "./NamespaceSelector"; import H3Section from "../../../../Common/H3Section"; -const styles = (theme: Theme) => - createStyles({ - sizePreview: { - marginLeft: 10, - background: "#FFFFFF", - border: "1px solid #EAEAEA", - padding: 2, - marginTop: 20, - }, - ...formFieldStyles, - ...modalBasic, - ...wizardCommon, - }); - const NameTenantField = () => { const dispatch = useAppDispatch(); const tenantName = useSelector( @@ -68,7 +43,7 @@ const NameTenantField = () => { ); return ( - ) => { @@ -83,11 +58,10 @@ const NameTenantField = () => { }; interface INameTenantMainScreen { - classes: any; formToRender?: IMkEnvs; } -const NameTenantMain = ({ classes, formToRender }: INameTenantMainScreen) => { +const NameTenantMain = ({ formToRender }: INameTenantMainScreen) => { const dispatch = useAppDispatch(); const selectedStorageClass = useSelector( @@ -124,67 +98,54 @@ const NameTenantMain = ({ classes, formToRender }: INameTenantMainScreen) => { return ( - + - - - -
- Name - - How would you like to name this new tenant? - -
-
- -
-
- - - + + + + Name + + How would you like to name this new tenant? + + + + {formToRender === IMkEnvs.default ? ( - - ) => { - updateField( - "selectedStorageClass", - e.target.value as string, - ); - }} - label="Storage Class" - value={selectedStorageClass} - options={storageClasses} - disabled={storageClasses.length < 1} - /> - + { + dispatch( + setStorageType({ + storageType: value, + features: features, + }), + ); + }} + label={get( + mkPanelConfigurations, + `${formToRender}.variantSelectorLabel`, + "Storage Type", + )} + value={selectedStorageType} + options={get( + mkPanelConfigurations, + `${formToRender}.variantSelectorValues`, + [], + )} + /> )} {formToRender === IMkEnvs.default ? ( @@ -195,17 +156,25 @@ const NameTenantMain = ({ classes, formToRender }: INameTenantMainScreen) => { null, ) )} -
-
+ +
- -
+ + -
+
); }; -export default withStyles(styles)(NameTenantMain); +export default NameTenantMain; diff --git a/web-app/src/screens/Console/Tenants/AddTenant/Steps/TenantResources/NamespaceSelector.tsx b/web-app/src/screens/Console/Tenants/AddTenant/Steps/TenantResources/NamespaceSelector.tsx index 8b55e5b2a07..5e34ef2a657 100644 --- a/web-app/src/screens/Console/Tenants/AddTenant/Steps/TenantResources/NamespaceSelector.tsx +++ b/web-app/src/screens/Console/Tenants/AddTenant/Steps/TenantResources/NamespaceSelector.tsx @@ -15,15 +15,14 @@ // along with this program. If not, see . import React, { Fragment, useEffect, useMemo } from "react"; -import { AddIcon } from "mds"; -import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; -import { openAddNSModal, setNamespace } from "../../createTenantSlice"; +import debounce from "lodash/debounce"; +import { AddIcon, InputBox } from "mds"; import { useSelector } from "react-redux"; +import { openAddNSModal, setNamespace } from "../../createTenantSlice"; import { AppState, useAppDispatch } from "../../../../../../store"; -import AddNamespaceModal from "../helpers/AddNamespaceModal"; -import debounce from "lodash/debounce"; import { IMkEnvs } from "./utils"; import { validateNamespaceAsync } from "../../thunks/namespaceThunks"; +import AddNamespaceModal from "../helpers/AddNamespaceModal"; const NamespaceSelector = ({ formToRender }: { formToRender?: IMkEnvs }) => { const dispatch = useAppDispatch(); @@ -66,7 +65,7 @@ const NamespaceSelector = ({ formToRender }: { formToRender?: IMkEnvs }) => { return ( {openAddNSConfirm && } - ) => { @@ -75,7 +74,6 @@ const NamespaceSelector = ({ formToRender }: { formToRender?: IMkEnvs }) => { label="Namespace" value={namespace} error={namespaceError || ""} - overlayId={"add-namespace"} overlayIcon={showNSCreateButton ? : null} overlayAction={addNamespace} required diff --git a/web-app/src/screens/Console/Tenants/AddTenant/Steps/TenantResources/TenantSize.tsx b/web-app/src/screens/Console/Tenants/AddTenant/Steps/TenantResources/TenantSize.tsx index 1471342e1d5..dc189d89a0a 100644 --- a/web-app/src/screens/Console/Tenants/AddTenant/Steps/TenantResources/TenantSize.tsx +++ b/web-app/src/screens/Console/Tenants/AddTenant/Steps/TenantResources/TenantSize.tsx @@ -16,17 +16,8 @@ import React, { Fragment, useCallback, useEffect, useState } from "react"; import { useSelector } from "react-redux"; -import { Theme } from "@mui/material/styles"; -import { SelectChangeEvent } from "@mui/material"; -import createStyles from "@mui/styles/createStyles"; -import withStyles from "@mui/styles/withStyles"; +import { Box, InputBox, Select } from "mds"; import { AppState, useAppDispatch } from "../../../../../../store"; -import { - formFieldStyles, - modalBasic, - wizardCommon, -} from "../../../../Common/FormComponents/common/styleLibrary"; -import Grid from "@mui/material/Grid"; import { calculateDistribution, erasureCodeCalc, @@ -38,28 +29,18 @@ import { clearValidationError } from "../../../utils"; import { ecListTransform } from "../../../ListTenants/utils"; import { ICapacity } from "../../../../../../common/types"; import { commonFormValidation } from "../../../../../../utils/validationFunctions"; +import { IMkEnvs } from "./utils"; +import { isPageValid, updateAddField } from "../../createTenantSlice"; import api from "../../../../../../common/api"; -import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; -import SelectWrapper from "../../../../Common/FormComponents/SelectWrapper/SelectWrapper"; import TenantSizeResources from "./TenantSizeResources"; import InputUnitMenu from "../../../../Common/FormComponents/InputUnitMenu/InputUnitMenu"; -import { IMkEnvs } from "./utils"; -import { isPageValid, updateAddField } from "../../createTenantSlice"; import H3Section from "../../../../Common/H3Section"; interface ITenantSizeProps { - classes: any; formToRender?: IMkEnvs; } -const styles = (theme: Theme) => - createStyles({ - ...formFieldStyles, - ...modalBasic, - ...wizardCommon, - }); - -const TenantSize = ({ classes, formToRender }: ITenantSizeProps) => { +const TenantSize = ({ formToRender }: ITenantSizeProps) => { const dispatch = useAppDispatch(); const volumeSize = useSelector( @@ -310,109 +291,92 @@ const TenantSize = ({ classes, formToRender }: ITenantSizeProps) => { return ( - -
- Capacity - - Please select the desired capacity - -
-
+ + Capacity + Please select the desired capacity + {distribution.error !== "" && ( - -
{distribution.error}
-
+ {distribution.error} )} - - ) => { - if (e.target.validity.valid) { - updateField("nodes", e.target.value); - cleanValidation("nodes"); - } - }} - label="Number of Servers" - disabled={selectedStorageClass === ""} - value={nodes} - min="4" - required - error={validationErrors["nodes"] || ""} - pattern={"[0-9]*"} - /> - - - ) => { - if (e.target.validity.valid) { - updateField("drivesPerServer", e.target.value); - cleanValidation("drivesps"); - } - }} - label="Drives per Server" - value={drivesPerServer} - disabled={selectedStorageClass === ""} - min="1" - required - error={validationErrors["drivesps"] || ""} - pattern={"[0-9]*"} - /> - - -
- ) => { - updateField("volumeSize", e.target.value); - cleanValidation("volume_size"); + ) => { + if (e.target.validity.valid) { + updateField("nodes", e.target.value); + cleanValidation("nodes"); + } + }} + label="Number of Servers" + disabled={selectedStorageClass === ""} + value={nodes} + min="4" + required + error={validationErrors["nodes"] || ""} + pattern={"[0-9]*"} + /> + ) => { + if (e.target.validity.valid) { + updateField("drivesPerServer", e.target.value); + cleanValidation("drivesps"); + } + }} + label="Drives per Server" + value={drivesPerServer} + disabled={selectedStorageClass === ""} + min="1" + required + error={validationErrors["drivesps"] || ""} + pattern={"[0-9]*"} + /> + ) => { + updateField("volumeSize", e.target.value); + cleanValidation("volume_size"); + }} + label="Total Size" + value={volumeSize} + disabled={selectedStorageClass === ""} + required + error={validationErrors["volume_size"] || ""} + min="0" + overlayObject={ + { + updateField("sizeFactor", newValue); }} - label="Total Size" - value={volumeSize} + unitSelected={sizeFactor} + unitsList={k8sScalarUnitsExcluding(["Ki", "Mi"])} disabled={selectedStorageClass === ""} - required - error={validationErrors["volume_size"] || ""} - min="0" - overlayObject={ - { - updateField("sizeFactor", newValue); - }} - unitSelected={sizeFactor} - unitsList={k8sScalarUnitsExcluding(["Ki", "Mi"])} - disabled={selectedStorageClass === ""} - /> - } /> -
-
- - - ) => { - updateField("ecParity", e.target.value as string); - }} - label="Erasure Code Parity" - disabled={selectedStorageClass === ""} - value={ecParity} - options={ecParityChoices} - /> - - Please select the desired parity. This setting will change the max - usable capacity in the cluster - - + } + /> +