Migrated Register page components to mds (#3034)

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
Alex
2023-09-07 11:48:29 -06:00
committed by GitHub
parent 8dd94f5336
commit 698f72f828
14 changed files with 503 additions and 996 deletions

View File

@@ -18,14 +18,14 @@ import React, { Fragment } from "react";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { selectorTypes } from "../SelectWrapper/SelectWrapper";
import { SelectorType } from "mds";
import { Menu, MenuItem } from "@mui/material";
interface IInputUnitBox {
classes: any;
id: string;
unitSelected: string;
unitsList: selectorTypes[];
unitsList: SelectorType[];
disabled?: boolean;
onUnitChange?: (newValue: string) => void;
}

View File

@@ -1,144 +0,0 @@
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import Grid from "@mui/material/Grid";
import {
FormControl,
InputBase,
InputLabel,
MenuItem,
Select,
SelectChangeEvent,
Tooltip,
} from "@mui/material";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { fieldBasic, tooltipHelper } from "../common/styleLibrary";
import { HelpIcon } from "mds";
export interface selectorTypes {
label: string;
value: string;
}
interface SelectProps {
options: selectorTypes[];
value: string;
label: string;
id: string;
name: string;
tooltip?: string;
onChange: (e: SelectChangeEvent<string>) => void;
disabled?: boolean;
classes: any;
}
const styles = (theme: Theme) =>
createStyles({
...fieldBasic,
...tooltipHelper,
fieldContainer: {
display: "flex",
"@media (max-width: 600px)": {
flexFlow: "column",
},
},
});
const SelectStyled = withStyles((theme: Theme) =>
createStyles({
root: {
height: 38,
lineHeight: 1,
"label + &": {
marginTop: theme.spacing(3),
},
},
input: {
height: 38,
position: "relative",
color: "#07193E",
fontSize: 13,
fontWeight: 600,
padding: "8px 20px 10px 10px",
border: "#e5e5e5 1px solid",
borderRadius: 4,
display: "flex",
alignItems: "center",
"&:hover": {
borderColor: "#393939",
},
"&:focus": {
backgroundColor: "#fff",
},
},
}),
)(InputBase);
const SelectWrapper = ({
classes,
id,
name,
onChange,
options,
label,
tooltip = "",
value,
disabled = false,
}: SelectProps) => {
return (
<React.Fragment>
<Grid item xs={12} className={classes.fieldContainer}>
{label !== "" && (
<InputLabel htmlFor={id} className={classes.inputLabel}>
<span>{label}</span>
{tooltip !== "" && (
<div className={classes.tooltipContainer}>
<Tooltip title={tooltip} placement="top-start">
<div className={classes.tooltip}>
<HelpIcon />
</div>
</Tooltip>
</div>
)}
</InputLabel>
)}
<FormControl fullWidth>
<Select
id={id}
name={name}
value={value}
onChange={onChange}
input={<SelectStyled />}
disabled={disabled}
>
{options.map((option) => (
<MenuItem
value={option.value}
key={`select-${name}-${option.label}`}
>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
</React.Fragment>
);
};
export default withStyles(styles)(SelectWrapper);

View File

@@ -14,42 +14,27 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment, useCallback, useEffect, useState } from "react";
import { Box } from "@mui/material";
import { Button, OnlineRegistrationIcon } from "mds";
import { FormTitle } from "./utils";
import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import GetApiKeyModal from "./GetApiKeyModal";
import RegisterHelpBox from "./RegisterHelpBox";
import React, { useCallback, useEffect, useState } from "react";
import { Box, Button, FormLayout, InputBox, OnlineRegistrationIcon } from "mds";
import { useNavigate } from "react-router-dom";
import { SubnetLoginRequest, SubnetLoginResponse } from "../License/types";
import api from "../../../common/api";
import { useAppDispatch } from "../../../store";
import {
setErrorSnackMessage,
setServerNeedsRestart,
} from "../../../systemSlice";
import { ErrorResponseHandler } from "../../../common/types";
import { spacingUtils } from "../Common/FormComponents/common/styleLibrary";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { useNavigate } from "react-router-dom";
import { modalStyleUtils } from "../Common/FormComponents/common/styleLibrary";
import { IAM_PAGES } from "../../../common/SecureComponent/permissions";
import GetApiKeyModal from "./GetApiKeyModal";
import RegisterHelpBox from "./RegisterHelpBox";
import api from "../../../common/api";
interface IApiKeyRegister {
classes: any;
registerEndpoint: string;
}
const styles = (theme: Theme) =>
createStyles({
sizedLabel: {
minWidth: "75px",
},
...spacingUtils,
});
const ApiKeyRegister = ({ classes, registerEndpoint }: IApiKeyRegister) => {
const ApiKeyRegister = ({ registerEndpoint }: IApiKeyRegister) => {
const navigate = useNavigate();
const [showApiKeyModal, setShowApiKeyModal] = useState(false);
@@ -92,108 +77,66 @@ const ApiKeyRegister = ({ classes, registerEndpoint }: IApiKeyRegister) => {
};
return (
<Fragment>
<Box
sx={{
"& .title-text": {
marginLeft: "27px",
fontWeight: 600,
},
}}
>
<FormTitle
icon={<OnlineRegistrationIcon />}
title={`Register cluster with API key`}
/>
</Box>
<FormLayout
title={"Register cluster with API key"}
icon={<OnlineRegistrationIcon />}
containerPadding={false}
withBorders={false}
helpBox={<RegisterHelpBox />}
>
<Box
sx={{
fontSize: 14,
display: "flex",
flexFlow: {
xs: "column",
md: "row",
},
flexFlow: "column",
marginBottom: "30px",
}}
>
<Box
sx={{
display: "flex",
flexFlow: "column",
flex: "2",
}}
>
<Box
sx={{
fontSize: "16px",
display: "flex",
flexFlow: "column",
marginTop: "30px",
marginBottom: "30px",
}}
>
Use your MinIO Subscription Network API Key to register this
cluster.
</Box>
<Box
sx={{
flex: "1",
}}
>
<InputBoxWrapper
className={classes.spacerBottom}
classes={{
inputLabel: classes.sizedLabel,
}}
id="api-key"
name="api-key"
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
setApiKey(event.target.value)
}
label="API Key"
value={apiKey}
/>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
"& button": {
marginLeft: "8px",
},
}}
>
<Button
id={"get-from-subnet"}
variant="regular"
className={classes.spacerRight}
disabled={loading}
onClick={() => setShowApiKeyModal(true)}
label={"Get from SUBNET"}
/>
<Button
id={"register"}
type="submit"
variant="callAction"
disabled={loading || apiKey.trim().length === 0}
onClick={() => onRegister()}
label={"Register"}
/>
<GetApiKeyModal
open={showApiKeyModal}
closeModal={() => setShowApiKeyModal(false)}
onSet={(value) => {
setApiKey(value);
setFromModal(true);
}}
/>
</Box>
</Box>
</Box>
<RegisterHelpBox />
Use your MinIO Subscription Network API Key to register this cluster.
</Box>
</Fragment>
<Box
sx={{
flex: "1",
}}
>
<InputBox
id="api-key"
name="api-key"
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
setApiKey(event.target.value)
}
label="API Key"
value={apiKey}
/>
<Box sx={modalStyleUtils.modalButtonBar}>
<Button
id={"get-from-subnet"}
variant="regular"
disabled={loading}
onClick={() => setShowApiKeyModal(true)}
label={"Get from SUBNET"}
/>
<Button
id={"register"}
type="submit"
variant="callAction"
disabled={loading || apiKey.trim().length === 0}
onClick={() => onRegister()}
label={"Register"}
/>
</Box>
</Box>
<GetApiKeyModal
open={showApiKeyModal}
closeModal={() => setShowApiKeyModal(false)}
onSet={(value) => {
setApiKey(value);
setFromModal(true);
}}
/>
</FormLayout>
);
};
export default withStyles(styles)(ApiKeyRegister);
export default ApiKeyRegister;

