diff --git a/portal-ui/src/icons/PrometheusErrorIcon.tsx b/portal-ui/src/icons/PrometheusErrorIcon.tsx new file mode 100644 index 000000000..a6a464d5c --- /dev/null +++ b/portal-ui/src/icons/PrometheusErrorIcon.tsx @@ -0,0 +1,69 @@ +// 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 . + +import * as React from "react"; +import { SVGProps } from "react"; + +const PrometheusErrorIcon = (props: SVGProps) => ( + + + + + + + + + + + + +); + +export default PrometheusErrorIcon; diff --git a/portal-ui/src/icons/index.ts b/portal-ui/src/icons/index.ts index c8dea142d..deec556b5 100644 --- a/portal-ui/src/icons/index.ts +++ b/portal-ui/src/icons/index.ts @@ -162,3 +162,4 @@ export { default as HelpIconFilled } from "./HelpIconFilled"; export { default as CallHomeFeatureIcon } from "./CallHomeFeatureIcon"; export { default as DiagnosticsFeatureIcon } from "./DiagnosticsFeatureIcon"; export { default as PerformanceFeatureIcon } from "./PerformanceFeatureIcon"; +export { default as PrometheusErrorIcon } from "./PrometheusErrorIcon"; diff --git a/portal-ui/src/screens/Console/Dashboard/BasicDashboard/BasicDashboard.tsx b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/BasicDashboard.tsx index 5ba55bbb6..e813ad94a 100644 --- a/portal-ui/src/screens/Console/Dashboard/BasicDashboard/BasicDashboard.tsx +++ b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/BasicDashboard.tsx @@ -1,5 +1,5 @@ // This file is part of MinIO Console Server -// Copyright (c) 2021 MinIO, Inc. +// 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 @@ -14,95 +14,86 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import React, { Fragment, useState } from "react"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import withStyles from "@mui/styles/withStyles"; -import Grid from "@mui/material/Grid"; -import { IDriveInfo, Usage } from "../types"; -import { calculateBytes, representationNumber } from "../../../../common/utils"; -import { TabPanel } from "../../../shared/tabs"; -import ServerInfoCard from "./ServerInfoCard"; -import DriveInfoCard from "./DriveInfoCard"; -import CommonCard from "../CommonCard"; -import TabSelector from "../../Common/TabSelector/TabSelector"; -import GeneralUsePaginator from "../../Common/GeneralUsePaginator/GeneralUsePaginator"; -import { widgetContainerCommon } from "../../Common/FormComponents/common/styleLibrary"; -import { PrometheusIcon } from "../../../../icons"; +import React, { Fragment } from "react"; +import { Box } from "@mui/material"; +import { + BucketsIcon, + DrivesIcon, + PrometheusErrorIcon, + ServersIcon, + TotalObjectsIcon, +} from "../../../../icons"; import HelpBox from "../../../../common/HelpBox"; +import { calculateBytes, representationNumber } from "../../../../common/utils"; +import { IDriveInfo, Usage } from "../types"; +import StatusCountCard from "./StatusCountCard"; +import groupBy from "lodash/groupBy"; +import ServersList from "./ServersList"; +import CounterCard from "./CounterCard"; +import ReportedUsage from "./ReportedUsage"; -const styles = (theme: Theme) => - createStyles({ - generalStatusTitle: { - color: "#767676", - fontSize: 16, - fontWeight: "bold", - margin: "15px 10px 0 10px", - }, - paginatorContainer: { - maxWidth: 1185, - width: "100%", - }, - ...widgetContainerCommon, - }); +const BoxItem = ({ + children, + background = "#ffffff", +}: { + children: any; + background?: string; +}) => { + return ( + + {children} + + ); +}; interface IDashboardProps { - classes: any; usage: Usage | null; } -const itemsPerPage = 5; - -const BasicDashboard = ({ classes, usage }: IDashboardProps) => { - const [curTab, setCurTab] = useState(0); - const [serversPageNumber, setServersPageNumber] = useState(1); - const [drivesPageNumber, setDrivesPageNumber] = useState(1); - - const prettyUsage = (usage: string | undefined) => { - if (usage === undefined) { - return { total: "0", unit: "Mi" }; - } - - const calculatedBytes = calculateBytes(usage); - - return calculatedBytes; - }; - - const prettyNumber = (usage: number | undefined) => { - if (usage === undefined) { +const getServersList = (usage: Usage | null) => { + if (usage !== null) { + return usage.servers.sort(function (a, b) { + const nameA = a.endpoint.toLowerCase(); + const nameB = b.endpoint.toLowerCase(); + if (nameA < nameB) { + return -1; + } + if (nameA > nameB) { + return 1; + } return 0; - } + }); + } - return usage.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); - }; + return []; +}; - const makeServerArray = (usage: Usage | null) => { - if (usage !== null) { - return usage.servers.sort(function (a, b) { - var nameA = a.endpoint.toLowerCase(); - var nameB = b.endpoint.toLowerCase(); - if (nameA < nameB) { - return -1; - } - if (nameA > nameB) { - return 1; - } - return 0; - }); - } +const prettyUsage = (usage: string | undefined) => { + if (usage === undefined) { + return { total: "0", unit: "Mi" }; + } - return []; - }; + return calculateBytes(usage); +}; - const serverArray = makeServerArray(usage || null); +const BasicDashboard = ({ usage }: IDashboardProps) => { + const usageValue = usage && usage.usage ? usage.usage.toString() : "0"; + const usageToRepresent = prettyUsage(usageValue); - const usageToRepresent = prettyUsage( - usage && usage.usage ? usage.usage.toString() : "0" - ); + const serverList = getServersList(usage || null); let allDrivesArray: IDriveInfo[] = []; - serverArray.forEach((server) => { + serverList.forEach((server) => { const drivesInput = server.drives.map((drive) => { return drive; }); @@ -110,29 +101,35 @@ const BasicDashboard = ({ classes, usage }: IDashboardProps) => { allDrivesArray = [...allDrivesArray, ...drivesInput]; }); - const splitedServers = serverArray.slice( - serversPageNumber * itemsPerPage - itemsPerPage, - serversPageNumber * itemsPerPage - ); - - const splitedDrives = allDrivesArray.slice( - drivesPageNumber * itemsPerPage - itemsPerPage, - drivesPageNumber * itemsPerPage - ); + const serversGroup = groupBy(serverList, "state"); + const { offline: offlineServers = [], online: onlineServers = [] } = + serversGroup; + const drivesGroup = groupBy(allDrivesArray, "state"); + const { offline: offlineDrives = [], ok: onlineDrives = [] } = drivesGroup; return ( - -
- {usage?.prometheusNotReady && ( - - + + + + {usage?.prometheusNotReady && ( } + iconComponent={} title={"We can't retrieve advanced metrics at this time"} help={ @@ -145,160 +142,131 @@ const BasicDashboard = ({ classes, usage }: IDashboardProps) => { } /> - - - )} - - - General Status - - - - - - - - - - - - - - - - - { - setCurTab(newValue); - }} - tabOptions={[{ label: "Servers" }, { label: "Drives" }]} - /> - - - -
- -
- {splitedServers.map((server, index) => ( - - - - ))} -
- -
- -
- {splitedDrives.map((drive, index) => ( - - - - ))} -
-
-
- {!usage?.prometheusNotReady && ( - - + )} + + {!usage?.prometheusNotReady && ( } - title={"Monitoring"} + iconComponent={} + title={"We can’t retrieve advanced metrics at this time."} help={ - - The MinIO Dashboard is displaying basic metrics only due to - missing the{" "} - + - necessary settings - {" "} - for displaying extended metrics. -
-
- See{" "} - + theme.colors.link, + }, + }} > - Collect MinIO Metrics Using Prometheus - {" "} - for a complete tutorial on scraping and visualizing MinIO - metrics with Prometheus. -
+ + Read more about Prometheus on our Docs site. + + + } /> -
-
- )} - + )} + + + + + + } + counterValue={usage ? representationNumber(usage.buckets) : 0} + /> + + + } + counterValue={usage ? representationNumber(usage.objects) : 0} + /> + + + } + /> + + + } + /> + + + + + + + + + + + + + + ); }; -export default withStyles(styles)(BasicDashboard); +export default BasicDashboard; diff --git a/portal-ui/src/screens/Console/Dashboard/BasicDashboard/CounterCard.tsx b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/CounterCard.tsx new file mode 100644 index 000000000..a865faa05 --- /dev/null +++ b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/CounterCard.tsx @@ -0,0 +1,118 @@ +// 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 . + +import { Box, Tooltip } from "@mui/material"; +import React from "react"; + +const CounterCard = ({ + counterValue, + label = "", + icon = null, +}: { + counterValue: string | number; + label?: any; + icon?: any; +}) => { + return ( + + + + + {label} + + + + + {counterValue} + + + + + {icon} + + + + ); +}; + +export default CounterCard; diff --git a/portal-ui/src/screens/Console/Dashboard/BasicDashboard/DriveInfoCard.tsx b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/DriveInfoCard.tsx deleted file mode 100644 index 24d1e241f..000000000 --- a/portal-ui/src/screens/Console/Dashboard/BasicDashboard/DriveInfoCard.tsx +++ /dev/null @@ -1,91 +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 . - -import React, { Fragment } from "react"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import withStyles from "@mui/styles/withStyles"; -import Grid from "@mui/material/Grid"; -import { IDriveInfo } from "../types"; -import { niceBytes } from "../../../../common/utils"; -import { Card, CardHeader } from "@mui/material"; -import { CircleIcon } from "../../../../icons"; -import { commonDashboardInfocard } from "../../Common/FormComponents/common/styleLibrary"; - -const styles = (theme: Theme) => - createStyles({ - ...commonDashboardInfocard, - }); - -interface ICardProps { - classes: any; - drive: IDriveInfo; -} - -const DriveInfoCard = ({ classes, drive }: ICardProps) => { - const driveStatusToClass = (health_status: string) => { - switch (health_status) { - case "offline": - return classes.redState; - case "ok": - return classes.greenState; - default: - return classes.greyState; - } - }; - - return ( - - - - {drive.state && ( - - - - )} - {drive.endpoint || ""} -
- } - subheader={ - - - Capacity:{" "} - {niceBytes( - drive.totalSpace ? drive.totalSpace.toString() : "0" - )} - - - Used:{" "} - {niceBytes(drive.usedSpace ? drive.usedSpace.toString() : "0")} - - - Available:{" "} - {niceBytes( - drive.availableSpace ? drive.availableSpace.toString() : "0" - )} - - - } - /> - -
- ); -}; - -export default withStyles(styles)(DriveInfoCard); diff --git a/portal-ui/src/screens/Console/Dashboard/BasicDashboard/DriveInfoItem.tsx b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/DriveInfoItem.tsx new file mode 100644 index 000000000..abf83c541 --- /dev/null +++ b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/DriveInfoItem.tsx @@ -0,0 +1,175 @@ +// 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 . + +import React from "react"; +import { Theme } from "@mui/material/styles"; +import createStyles from "@mui/styles/createStyles"; +import withStyles from "@mui/styles/withStyles"; +import { IDriveInfo } from "../types"; +import { niceBytes } from "../../../../common/utils"; +import { Box } from "@mui/material"; +import { CircleIcon, DrivesIcon } from "../../../../icons"; +import { commonDashboardInfocard } from "../../Common/FormComponents/common/styleLibrary"; +import { STATUS_COLORS } from "./Utils"; + +const styles = (theme: Theme) => + createStyles({ + ...commonDashboardInfocard, + }); + +interface ICardProps { + classes?: any; + drive: IDriveInfo; +} + +const driveStatusColor = (health_status: string) => { + switch (health_status) { + case "offline": + return STATUS_COLORS.RED; + case "ok": + return STATUS_COLORS.GREEN; + default: + return STATUS_COLORS.YELLOW; + } +}; + +const DriveInfoItem = ({ classes, drive }: ICardProps) => { + return ( + + + + + + + + {drive.state && } +
{drive.endpoint || ""}
+
+ + + + +
+ {niceBytes(drive.totalSpace ? drive.totalSpace.toString() : "0")} +
+
+ + + +
+ {niceBytes(drive.usedSpace ? drive.usedSpace.toString() : "0")} +
+
+ + +
+ {niceBytes( + drive.availableSpace ? drive.availableSpace.toString() : "0" + )} +
+
+
+
+
+ ); +}; + +export default withStyles(styles)(DriveInfoItem); diff --git a/portal-ui/src/screens/Console/Dashboard/BasicDashboard/ReportedUsage.tsx b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/ReportedUsage.tsx new file mode 100644 index 000000000..aaeef0e62 --- /dev/null +++ b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/ReportedUsage.tsx @@ -0,0 +1,85 @@ +// 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 . + +import { ReportedUsageIcon } from "../../../../icons"; +import { Box, Tooltip } from "@mui/material"; +import React from "react"; + +const ReportedUsage = ({ + usageValue, + total, + unit, +}: { + usageValue: string; + total: number | string; + unit: string; +}) => { + return ( + +
+ Reported Usage +
+ + + + + +
+ ); +}; + +export default ReportedUsage; diff --git a/portal-ui/src/screens/Console/Dashboard/BasicDashboard/ServerInfoCard.tsx b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/ServerInfoCard.tsx deleted file mode 100644 index 1a1380e89..000000000 --- a/portal-ui/src/screens/Console/Dashboard/BasicDashboard/ServerInfoCard.tsx +++ /dev/null @@ -1,121 +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 . -import React from "react"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import withStyles from "@mui/styles/withStyles"; -import Grid from "@mui/material/Grid"; -import { ServerInfo } from "../types"; -import { niceDays } from "../../../../common/utils"; -import { Card, CardHeader } from "@mui/material"; -import { CircleIcon, VersionIcon } from "../../../../icons"; -import get from "lodash/get"; -import { commonDashboardInfocard } from "../../Common/FormComponents/common/styleLibrary"; - -const styles = (theme: Theme) => - createStyles({ - ...commonDashboardInfocard, - }); - -interface ICardProps { - classes: any; - server: ServerInfo; - index: number; -} - -const ServerInfoCard = ({ classes, server, index }: ICardProps) => { - const serverStatusToClass = (health_status: string) => { - switch (health_status) { - case "offline": - return classes.redState; - case "online": - return classes.greenState; - default: - return classes.greyState; - } - }; - const networkKeys = Object.keys(get(server, "network", {})); - const networkTotal = networkKeys.length; - const totalDrives = server.drives ? server.drives.length : 0; - const activeNetwork = networkKeys.reduce((acc: number, currValue: string) => { - const item = server.network[currValue]; - if (item === "online") { - return acc + 1; - } - return acc; - }, 0); - const activeDisks = server.drives - ? server.drives.filter((element) => element.state === "ok").length - : 0; - return ( - - -
Server {index}
-
- {server.state && ( - - - - )} - {server.endpoint || ""} -
- - } - subheader={ - - - - - - Drives: {activeDisks}/{totalDrives}{" "} - - - - - - Network: {activeNetwork}/{networkTotal}{" "} - - - Uptime: {server.uptime ? niceDays(server.uptime) : "N/A"} - - - - Version {server.version ? server.version : "N/A"} - - - } - /> -
- ); -}; -export default withStyles(styles)(ServerInfoCard); diff --git a/portal-ui/src/screens/Console/Dashboard/BasicDashboard/ServerInfoItem.tsx b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/ServerInfoItem.tsx new file mode 100644 index 000000000..0bcb41fd6 --- /dev/null +++ b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/ServerInfoItem.tsx @@ -0,0 +1,239 @@ +// 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 . +import React from "react"; +import { Theme } from "@mui/material/styles"; +import createStyles from "@mui/styles/createStyles"; +import withStyles from "@mui/styles/withStyles"; +import { ServerInfo } from "../types"; +import { niceDays } from "../../../../common/utils"; +import { Box } from "@mui/material"; +import { + CircleIcon, + DrivesIcon, + UptimeIcon, + VersionIcon, + WarpIcon, +} from "../../../../icons"; +import get from "lodash/get"; +import { commonDashboardInfocard } from "../../Common/FormComponents/common/styleLibrary"; +import { + getDriveStatusColor, + getNetworkStatusColor, + serverStatusColor, +} from "./Utils"; + +const styles = (theme: Theme) => + createStyles({ + ...commonDashboardInfocard, + }); + +interface ICardProps { + classes?: any; + server: ServerInfo; + index: number; +} + +const ServerStatItem = ({ + label = "", + value = "", + statusColor = "", + hasStatus = false, + icon = null, +}: { + label?: string; + value?: any; + hasStatus?: boolean; + statusColor: string | undefined; + icon?: any; +}) => { + return ( + + + {icon} + {hasStatus ? ( + + + + ) : ( + + )} + + +
{label}
+
{value}
+
+
+ ); +}; + +const ServerInfoItem = ({ classes = {}, server, index }: ICardProps) => { + const networkKeys = Object.keys(get(server, "network", {})); + const networkTotal = networkKeys.length; + const totalDrives = server.drives ? server.drives.length : 0; + const activeNetwork = networkKeys.reduce((acc: number, currValue: string) => { + const item = server.network[currValue]; + if (item === "online") { + return acc + 1; + } + return acc; + }, 0); + const activeDisks = server.drives + ? server.drives.filter((element) => element.state === "ok").length + : 0; + return ( + + + {server?.state && ( + + + + )} + + {server.endpoint || ""} + + + + } + hasStatus={true} + value={`${activeDisks}/${totalDrives}`} + /> + } + hasStatus={true} + value={`${activeNetwork}/${networkTotal}`} + /> + + } + value={server?.uptime ? niceDays(server.uptime) : "N/A"} + /> + + } + value={ + + {server.version ? server.version : "N/A"} + + } + /> + + + ); +}; +export default withStyles(styles)(ServerInfoItem); diff --git a/portal-ui/src/screens/Console/Dashboard/BasicDashboard/ServersList.tsx b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/ServersList.tsx new file mode 100644 index 000000000..77ef9de53 --- /dev/null +++ b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/ServersList.tsx @@ -0,0 +1,146 @@ +// 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 . + +import React from "react"; +import ListSubheader from "@mui/material/ListSubheader"; +import List from "@mui/material/List"; +import ListItemButton from "@mui/material/ListItemButton"; +import Collapse from "@mui/material/Collapse"; +import ExpandLess from "@mui/icons-material/ExpandLess"; +import ExpandMore from "@mui/icons-material/ExpandMore"; +import { ServerInfo } from "../types"; +import ServerInfoItem from "./ServerInfoItem"; +import { Box } from "@mui/material"; +import DriveInfoItem from "./DriveInfoItem"; + +const ServersList = ({ data }: { data: ServerInfo[] }) => { + const [expanded, setExpanded] = React.useState(""); + + const handleClick = (key: string) => { + setExpanded(key); + }; + + return ( + + Servers ({data.length}) + + } + > + {data.map((serverInfo, index) => { + const key = `${serverInfo.endpoint}-${index}`; + const isExpanded = expanded === key; + return ( + + { + if (!isExpanded) { + handleClick(key); + } else { + handleClick(""); + } + }} + className={isExpanded ? "expanded" : ""} + sx={{ + display: "flex", + alignItems: "center", + justifyContent: "space-between", + borderBottom: "1px solid #eaeaea", + "&:hover": { + background: "#F8F8F8", + }, + "&.expanded": { + borderBottom: "none", + }, + }} + > + + + {isExpanded ? : } + + + {isExpanded ? ( + + + Drives ({serverInfo.drives.length}) + + + + {serverInfo.drives.map((driveInfo, index) => { + return ( + + ); + })} + + + ) : null} + + ); + })} + + ); +}; + +export default ServersList; diff --git a/portal-ui/src/screens/Console/Dashboard/BasicDashboard/StatusCountCard.tsx b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/StatusCountCard.tsx new file mode 100644 index 000000000..eae190290 --- /dev/null +++ b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/StatusCountCard.tsx @@ -0,0 +1,147 @@ +// 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 . + +import React from "react"; +import { Box } from "@mui/material"; +import { CircleIcon } from "../../../../icons"; + +export const StatusCountCard = ({ + onlineCount = 0, + offlineCount = 0, + icon = null, + label = "", +}: { + icon: any; + onlineCount: number; + offlineCount: number; + label: string; +}) => { + return ( + + + + + {label} + + + + + +
Online
+
+ {onlineCount} +
+ + + +
Offline
+
+ {offlineCount} +
+
+
+ + {icon} + +
+
+ ); +}; + +export default StatusCountCard; diff --git a/portal-ui/src/screens/Console/Dashboard/BasicDashboard/Utils.tsx b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/Utils.tsx new file mode 100644 index 000000000..d8a3dc032 --- /dev/null +++ b/portal-ui/src/screens/Console/Dashboard/BasicDashboard/Utils.tsx @@ -0,0 +1,61 @@ +// 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 . + +export const STATUS_COLORS = { + RED: "#C83B51", + GREEN: "#4CCB92", + YELLOW: "#E7A219", +}; + +export const getDriveStatusColor = ( + activeDisks: number, + totalDrives: number +) => { + if (activeDisks <= totalDrives / 2) { + return STATUS_COLORS.RED; + } + if (totalDrives !== 2 && activeDisks === totalDrives / 2 + 1) { + return STATUS_COLORS.YELLOW; + } + if (activeDisks === totalDrives) { + return STATUS_COLORS.GREEN; + } +}; + +export const serverStatusColor = (health_status: string) => { + switch (health_status) { + case "offline": + return STATUS_COLORS.RED; + case "online": + return STATUS_COLORS.GREEN; + default: + return STATUS_COLORS.YELLOW; + } +}; +export const getNetworkStatusColor = ( + activeNetwork: number, + networkTotal: number +) => { + if (activeNetwork <= networkTotal / 2) { + return STATUS_COLORS.RED; + } + if (activeNetwork === networkTotal / 2 + 1) { + return STATUS_COLORS.YELLOW; + } + if (activeNetwork === networkTotal) { + return STATUS_COLORS.GREEN; + } +}; diff --git a/portal-ui/src/screens/Console/Dashboard/Dashboard.tsx b/portal-ui/src/screens/Console/Dashboard/Dashboard.tsx index 195d1797b..78fa81230 100644 --- a/portal-ui/src/screens/Console/Dashboard/Dashboard.tsx +++ b/portal-ui/src/screens/Console/Dashboard/Dashboard.tsx @@ -24,12 +24,12 @@ import { containerForHeader } from "../Common/FormComponents/common/styleLibrary import { Theme } from "@mui/material/styles"; import createStyles from "@mui/styles/createStyles"; import withStyles from "@mui/styles/withStyles"; -import BasicDashboard from "./BasicDashboard/BasicDashboard"; import { LinearProgress } from "@mui/material"; import api from "../../../common/api"; import { Usage } from "./types"; import { setErrorSnackMessage } from "../../../actions"; import { ErrorResponseHandler } from "../../../common/types"; +import BasicDashboard from "./BasicDashboard/BasicDashboard"; interface IDashboardSimple { classes: any; @@ -82,9 +82,7 @@ const Dashboard = ({ classes, displayErrorMessage }: IDashboardSimple) => { ) : ( - - - + )} )}