Migrated Site Replication Pages (#3011)
- Improved & Simplified UI elements Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
@@ -32,6 +32,7 @@ import {
|
||||
PageLayout,
|
||||
RadioGroup,
|
||||
Switch,
|
||||
SectionTitle,
|
||||
} from "mds";
|
||||
import { k8sScalarUnitsExcluding } from "../../../../../common/utils";
|
||||
import { AppState, useAppDispatch } from "../../../../../store";
|
||||
@@ -44,7 +45,6 @@ import {
|
||||
} from "../../../../../systemSlice";
|
||||
import InputUnitMenu from "../../../Common/FormComponents/InputUnitMenu/InputUnitMenu";
|
||||
import TooltipWrapper from "../../../Common/TooltipWrapper/TooltipWrapper";
|
||||
import SectionTitle from "../../../Common/SectionTitle";
|
||||
import {
|
||||
resetForm,
|
||||
setEnableObjectLocking,
|
||||
@@ -277,7 +277,7 @@ const AddBucket = () => {
|
||||
<Box sx={{ margin: "10px 0" }}>
|
||||
<BucketNamingRules errorList={validationResult} />
|
||||
</Box>
|
||||
<SectionTitle>Features</SectionTitle>
|
||||
<SectionTitle separator>Features</SectionTitle>
|
||||
<Box sx={{ marginTop: 10 }}>
|
||||
{!distributedSetup && (
|
||||
<Fragment>
|
||||
|
||||
@@ -15,13 +15,21 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment, useEffect, useState } from "react";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import { Box, LinearProgress } from "@mui/material";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { BackLink, Button, ClustersIcon, HelpBox, PageLayout } from "mds";
|
||||
import {
|
||||
BackLink,
|
||||
Button,
|
||||
ClustersIcon,
|
||||
HelpBox,
|
||||
PageLayout,
|
||||
Box,
|
||||
Grid,
|
||||
ProgressBar,
|
||||
InputLabel,
|
||||
SectionTitle,
|
||||
} from "mds";
|
||||
import useApi from "../../Common/Hooks/useApi";
|
||||
import { IAM_PAGES } from "../../../../common/SecureComponent/permissions";
|
||||
import SectionTitle from "../../Common/SectionTitle";
|
||||
import {
|
||||
setErrorSnackMessage,
|
||||
setHelpName,
|
||||
@@ -58,17 +66,18 @@ const isEmptyValue = (value: string): boolean => {
|
||||
const TableHeader = () => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Box
|
||||
sx={{
|
||||
fontSize: "14px",
|
||||
marginLeft: "5px",
|
||||
}}
|
||||
>
|
||||
Site Name
|
||||
<Box>
|
||||
<InputLabel>Site Name</InputLabel>
|
||||
</Box>
|
||||
<Box>
|
||||
<InputLabel>Endpoint {"*"}</InputLabel>
|
||||
</Box>
|
||||
<Box>
|
||||
<InputLabel>Access Key {"*"}</InputLabel>
|
||||
</Box>
|
||||
<Box>
|
||||
<InputLabel>Secret Key {"*"}</InputLabel>
|
||||
</Box>
|
||||
<Box sx={{ fontSize: "14px", marginLeft: "5px" }}>Endpoint {"*"}</Box>
|
||||
<Box sx={{ fontSize: "14px", marginLeft: "5px" }}>Access Key {"*"}</Box>
|
||||
<Box sx={{ fontSize: "14px", marginLeft: "5px" }}>Secret Key {"*"}</Box>
|
||||
<Box> </Box>
|
||||
</React.Fragment>
|
||||
);
|
||||
@@ -272,10 +281,10 @@ const AddReplicationSites = () => {
|
||||
>
|
||||
<SiteTypeHeader title={"This Site"} />
|
||||
<Box
|
||||
withBorders
|
||||
sx={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: ".8fr 1.2fr .8fr .8fr .2fr",
|
||||
border: "1px solid #eaeaea",
|
||||
padding: "15px",
|
||||
gap: "10px",
|
||||
maxHeight: "430px",
|
||||
@@ -330,10 +339,10 @@ const AddReplicationSites = () => {
|
||||
>
|
||||
<SiteTypeHeader title={"Peer Sites"} />
|
||||
<Box
|
||||
withBorders
|
||||
sx={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: ".8fr 1.2fr .8fr .8fr .2fr",
|
||||
border: "1px solid #eaeaea",
|
||||
padding: "15px",
|
||||
gap: "10px",
|
||||
maxHeight: "430px",
|
||||
@@ -421,11 +430,11 @@ const AddReplicationSites = () => {
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<SectionTitle icon={<ClustersIcon />}>
|
||||
<SectionTitle separator icon={<ClustersIcon />}>
|
||||
Add Sites for Replication
|
||||
</SectionTitle>
|
||||
|
||||
{isSiteInfoLoading || isAdding ? <LinearProgress /> : null}
|
||||
{isSiteInfoLoading || isAdding ? <ProgressBar /> : null}
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
@@ -526,17 +535,6 @@ const AddReplicationSites = () => {
|
||||
flexFlow: "column",
|
||||
fontSize: "14px",
|
||||
flex: "2",
|
||||
"& .step-number": {
|
||||
color: "#ffffff",
|
||||
height: "25px",
|
||||
width: "25px",
|
||||
background: "#081C42",
|
||||
marginRight: "10px",
|
||||
textAlign: "center",
|
||||
fontWeight: 600,
|
||||
borderRadius: "50%",
|
||||
},
|
||||
|
||||
"& li": {
|
||||
fontSize: "14px",
|
||||
display: "flex",
|
||||
@@ -547,15 +545,6 @@ const AddReplicationSites = () => {
|
||||
"&.step-text": {
|
||||
fontWeight: 400,
|
||||
},
|
||||
"&:before": {
|
||||
content: "' '",
|
||||
height: "7px",
|
||||
width: "7px",
|
||||
backgroundColor: "#2781B0",
|
||||
marginRight: "10px",
|
||||
marginTop: "12px",
|
||||
flexShrink: 0,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -15,10 +15,7 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { Button, EditIcon } from "mds";
|
||||
import { Box, DialogContentText } from "@mui/material";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import { Box, Button, EditIcon, Grid, InputBox, InputLabel } from "mds";
|
||||
import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper";
|
||||
import useApi from "../../Common/Hooks/useApi";
|
||||
import {
|
||||
@@ -26,31 +23,24 @@ import {
|
||||
setSnackBarMessage,
|
||||
} from "../../../../systemSlice";
|
||||
import { useAppDispatch } from "../../../../store";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import {
|
||||
formFieldStyles,
|
||||
modalStyleUtils,
|
||||
spacingUtils,
|
||||
} from "../../Common/FormComponents/common/styleLibrary";
|
||||
import { modalStyleUtils } from "../../Common/FormComponents/common/styleLibrary";
|
||||
import styled from "styled-components";
|
||||
import get from "lodash/get";
|
||||
|
||||
const SiteEndpointContainer = styled.div(({ theme }) => ({
|
||||
"& .alertText": {
|
||||
color: get(theme, "signalColors.danger", "#C51B3F"),
|
||||
},
|
||||
}));
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
...modalStyleUtils,
|
||||
...formFieldStyles,
|
||||
...spacingUtils,
|
||||
});
|
||||
const EditSiteEndPoint = ({
|
||||
editSite = {},
|
||||
onClose,
|
||||
onComplete,
|
||||
classes = {},
|
||||
}: {
|
||||
editSite: any;
|
||||
onClose: () => void;
|
||||
onComplete: () => void;
|
||||
classes: any;
|
||||
}) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const [editEndPointName, setEditEndPointName] = useState<string>("");
|
||||
@@ -99,7 +89,7 @@ const EditSiteEndPoint = ({
|
||||
titleIcon={<EditIcon />}
|
||||
onClose={onClose}
|
||||
>
|
||||
<DialogContentText>
|
||||
<SiteEndpointContainer>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
@@ -118,8 +108,8 @@ const EditSiteEndPoint = ({
|
||||
</Box>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<Box sx={{ marginBottom: "5px" }}> New Endpoint:</Box>
|
||||
<InputBoxWrapper
|
||||
<InputLabel sx={{ marginBottom: 5 }}>New Endpoint:</InputLabel>
|
||||
<InputBox
|
||||
id="edit-rep-peer-endpoint"
|
||||
name="edit-rep-peer-endpoint"
|
||||
placeholder={"https://dr.minio-storage:9000"}
|
||||
@@ -130,31 +120,32 @@ const EditSiteEndPoint = ({
|
||||
value={editEndPointName}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} marginBottom={"15px"}>
|
||||
<Box
|
||||
sx={{
|
||||
fontStyle: "italic",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
fontSize: "12px",
|
||||
marginTop: 2,
|
||||
}}
|
||||
>
|
||||
<Box sx={{ fontWeight: 600 }}>Note:</Box>{" "}
|
||||
<Box sx={{ marginLeft: 1, color: "red" }}>
|
||||
Access Key and Secret Key should be same on the new site/endpoint.
|
||||
</Box>
|
||||
</Box>
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
sx={{
|
||||
marginBottom: 15,
|
||||
fontStyle: "italic",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
fontSize: "12px",
|
||||
marginTop: 2,
|
||||
}}
|
||||
>
|
||||
<strong>Note:</strong>
|
||||
<span className={"alertText"}>
|
||||
Access Key and Secret Key should be same on the new site/endpoint.
|
||||
</span>
|
||||
</Grid>
|
||||
</DialogContentText>
|
||||
</SiteEndpointContainer>
|
||||
|
||||
<Grid item xs={12} className={classes.modalButtonBar}>
|
||||
<Grid item xs={12} sx={modalStyleUtils.modalButtonBar}>
|
||||
<Button
|
||||
id={"close"}
|
||||
type="button"
|
||||
variant="regular"
|
||||
onClick={onClose}
|
||||
label={"Close"}
|
||||
label={"Cancel"}
|
||||
/>
|
||||
<Button
|
||||
id={"update"}
|
||||
@@ -168,4 +159,4 @@ const EditSiteEndPoint = ({
|
||||
</ModalWrapper>
|
||||
);
|
||||
};
|
||||
export default withStyles(styles)(EditSiteEndPoint);
|
||||
export default EditSiteEndPoint;
|
||||
|
||||
@@ -15,10 +15,16 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { Box, Grid } from "@mui/material";
|
||||
import { Button, ClustersIcon, Loader } from "mds";
|
||||
import SelectWrapper from "../../Common/FormComponents/SelectWrapper/SelectWrapper";
|
||||
import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import {
|
||||
Box,
|
||||
breakPoints,
|
||||
Button,
|
||||
ClustersIcon,
|
||||
Grid,
|
||||
Loader,
|
||||
Select,
|
||||
InputBox,
|
||||
} from "mds";
|
||||
import useApi from "../../Common/Hooks/useApi";
|
||||
import { StatsResponseType } from "./SiteReplicationStatus";
|
||||
import BucketEntityStatus from "./LookupStatus/BucketEntityStatus";
|
||||
@@ -67,10 +73,12 @@ const EntityReplicationLookup = () => {
|
||||
sx={{
|
||||
display: "grid",
|
||||
alignItems: "center",
|
||||
gridTemplateColumns: {
|
||||
md: ".7fr .9fr 1.2fr .3fr",
|
||||
sm: "1.2fr .7fr .7fr .3fr",
|
||||
xs: "1fr",
|
||||
gridTemplateColumns: ".7fr .9fr 1.2fr .3fr",
|
||||
[`@media (max-width: ${breakPoints.sm}px)`]: {
|
||||
gridTemplateColumns: "1fr",
|
||||
},
|
||||
[`@media (max-width: ${breakPoints.md}px)`]: {
|
||||
gridTemplateColumns: "1.2fr .7fr .7fr .3fr",
|
||||
},
|
||||
gap: "15px",
|
||||
}}
|
||||
@@ -80,17 +88,17 @@ const EntityReplicationLookup = () => {
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
marginLeft: {
|
||||
md: "-25px",
|
||||
xs: "0px",
|
||||
marginLeft: -25,
|
||||
[`@media (max-width: ${breakPoints.sm}px)`]: {
|
||||
marginLeft: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<SelectWrapper
|
||||
<Select
|
||||
id="replicationEntityLookup"
|
||||
name="replicationEntityLookup"
|
||||
onChange={(e) => {
|
||||
setEntityType(e.target.value);
|
||||
onChange={(value) => {
|
||||
setEntityType(value);
|
||||
setStatsLoaded(false);
|
||||
}}
|
||||
label=""
|
||||
@@ -122,7 +130,7 @@ const EntityReplicationLookup = () => {
|
||||
flex: 2,
|
||||
}}
|
||||
>
|
||||
<InputBoxWrapper
|
||||
<InputBox
|
||||
id="replicationLookupEntityValue"
|
||||
name="replicationLookupEntityValue"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
@@ -159,10 +167,12 @@ const EntityReplicationLookup = () => {
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
display={"flex"}
|
||||
alignItems={"center"}
|
||||
justifyContent={"center"}
|
||||
marginTop={"45px"}
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
marginTop: 45,
|
||||
}}
|
||||
>
|
||||
<Loader style={{ width: 25, height: 25 }} />
|
||||
</Grid>
|
||||
|
||||
@@ -15,8 +15,56 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React from "react";
|
||||
import { Box } from "@mui/material";
|
||||
import { CircleIcon } from "mds";
|
||||
import styled from "styled-components";
|
||||
import get from "lodash/get";
|
||||
import { Box, CircleIcon } from "mds";
|
||||
|
||||
const LookupTableBase = styled.div(({ theme }) => ({
|
||||
marginTop: 15,
|
||||
table: {
|
||||
width: "100%",
|
||||
borderCollapse: "collapse",
|
||||
"& .feature-cell": {
|
||||
fontWeight: 600,
|
||||
fontSize: 14,
|
||||
paddingLeft: 15,
|
||||
},
|
||||
"& .status-cell": {
|
||||
textAlign: "center",
|
||||
},
|
||||
"& .header-cell": {
|
||||
textAlign: "center",
|
||||
},
|
||||
"& tr": {
|
||||
height: 38,
|
||||
"& td": {
|
||||
borderBottom: `1px solid ${get(theme, "borderColor", "#E2E2E2")}`,
|
||||
},
|
||||
"& th": {
|
||||
borderBottom: `2px solid ${get(theme, "borderColor", "#E2E2E2")}`,
|
||||
},
|
||||
},
|
||||
"& .indicator": {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
"& .min-icon": {
|
||||
height: 15,
|
||||
width: 15,
|
||||
},
|
||||
"&.active": {
|
||||
"& .min-icon": {
|
||||
fill: get(theme, "signalColors.good", "#4CCB92"),
|
||||
},
|
||||
},
|
||||
"&.deactivated": {
|
||||
"& .min-icon": {
|
||||
fill: get(theme, "signalColors.danger", "#C51B3F"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
const LookupStatusTable = ({
|
||||
matrixData = [],
|
||||
@@ -32,9 +80,9 @@ const LookupStatusTable = ({
|
||||
|
||||
const tableHeader = header.map((hC: string, hcIdx: number) => {
|
||||
return (
|
||||
<td className="header-cell" key={`${0}${hcIdx}`}>
|
||||
<th className="header-cell" key={`${0}${hcIdx}`}>
|
||||
{hC}
|
||||
</td>
|
||||
</th>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -51,35 +99,13 @@ const LookupStatusTable = ({
|
||||
}
|
||||
if (v === true) {
|
||||
indicator = (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
"& .min-icon": {
|
||||
fill: "#4CCB92",
|
||||
height: "15px",
|
||||
width: "15px",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box className={`indicator active`}>
|
||||
<CircleIcon />
|
||||
</Box>
|
||||
);
|
||||
} else if (v === false) {
|
||||
indicator = (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
"& .min-icon": {
|
||||
fill: "#C83B51",
|
||||
height: "15px",
|
||||
width: "15px",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box className={`indicator deactivated`}>
|
||||
<CircleIcon />
|
||||
</Box>
|
||||
);
|
||||
@@ -99,34 +125,8 @@ const LookupStatusTable = ({
|
||||
});
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
marginTop: "15px",
|
||||
table: {
|
||||
width: "100%",
|
||||
borderCollapse: "collapse",
|
||||
|
||||
"& .feature-cell": {
|
||||
fontWeight: 600,
|
||||
fontSize: "14px",
|
||||
paddingLeft: "15px",
|
||||
},
|
||||
"& .status-cell": {
|
||||
textAlign: "center",
|
||||
},
|
||||
"& .header-cell": {
|
||||
textAlign: "center",
|
||||
},
|
||||
"& tr": {
|
||||
height: "38px",
|
||||
},
|
||||
"tr td ": {
|
||||
border: "1px solid #f1f1f1",
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box sx={{ marginTop: "15px", marginBottom: "15px" }}>
|
||||
<LookupTableBase>
|
||||
<Box sx={{ marginTop: 15, marginBottom: 15 }}>
|
||||
Replication status for {entityType}: <strong>{entityName}</strong>.
|
||||
</Box>
|
||||
<table>
|
||||
@@ -135,7 +135,7 @@ const LookupStatusTable = ({
|
||||
</thead>
|
||||
<tbody>{tableRowsToRender}</tbody>
|
||||
</table>
|
||||
</Box>
|
||||
</LookupTableBase>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -14,36 +14,38 @@
|
||||
// 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, { useState } from "react";
|
||||
import List from "@mui/material/List";
|
||||
import ListItemButton from "@mui/material/ListItemButton";
|
||||
import { Box, DialogContentText, Tooltip } from "@mui/material";
|
||||
import React, { Fragment, useState } from "react";
|
||||
import {
|
||||
Button,
|
||||
Box,
|
||||
CircleIcon,
|
||||
ConfirmDeleteIcon,
|
||||
EditIcon,
|
||||
TrashIcon,
|
||||
DataTable,
|
||||
IColumns,
|
||||
ItemActions,
|
||||
Tooltip,
|
||||
} from "mds";
|
||||
import styled from "styled-components";
|
||||
import get from "lodash/get";
|
||||
import { ReplicationSite } from "./SiteReplication";
|
||||
import ConfirmDialog from "../../Common/ModalWrapper/ConfirmDialog";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import {
|
||||
formFieldStyles,
|
||||
modalStyleUtils,
|
||||
spacingUtils,
|
||||
} from "../../Common/FormComponents/common/styleLibrary";
|
||||
import TooltipWrapper from "../../Common/TooltipWrapper/TooltipWrapper";
|
||||
import EditSiteEndPoint from "./EditSiteEndPoint";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
...modalStyleUtils,
|
||||
...formFieldStyles,
|
||||
...spacingUtils,
|
||||
});
|
||||
const EndpointRender = styled.div(({ theme }) => ({
|
||||
display: "flex",
|
||||
gap: 10,
|
||||
"& .currentIndicator": {
|
||||
"& .min-icon": {
|
||||
width: 12,
|
||||
height: 12,
|
||||
fill: get(theme, "signalColors.good", "#4CCB92"),
|
||||
},
|
||||
},
|
||||
"& .endpointName": {
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap",
|
||||
},
|
||||
}));
|
||||
|
||||
const ReplicationSites = ({
|
||||
sites,
|
||||
@@ -53,215 +55,93 @@ const ReplicationSites = ({
|
||||
sites: ReplicationSite[];
|
||||
onDeleteSite: (isAll: boolean, sites: string[]) => void;
|
||||
onRefresh: () => void;
|
||||
classes: any;
|
||||
}) => {
|
||||
const [deleteSiteKey, setIsDeleteSiteKey] = useState<string>("");
|
||||
const [editSite, setEditSite] = useState<any>(null);
|
||||
|
||||
const replicationColumns: IColumns[] = [
|
||||
{ label: "Site Name", elementKey: "name" },
|
||||
{
|
||||
label: "Endpoint",
|
||||
elementKey: "endpoint",
|
||||
renderFullObject: true,
|
||||
renderFunction: (siteInfo) => (
|
||||
<EndpointRender>
|
||||
{siteInfo.isCurrent ? (
|
||||
<Tooltip tooltip={"This site/cluster"} placement="top">
|
||||
<Box className={"currentIndicator"}>
|
||||
<CircleIcon />
|
||||
</Box>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
<Tooltip tooltip={siteInfo.endpoint}>
|
||||
<Box className={"endpointName"}>{siteInfo.endpoint}</Box>
|
||||
</Tooltip>
|
||||
</EndpointRender>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const actions: ItemActions[] = [
|
||||
{
|
||||
type: "edit",
|
||||
onClick: (valueToSend) => setEditSite(valueToSend),
|
||||
tooltip: "Edit Endpoint",
|
||||
},
|
||||
{
|
||||
type: "delete",
|
||||
onClick: (valueToSend) => setIsDeleteSiteKey(valueToSend.name),
|
||||
tooltip: "Delete Site",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<List
|
||||
sx={{
|
||||
width: "100%",
|
||||
flex: 1,
|
||||
padding: "0",
|
||||
marginTop: "25px",
|
||||
height: "calc( 100vh - 640px )",
|
||||
minHeight: "250px",
|
||||
border: "1px solid #eaeaea",
|
||||
marginBottom: "25px",
|
||||
overflowY: "auto",
|
||||
}}
|
||||
component="div"
|
||||
aria-labelledby="nested-list-subheader"
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
borderBottom: "1px solid #f1f1f1",
|
||||
padding: "25px 25px 25px 20px",
|
||||
<Fragment>
|
||||
<DataTable
|
||||
columns={replicationColumns}
|
||||
records={sites}
|
||||
itemActions={actions}
|
||||
idField={"name"}
|
||||
customPaperHeight={"calc(100vh - 660px)"}
|
||||
sx={{ marginBottom: 20 }}
|
||||
/>
|
||||
|
||||
{deleteSiteKey !== "" && (
|
||||
<ConfirmDialog
|
||||
title={`Delete Replication Site`}
|
||||
confirmText={"Delete"}
|
||||
isOpen={deleteSiteKey !== ""}
|
||||
titleIcon={<ConfirmDeleteIcon />}
|
||||
isLoading={false}
|
||||
onConfirm={() => {
|
||||
onDeleteSite(false, [deleteSiteKey]);
|
||||
}}
|
||||
>
|
||||
List of Replicated Sites
|
||||
</Box>
|
||||
{sites.map((siteInfo, index) => {
|
||||
const key = `${siteInfo.name}`;
|
||||
onClose={() => {
|
||||
setIsDeleteSiteKey("");
|
||||
}}
|
||||
confirmationContent={
|
||||
<Fragment>
|
||||
Are you sure you want to remove the replication site:{" "}
|
||||
<strong>{deleteSiteKey}</strong>?
|
||||
</Fragment>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
return (
|
||||
<React.Fragment key={`${key}-${index}`}>
|
||||
<ListItemButton
|
||||
disableRipple
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
border: "1px solid #f1f1f1",
|
||||
borderLeft: "0",
|
||||
borderRight: "0",
|
||||
borderTop: "0",
|
||||
padding: "6px 10px 6px 20px",
|
||||
"&:hover": {
|
||||
background: "#bebbbb0d",
|
||||
},
|
||||
"&.expanded": {
|
||||
marginBottom: "0",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
flex: 2,
|
||||
display: "grid",
|
||||
gridTemplateColumns: {
|
||||
sm: "1fr 1fr ",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
{siteInfo.name}
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
{siteInfo.isCurrent ? (
|
||||
<Tooltip title={"This site/cluster"} placement="top">
|
||||
<Box
|
||||
sx={{
|
||||
"& .min-icon": {
|
||||
height: "12px",
|
||||
fill: "green",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<CircleIcon />
|
||||
</Box>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
<Tooltip title={siteInfo.endpoint}>
|
||||
<Box
|
||||
sx={{
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap",
|
||||
marginLeft: siteInfo.isCurrent ? "" : "24px",
|
||||
}}
|
||||
>
|
||||
{siteInfo.endpoint}
|
||||
</Box>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
marginLeft: "25px",
|
||||
marginRight: "25px",
|
||||
width: "60px",
|
||||
flexShrink: 0,
|
||||
|
||||
"& button": {
|
||||
borderRadius: "50%",
|
||||
background: "#F8F8F8",
|
||||
border: "none",
|
||||
|
||||
"&:hover": {
|
||||
background: "#E2E2E2",
|
||||
},
|
||||
|
||||
"& svg": {
|
||||
fill: "#696565",
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<TooltipWrapper tooltip="Delete Site">
|
||||
<Button
|
||||
id={`delete-site-${key}-${index}`}
|
||||
variant="secondary"
|
||||
disabled={siteInfo.isCurrent}
|
||||
icon={<TrashIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setIsDeleteSiteKey(key);
|
||||
}}
|
||||
style={{
|
||||
width: "25px",
|
||||
height: "25px",
|
||||
padding: "0",
|
||||
}}
|
||||
/>
|
||||
</TooltipWrapper>
|
||||
<TooltipWrapper tooltip={"Edit Endpoint"}>
|
||||
<Button
|
||||
id={`edit-icon-${key}-${index}`}
|
||||
variant="regular"
|
||||
disabled={siteInfo.isCurrent}
|
||||
icon={<EditIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setEditSite(siteInfo);
|
||||
}}
|
||||
style={{
|
||||
width: "25px",
|
||||
height: "25px",
|
||||
padding: "0",
|
||||
marginLeft: "8px",
|
||||
}}
|
||||
/>
|
||||
</TooltipWrapper>
|
||||
</Box>
|
||||
</ListItemButton>
|
||||
|
||||
{deleteSiteKey === key ? (
|
||||
<ConfirmDialog
|
||||
title={`Delete Replication Site`}
|
||||
confirmText={"Delete"}
|
||||
isOpen={true}
|
||||
titleIcon={<ConfirmDeleteIcon />}
|
||||
isLoading={false}
|
||||
onConfirm={() => {
|
||||
onDeleteSite(false, [key]);
|
||||
}}
|
||||
onClose={() => {
|
||||
setIsDeleteSiteKey("");
|
||||
}}
|
||||
confirmationContent={
|
||||
<DialogContentText>
|
||||
Are you sure you want to remove the replication site:{" "}
|
||||
{key}.?
|
||||
</DialogContentText>
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{editSite?.name === key ? (
|
||||
<EditSiteEndPoint
|
||||
onComplete={() => {
|
||||
setEditSite(null);
|
||||
onRefresh();
|
||||
}}
|
||||
editSite={editSite}
|
||||
onClose={() => {
|
||||
setEditSite(null);
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
</Box>
|
||||
{editSite !== null && (
|
||||
<EditSiteEndPoint
|
||||
onComplete={() => {
|
||||
setEditSite(null);
|
||||
onRefresh();
|
||||
}}
|
||||
editSite={editSite}
|
||||
onClose={() => {
|
||||
setEditSite(null);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(ReplicationSites);
|
||||
export default ReplicationSites;
|
||||
|
||||
@@ -15,13 +15,23 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment } from "react";
|
||||
import { Box } from "@mui/material";
|
||||
import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import TooltipWrapper from "../../Common/TooltipWrapper/TooltipWrapper";
|
||||
import { AddIcon, Button, RemoveIcon } from "mds";
|
||||
import { AddIcon, Box, Button, Grid, InputBox, RemoveIcon } from "mds";
|
||||
import { SiteInputRow } from "./Types";
|
||||
|
||||
interface ISRSiteInputRowProps {
|
||||
rowData: SiteInputRow;
|
||||
rowId: number;
|
||||
onFieldChange: (e: any, fieldName: string, index: number) => void;
|
||||
onAddClick?: (index: number) => void;
|
||||
onRemoveClick?: (index: number) => void;
|
||||
canAdd?: boolean;
|
||||
canRemove?: boolean;
|
||||
showRowActions?: boolean;
|
||||
disabledFields?: string[];
|
||||
fieldErrors?: Record<string, string>;
|
||||
}
|
||||
|
||||
const SRSiteInputRow = ({
|
||||
rowData,
|
||||
rowId: index,
|
||||
@@ -33,30 +43,17 @@ const SRSiteInputRow = ({
|
||||
showRowActions = true,
|
||||
disabledFields = [],
|
||||
fieldErrors = {},
|
||||
}: {
|
||||
rowData: SiteInputRow;
|
||||
rowId: number;
|
||||
onFieldChange: (e: any, fieldName: string, index: number) => void;
|
||||
onAddClick?: (index: number) => void;
|
||||
onRemoveClick?: (index: number) => void;
|
||||
canAdd?: boolean;
|
||||
canRemove?: boolean;
|
||||
showRowActions?: boolean;
|
||||
disabledFields?: string[];
|
||||
fieldErrors?: Record<string, string>;
|
||||
}) => {
|
||||
}: ISRSiteInputRowProps) => {
|
||||
const { endpoint = "", accessKey = "", secretKey = "", name = "" } = rowData;
|
||||
return (
|
||||
<Fragment key={`${index}`}>
|
||||
<Box>
|
||||
<InputBoxWrapper
|
||||
<InputBox
|
||||
id={`add-rep-peer-site-${index}`}
|
||||
name={`add-rep-peer-site-${index}`}
|
||||
placeholder={`site-name`}
|
||||
label=""
|
||||
extraInputProps={{
|
||||
readOnly: disabledFields.includes("name"),
|
||||
}}
|
||||
readOnly={disabledFields.includes("name")}
|
||||
value={name}
|
||||
onChange={(e) => {
|
||||
onFieldChange(e, "name", index);
|
||||
@@ -65,14 +62,12 @@ const SRSiteInputRow = ({
|
||||
/>
|
||||
</Box>
|
||||
<Box>
|
||||
<InputBoxWrapper
|
||||
<InputBox
|
||||
id={`add-rep-peer-site-ep-${index}`}
|
||||
name={`add-rep-peer-site-ep-${index}`}
|
||||
placeholder={`https://dr.minio-storage:900${index}`}
|
||||
label=""
|
||||
extraInputProps={{
|
||||
readOnly: disabledFields.includes("endpoint"),
|
||||
}}
|
||||
readOnly={disabledFields.includes("endpoint")}
|
||||
error={fieldErrors["endpoint"]}
|
||||
value={endpoint}
|
||||
onChange={(e) => {
|
||||
@@ -83,7 +78,7 @@ const SRSiteInputRow = ({
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<InputBoxWrapper
|
||||
<InputBox
|
||||
id={`add-rep-peer-site-ac-${index}`}
|
||||
name={`add-rep-peer-site-ac-${index}`}
|
||||
label=""
|
||||
@@ -98,7 +93,7 @@ const SRSiteInputRow = ({
|
||||
/>
|
||||
</Box>
|
||||
<Box>
|
||||
<InputBoxWrapper
|
||||
<InputBox
|
||||
id={`add-rep-peer-site-sk-${index}`}
|
||||
name={`add-rep-peer-site-sk-${index}`}
|
||||
label=""
|
||||
@@ -113,7 +108,7 @@ const SRSiteInputRow = ({
|
||||
data-test-id={`add-rep-peer-site-sk-${index}`}
|
||||
/>
|
||||
</Box>
|
||||
<Grid item xs={12} alignItems={"center"} display={"flex"}>
|
||||
<Grid item xs={12} sx={{ alignItems: "center", display: "flex" }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
|
||||
@@ -16,31 +16,32 @@
|
||||
|
||||
import React, { Fragment, useEffect, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import { Box, DialogContentText, Grid } from "@mui/material";
|
||||
import useApi from "../../Common/Hooks/useApi";
|
||||
import ReplicationSites from "./ReplicationSites";
|
||||
import {
|
||||
ActionLink,
|
||||
AddIcon,
|
||||
Box,
|
||||
Button,
|
||||
ClustersIcon,
|
||||
ConfirmDeleteIcon,
|
||||
Grid,
|
||||
HelpBox,
|
||||
Loader,
|
||||
PageLayout,
|
||||
RecoverIcon,
|
||||
SectionTitle,
|
||||
TrashIcon,
|
||||
} from "mds";
|
||||
import { ErrorResponseHandler } from "../../../../common/types";
|
||||
import ConfirmDialog from "../../Common/ModalWrapper/ConfirmDialog";
|
||||
import { IAM_PAGES } from "../../../../common/SecureComponent/permissions";
|
||||
import {
|
||||
setErrorSnackMessage,
|
||||
setHelpName,
|
||||
setSnackBarMessage,
|
||||
} from "../../../../systemSlice";
|
||||
import AButton from "../../Common/AButton/AButton";
|
||||
import { useAppDispatch } from "../../../../store";
|
||||
import ConfirmDialog from "../../Common/ModalWrapper/ConfirmDialog";
|
||||
import useApi from "../../Common/Hooks/useApi";
|
||||
import ReplicationSites from "./ReplicationSites";
|
||||
import TooltipWrapper from "../../Common/TooltipWrapper/TooltipWrapper";
|
||||
import PageHeaderWrapper from "../../Common/PageHeaderWrapper/PageHeaderWrapper";
|
||||
import HelpMenu from "../../HelpMenu";
|
||||
@@ -120,59 +121,64 @@ const SiteReplication = () => {
|
||||
return (
|
||||
<Fragment>
|
||||
<PageHeaderWrapper label={"Site Replication"} actions={<HelpMenu />} />
|
||||
|
||||
<PageLayout>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-end",
|
||||
"& button": {
|
||||
marginLeft: "8px",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{hasSites ? (
|
||||
<Fragment>
|
||||
<TooltipWrapper tooltip={"Delete All"}>
|
||||
<Button
|
||||
id={"delete-all"}
|
||||
label={"Delete All"}
|
||||
variant="secondary"
|
||||
disabled={isRemoving}
|
||||
icon={<TrashIcon />}
|
||||
onClick={() => {
|
||||
setIsDeleteAll(true);
|
||||
}}
|
||||
/>
|
||||
</TooltipWrapper>
|
||||
<TooltipWrapper tooltip={"Replication Status"}>
|
||||
<Button
|
||||
id={"replication-status"}
|
||||
label={"Replication Status"}
|
||||
variant="regular"
|
||||
icon={<RecoverIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
navigate(IAM_PAGES.SITE_REPLICATION_STATUS);
|
||||
}}
|
||||
/>
|
||||
</TooltipWrapper>
|
||||
</Fragment>
|
||||
) : null}
|
||||
<TooltipWrapper tooltip={"Add Replication Sites"}>
|
||||
<Button
|
||||
id={"add-replication-site"}
|
||||
label={"Add Sites"}
|
||||
variant="callAction"
|
||||
disabled={isRemoving}
|
||||
icon={<AddIcon />}
|
||||
onClick={() => {
|
||||
navigate(IAM_PAGES.SITE_REPLICATION_ADD);
|
||||
<SectionTitle
|
||||
separator={!!hasSites}
|
||||
sx={{ marginBottom: 15 }}
|
||||
actions={
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-end",
|
||||
gap: 8,
|
||||
}}
|
||||
/>
|
||||
</TooltipWrapper>
|
||||
</Box>
|
||||
>
|
||||
{hasSites ? (
|
||||
<Fragment>
|
||||
<TooltipWrapper tooltip={"Delete All"}>
|
||||
<Button
|
||||
id={"delete-all"}
|
||||
label={"Delete All"}
|
||||
variant="secondary"
|
||||
disabled={isRemoving}
|
||||
icon={<TrashIcon />}
|
||||
onClick={() => {
|
||||
setIsDeleteAll(true);
|
||||
}}
|
||||
/>
|
||||
</TooltipWrapper>
|
||||
<TooltipWrapper tooltip={"Replication Status"}>
|
||||
<Button
|
||||
id={"replication-status"}
|
||||
label={"Replication Status"}
|
||||
variant="regular"
|
||||
icon={<RecoverIcon />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
navigate(IAM_PAGES.SITE_REPLICATION_STATUS);
|
||||
}}
|
||||
/>
|
||||
</TooltipWrapper>
|
||||
</Fragment>
|
||||
) : null}
|
||||
<TooltipWrapper tooltip={"Add Replication Sites"}>
|
||||
<Button
|
||||
id={"add-replication-site"}
|
||||
label={"Add Sites"}
|
||||
variant="callAction"
|
||||
disabled={isRemoving}
|
||||
icon={<AddIcon />}
|
||||
onClick={() => {
|
||||
navigate(IAM_PAGES.SITE_REPLICATION_ADD);
|
||||
}}
|
||||
/>
|
||||
</TooltipWrapper>
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
{hasSites ? "List of Replicated Sites" : ""}
|
||||
</SectionTitle>
|
||||
{hasSites ? (
|
||||
<ReplicationSites
|
||||
sites={sites}
|
||||
@@ -193,12 +199,7 @@ const SiteReplication = () => {
|
||||
</Box>
|
||||
) : null}
|
||||
{!hasSites && !isSiteInfoLoading ? (
|
||||
<Grid
|
||||
container
|
||||
justifyContent={"center"}
|
||||
alignContent={"center"}
|
||||
alignItems={"center"}
|
||||
>
|
||||
<Grid container>
|
||||
<Grid item xs={8}>
|
||||
<HelpBox
|
||||
title={"Site Replication"}
|
||||
@@ -211,13 +212,15 @@ const SiteReplication = () => {
|
||||
<br />
|
||||
<br />
|
||||
To get started,{" "}
|
||||
<AButton
|
||||
<ActionLink
|
||||
isLoading={false}
|
||||
label={""}
|
||||
onClick={() => {
|
||||
navigate(IAM_PAGES.SITE_REPLICATION_ADD);
|
||||
}}
|
||||
>
|
||||
Add a Replication Site
|
||||
</AButton>
|
||||
</ActionLink>
|
||||
.
|
||||
<br />
|
||||
You can learn more at our{" "}
|
||||
@@ -294,9 +297,9 @@ const SiteReplication = () => {
|
||||
setIsDeleteAll(false);
|
||||
}}
|
||||
confirmationContent={
|
||||
<DialogContentText>
|
||||
<Fragment>
|
||||
Are you sure you want to remove all the replication sites?.
|
||||
</DialogContentText>
|
||||
</Fragment>
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
@@ -15,30 +15,31 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment, useEffect, useState } from "react";
|
||||
import { Box, Grid } from "@mui/material";
|
||||
import {
|
||||
BackLink,
|
||||
Box,
|
||||
breakPoints,
|
||||
BucketsIcon,
|
||||
Button,
|
||||
Grid,
|
||||
GroupsIcon,
|
||||
IAMPoliciesIcon,
|
||||
Loader,
|
||||
PageLayout,
|
||||
RefreshIcon,
|
||||
UsersIcon,
|
||||
SectionTitle,
|
||||
} from "mds";
|
||||
import useApi from "../../Common/Hooks/useApi";
|
||||
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { IAM_PAGES } from "../../../../common/SecureComponent/permissions";
|
||||
import ScreenTitle from "../../Common/ScreenTitle/ScreenTitle";
|
||||
import { useAppDispatch } from "../../../../store";
|
||||
import { setHelpName } from "../../../../systemSlice";
|
||||
import useApi from "../../Common/Hooks/useApi";
|
||||
import StatusCountCard from "../../Dashboard/BasicDashboard/StatusCountCard";
|
||||
import EntityReplicationLookup from "./EntityReplicationLookup";
|
||||
import TooltipWrapper from "../../Common/TooltipWrapper/TooltipWrapper";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import PageHeaderWrapper from "../../Common/PageHeaderWrapper/PageHeaderWrapper";
|
||||
import HelpMenu from "../../HelpMenu";
|
||||
import { useAppDispatch } from "../../../../store";
|
||||
import { setHelpName } from "../../../../systemSlice";
|
||||
|
||||
export type StatsResponseType = {
|
||||
maxBuckets?: number;
|
||||
@@ -66,11 +67,11 @@ const SREntityStatus = ({
|
||||
const statEntityLen = Object.keys(entityStatObj || {})?.length;
|
||||
return (
|
||||
<Box
|
||||
withBorders
|
||||
sx={{
|
||||
border: "1px solid #f1f1f1",
|
||||
padding: "25px",
|
||||
maxWidth: {
|
||||
sm: "100%",
|
||||
[`@media (min-width: ${breakPoints.sm}px)`]: {
|
||||
maxWidth: "100%",
|
||||
},
|
||||
}}
|
||||
>
|
||||
@@ -140,8 +141,7 @@ const SiteReplicationStatus = () => {
|
||||
/>
|
||||
|
||||
<PageLayout>
|
||||
<ScreenTitle
|
||||
title={"Replication status from all Sites"}
|
||||
<SectionTitle
|
||||
actions={
|
||||
<Fragment>
|
||||
<TooltipWrapper tooltip={"Refresh"}>
|
||||
@@ -158,17 +158,22 @@ const SiteReplicationStatus = () => {
|
||||
</TooltipWrapper>
|
||||
</Fragment>
|
||||
}
|
||||
/>
|
||||
separator
|
||||
>
|
||||
Replication status from all Sites
|
||||
</SectionTitle>
|
||||
|
||||
{!isStatsLoading ? (
|
||||
<Box
|
||||
sx={{
|
||||
display: "grid",
|
||||
marginTop: "25px",
|
||||
gridTemplateColumns: {
|
||||
md: "1fr 1fr 1fr 1fr",
|
||||
sm: "1fr 1fr",
|
||||
xs: "1fr",
|
||||
gridTemplateColumns: "1fr 1fr 1fr 1fr",
|
||||
[`@media (max-width: ${breakPoints.md}px)`]: {
|
||||
gridTemplateColumns: "1fr 1fr",
|
||||
},
|
||||
[`@media (max-width: ${breakPoints.sm}px)`]: {
|
||||
gridTemplateColumns: "1fr",
|
||||
},
|
||||
gap: "30px",
|
||||
}}
|
||||
@@ -202,21 +207,23 @@ const SiteReplicationStatus = () => {
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
display={"flex"}
|
||||
alignItems={"center"}
|
||||
justifyContent={"center"}
|
||||
marginTop={"45px"}
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
marginTop: 45,
|
||||
}}
|
||||
>
|
||||
<Loader style={{ width: 25, height: 25 }} />
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
<Box
|
||||
withBorders
|
||||
sx={{
|
||||
border: "1px solid #eaeaea",
|
||||
minHeight: {
|
||||
sm: "450px",
|
||||
xs: "250px",
|
||||
minHeight: 450,
|
||||
[`@media (max-width: ${breakPoints.sm}px)`]: {
|
||||
minHeight: 250,
|
||||
},
|
||||
marginTop: "25px",
|
||||
padding: "25px",
|
||||
|
||||
@@ -15,8 +15,98 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React from "react";
|
||||
import { Box } from "@mui/material";
|
||||
import { CircleIcon } from "mds";
|
||||
import styled from "styled-components";
|
||||
import get from "lodash/get";
|
||||
import { Box, breakPoints, CircleIcon } from "mds";
|
||||
|
||||
const StatusCountBase = styled.div(({ theme }) => ({
|
||||
fontFamily: "Inter,sans-serif",
|
||||
maxWidth: "321px",
|
||||
display: "flex",
|
||||
marginLeft: "auto",
|
||||
marginRight: "auto",
|
||||
cursor: "default",
|
||||
color: get(theme, "signalColors.main", "#07193E"),
|
||||
"& .mainBox": {
|
||||
flex: 1,
|
||||
display: "flex",
|
||||
padding: "0 8px 0 8px",
|
||||
[`@media (max-width: ${breakPoints.sm}px)`]: {
|
||||
padding: "0 10px 0 10px",
|
||||
},
|
||||
"& .indicatorIcon": {
|
||||
width: "20px",
|
||||
height: "20px",
|
||||
marginTop: "8px",
|
||||
maxWidth: "26px",
|
||||
"& .min-icon": {
|
||||
width: "16px",
|
||||
height: "16px",
|
||||
},
|
||||
},
|
||||
"& .indicatorContainer": {
|
||||
flex: 1,
|
||||
display: "flex",
|
||||
flexFlow: "column",
|
||||
"& .indicatorLabel": {
|
||||
fontSize: "16px",
|
||||
fontWeight: 600,
|
||||
},
|
||||
"& .counterIndicator": {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "5px",
|
||||
justifyContent: "space-between",
|
||||
paddingBottom: 0,
|
||||
fontSize: "55px",
|
||||
[`@media (max-width: ${breakPoints.sm}px)`]: {
|
||||
paddingBottom: 10,
|
||||
fontSize: "35px",
|
||||
},
|
||||
[`@media (max-width: ${breakPoints.lg}px)`]: {
|
||||
fontSize: "45px",
|
||||
},
|
||||
[`@media (max-width: ${breakPoints.xl}px)`]: {
|
||||
fontSize: "50px",
|
||||
},
|
||||
flexFlow: "row",
|
||||
fontWeight: 600,
|
||||
|
||||
"& .stat-text": {
|
||||
color: get(theme, "mutedText", "#87888D"),
|
||||
fontSize: "12px",
|
||||
marginTop: "8px",
|
||||
},
|
||||
"& .stat-value": {
|
||||
textAlign: "center",
|
||||
height: "50px",
|
||||
},
|
||||
"& .min-icon": {
|
||||
marginRight: "8px",
|
||||
marginTop: "8px",
|
||||
height: "10px",
|
||||
width: "10px",
|
||||
},
|
||||
},
|
||||
"& .onlineCounter": {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
marginTop: "5px",
|
||||
"& .min-icon": {
|
||||
fill: get(theme, "signalColors.good", "#4CCB92"),
|
||||
},
|
||||
},
|
||||
"& .offlineCount": {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
marginTop: "8px",
|
||||
"& .min-icon": {
|
||||
fill: get(theme, "signalColors.danger", "#C51B3F"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export const StatusCountCard = ({
|
||||
onlineCount = 0,
|
||||
@@ -34,91 +124,15 @@ export const StatusCountCard = ({
|
||||
notOkStatusText?: string;
|
||||
}) => {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
fontFamily: "Inter,sans-serif",
|
||||
color: "#07193E",
|
||||
maxWidth: "321px",
|
||||
display: "flex",
|
||||
marginLeft: "auto",
|
||||
marginRight: "auto",
|
||||
cursor: "default",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
flex: 1,
|
||||
display: "flex",
|
||||
padding: {
|
||||
sm: "0 8px 0 8px",
|
||||
xs: "0 10px 0 10px",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
flex: 1,
|
||||
display: "flex",
|
||||
flexFlow: "column",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
fontSize: "16px",
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</Box>
|
||||
<StatusCountBase>
|
||||
<Box className={"mainBox"}>
|
||||
<Box className={"indicatorContainer"}>
|
||||
<Box className={"indicatorLabel"}>{label}</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "5px",
|
||||
justifyContent: "space-between",
|
||||
paddingBottom: {
|
||||
md: "0px",
|
||||
xs: "10px",
|
||||
},
|
||||
fontSize: {
|
||||
xl: "55px",
|
||||
lg: "50px",
|
||||
md: "45px",
|
||||
xs: "35px",
|
||||
},
|
||||
flexFlow: "row",
|
||||
fontWeight: 600,
|
||||
|
||||
"& .stat-text": {
|
||||
color: "#696969",
|
||||
fontSize: "12px",
|
||||
marginTop: "8px",
|
||||
},
|
||||
"& .stat-value": {
|
||||
textAlign: "center",
|
||||
height: "50px",
|
||||
},
|
||||
"& .min-icon": {
|
||||
marginRight: "8px",
|
||||
marginTop: "8px",
|
||||
height: "10px",
|
||||
width: "10px",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box className={"counterIndicator"}>
|
||||
<Box>
|
||||
<Box className="stat-value">{onlineCount}</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
marginTop: "5px",
|
||||
"& .min-icon": {
|
||||
fill: "#4CCB92",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box className={"onlineCounter"}>
|
||||
<CircleIcon />
|
||||
<div className="stat-text">{okStatusText}</div>
|
||||
</Box>
|
||||
@@ -126,38 +140,16 @@ export const StatusCountCard = ({
|
||||
|
||||
<Box>
|
||||
<Box className="stat-value">{offlineCount}</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
marginTop: "8px",
|
||||
"& .min-icon": {
|
||||
fill: "#C83B51",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box className={"offlineCount"}>
|
||||
<CircleIcon />{" "}
|
||||
<div className="stat-text">{notOkStatusText}</div>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
width: "20px",
|
||||
height: "20px",
|
||||
marginTop: "8px",
|
||||
maxWidth: "26px",
|
||||
"& .min-icon": {
|
||||
width: "16px",
|
||||
height: "16px",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{icon}
|
||||
</Box>
|
||||
<Box className={"indicatorIcon"}>{icon}</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</StatusCountBase>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user