mirror of
https://github.com/OpenMaxIO/openmaxio-object-browser
synced 2026-07-01 07:41:18 -07:00
884 lines
25 KiB
TypeScript
884 lines
25 KiB
TypeScript
// 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, { Fragment, useCallback, useEffect, useState } from "react";
|
|
import { Theme } from "@mui/material/styles";
|
|
import createStyles from "@mui/styles/createStyles";
|
|
import {
|
|
actionsTray,
|
|
containerForHeader,
|
|
searchField,
|
|
spacingUtils,
|
|
} from "../Common/FormComponents/common/styleLibrary";
|
|
import withStyles from "@mui/styles/withStyles";
|
|
import { Box, Button, Link } from "@mui/material";
|
|
import PageHeader from "../Common/PageHeader/PageHeader";
|
|
import PageLayout from "../Common/Layout/PageLayout";
|
|
import { CopyIcon, UsersIcon } from "../../../icons";
|
|
import RemoveRedEyeIcon from "@mui/icons-material/RemoveRedEye";
|
|
import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
|
|
import OnlineRegistrationIcon from "../../../icons/OnlineRegistrationIcon";
|
|
import OfflineRegistrationIcon from "../../../icons/OfflineRegistrationIcon";
|
|
import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
|
import api from "../../../common/api";
|
|
|
|
import {
|
|
SubnetInfo,
|
|
SubnetLoginRequest,
|
|
SubnetLoginResponse,
|
|
SubnetLoginWithMFARequest,
|
|
SubnetOrganization,
|
|
SubnetRegisterRequest,
|
|
SubnetRegTokenResponse,
|
|
} from "../License/types";
|
|
import { ErrorResponseHandler } from "../../../common/types";
|
|
import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
|
|
import SelectWrapper from "../Common/FormComponents/SelectWrapper/SelectWrapper";
|
|
import { hasPermission } from "../../../common/SecureComponent";
|
|
import {
|
|
CONSOLE_UI_RESOURCE,
|
|
IAM_PAGES,
|
|
IAM_PAGES_PERMISSIONS,
|
|
} from "../../../common/SecureComponent/permissions";
|
|
import { useSelector } from "react-redux";
|
|
|
|
import RegisterHelpBox from "./RegisterHelpBox";
|
|
import { selOpMode, setErrorSnackMessage } from "../../../systemSlice";
|
|
import { useAppDispatch } from "../../../store";
|
|
import Tabs from "@mui/material/Tabs";
|
|
import Tab from "@mui/material/Tab";
|
|
import { TabPanel } from "../../shared/tabs";
|
|
import { ClusterRegistered, FormTitle, ProxyConfiguration } from "./utils";
|
|
import ApiKeyRegister from "./ApiKeyRegister";
|
|
interface IRegister {
|
|
classes: any;
|
|
}
|
|
|
|
const styles = (theme: Theme) =>
|
|
createStyles({
|
|
registerActivationIcon: {
|
|
color: theme.palette.primary.main,
|
|
fontSize: 16,
|
|
fontWeight: "bold",
|
|
marginBottom: 20,
|
|
"& .min-icon": {
|
|
width: 32.12,
|
|
height: 25,
|
|
marginRight: 10,
|
|
verticalAlign: "middle",
|
|
},
|
|
},
|
|
registerActivationMode: {
|
|
textAlign: "right",
|
|
"& a": {
|
|
cursor: "pointer",
|
|
},
|
|
},
|
|
subnetDescription: {
|
|
textAlign: "left",
|
|
Font: "normal normal normal 14px/17px Lato",
|
|
letterSpacing: 0,
|
|
color: "#000000",
|
|
"& span": {
|
|
fontWeight: "bold",
|
|
},
|
|
},
|
|
registeredStatus: {
|
|
border: "1px solid #E2E2E2",
|
|
padding: "24px 24px 24px 24px",
|
|
borderRadius: 2,
|
|
marginBottom: 25,
|
|
backgroundColor: "#FBFAFA",
|
|
"& .min-icon": {
|
|
width: 20,
|
|
height: 20,
|
|
marginLeft: 48,
|
|
marginRight: 13,
|
|
verticalAlign: "middle",
|
|
marginTop: -3,
|
|
},
|
|
"& span": {
|
|
fontWeight: "bold",
|
|
},
|
|
},
|
|
copyInputBox: {
|
|
"& button": {
|
|
border: "1px solid #5E5E5E",
|
|
borderRadius: 2,
|
|
},
|
|
},
|
|
link: {
|
|
color: "#2781B0",
|
|
cursor: "pointer",
|
|
},
|
|
sizedLabel: {
|
|
minWidth: "75px",
|
|
},
|
|
...actionsTray,
|
|
...searchField,
|
|
...spacingUtils,
|
|
...containerForHeader(theme.spacing(4)),
|
|
});
|
|
|
|
const Register = ({ classes }: IRegister) => {
|
|
const dispatch = useAppDispatch();
|
|
const operatorMode = useSelector(selOpMode);
|
|
const [license, setLicense] = useState<string>("");
|
|
const [subnetPassword, setSubnetPassword] = useState<string>("");
|
|
const [subnetEmail, setSubnetEmail] = useState<string>("");
|
|
const [subnetMFAToken, setSubnetMFAToken] = useState<string>("");
|
|
const [subnetOTP, setSubnetOTP] = useState<string>("");
|
|
const [subnetAccessToken, setSubnetAccessToken] = useState<string>("");
|
|
const [selectedSubnetOrganization, setSelectedSubnetOrganization] =
|
|
useState<string>("");
|
|
const [subnetRegToken, setSubnetRegToken] = useState<string>("");
|
|
const [subnetOrganizations, setSubnetOrganizations] = useState<
|
|
SubnetOrganization[]
|
|
>([]);
|
|
const [showPassword, setShowPassword] = useState<boolean>(false);
|
|
const [loading, setLoading] = useState<boolean>(false);
|
|
const [loadingLicenseInfo, setLoadingLicenseInfo] = useState<boolean>(false);
|
|
const [clusterRegistered, setClusterRegistered] = useState<boolean>(false);
|
|
const [licenseInfo, setLicenseInfo] = useState<SubnetInfo | undefined>();
|
|
const [curTab, setCurTab] = useState<number>(0);
|
|
|
|
const [initialLicenseLoading, setInitialLicenseLoading] =
|
|
useState<boolean>(true);
|
|
const clearForm = () => {
|
|
setSubnetAccessToken("");
|
|
setSelectedSubnetOrganization("");
|
|
setSubnetRegToken("");
|
|
setShowPassword(false);
|
|
setSubnetOrganizations([]);
|
|
setLicense("");
|
|
setSubnetPassword("");
|
|
setSubnetEmail("");
|
|
setSubnetMFAToken("");
|
|
setSubnetOTP("");
|
|
};
|
|
|
|
const getSubnetInfo = hasPermission(
|
|
CONSOLE_UI_RESOURCE,
|
|
IAM_PAGES_PERMISSIONS[IAM_PAGES.LICENSE],
|
|
true
|
|
);
|
|
|
|
const fetchLicenseInfo = useCallback(() => {
|
|
if (loadingLicenseInfo) {
|
|
return;
|
|
}
|
|
if (getSubnetInfo) {
|
|
setLoadingLicenseInfo(true);
|
|
api
|
|
.invoke("GET", `/api/v1/subnet/info`)
|
|
.then((res: SubnetInfo) => {
|
|
setLicenseInfo(res);
|
|
setClusterRegistered(true);
|
|
setLoadingLicenseInfo(false);
|
|
})
|
|
.catch((err: ErrorResponseHandler) => {
|
|
if (err.errorMessage !== "License not found") {
|
|
dispatch(setErrorSnackMessage(err));
|
|
}
|
|
setClusterRegistered(false);
|
|
setLoadingLicenseInfo(false);
|
|
});
|
|
} else {
|
|
setLoadingLicenseInfo(false);
|
|
}
|
|
}, [loadingLicenseInfo, getSubnetInfo, dispatch]);
|
|
|
|
const fetchSubnetRegToken = () => {
|
|
if (loading || subnetRegToken) {
|
|
return;
|
|
}
|
|
setLoading(true);
|
|
api
|
|
.invoke("GET", "/api/v1/subnet/registration-token")
|
|
.then((resp: SubnetRegTokenResponse) => {
|
|
setLoading(false);
|
|
if (resp && resp.regToken) {
|
|
setSubnetRegToken(resp.regToken);
|
|
}
|
|
})
|
|
.catch((err: ErrorResponseHandler) => {
|
|
console.error(err);
|
|
dispatch(setErrorSnackMessage(err));
|
|
setLoading(false);
|
|
});
|
|
};
|
|
|
|
const callRegister = (token: string, account_id: string) => {
|
|
const request: SubnetRegisterRequest = {
|
|
token: token,
|
|
account_id: account_id,
|
|
};
|
|
api
|
|
.invoke("POST", "/api/v1/subnet/register", request)
|
|
.then(() => {
|
|
setLoading(false);
|
|
clearForm();
|
|
fetchLicenseInfo();
|
|
})
|
|
.catch((err: ErrorResponseHandler) => {
|
|
dispatch(setErrorSnackMessage(err));
|
|
setLoading(false);
|
|
});
|
|
};
|
|
const subnetRegister = () => {
|
|
if (loading) {
|
|
return;
|
|
}
|
|
setLoading(true);
|
|
if (subnetAccessToken && selectedSubnetOrganization) {
|
|
callRegister(subnetAccessToken, selectedSubnetOrganization);
|
|
}
|
|
};
|
|
|
|
const subnetLoginWithMFA = () => {
|
|
if (loading) {
|
|
return;
|
|
}
|
|
setLoading(true);
|
|
const request: SubnetLoginWithMFARequest = {
|
|
username: subnetEmail,
|
|
otp: subnetOTP,
|
|
mfa_token: subnetMFAToken,
|
|
};
|
|
api
|
|
.invoke("POST", "/api/v1/subnet/login/mfa", request)
|
|
.then((resp: SubnetLoginResponse) => {
|
|
setLoading(false);
|
|
if (resp && resp.access_token && resp.organizations.length > 0) {
|
|
if (resp.organizations.length === 1) {
|
|
callRegister(
|
|
resp.access_token,
|
|
resp.organizations[0].accountId.toString()
|
|
);
|
|
} else {
|
|
setSubnetAccessToken(resp.access_token);
|
|
setSubnetOrganizations(resp.organizations);
|
|
setSelectedSubnetOrganization(
|
|
resp.organizations[0].accountId.toString()
|
|
);
|
|
}
|
|
}
|
|
})
|
|
.catch((err: ErrorResponseHandler) => {
|
|
dispatch(setErrorSnackMessage(err));
|
|
setLoading(false);
|
|
setSubnetOTP("");
|
|
});
|
|
};
|
|
|
|
const subnetLogin = () => {
|
|
if (loading) {
|
|
return;
|
|
}
|
|
setLoading(true);
|
|
let request: SubnetLoginRequest = {
|
|
username: subnetEmail,
|
|
password: subnetPassword,
|
|
apiKey: license,
|
|
};
|
|
api
|
|
.invoke("POST", "/api/v1/subnet/login", request)
|
|
.then((resp: SubnetLoginResponse) => {
|
|
setLoading(false);
|
|
if (resp && resp.registered) {
|
|
clearForm();
|
|
fetchLicenseInfo();
|
|
} else if (resp && resp.mfa_token) {
|
|
setSubnetMFAToken(resp.mfa_token);
|
|
} else if (resp && resp.access_token && resp.organizations.length > 0) {
|
|
setSubnetAccessToken(resp.access_token);
|
|
setSubnetOrganizations(resp.organizations);
|
|
setSelectedSubnetOrganization(
|
|
resp.organizations[0].accountId.toString()
|
|
);
|
|
}
|
|
})
|
|
.catch((err: ErrorResponseHandler) => {
|
|
dispatch(setErrorSnackMessage(err));
|
|
setLoading(false);
|
|
clearForm();
|
|
});
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (initialLicenseLoading) {
|
|
fetchLicenseInfo();
|
|
setInitialLicenseLoading(false);
|
|
}
|
|
}, [fetchLicenseInfo, initialLicenseLoading, setInitialLicenseLoading]);
|
|
|
|
let clusterRegistrationForm: JSX.Element = <Fragment />;
|
|
|
|
if (subnetAccessToken && subnetOrganizations.length > 0) {
|
|
clusterRegistrationForm = (
|
|
<Box
|
|
sx={{
|
|
display: "flex",
|
|
}}
|
|
>
|
|
<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) =>
|
|
setSelectedSubnetOrganization(e.target.value as string)
|
|
}
|
|
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
|
|
className={classes.button}
|
|
color="primary"
|
|
onClick={() => subnetRegister()}
|
|
disabled={loading || subnetAccessToken.trim().length === 0}
|
|
variant="contained"
|
|
>
|
|
Register
|
|
</Button>
|
|
</Box>
|
|
</Box>
|
|
</Box>
|
|
<RegisterHelpBox />
|
|
</Box>
|
|
);
|
|
} else if (subnetMFAToken) {
|
|
clusterRegistrationForm = (
|
|
<Box
|
|
sx={{
|
|
display: "flex",
|
|
}}
|
|
>
|
|
<Box
|
|
sx={{
|
|
display: "flex",
|
|
flexFlow: "column",
|
|
flex: "2",
|
|
}}
|
|
>
|
|
<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>) =>
|
|
setSubnetOTP(event.target.value)
|
|
}
|
|
placeholder=""
|
|
label=""
|
|
value={subnetOTP}
|
|
/>
|
|
</Box>
|
|
<Box
|
|
sx={{
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "flex-end",
|
|
}}
|
|
>
|
|
<Button
|
|
color="primary"
|
|
onClick={() => subnetLoginWithMFA()}
|
|
disabled={
|
|
loading ||
|
|
subnetOTP.trim().length === 0 ||
|
|
subnetMFAToken.trim().length === 0
|
|
}
|
|
variant="contained"
|
|
>
|
|
Verify
|
|
</Button>
|
|
</Box>
|
|
</Box>
|
|
|
|
<RegisterHelpBox />
|
|
</Box>
|
|
);
|
|
} else {
|
|
clusterRegistrationForm = (
|
|
<Fragment>
|
|
<Box
|
|
sx={{
|
|
"& .title-text": {
|
|
marginLeft: "27px",
|
|
fontWeight: 600,
|
|
},
|
|
}}
|
|
>
|
|
<FormTitle
|
|
icon={<OnlineRegistrationIcon />}
|
|
title={`Online activation of MinIO Subscription Network License`}
|
|
/>
|
|
</Box>
|
|
<Box
|
|
sx={{
|
|
display: "flex",
|
|
flexFlow: {
|
|
xs: "column",
|
|
md: "row",
|
|
},
|
|
}}
|
|
>
|
|
<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>) =>
|
|
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>) =>
|
|
setSubnetPassword(event.target.value)
|
|
}
|
|
label="Password"
|
|
type={showPassword ? "text" : "password"}
|
|
value={subnetPassword}
|
|
overlayIcon={
|
|
showPassword ? <VisibilityOffIcon /> : <RemoveRedEyeIcon />
|
|
}
|
|
overlayAction={() => setShowPassword(!showPassword)}
|
|
/>
|
|
|
|
<Box
|
|
sx={{
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "flex-end",
|
|
}}
|
|
>
|
|
<Button
|
|
type="submit"
|
|
className={classes.spacerRight}
|
|
variant="outlined"
|
|
onClick={(e) => {
|
|
e.preventDefault();
|
|
window.open(
|
|
`https://min.io/signup?ref=${
|
|
operatorMode ? "op" : "con"
|
|
}`,
|
|
"_blank"
|
|
);
|
|
}}
|
|
>
|
|
Sign up
|
|
</Button>
|
|
<Button
|
|
type="submit"
|
|
variant="contained"
|
|
color="primary"
|
|
disabled={
|
|
loading ||
|
|
subnetEmail.trim().length === 0 ||
|
|
subnetPassword.trim().length === 0
|
|
}
|
|
onClick={() => subnetLogin()}
|
|
>
|
|
Register
|
|
</Button>
|
|
</Box>
|
|
</Box>
|
|
</Box>
|
|
<RegisterHelpBox />
|
|
</Box>
|
|
</Fragment>
|
|
);
|
|
}
|
|
|
|
const apiKeyRegistration = (
|
|
<Fragment>
|
|
<Box
|
|
sx={{
|
|
border: "1px solid #eaeaea",
|
|
borderRadius: "2px",
|
|
display: "flex",
|
|
flexFlow: "column",
|
|
padding: "43px",
|
|
}}
|
|
>
|
|
{clusterRegistered && licenseInfo ? (
|
|
<ClusterRegistered
|
|
email={licenseInfo.email}
|
|
linkClass={classes.link}
|
|
/>
|
|
) : (
|
|
<ApiKeyRegister
|
|
afterRegister={fetchLicenseInfo}
|
|
registerEndpoint={"/api/v1/subnet/login"}
|
|
/>
|
|
)}
|
|
</Box>
|
|
<ProxyConfiguration linkClass={classes.link} />
|
|
</Fragment>
|
|
);
|
|
|
|
const offlineRegistration = (
|
|
<Fragment>
|
|
<Box
|
|
sx={{
|
|
border: "1px solid #eaeaea",
|
|
borderRadius: "2px",
|
|
display: "flex",
|
|
flexFlow: "column",
|
|
padding: "43px",
|
|
}}
|
|
>
|
|
{clusterRegistered && licenseInfo ? (
|
|
<ClusterRegistered
|
|
email={licenseInfo.email}
|
|
linkClass={classes.link}
|
|
/>
|
|
) : null}
|
|
<Box
|
|
sx={{
|
|
"& .title-text": {
|
|
marginLeft: "27px",
|
|
fontWeight: 600,
|
|
},
|
|
}}
|
|
>
|
|
<FormTitle
|
|
icon={<OfflineRegistrationIcon />}
|
|
title={`Register cluster in an Airgap environment`}
|
|
/>
|
|
</Box>
|
|
|
|
<Box
|
|
sx={{
|
|
display: "flex",
|
|
}}
|
|
>
|
|
<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-number">1</div>{" "}
|
|
<div className="step-text">
|
|
Copy the following registration token
|
|
</div>
|
|
</Box>
|
|
|
|
<Box
|
|
sx={{
|
|
flex: "1",
|
|
marginTop: "15px",
|
|
marginLeft: "35px",
|
|
"& input": {
|
|
color: "#737373",
|
|
},
|
|
}}
|
|
>
|
|
<InputBoxWrapper
|
|
id="registration-token"
|
|
name="registration-token"
|
|
placeholder=""
|
|
label=""
|
|
type="text"
|
|
onChange={() => {}}
|
|
value={subnetRegToken}
|
|
overlayIcon={<CopyIcon />}
|
|
extraInputProps={{
|
|
readOnly: true,
|
|
}}
|
|
overlayAction={() =>
|
|
navigator.clipboard.writeText(subnetRegToken)
|
|
}
|
|
/>
|
|
</Box>
|
|
</Box>
|
|
|
|
<Box>
|
|
<Box className="step-row">
|
|
<div className="step-number">2</div>
|
|
<div className="step-text">
|
|
Navigate to SUBNET and register your cluster
|
|
</div>
|
|
</Box>
|
|
|
|
<Box
|
|
sx={{
|
|
flex: "1",
|
|
marginLeft: "35px",
|
|
}}
|
|
>
|
|
<Link
|
|
className={classes.link}
|
|
color="inherit"
|
|
href="https://subnet.min.io/cluster/register"
|
|
target="_blank"
|
|
>
|
|
https://subnet.min.io/cluster/register
|
|
</Link>
|
|
</Box>
|
|
</Box>
|
|
|
|
<Box
|
|
sx={{
|
|
fontSize: "16px",
|
|
display: "flex",
|
|
flexFlow: "column",
|
|
marginTop: "15px",
|
|
marginBottom: "15px",
|
|
}}
|
|
>
|
|
<Box className="step-row">
|
|
<div className="step-number">3</div>{" "}
|
|
<div className="step-text">
|
|
Enter the API key generated by SUBNET
|
|
</div>
|
|
</Box>
|
|
|
|
<Box
|
|
sx={{
|
|
flex: "1",
|
|
marginTop: "15px",
|
|
marginLeft: "35px",
|
|
}}
|
|
>
|
|
<InputBoxWrapper
|
|
value={license}
|
|
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
|
setLicense(event.target.value)
|
|
}
|
|
id="api-key"
|
|
name="api-key"
|
|
placeholder=""
|
|
label=""
|
|
type="text"
|
|
/>
|
|
</Box>
|
|
</Box>
|
|
|
|
<Box
|
|
sx={{
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "flex-end",
|
|
marginTop: "15px",
|
|
}}
|
|
>
|
|
<Button
|
|
variant="contained"
|
|
color="primary"
|
|
onClick={() => subnetLogin()}
|
|
disabled={loading || license.trim().length === 0}
|
|
>
|
|
Register
|
|
</Button>
|
|
</Box>
|
|
</Box>
|
|
<RegisterHelpBox />
|
|
</Box>
|
|
</Box>
|
|
</Fragment>
|
|
);
|
|
|
|
const regUi = (
|
|
<Fragment>
|
|
<Box
|
|
sx={{
|
|
border: "1px solid #eaeaea",
|
|
borderRadius: "2px",
|
|
display: "flex",
|
|
flexFlow: "column",
|
|
padding: "43px",
|
|
}}
|
|
>
|
|
{clusterRegistered && licenseInfo ? (
|
|
<ClusterRegistered
|
|
email={licenseInfo.email}
|
|
linkClass={classes.link}
|
|
/>
|
|
) : (
|
|
clusterRegistrationForm
|
|
)}
|
|
</Box>
|
|
|
|
{!clusterRegistered && <ProxyConfiguration linkClass={classes.link} />}
|
|
</Fragment>
|
|
);
|
|
|
|
const loadingUi = <div>Loading..</div>;
|
|
const uiToShow = loadingLicenseInfo ? loadingUi : regUi;
|
|
|
|
return (
|
|
<Fragment>
|
|
<PageHeader
|
|
label="Register to MinIO Subscription Network"
|
|
actions={<React.Fragment />}
|
|
/>
|
|
|
|
<PageLayout>
|
|
<Tabs
|
|
value={curTab}
|
|
onChange={(e: React.ChangeEvent<{}>, newValue: number) => {
|
|
setCurTab(newValue);
|
|
}}
|
|
indicatorColor="primary"
|
|
textColor="primary"
|
|
aria-label="cluster-tabs"
|
|
variant="scrollable"
|
|
scrollButtons="auto"
|
|
>
|
|
<Tab
|
|
label="Credentials"
|
|
id="simple-tab-0"
|
|
aria-controls="simple-tabpanel-0"
|
|
/>
|
|
<Tab
|
|
label="API Key"
|
|
id="simple-tab-1"
|
|
aria-controls="simple-tabpanel-1"
|
|
/>
|
|
<Tab
|
|
label="Airgap"
|
|
id="simple-tab-2"
|
|
aria-controls="simple-tabpanel-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>
|
|
</PageLayout>
|
|
</Fragment>
|
|
);
|
|
};
|
|
|
|
export default withStyles(styles)(Register);
|