Two Column Basic Dashboard (#1002)

* Two Column Basic Dashboard

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* Change title

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* Remove Flex Grow

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
This commit is contained in:
Daniel Valdivia
2021-09-01 19:23:25 -07:00
committed by GitHub
parent 1ab37e0b00
commit 1ba2627810
3 changed files with 168 additions and 311 deletions

View File

@@ -18,7 +18,6 @@ import React, { Fragment } from "react";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import clsx from "clsx";
import Grid from "@material-ui/core/Grid";
import Paper from "@material-ui/core/Paper";
import Typography from "@material-ui/core/Typography";
import { Usage } from "../types";
import { niceBytes } from "../../../../common/utils";
@@ -31,69 +30,10 @@ import {
StorageIcon,
TotalObjectsIcon,
} from "../../../../icons";
import { Card, CardHeader } from "@material-ui/core";
const styles = (theme: Theme) =>
createStyles({
paper: {
padding: theme.spacing(2),
display: "flex",
overflow: "auto",
flexDirection: "column",
border: "#eaedee 1px solid",
borderRadius: 5,
boxShadow: "none",
marginBottom: 15,
},
fixedHeight: {
height: 165,
minWidth: 247,
marginRight: 20,
padding: "25px 28px",
"& svg:not(.computerIcon)": {
maxHeight: 18,
},
},
serversContainer: {
height: "auto",
overflow: "hidden" as const,
},
drivesContainer: {
overflow: "flex",
},
infoHeight: {
height: 180,
minWidth: 247,
marginRight: 20,
padding: "25px 28px",
"& svg": {
maxHeight: 18,
},
},
consumptionValue: {
color: "#000000",
fontSize: "60px",
fontWeight: "bold",
},
endpoint: {
color: "#000000",
fontSize: "20px",
fontWeight: "bold",
},
infoValue: {
fontWeight: 500,
color: "#777777",
fontSize: 14,
marginTop: 9,
},
icon: {
marginRight: 10,
color: "#777777",
},
notationContainer: {
display: "flex",
flexWrap: "wrap",
marginTop: 20,
},
dashboardBG: {
width: 390,
height: 255,
@@ -106,27 +46,11 @@ const styles = (theme: Theme) =>
bottom: 0,
backgroundRepeat: "no-repeat",
},
elementTitle: {
fontWeight: 500,
color: "#777777",
fontSize: 14,
marginTop: -9,
},
smallUnit: {
fontSize: 20,
},
serversListContainer: {
overflowY: "auto",
height: 200,
width: "100%",
},
cardsContainer: {
display: "flex",
flexWrap: "wrap",
justifyContent: "center",
},
serversAdj: {
maxWidth: 1380,
maxHeight: 440,
overflowY: "auto",
overflowX: "hidden",
},
});
@@ -136,12 +60,6 @@ interface IDashboardProps {
}
const BasicDashboard = ({ classes, usage }: IDashboardProps) => {
const fixedHeightPaper = clsx(classes.paper, classes.fixedHeight);
const expandedServersPaperContainer = clsx(
classes.paper,
classes.serversContainer
);
const prettyUsage = (usage: string | undefined) => {
if (usage === undefined) {
return "0";
@@ -190,101 +108,77 @@ const BasicDashboard = ({ classes, usage }: IDashboardProps) => {
return (
<Fragment>
<div className={classes.dashboardBG} />
<Grid container className={classes.dashboardContainer}>
<Grid container spacing={3} className={classes.container}>
<Grid item xs={12} className={classes.notationContainer}>
<Paper className={fixedHeightPaper}>
<Grid container direction="row" alignItems="center">
<Grid item className={classes.icon}>
<BucketsIcon />
</Grid>
<Grid item>
<Typography className={classes.elementTitle}>
All buckets
</Typography>
</Grid>
</Grid>
<Typography className={classes.consumptionValue}>
{usage ? prettyNumber(usage.buckets) : 0}
</Typography>
</Paper>
<Paper className={fixedHeightPaper}>
<Grid container direction="row" alignItems="center">
<Grid item className={classes.icon}>
<ReportedUsageIcon />
</Grid>
<Grid item>
<Typography className={classes.elementTitle}>
Usage
</Typography>
</Grid>
</Grid>
<Typography className={classes.consumptionValue}>
{usage ? prettyUsage(usage.usage + "") : 0}
</Typography>
</Paper>
<Paper className={fixedHeightPaper}>
<Grid container direction="row" alignItems="center">
<Grid item className={classes.icon}>
<TotalObjectsIcon />
</Grid>
<Grid item>
<Typography className={classes.elementTitle}>
{" "}
Total Objects
</Typography>
</Grid>
</Grid>
<Typography className={classes.consumptionValue}>
{usage ? prettyNumber(usage.objects) : 0}
</Typography>
</Paper>
<Grid container spacing={2}>
<Grid item xs={6}>
<Grid container spacing={2}>
<Grid item xs={6}>
<Card className={classes.cardRoot}>
<CardHeader
avatar={<BucketsIcon />}
title="Number of Buckets"
subheader={usage ? prettyNumber(usage.buckets) : 0}
/>
</Card>
</Grid>
<Grid item xs={6}>
<Card className={classes.cardRoot}>
<CardHeader
avatar={<ReportedUsageIcon />}
title="Usage"
subheader={usage ? prettyUsage(usage.usage + "") : 0}
/>
</Card>
</Grid>
<Grid item xs={6}>
<Card className={classes.cardRoot}>
<CardHeader
avatar={<TotalObjectsIcon />}
title="Total Objects"
subheader={usage ? prettyNumber(usage.objects) : 0}
/>
</Card>
</Grid>
<Grid item xs={6} />
</Grid>
<Grid item xs={12} className={classes.serversAdj}>
<Paper className={expandedServersPaperContainer}>
<div>
<Grid container direction="row" alignItems="center">
<Grid item className={classes.icon}>
<ServersIcon />
</Grid>
<Grid item>
<Typography className={classes.elementTitle}>
{" "}
Servers
</Typography>
</Grid>
</Grid>
</div>
<div>
<div className={classes.cardsContainer}>
{serverArray.map((server, index) => (
<ServerInfoCard
server={server}
key={`serverDS-${index.toString()}`}
/>
))}
</div>
</div>
<div>
<Grid container direction="row" alignItems="center">
<Grid item className={classes.icon}>
<StorageIcon />
<Grid item xs={12}>
<Grid container alignItems="center" spacing={2}>
<Grid item>
<StorageIcon />
</Grid>
<Grid item>
<Typography variant="h5">Drives Status</Typography>
</Grid>
</Grid>
<Grid container spacing={1} className={classes.cardsContainer}>
{serverArray.map((server, index) =>
server.drives.map((drive) => (
<Grid item xs={12}>
<DriveInfoCard drive={drive} />
</Grid>
<Grid item>
<Typography className={classes.elementTitle}>
{" "}
Drives
</Typography>
</Grid>
</Grid>
</div>
<div className={classes.cardsContainer}>
{serverArray.map((server, index) =>
server.drives.map((drive) => <DriveInfoCard drive={drive} />)
)}
</div>
</Paper>
))
)}
</Grid>
</Grid>
</Grid>
<Grid item xs={6}>
<Grid container alignItems="center" spacing={2}>
<Grid item>
<ServersIcon />
</Grid>
<Grid item>
<Typography variant="h5">Servers Status</Typography>
</Grid>
</Grid>
<Grid container spacing={1}>
{serverArray.map((server, index) => (
<Grid item xs={12}>
<ServerInfoCard
server={server}
key={`serverDS-${index.toString()}`}
/>
</Grid>
))}
</Grid>
</Grid>
</Grid>

View File

@@ -14,45 +14,21 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import React, { Fragment } from "react";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import ComputerIcon from "@material-ui/icons/Computer";
import HealIcon from "../../../../icons/HealIcon";
import Grid from "@material-ui/core/Grid";
import Paper from "@material-ui/core/Paper";
import { IDriveInfo } from "../types";
import { niceBytes } from "../../../../common/utils";
import { Tooltip } from "@material-ui/core";
import HelpIcon from "../../../../icons/HelpIcon";
import { Card, CardHeader } from "@material-ui/core";
import { CircleIcon, StorageIcon } from "../../../../icons";
const styles = (theme: Theme) =>
createStyles({
serverCard: {
padding: 15,
margin: 8,
width: "100%",
maxWidth: 620,
"& .computerIcon": {
marginRight: 10,
},
},
titleContainer: {
display: "flex",
},
cardIconContainer: {
display: "flex",
position: "relative",
alignItems: "center",
},
endpoint: {
color: "#000000",
fontSize: 20,
fontWeight: "bold",
position: "relative" as const,
textOverflow: "ellipsis",
whiteSpace: "nowrap",
overflow: "hidden",
},
stateContainer: {
display: "flex",
flexWrap: "wrap",
@@ -85,7 +61,11 @@ const styles = (theme: Theme) =>
fontSize: 10,
left: 18,
height: 10,
bottom: 5,
bottom: 2,
"& .MuiSvgIcon-root": {
width: 10,
height: 10,
},
},
innerState: {
fontSize: 10,
@@ -94,6 +74,11 @@ const styles = (theme: Theme) =>
alignItems: "center",
marginTop: -3,
},
cardHeader: {
"& .MuiCardHeader-title": {
fontWeight: "bolder",
},
},
});
interface ICardProps {
@@ -115,42 +100,41 @@ const DriveInfoCard = ({ classes, drive }: ICardProps) => {
};
return (
<Paper className={classes.serverCard}>
<Grid container direction="row" alignItems="center">
<Grid item xs={12}>
<div className={classes.titleContainer}>
<Fragment>
<Card>
<CardHeader
className={classes.cardHeader}
avatar={
<div className={classes.cardIconContainer}>
<ComputerIcon className="computerIcon" />
<StorageIcon className="computerIcon" />
<div className={classes.healthStatusIcon}>
{drive.state && (
<span className={driveStatusToClass(drive.state)}></span>
<span className={driveStatusToClass(drive.state)}>
<CircleIcon />
</span>
)}
</div>
</div>{" "}
<Tooltip title={drive.endpoint} placement="bottom">
<div className={classes.endpoint}>{drive.endpoint}</div>
</Tooltip>
<span className={classes.infoValue}>
{drive.healing && <HealIcon />}
{drive.rootDisk && <HelpIcon />}
</span>
</div>
</Grid>
<Grid item xs={12} className={classes.stateContainer}>
<span className={classes.infoValue}>
<strong>Total Space:</strong>{" "}
{niceBytes(drive.totalSpace.toString())}
</span>
<span className={classes.infoValue}>
<strong>Used Space:</strong> {niceBytes(drive.usedSpace.toString())}
</span>
<span className={classes.infoValue}>
<strong>Available Space:</strong>{" "}
{niceBytes(drive.availableSpace.toString())}
</span>
</Grid>
</Grid>
</Paper>
</div>
}
title={drive.endpoint}
subheader={
<Grid item xs={12} className={classes.stateContainer}>
<span className={classes.infoValue}>
<strong>Capacity:</strong>{" "}
{niceBytes(drive.totalSpace.toString())}
</span>
<span className={classes.infoValue}>
<strong>Used:</strong> {niceBytes(drive.usedSpace.toString())}
</span>
<span className={classes.infoValue}>
<strong>Available:</strong>{" "}
{niceBytes(drive.availableSpace.toString())}
</span>
</Grid>
}
/>
</Card>
</Fragment>
);
};

View File

@@ -18,40 +18,18 @@ import React from "react";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import ComputerIcon from "@material-ui/icons/Computer";
import Grid from "@material-ui/core/Grid";
import Paper from "@material-ui/core/Paper";
import { ServerInfo } from "../types";
import { niceDays } from "../../../../common/utils";
import { Tooltip } from "@material-ui/core";
import { Card, CardHeader } from "@material-ui/core";
import { CircleIcon } from "../../../../icons";
const styles = (theme: Theme) =>
createStyles({
serverCard: {
padding: 15,
margin: 8,
width: "100%",
maxWidth: 620,
"& .computerIcon": {
marginRight: 10,
},
},
titleContainer: {
display: "flex",
},
cardIconContainer: {
display: "flex",
position: "relative",
alignItems: "center",
},
endpoint: {
color: "#000000",
fontSize: 20,
fontWeight: "bold",
position: "relative" as const,
textOverflow: "ellipsis",
whiteSpace: "nowrap",
overflow: "hidden",
},
stateContainer: {
display: "flex",
flexWrap: "wrap",
@@ -101,6 +79,11 @@ const styles = (theme: Theme) =>
alignItems: "center",
marginTop: -3,
},
cardHeader: {
"& .MuiCardHeader-title": {
fontWeight: "bolder",
},
},
});
interface ICardProps {
@@ -139,59 +122,55 @@ const ServerInfoCard = ({ classes, server }: ICardProps) => {
).length;
return (
<Paper className={classes.serverCard}>
<Grid container direction="row" alignItems="center">
<Grid item xs={12}>
<div className={classes.titleContainer}>
<div className={classes.cardIconContainer}>
<ComputerIcon className="computerIcon" />
<div className={classes.healthStatusIcon}>
{server.state && (
<span className={serverStatusToClass(server.state)}>
<CircleIcon />
</span>
)}
</div>
</div>{" "}
<Tooltip title={server.endpoint} placement="bottom">
<div className={classes.endpoint}>{server.endpoint}</div>
</Tooltip>
<Card>
<CardHeader
className={classes.cardHeader}
avatar={
<div className={classes.cardIconContainer}>
<ComputerIcon className="computerIcon" />
<div className={classes.healthStatusIcon}>
{server.state && (
<span className={serverStatusToClass(server.state)}>
<CircleIcon />
</span>
)}
</div>
</div>
<div className={classes.infoValue}>
<strong>Version:</strong> {server.version}
</div>
</Grid>
<Grid item xs={12} className={classes.stateContainer}>
<span className={classes.infoValue}>
<strong>Drives:</strong> {activeDisks}/{totalDrives}{" "}
<span
className={`${classes.innerState} ${
activeDisks <= totalDrives / 2 && classes.redState
} ${activeDisks === totalDrives / 2 + 1 && classes.yellowState} ${
activeDisks === totalDrives && classes.greenState
}`}
>
<CircleIcon />
}
title={server.endpoint}
subheader={
<Grid item xs={12} className={classes.stateContainer}>
<span className={classes.infoValue}>
<strong>Drives:</strong> {activeDisks}/{totalDrives}{" "}
<span
className={`${classes.innerState} ${
activeDisks <= totalDrives / 2 && classes.redState
} ${
activeDisks === totalDrives / 2 + 1 && classes.yellowState
} ${activeDisks === totalDrives && classes.greenState}`}
>
<CircleIcon />
</span>
</span>
</span>
<span className={classes.infoValue}>
<strong>Network:</strong> {activeNetwork}/{networkTotal}{" "}
<span
className={`${classes.innerState} ${
activeNetwork <= networkTotal / 2 && classes.redState
} ${
activeNetwork === networkTotal / 2 + 1 && classes.yellowState
} ${activeNetwork === networkTotal && classes.greenState}`}
>
<CircleIcon />
<span className={classes.infoValue}>
<strong>Network:</strong> {activeNetwork}/{networkTotal}{" "}
<span
className={`${classes.innerState} ${
activeNetwork <= networkTotal / 2 && classes.redState
} ${
activeNetwork === networkTotal / 2 + 1 && classes.yellowState
} ${activeNetwork === networkTotal && classes.greenState}`}
>
<CircleIcon />
</span>
</span>
</span>
<span className={classes.infoValue}>
<strong>Uptime:</strong> {niceDays(server.uptime)}
</span>
</Grid>
</Grid>
</Paper>
<span className={classes.infoValue}>
<strong>Uptime:</strong> {niceDays(server.uptime)}
</span>
</Grid>
}
/>
</Card>
);
};