View File

@@ -15,15 +15,13 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { Box } from "@mui/material";
import { FormTitle } from "./utils";
import SelectWrapper from "../Common/FormComponents/SelectWrapper/SelectWrapper";
import { Box, Button, FormLayout, Select } from "mds";
import { setLoading, setSelectedSubnetOrganization } from "./registerSlice";
import { Button } from "mds";
import RegisterHelpBox from "./RegisterHelpBox";
import { useSelector } from "react-redux";
import { AppState, useAppDispatch } from "../../../store";
import { callRegister } from "./registerThunks";
import { modalStyleUtils } from "../Common/FormComponents/common/styleLibrary";
import RegisterHelpBox from "./RegisterHelpBox";
const ClusterRegistrationForm = () => {
const dispatch = useAppDispatch();
@@ -40,76 +38,48 @@ const ClusterRegistrationForm = () => {
const loading = useSelector((state: AppState) => state.register.loading);
return (
<Box
sx={{
display: "flex",
}}
<FormLayout
title={"Register MinIO cluster"}
containerPadding
withBorders={false}
helpBox={<RegisterHelpBox />}
>
<Box
sx={{
display: "flex",
flexFlow: "column",
flex: "2",
}}
>
<Box
sx={{
marginTop: "15px",
marginBottom: "15px",
"& .title-text": {
marginLeft: "0px",
},
}}
>
<FormTitle title={`Register MinIO cluster`} />
</Box>
<Box>
<SelectWrapper
id="subnet-organization"
name="subnet-organization"
onChange={(e) =>
dispatch(setSelectedSubnetOrganization(e.target.value as string))
<Select
id="subnet-organization"
name="subnet-organization"
onChange={(value) =>
dispatch(setSelectedSubnetOrganization(value as string))
}
label="Select an organization"
value={selectedSubnetOrganization}
options={subnetOrganizations.map((organization) => ({
label: organization.company,
value: organization.accountId.toString(),
}))}
/>
<Box sx={modalStyleUtils.modalButtonBar}>
<Button
id={"register-cluster"}
onClick={() => () => {
if (loading) {
return;
}
label="Select an organization"
value={selectedSubnetOrganization}
options={subnetOrganizations.map((organization) => ({
label: organization.company,
value: organization.accountId.toString(),
}))}
/>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
marginTop: "15px",
}}
>
<Button
id={"register-cluster"}
onClick={() => () => {
if (loading) {
return;
}
dispatch(setLoading(true));
if (subnetAccessToken && selectedSubnetOrganization) {
dispatch(
callRegister({
token: subnetAccessToken,
account_id: selectedSubnetOrganization,
}),
);
}
}}
disabled={loading || subnetAccessToken.trim().length === 0}
variant="callAction"
label={"Register"}
/>
</Box>
</Box>
dispatch(setLoading(true));
if (subnetAccessToken && selectedSubnetOrganization) {
dispatch(
callRegister({
token: subnetAccessToken,
account_id: selectedSubnetOrganization,
}),
);
}
}}
disabled={loading || subnetAccessToken.trim().length === 0}
variant="callAction"
label={"Register"}
/>
</Box>
<RegisterHelpBox />
</Box>
</FormLayout>
);
};

View File

