diff --git a/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/DescriptionIcon.tsx b/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/DescriptionIcon.tsx index 30198c88f..03674dfd9 100644 --- a/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/DescriptionIcon.tsx +++ b/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/DescriptionIcon.tsx @@ -1,7 +1,7 @@ import React from "react"; import { IIcon, selected, unSelected } from "./common"; -const PencilIcon = ({ active = false }: IIcon) => { +const DescriptionIcon = ({ active = false }: IIcon) => { return ( { ); }; -export default PencilIcon; +export default DescriptionIcon; diff --git a/portal-ui/src/screens/Console/Tenants/TenantDetails/TenantDetails.tsx b/portal-ui/src/screens/Console/Tenants/TenantDetails/TenantDetails.tsx index d181d6390..a820e66ad 100644 --- a/portal-ui/src/screens/Console/Tenants/TenantDetails/TenantDetails.tsx +++ b/portal-ui/src/screens/Console/Tenants/TenantDetails/TenantDetails.tsx @@ -22,7 +22,7 @@ import { modalBasic, } from "../../Common/FormComponents/common/styleLibrary"; import Grid from "@material-ui/core/Grid"; -import { Button } from "@material-ui/core"; +import { Button, IconButton } from "@material-ui/core"; import Tabs from "@material-ui/core/Tabs"; import Tab from "@material-ui/core/Tab"; import { CreateIcon } from "../../../../icons"; @@ -40,6 +40,9 @@ import Watch from "./Watch/Watch"; import Heal from "./Heal/Heal"; import PageHeader from "../../Common/PageHeader/PageHeader"; import UsageBarWrapper from "../../Common/UsageBarWrapper/UsageBarWrapper"; +import UpdateTenantModal from "./UpdateTenantModal"; +import EditIcon from "@material-ui/icons/Edit"; +import PencilIcon from "../../Common/TableWrapper/TableActionIcons/PencilIcon"; interface ITenantDetailsProps { classes: any; @@ -100,6 +103,18 @@ const styles = (theme: Theme) => actionsTray: { textAlign: "right", }, + updateButton: { + backgroundColor: "transparent", + border: 0, + padding: "0 6px", + cursor: "pointer", + "&:focus, &:active": { + outline: "none", + }, + "& svg": { + height: 12, + }, + }, ...modalBasic, ...containerForHeader(theme.spacing(4)), }); @@ -119,6 +134,7 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => { const [loadingUsage, setLoadingUsage] = useState(true); const [usageError, setUsageError] = useState(""); const [usage, setUsage] = useState(0); + const [updateMinioVersion, setUpdateMinioVersion] = useState(false); const tenantName = match.params["tenantName"]; const tenantNamespace = match.params["tenantNamespace"]; @@ -228,6 +244,16 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => { closeModalAndRefresh={closeReplicationAndRefresh} /> )} + {updateMinioVersion && ( + { + setUpdateMinioVersion(false); + }} + idTenant={tenantName} + namespace={tenantNamespace} + /> + )} ${match.params["tenantName"]}`} /> @@ -245,7 +271,17 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
Capacity:
{niceBytes(capacity.toString(10))}
Minio:
-
{tenant ? tenant.image : ""}
+
+ {tenant ? tenant.image : ""}{" "} + +
Clusters:
{poolCount}
Console:
diff --git a/portal-ui/src/screens/Console/Tenants/TenantDetails/UpdateTenantModal.tsx b/portal-ui/src/screens/Console/Tenants/TenantDetails/UpdateTenantModal.tsx new file mode 100644 index 000000000..fb6d53b41 --- /dev/null +++ b/portal-ui/src/screens/Console/Tenants/TenantDetails/UpdateTenantModal.tsx @@ -0,0 +1,252 @@ +import React, { useState, Fragment, useEffect } from "react"; +import { createStyles, Theme, withStyles } from "@material-ui/core/styles"; +import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper"; +import { Button, Grid } from "@material-ui/core"; +import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; +import FormSwitchWrapper from "../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper"; +import api from "../../../../common/api"; +import { modalBasic } from "../../Common/FormComponents/common/styleLibrary"; + +interface IUpdateTenantModal { + open: boolean; + closeModalAndRefresh: (update: boolean) => any; + namespace: string; + idTenant: string; + classes: any; +} + +const styles = (theme: Theme) => + createStyles({ + errorBlock: { + color: "red", + }, + buttonContainer: { + textAlign: "right", + }, + ...modalBasic, + }); + +const UpdateTenantModal = ({ + open, + closeModalAndRefresh, + namespace, + idTenant, + classes, +}: IUpdateTenantModal) => { + const [isLoading, setIsLoading] = useState(true); + const [isSending, setIsSending] = useState(false); + const [error, setError] = useState(""); + const [minioImage, setMinioImage] = useState(""); + const [consoleImage, setConsoleImage] = useState(""); + const [imageRegistry, setImageRegistry] = useState(false); + const [imageRegistryEndpoint, setImageRegistryEndpoint] = useState( + "" + ); + const [imageRegistryUsername, setImageRegistryUsername] = useState( + "" + ); + const [imageRegistryPassword, setImageRegistryPassword] = useState( + "" + ); + const [validMinioImage, setValidMinioImage] = useState(true); + const [validConsoleImage, setValidConsoleImage] = useState(true); + + useEffect(() => { + validateImage("minioImage"); + }, [minioImage]); + + useEffect(() => { + validateImage("consoleImage"); + }, [consoleImage]); + + const closeAction = () => { + closeModalAndRefresh(false); + }; + + const resetForm = () => { + setMinioImage(""); + setConsoleImage(""); + setImageRegistry(false); + setImageRegistryEndpoint(""); + setImageRegistryUsername(""); + setImageRegistryPassword(""); + }; + + const updateMinIOImage = () => { + setIsSending(true); + + let payload = { + image: minioImage, + console_image: consoleImage, + enable_prometheus: true, + }; + + if (imageRegistry) { + const registry: any = { + image_registry: { + registry: imageRegistryEndpoint, + username: imageRegistryUsername, + password: imageRegistryPassword, + }, + }; + payload = { + ...payload, + ...registry, + }; + } + + api + .invoke( + "PUT", + `/api/v1/namespaces/${namespace}/tenants/${idTenant}`, + payload + ) + .then((res) => { + setIsSending(false); + closeModalAndRefresh(true); + }) + .catch((error) => { + setError(error); + setIsSending(false); + }); + }; + + const validateImage = (fieldToCheck: string) => { + const pattern = new RegExp("^$|^((.*?)/(.*?):(.+))$"); + + switch (fieldToCheck) { + case "consoleImage": + setValidConsoleImage(pattern.test(consoleImage)); + break; + case "minioImage": + setValidMinioImage(pattern.test(minioImage)); + break; + } + }; + + return ( + + + + {error !== "" && {error}} + + Please enter the MinIO image from dockerhub to use. If blank, then + latest build will be used. + +
+
+ + { + setMinioImage(e.target.value); + }} + /> + + + { + setConsoleImage(e.target.value); + }} + /> + + + ) => { + setImageRegistry(!imageRegistry); + }} + label={"Set Custom Image Registry"} + indicatorLabels={["Yes", "No"]} + /> + + {imageRegistry && ( + + + { + setImageRegistryEndpoint(e.target.value); + }} + /> + + + { + setImageRegistryUsername(e.target.value); + }} + /> + + + { + setImageRegistryPassword(e.target.value); + }} + /> + + + )} +
+ + + + +
+
+ ); +}; + +export default withStyles(styles)(UpdateTenantModal);