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 { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import clsx from "clsx"; import clsx from "clsx";
import Grid from "@material-ui/core/Grid"; import Grid from "@material-ui/core/Grid";
import Paper from "@material-ui/core/Paper";
import Typography from "@material-ui/core/Typography"; import Typography from "@material-ui/core/Typography";
import { Usage } from "../types"; import { Usage } from "../types";
import { niceBytes } from "../../../../common/utils"; import { niceBytes } from "../../../../common/utils";
@@ -31,69 +30,10 @@ import {
StorageIcon, StorageIcon,
TotalObjectsIcon, TotalObjectsIcon,
} from "../../../../icons"; } from "../../../../icons";
import { Card, CardHeader } from "@material-ui/core";
const styles = (theme: Theme) => const styles = (theme: Theme) =>
createStyles({ 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: { dashboardBG: {
width: 390, width: 390,
height: 255, height: 255,
@@ -106,27 +46,11 @@ const styles = (theme: Theme) =>
bottom: 0, bottom: 0,
backgroundRepeat: "no-repeat", backgroundRepeat: "no-repeat",
}, },
elementTitle: {
fontWeight: 500,
color: "#777777",
fontSize: 14,
marginTop: -9,
},
smallUnit: {
fontSize: 20,
},
serversListContainer: {
overflowY: "auto",
height: 200,
width: "100%",
},
cardsContainer: { cardsContainer: {
display: "flex", maxHeight: 440,
flexWrap: "wrap", overflowY: "auto",
justifyContent: "center", overflowX: "hidden",
},
serversAdj: {
maxWidth: 1380,
}, },
}); });
@@ -136,12 +60,6 @@ interface IDashboardProps {
} }
const BasicDashboard = ({ classes, usage }: 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) => { const prettyUsage = (usage: string | undefined) => {
if (usage === undefined) { if (usage === undefined) {
return "0"; return "0";
@@ -190,101 +108,77 @@ const BasicDashboard = ({ classes, usage }: IDashboardProps) => {
return ( return (
<Fragment> <Fragment>
<div className={classes.dashboardBG} /> <div className={classes.dashboardBG} />
<Grid container className={classes.dashboardContainer}> <Grid container spacing={2}>
<Grid container spacing={3} className={classes.container}> <Grid item xs={6}>
<Grid item xs={12} className={classes.notationContainer}> <Grid container spacing={2}>
<Paper className={fixedHeightPaper}> <Grid item xs={6}>
<Grid container direction="row" alignItems="center"> <Card className={classes.cardRoot}>
<Grid item className={classes.icon}> <CardHeader
<BucketsIcon /> avatar={<BucketsIcon />}
</Grid> title="Number of Buckets"
<Grid item> subheader={usage ? prettyNumber(usage.buckets) : 0}
<Typography className={classes.elementTitle}> />
All buckets </Card>
</Typography> </Grid>
</Grid> <Grid item xs={6}>
</Grid> <Card className={classes.cardRoot}>
<Typography className={classes.consumptionValue}> <CardHeader
{usage ? prettyNumber(usage.buckets) : 0} avatar={<ReportedUsageIcon />}
</Typography> title="Usage"
</Paper> subheader={usage ? prettyUsage(usage.usage + "") : 0}
<Paper className={fixedHeightPaper}> />
<Grid container direction="row" alignItems="center"> </Card>
<Grid item className={classes.icon}> </Grid>
<ReportedUsageIcon /> <Grid item xs={6}>
</Grid> <Card className={classes.cardRoot}>
<Grid item> <CardHeader
<Typography className={classes.elementTitle}> avatar={<TotalObjectsIcon />}
Usage title="Total Objects"
</Typography> subheader={usage ? prettyNumber(usage.objects) : 0}
</Grid> />
</Grid> </Card>
<Typography className={classes.consumptionValue}> </Grid>
{usage ? prettyUsage(usage.usage + "") : 0} <Grid item xs={6} />
</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> </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> <Grid item xs={12}>
<div className={classes.cardsContainer}> <Grid container alignItems="center" spacing={2}>
{serverArray.map((server, index) => ( <Grid item>
<ServerInfoCard <StorageIcon />
server={server} </Grid>
key={`serverDS-${index.toString()}`} <Grid item>
/> <Typography variant="h5">Drives Status</Typography>
))} </Grid>
</div> </Grid>
</div> <Grid container spacing={1} className={classes.cardsContainer}>
<div> {serverArray.map((server, index) =>
<Grid container direction="row" alignItems="center"> server.drives.map((drive) => (
<Grid item className={classes.icon}> <Grid item xs={12}>
<StorageIcon /> <DriveInfoCard drive={drive} />
</Grid> </Grid>
<Grid item> ))
<Typography className={classes.elementTitle}> )}
{" "} </Grid>
Drives </Grid>
</Typography> </Grid>
</Grid> <Grid item xs={6}>
</Grid> <Grid container alignItems="center" spacing={2}>
</div> <Grid item>
<div className={classes.cardsContainer}> <ServersIcon />
{serverArray.map((server, index) => </Grid>
server.drives.map((drive) => <DriveInfoCard drive={drive} />) <Grid item>
)} <Typography variant="h5">Servers Status</Typography>
</div> </Grid>
</Paper> </Grid>
<Grid container spacing={1}>
{serverArray.map((server, index) => (
<Grid item xs={12}>
<ServerInfoCard
server={server}
key={`serverDS-${index.toString()}`}
/>
</Grid>
))}
</Grid> </Grid>
</Grid> </Grid>
</Grid> </Grid>

View File

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

View File

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