@@ -14,52 +14,24 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import RemoveRedEyeIcon from "@mui/icons-material/RemoveRedEye";
import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
import {
containerForHeader,
spacingUtils,
} from "../Common/FormComponents/common/styleLibrary";
import ConfirmDialog from "../Common/ModalWrapper/ConfirmDialog";
import useApi from "../Common/Hooks/useApi";
import React, { useState } from "react";
import { InfoIcon, UsersIcon } from "mds";
import { Box, FormLayout, InfoIcon, InputBox, LockIcon, UsersIcon } from "mds";
import { ErrorResponseHandler } from "../../../common/types";
import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import { useAppDispatch } from "../../../store";
import { setErrorSnackMessage } from "../../../systemSlice";
import { Box } from "@mui/material";
const styles = (theme: Theme) =>
createStyles({
sizedLabel: {
minWidth: "75px",
},
...containerForHeader,
...spacingUtils,
});
import ConfirmDialog from "../Common/ModalWrapper/ConfirmDialog";
import useApi from "../Common/Hooks/useApi";
interface IGetApiKeyModalProps {
open: boolean;
closeModal: () => void;
onSet: (apiKey: string) => void;
classes: any;
}
const GetApiKeyModal = ({
open,
closeModal,
classes,
onSet,
}: IGetApiKeyModalProps) => {
const GetApiKeyModal = ({ open, closeModal, onSet }: IGetApiKeyModalProps) => {
const dispatch = useAppDispatch();
const [email, setEmail] = useState<string>("");
const [password, setPassword] = useState("");
const [showPassword, setShowPassword] = useState(false);
const [mfaToken, setMfaToken] = useState("");
const [subnetOTP, setSubnetOTP] = useState("");
@@ -68,7 +40,6 @@ const GetApiKeyModal = ({
closeModal();
setEmail("");
setPassword("");
setShowPassword(false);
setMfaToken("");
setSubnetOTP("");
};
@@ -107,12 +78,8 @@ const GetApiKeyModal = ({
const getCredentialsDialog = () => {
return (
<Box sx={{ width: 500 }}>
<InputBoxWrapper
className={classes.spacerBottom}
classes={{
inputLabel: classes.sizedLabel,
}}
<FormLayout withBorders={false} containerPadding={false}>
<InputBox
id="subnet-email"
name="subnet-email"
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
@@ -122,25 +89,17 @@ const GetApiKeyModal = ({
value={email}
overlayIcon={<UsersIcon />}
/>
<InputBoxWrapper
className={classes.spacerBottom}
classes={{
inputLabel: classes.sizedLabel,
}}
<InputBox
id="subnet-password"
name="subnet-password"
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
setPassword(event.target.value)
}
label="Password"
type={showPassword ? "text" : "password"}
type={"password"}
value={password}
overlayIcon={
showPassword ? <VisibilityOffIcon /> : <RemoveRedEyeIcon />
}
overlayAction={() => setShowPassword(!showPassword)}
/>
</Box>
</FormLayout>
);
};
@@ -150,11 +109,11 @@ const GetApiKeyModal = ({
<Box sx={{ display: "flex", flexFlow: "column", flex: "2" }}>
<Box
sx={{
fontSize: "16px",
fontSize: 14,
display: "flex",
flexFlow: "column",
marginTop: "30px",
marginBottom: "30px",
marginTop: 20,
marginBottom: 20,
}}
>
Two-Factor Authentication
@@ -171,8 +130,8 @@ const GetApiKeyModal = ({
marginTop: "30px",
}}
>
<InputBoxWrapper
overlayIcon={<LockOutlinedIcon />}
<InputBox
overlayIcon={<LockIcon />}
id="subnet-otp"
name="subnet-otp"
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
@@ -183,13 +142,6 @@ const GetApiKeyModal = ({
value={subnetOTP}
/>
</Box>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
}}
></Box>
</Box>
</Box>
);
@@ -218,4 +170,4 @@ const GetApiKeyModal = ({
) : null;
};
export default withStyles(styles)(GetApiKeyModal);
export default GetApiKeyModal;

View File

@@ -15,21 +15,27 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment, useState } from "react";
import { Box, Link } from "@mui/material";
import { ClusterRegistered, FormTitle } from "./utils";
import { Button, CopyIcon, OfflineRegistrationIcon } from "mds";
import TooltipWrapper from "../Common/TooltipWrapper/TooltipWrapper";
import CopyToClipboard from "react-copy-to-clipboard";
import RegisterHelpBox from "./RegisterHelpBox";
import {
Box,
Button,
CommentBox,
CopyIcon,
FormLayout,
OfflineRegistrationIcon,
} from "mds";
import { ClusterRegistered } from "./utils";
import { AppState, useAppDispatch } from "../../../store";
import { useSelector } from "react-redux";
import CommentBoxWrapper from "../Common/FormComponents/CommentBoxWrapper/CommentBoxWrapper";
import useApi from "../Common/Hooks/useApi";
import { fetchLicenseInfo } from "./registerThunks";
import {
setErrorSnackMessage,
setServerNeedsRestart,
} from "../../../systemSlice";
import { modalStyleUtils } from "../Common/FormComponents/common/styleLibrary";
import TooltipWrapper from "../Common/TooltipWrapper/TooltipWrapper";
import CopyToClipboard from "react-copy-to-clipboard";
import RegisterHelpBox from "./RegisterHelpBox";
import useApi from "../Common/Hooks/useApi";
const OfflineRegistration = () => {
const dispatch = useAppDispatch();
@@ -66,9 +72,8 @@ const OfflineRegistration = () => {
return (
<Fragment>
<Box
withBorders
sx={{
border: "1px solid #eaeaea",
borderRadius: "2px",
display: "flex",
flexFlow: "column",
padding: "43px",
@@ -77,146 +82,105 @@ const OfflineRegistration = () => {
{clusterRegistered && licenseInfo ? (
<ClusterRegistered email={licenseInfo.email} />
) : (
<Fragment>
<Box
sx={{
"& .title-text": {
marginLeft: "27px",
fontWeight: 600,
},
}}
>
<FormTitle
icon={<OfflineRegistrationIcon />}
title={`Register cluster in an Air-gap environment`}
/>
</Box>
<FormLayout
title={"Register cluster in an Air-gap environment"}
icon={<OfflineRegistrationIcon />}
helpBox={<RegisterHelpBox />}
withBorders={false}
containerPadding={false}
>
<Box
sx={{
display: "flex",
flexFlow: "column",
flex: "2",
marginTop: "15px",
"& .step-row": {
fontSize: 14,
display: "flex",
marginTop: "15px",
marginBottom: "15px",
},
}}
>
<Box
sx={{
display: "flex",
flexFlow: "column",
flex: "2",
marginTop: "15px",
"& .step-number": {
color: "#ffffff",
height: "25px",
width: "25px",
background: "#081C42",
marginRight: "10px",
textAlign: "center",
fontWeight: 600,
borderRadius: "50%",
},
"& .step-row": {
fontSize: "16px",
display: "flex",
marginTop: "15px",
marginBottom: "15px",
},
}}
>
<Box>
<Box className="step-row">
<div className="step-text">
Click on the link to register this cluster in SUBNET and
get a License Key for this Air-Gap deployment
</div>
</Box>
<Box
sx={{
flex: "1",
display: "flex",
alignItems: "center",
gap: 3,
}}
>
<Link
style={{
color: "#2781B0",
cursor: "pointer",
}}
color="inherit"
href={offlineRegUrl}
target="_blank"
>
https://subnet.min.io/cluster/register
</Link>
<TooltipWrapper tooltip={"Copy to Clipboard"}>
<CopyToClipboard text={offlineRegUrl}>
<Button
type={"button"}
id={"copy-ult-to-clip-board"}
icon={<CopyIcon />}
color={"primary"}
variant={"regular"}
/>
</CopyToClipboard>
</TooltipWrapper>
</Box>
<div
style={{
marginTop: "25px",
fontSize: "14px",
fontStyle: "italic",
color: "#5E5E5E",
}}
>
Note: If this machine does not have internet connection,
Copy paste the following URL in a browser where you access
SUBNET and follow the instructions to complete the
registration
</div>
<Box
sx={{
marginTop: "25px",
display: "flex",
flexDirection: "column",
}}
>
<label style={{ fontWeight: "bold", marginBottom: "10px" }}>
Paste the License Key{" "}
</label>
<CommentBoxWrapper
value={licenseKey}
disabled={isSaving}
label={""}
id={"licenseKey"}
name={"licenseKey"}
placeholder={"License Key"}
onChange={(e) => {
setLicenseKey(e.target.value);
}}
/>
</Box>
<Box
sx={{
marginTop: "25px",
}}
>
<Button
id={"apply-license-key"}
onClick={applyAirGapLicense}
variant={"callAction"}
disabled={!licenseKey || isSaving}
label={"Apply Cluster License"}
/>
<Box>
<Box className="step-row">
<Box className="step-text">
Click on the link to register this cluster in SUBNET and get
a License Key for this Air-Gap deployment
</Box>
</Box>
<Box
sx={{
flex: "1",
display: "flex",
alignItems: "center",
gap: 3,
}}
>
<a href={offlineRegUrl} target="_blank">
https://subnet.min.io/cluster/register
</a>
<TooltipWrapper tooltip={"Copy to Clipboard"}>
<CopyToClipboard text={offlineRegUrl}>
<Button
type={"button"}
id={"copy-ult-to-clip-board"}
icon={<CopyIcon />}
color={"primary"}
variant={"regular"}
/>
</CopyToClipboard>
</TooltipWrapper>
</Box>
<Box
className={"muted"}
sx={{
marginTop: "25px",
}}
>
Note: If this machine does not have internet connection, Copy
paste the following URL in a browser where you access SUBNET
and follow the instructions to complete the registration
</Box>
<Box
sx={{
marginTop: "25px",
display: "flex",
flexDirection: "column",
}}
>
<label style={{ fontWeight: "bold", marginBottom: "10px" }}>
Paste the License Key{" "}
</label>
<CommentBox
value={licenseKey}
disabled={isSaving}
label={""}
id={"licenseKey"}
name={"licenseKey"}
placeholder={"License Key"}
onChange={(e) => {
setLicenseKey(e.target.value);
}}
/>
</Box>
<Box sx={modalStyleUtils.modalButtonBar}>
<Button
id={"apply-license-key"}
onClick={applyAirGapLicense}
variant={"callAction"}
disabled={!licenseKey || isSaving}
label={"Apply Cluster License"}
/>
</Box>
</Box>
<RegisterHelpBox />
</Box>
</Fragment>
</FormLayout>
)}
</Box>
</Fragment>

View File

@@ -14,38 +14,23 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment } from "react";
import { Box } from "@mui/material";
import { FormTitle } from "./utils";
import { Button, OnlineRegistrationIcon, UsersIcon } from "mds";
import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
import RemoveRedEyeIcon from "@mui/icons-material/RemoveRedEye";
import React from "react";
import {
Box,
Button,
FormLayout,
InputBox,
OnlineRegistrationIcon,
UsersIcon,
} from "mds";
import RegisterHelpBox from "./RegisterHelpBox";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import { spacingUtils } from "../Common/FormComponents/common/styleLibrary";
import makeStyles from "@mui/styles/makeStyles";
import { modalStyleUtils } from "../Common/FormComponents/common/styleLibrary";
import { useSelector } from "react-redux";
import { AppState, useAppDispatch } from "../../../store";
import {
setShowPassword,
setSubnetEmail,
setSubnetPassword,
} from "./registerSlice";
import { setSubnetEmail, setSubnetPassword } from "./registerSlice";
import { subnetLogin } from "./registerThunks";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
sizedLabel: {
minWidth: "75px",
},
...spacingUtils,
}),
);
const OnlineRegistration = () => {
const classes = useStyles();
const dispatch = useAppDispatch();
const subnetPassword = useSelector(
@@ -54,131 +39,79 @@ const OnlineRegistration = () => {
const subnetEmail = useSelector(
(state: AppState) => state.register.subnetEmail,
);
const showPassword = useSelector(
(state: AppState) => state.register.showPassword,
);
const loading = useSelector((state: AppState) => state.register.loading);
return (
<Fragment>
<Box
sx={{
"& .title-text": {
marginLeft: "27px",
fontWeight: 600,
},
}}
>
<FormTitle
icon={<OnlineRegistrationIcon />}
title={`Online activation of MinIO Subscription Network License`}
/>
</Box>
<FormLayout
icon={<OnlineRegistrationIcon />}
title={"Online activation of MinIO Subscription Network License"}
withBorders={false}
containerPadding={false}
helpBox={<RegisterHelpBox />}
>
<Box
sx={{
fontSize: "14px",
display: "flex",
flexFlow: {
xs: "column",
md: "row",
},
flexFlow: "column",
marginBottom: "30px",
}}
>
<Box
sx={{
display: "flex",
flexFlow: "column",
flex: "2",
}}
>
<Box
sx={{
fontSize: "16px",
display: "flex",
flexFlow: "column",
marginTop: "30px",
marginBottom: "30px",
}}
>
Use your MinIO Subscription Network login credentials to register
this cluster.
</Box>
<Box
sx={{
flex: "1",
}}
>
<InputBoxWrapper
className={classes.spacerBottom}
classes={{
inputLabel: classes.sizedLabel,
}}
id="subnet-email"
name="subnet-email"
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
dispatch(setSubnetEmail(event.target.value))
}
label="Email"
value={subnetEmail}
overlayIcon={<UsersIcon />}
/>
<InputBoxWrapper
className={classes.spacerBottom}
classes={{
inputLabel: classes.sizedLabel,
}}
id="subnet-password"
name="subnet-password"
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
dispatch(setSubnetPassword(event.target.value))
}
label="Password"
type={showPassword ? "text" : "password"}
value={subnetPassword}
overlayIcon={
showPassword ? <VisibilityOffIcon /> : <RemoveRedEyeIcon />
}
overlayAction={() => dispatch(setShowPassword(!showPassword))}
/>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
"& button": {
marginLeft: "8px",
},
}}
>
<Button
id={"sign-up"}
type="submit"
className={classes.spacerRight}
variant="regular"
onClick={(e) => {
e.preventDefault();
window.open(`https://min.io/signup?ref=con`, "_blank");
}}
label={"Sign up"}
/>
<Button
id={"register-credentials"}
type="submit"
variant="callAction"
disabled={
loading ||
subnetEmail.trim().length === 0 ||
subnetPassword.trim().length === 0
}
onClick={() => dispatch(subnetLogin())}
label={"Register"}
/>
</Box>
</Box>
</Box>
<RegisterHelpBox />
Use your MinIO Subscription Network login credentials to register this
cluster.
</Box>
</Fragment>
<Box
sx={{
flex: "1",
}}
>
<InputBox
id="subnet-email"
name="subnet-email"
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
dispatch(setSubnetEmail(event.target.value))
}
label="Email"
value={subnetEmail}
overlayIcon={<UsersIcon />}
/>
<InputBox
id="subnet-password"
name="subnet-password"
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
dispatch(setSubnetPassword(event.target.value))
}
label="Password"
type={"password"}
value={subnetPassword}
/>
<Box sx={modalStyleUtils.modalButtonBar}>
<Button
id={"sign-up"}
type="submit"
variant="regular"
onClick={(e) => {
e.preventDefault();
window.open(`https://min.io/signup?ref=con`, "_blank");
}}
label={"Sign up"}
/>
<Button
id={"register-credentials"}
type="submit"
variant="callAction"
disabled={
loading ||
subnetEmail.trim().length === 0 ||
subnetPassword.trim().length === 0
}
onClick={() => dispatch(subnetLogin())}
label={"Register"}
/>
</Box>
</Box>
</FormLayout>
);
};

View File

@@ -15,23 +15,13 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment, useEffect, useState } from "react";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import { spacingUtils } from "../Common/FormComponents/common/styleLibrary";
import withStyles from "@mui/styles/withStyles";
import { Box } from "@mui/material";
import api from "../../../common/api";
import { Box, PageLayout, Tabs } from "mds";
import { SubnetRegTokenResponse } from "../License/types";
import { ErrorResponseHandler } from "../../../common/types";
import { useSelector } from "react-redux";
import { setErrorSnackMessage, setHelpName } from "../../../systemSlice";
import { AppState, useAppDispatch } from "../../../store";
import Tabs from "@mui/material/Tabs";
import Tab from "@mui/material/Tab";
import { TabPanel } from "../../shared/tabs";
import { ClusterRegistered, ProxyConfiguration } from "./utils";
import ApiKeyRegister from "./ApiKeyRegister";
import { fetchLicenseInfo } from "./registerThunks";
import {
resetRegisterForm,
@@ -44,22 +34,11 @@ import SubnetMFAToken from "./SubnetMFAToken";
import ClusterRegistrationForm from "./ClusterRegistrationForm";
import OnlineRegistration from "./OnlineRegistration";
import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper";
import { PageLayout } from "mds";
import HelpMenu from "../HelpMenu";
import api from "../../../common/api";
import ApiKeyRegister from "./ApiKeyRegister";
interface IRegister {
classes: any;
}
const styles = (theme: Theme) =>
createStyles({
sizedLabel: {
minWidth: "75px",
},
...spacingUtils,
});
const Register = ({ classes }: IRegister) => {
const Register = () => {
const dispatch = useAppDispatch();
const subnetMFAToken = useSelector(
@@ -98,25 +77,27 @@ const Register = ({ classes }: IRegister) => {
};
}, [dispatch]);
const fetchSubnetRegToken = () => {
if (loading || subnetRegToken) {
return;
useEffect(() => {
if (curTab === "simple-tab-2" && !loading && !subnetRegToken) {
const fetchSubnetRegToken = () => {
dispatch(setLoading(true));
api
.invoke("GET", "/api/v1/subnet/registration-token")
.then((resp: SubnetRegTokenResponse) => {
dispatch(setLoading(false));
if (resp && resp.regToken) {
dispatch(setSubnetRegToken(resp.regToken));
}
})
.catch((err: ErrorResponseHandler) => {
console.error(err);
dispatch(setErrorSnackMessage(err));
dispatch(setLoading(false));
});
};
fetchSubnetRegToken();
}
dispatch(setLoading(true));
api
.invoke("GET", "/api/v1/subnet/registration-token")
.then((resp: SubnetRegTokenResponse) => {
dispatch(setLoading(false));
if (resp && resp.regToken) {
dispatch(setSubnetRegToken(resp.regToken));
}
})
.catch((err: ErrorResponseHandler) => {
console.error(err);
dispatch(setErrorSnackMessage(err));
dispatch(setLoading(false));
});
};
}, [curTab, loading, subnetRegToken, dispatch]);
useEffect(() => {
if (initialLicenseLoading) {
@@ -125,7 +106,7 @@ const Register = ({ classes }: IRegister) => {
}
}, [initialLicenseLoading, setInitialLicenseLoading, dispatch]);
let clusterRegistrationForm: JSX.Element = <Fragment />;
let clusterRegistrationForm: React.ReactElement = <Fragment />;
if (subnetAccessToken && subnetOrganizations.length > 0) {
clusterRegistrationForm = <ClusterRegistrationForm />;
@@ -138,9 +119,8 @@ const Register = ({ classes }: IRegister) => {
const apiKeyRegistration = (
<Fragment>
<Box
withBorders
sx={{
border: "1px solid #eaeaea",
borderRadius: "2px",
display: "flex",
flexFlow: "column",
padding: "43px",
@@ -161,9 +141,8 @@ const Register = ({ classes }: IRegister) => {
const regUi = (
<Fragment>
<Box
withBorders
sx={{
border: "1px solid #eaeaea",
borderRadius: "2px",
display: "flex",
flexFlow: "column",
padding: "43px",
@@ -197,46 +176,38 @@ const Register = ({ classes }: IRegister) => {
<PageLayout>
<Tabs
value={curTab}
onChange={(e: React.ChangeEvent<{}>, newValue: number) => {
horizontal
currentTabOrPath={curTab}
onTabClick={(newValue: string) => {
dispatch(setCurTab(newValue));
}}
indicatorColor="primary"
textColor="primary"
aria-label="cluster-tabs"
variant="scrollable"
scrollButtons="auto"
>
<Tab
label="Credentials"
id="simple-tab-0"
aria-controls="simple-tab-panel-0"
/>
<Tab
label="API Key"
id="simple-tab-1"
aria-controls="simple-tab-panel-1"
/>
<Tab
label="Air-Gap"
id="simple-tab-2"
aria-controls="simple-tab-panel-2"
onClick={() => fetchSubnetRegToken()}
/>
</Tabs>
<TabPanel index={0} value={curTab}>
{uiToShow}
</TabPanel>
<TabPanel index={1} value={curTab}>
{apiKeyRegistration}
</TabPanel>
<TabPanel index={2} value={curTab}>
{offlineRegistration}
</TabPanel>
options={[
{
tabConfig: {
label: "Credentials",
id: "simple-tab-0",
},
content: uiToShow,
},
{
tabConfig: {
label: "API Key",
id: "simple-tab-1",
},
content: apiKeyRegistration,
},
{
tabConfig: {
label: "Air-Gap",
id: "simple-tab-2",
},
content: offlineRegistration,
},
]}
/>
</PageLayout>
</Fragment>
);
};
export default withStyles(styles)(Register);
export default Register;

View File

@@ -16,8 +16,7 @@
import React, { Fragment } from "react";
import { useNavigate } from "react-router-dom";
import { Box } from "@mui/material";
import { Button, Grid, HelpBox, WarnIcon } from "mds";
import { Box, breakPoints, Button, Grid, HelpBox, WarnIcon } from "mds";
interface IRegisterCluster {
compactMode?: boolean;
@@ -81,11 +80,11 @@ const RegisterCluster = ({ compactMode = false }: IRegisterCluster) => {
display: "flex",
alignItems: "center",
justifyContent: "center",
flexFlow: {
sm: "row",
xs: "column",
},
flexFlow: "row",
marginBottom: "15px",
[`@media (max-width: ${breakPoints.sm}px)`]: {
flexFlow: "column",
},
}}
>
<Grid container>
@@ -113,9 +112,9 @@ const RegisterCluster = ({ compactMode = false }: IRegisterCluster) => {
<Box
sx={{
display: "flex",
flexFlow: {
xs: "column",
md: "row",
flexFlow: "row",
[`@media (max-width: ${breakPoints.sm}px)`]: {
flexFlow: "column",
},
}}
>

View File

@@ -14,14 +14,15 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { Box, Link } from "@mui/material";
import React, { Fragment } from "react";
import {
CallHomeFeatureIcon,
DiagnosticsFeatureIcon,
ExtraFeaturesIcon,
HelpIconFilled,
PerformanceFeatureIcon,
Box,
HelpBox,
} from "mds";
const FeatureItem = ({
@@ -44,92 +45,55 @@ const FeatureItem = ({
}}
>
{icon}{" "}
<div style={{ fontSize: "14px", fontStyle: "italic", color: "#5E5E5E" }}>
<Box className="muted" style={{ fontSize: "14px", fontStyle: "italic" }}>
{description}
</div>
</Box>
</Box>
);
};
const RegisterHelpBox = ({ hasMargin = true }: { hasMargin?: boolean }) => {
const RegisterHelpBox = () => {
return (
<Box
sx={{
flex: 1,
border: "1px solid #eaeaea",
borderRadius: "2px",
display: "flex",
flexFlow: "column",
padding: "20px",
marginLeft: {
xs: "0px",
sm: "0px",
md: hasMargin ? "30px" : "",
},
marginTop: {
xs: "0px",
sm: hasMargin ? "30px" : "",
},
}}
>
<Box
sx={{
fontSize: "16px",
fontWeight: 600,
display: "flex",
alignItems: "center",
marginBottom: "16px",
<HelpBox
title={"Why should I register?"}
iconComponent={<HelpIconFilled />}
help={
<Fragment>
<Box sx={{ fontSize: "14px", marginBottom: "15px" }}>
Registering this cluster with the MinIO Subscription Network
(SUBNET) provides the following benefits in addition to the
commercial license and SLA backed support.
</Box>
"& .min-icon": {
height: "21px",
width: "21px",
marginRight: "15px",
},
}}
>
<HelpIconFilled />
<div>Why should I register?</div>
</Box>
<Box sx={{ fontSize: "14px", marginBottom: "15px" }}>
Registering this cluster with the MinIO Subscription Network (SUBNET)
provides the following benefits in addition to the commercial license
and SLA backed support.
</Box>
<Box
sx={{
display: "flex",
flexFlow: "column",
}}
>
<FeatureItem
icon={<CallHomeFeatureIcon />}
description={`Call Home Monitoring`}
/>
<FeatureItem
icon={<DiagnosticsFeatureIcon />}
description={`Health Diagnostics`}
/>
<FeatureItem
icon={<PerformanceFeatureIcon />}
description={`Performance Analysis`}
/>
<FeatureItem
icon={<ExtraFeaturesIcon />}
description={
<Link
href="https://min.io/signup?ref=con"
target="_blank"
sx={{
color: "#2781B0",
cursor: "pointer",
}}
>
More Features
</Link>
}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
flexFlow: "column",
}}
>
<FeatureItem
icon={<CallHomeFeatureIcon />}
description={`Call Home Monitoring`}
/>
<FeatureItem
icon={<DiagnosticsFeatureIcon />}
description={`Health Diagnostics`}
/>
<FeatureItem
icon={<PerformanceFeatureIcon />}
description={`Performance Analysis`}
/>
<FeatureItem
icon={<ExtraFeaturesIcon />}
description={
<a href="https://min.io/signup?ref=con" target="_blank">
More Features
</a>
}
/>
</Box>
</Fragment>
}
/>
);
};

View File

@@ -1,17 +1,32 @@
// This file is part of MinIO Console Server
// 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 <http://www.gnu.org/licenses/>.
import React from "react";
import { Box } from "@mui/material";
import { VerifiedIcon } from "mds";
import { VerifiedIcon, Box, breakPoints } from "mds";
const RegistrationStatusBanner = ({ email = "" }: { email?: string }) => {
return (
<Box
sx={{
height: "67px",
height: 67,
color: "#ffffff",
display: "flex",
position: "relative",
top: "-30px",
left: "-32px",
top: -30,
left: -32,
width: "calc(100% + 64px)",
alignItems: "center",
justifyContent: "space-between",
@@ -51,9 +66,9 @@ const RegistrationStatusBanner = ({ email = "" }: { email?: string }) => {
sx={{
alignItems: "center",
justifyContent: "flex-start",
display: {
sm: "flex",
xs: "none",
display: "flex",
[`@media (max-width: ${breakPoints.sm}px)`]: {
display: "none",
},
}}
>

View File

@@ -15,15 +15,13 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { Box } from "@mui/material";
import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
import { setSubnetOTP } from "./registerSlice";
import { Button } from "mds";
import RegisterHelpBox from "./RegisterHelpBox";
import { AppState, useAppDispatch } from "../../../store";
import { Box, Button, FormLayout, InputBox, LockIcon } from "mds";
import { useSelector } from "react-redux";
import { setSubnetOTP } from "./registerSlice";
import { AppState, useAppDispatch } from "../../../store";
import { subnetLoginWithMFA } from "./registerThunks";
import { modalStyleUtils } from "../Common/FormComponents/common/styleLibrary";
import RegisterHelpBox from "./RegisterHelpBox";
const SubnetMFAToken = () => {
const dispatch = useAppDispatch();
@@ -35,76 +33,51 @@ const SubnetMFAToken = () => {
const loading = useSelector((state: AppState) => state.register.loading);
return (
<Box
sx={{
display: "flex",
}}
<FormLayout
title={"Two-Factor Authentication"}
helpBox={<RegisterHelpBox />}
withBorders={false}
containerPadding={false}
>
<Box
sx={{
fontSize: 14,
display: "flex",
flexFlow: "column",
flex: "2",
marginBottom: "30px",
}}
>
<Box
sx={{
fontSize: "16px",
display: "flex",
flexFlow: "column",
marginTop: "30px",
marginBottom: "30px",
}}
>
Two-Factor Authentication
</Box>
<Box>
Please enter the 6-digit verification code that was sent to your email
address. This code will be valid for 5 minutes.
</Box>
<Box
sx={{
flex: "1",
marginTop: "30px",
}}
>
<InputBoxWrapper
overlayIcon={<LockOutlinedIcon />}
id="subnet-otp"
name="subnet-otp"
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
dispatch(setSubnetOTP(event.target.value))
}
placeholder=""
label=""
value={subnetOTP}
/>
</Box>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
}}
>
<Button
id={"verify"}
onClick={() => dispatch(subnetLoginWithMFA())}
disabled={
loading ||
subnetOTP.trim().length === 0 ||
subnetMFAToken.trim().length === 0
}
variant="callAction"
label={"Verify"}
/>
</Box>
Please enter the 6-digit verification code that was sent to your email
address. This code will be valid for 5 minutes.
</Box>
<RegisterHelpBox />
</Box>
<Box>
<InputBox
overlayIcon={<LockIcon />}
id="subnet-otp"
name="subnet-otp"
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
dispatch(setSubnetOTP(event.target.value))
}
placeholder=""
label=""
value={subnetOTP}
/>
</Box>
<Box sx={modalStyleUtils.modalButtonBar}>
<Button
id={"verify"}
onClick={() => dispatch(subnetLoginWithMFA())}
disabled={
loading ||
subnetOTP.trim().length === 0 ||
subnetMFAToken.trim().length === 0
}
variant="callAction"
label={"Verify"}
/>
</Box>
</FormLayout>
);
};
export default SubnetMFAToken;

View File

@@ -27,12 +27,11 @@ export interface RegisterState {
selectedSubnetOrganization: string;
subnetRegToken: string;
subnetOrganizations: SubnetOrganization[];
showPassword: boolean;
loading: boolean;
loadingLicenseInfo: boolean;
clusterRegistered: boolean;
licenseInfo: SubnetInfo | undefined;
curTab: number;
curTab: string;
}
const initialState: RegisterState = {
@@ -45,12 +44,11 @@ const initialState: RegisterState = {
selectedSubnetOrganization: "",
subnetRegToken: "",
subnetOrganizations: [],
showPassword: false,
loading: false,
loadingLicenseInfo: false,
clusterRegistered: false,
licenseInfo: undefined,
curTab: 0,
curTab: "simple-tab-0",
};
export const registerSlice = createSlice({
@@ -87,9 +85,6 @@ export const registerSlice = createSlice({
) => {
state.subnetOrganizations = action.payload;
},
setShowPassword: (state, action: PayloadAction<boolean>) => {
state.showPassword = action.payload;
},
setLoading: (state, action: PayloadAction<boolean>) => {
state.loading = action.payload;
},
@@ -102,7 +97,7 @@ export const registerSlice = createSlice({
setLicenseInfo: (state, action: PayloadAction<SubnetInfo | undefined>) => {
state.licenseInfo = action.payload;
},
setCurTab: (state, action: PayloadAction<number>) => {
setCurTab: (state, action: PayloadAction<string>) => {
state.curTab = action.payload;
},
resetRegisterForm: () => initialState,
@@ -120,7 +115,6 @@ export const {
setSelectedSubnetOrganization,
setSubnetRegToken,
setSubnetOrganizations,
setShowPassword,
setLoading,
setLoadingLicenseInfo,
setClusterRegistered,

View File

@@ -1,56 +1,37 @@
import { Box, Grid, Link } from "@mui/material";
import { Fragment, useState } from "react";
import { CopyIcon, SettingsIcon } from "mds";
import FormSwitchWrapper from "../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import RegistrationStatusBanner from "./RegistrationStatusBanner";
// This file is part of MinIO Console Server
// 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 <http://www.gnu.org/licenses/>.
export const FormTitle = ({
icon = null,
title,
}: {
icon?: any;
title: any;
}) => {
return (
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "flex-start",
}}
>
{icon}
<div className="title-text">{title}</div>
</Box>
);
};
import React, { Fragment, useState } from "react";
import { CopyIcon, SettingsIcon, Box, Grid, Switch, InputBox } from "mds";
import RegistrationStatusBanner from "./RegistrationStatusBanner";
export const ClusterRegistered = ({ email }: { email: string }) => {
return (
<Fragment>
<RegistrationStatusBanner email={email} />
<Grid item xs={12} marginTop={"25px"}>
<Grid item xs={12} sx={{ marginTop: 25 }}>
<Box
sx={{
padding: "20px",
"& a": {
color: "#2781B0",
cursor: "pointer",
},
}}
>
Login to{" "}
<Link
href="https://subnet.min.io"
target="_blank"
style={{
color: "#2781B0",
cursor: "pointer",
}}
>
<a href="https://subnet.min.io" target="_blank">
SUBNET
</Link>{" "}
</a>{" "}
to avail support for this MinIO cluster
</Box>
</Grid>
@@ -65,9 +46,8 @@ export const ProxyConfiguration = () => {
return (
<Fragment>
<Box
withBorders
sx={{
border: "1px solid #eaeaea",
borderRadius: "2px",
display: "flex",
padding: "23px",
marginTop: "40px",
@@ -103,21 +83,17 @@ export const ProxyConfiguration = () => {
}}
>
For airgap/firewalled environments it is possible to{" "}
<Link
style={{
color: "#2781B0",
cursor: "pointer",
}}
<a
href="https://min.io/docs/minio/linux/reference/minio-mc-admin/mc-admin-config.html?ref=con"
target="_blank"
>
configure a proxy
</Link>{" "}
</a>{" "}
to connect to SUBNET .
</Box>
<Box>
{displaySubnetProxy && (
<InputBoxWrapper
<InputBox
disabled
id="subnetProxy"
name="subnetProxy"
@@ -126,9 +102,6 @@ export const ProxyConfiguration = () => {
label=""
value={proxyConfigurationCommand}
overlayIcon={<CopyIcon />}
extraInputProps={{
readOnly: true,
}}
overlayAction={() =>
navigator.clipboard.writeText(proxyConfigurationCommand)
}
@@ -141,7 +114,7 @@ export const ProxyConfiguration = () => {
display: "flex",
}}
>
<FormSwitchWrapper
<Switch
value="enableProxy"
id="enableProxy"
name="enableProxy"