From cdb37800cc639f7c0291bca54882ca9d95f80d8e Mon Sep 17 00:00:00 2001 From: Alan Guo Date: Sun, 22 Jan 2023 16:23:39 -0800 Subject: [PATCH] Polish the new IA for dashboard (#31770) Signed-off-by: Alan Guo Update to more closely match the design spec. --- dashboard/client/src/App.tsx | 11 ++++- .../client/src/common/CollapsibleSection.tsx | 48 +++++++++++++++---- dashboard/client/src/pages/job/JobDetail.tsx | 8 +++- .../src/pages/job/JobDetailActorPage.tsx | 37 ++++++++++++++ .../client/src/pages/job/JobDetailLayout.tsx | 12 ++++- .../client/src/pages/layout/MainNavLayout.tsx | 19 +++++--- dashboard/client/src/pages/log/Logs.tsx | 2 +- .../client/src/pages/metrics/Metrics.tsx | 32 +++++++++---- .../src/pages/overview/OverviewPage.tsx | 15 ++++-- .../pages/overview/cards/NodeCountCard.tsx | 1 + .../src/pages/overview/cards/OverviewCard.tsx | 5 +- .../cards/RecentJobsCard.component.test.tsx | 2 +- .../pages/overview/cards/RecentJobsCard.tsx | 12 +++-- dashboard/client/src/theme.ts | 16 +++++++ .../metrics/grafana_dashboard_base.json | 2 +- 15 files changed, 180 insertions(+), 42 deletions(-) create mode 100644 dashboard/client/src/pages/job/JobDetailActorPage.tsx diff --git a/dashboard/client/src/App.tsx b/dashboard/client/src/App.tsx index c48be1456e9f8..302a9afe3985c 100644 --- a/dashboard/client/src/App.tsx +++ b/dashboard/client/src/App.tsx @@ -8,6 +8,7 @@ import Events from "./pages/event/Events"; import Loading from "./pages/exception/Loading"; import JobList, { NewIAJobsPage } from "./pages/job"; import { JobDetailChartsPage } from "./pages/job/JobDetail"; +import { JobDetailActorsPage } from "./pages/job/JobDetailActorPage"; import { JobDetailInfoPage } from "./pages/job/JobDetailInfoPage"; import { JobDetailLayout } from "./pages/job/JobDetailLayout"; import { DEFAULT_VALUE, MainNavContext } from "./pages/layout/mainNavContext"; @@ -205,11 +206,19 @@ const App = () => { - + } path="" /> + + + + } + path="actors" + /> } path="logs"> diff --git a/dashboard/client/src/common/CollapsibleSection.tsx b/dashboard/client/src/common/CollapsibleSection.tsx index 879ce6bf692c0..2f42d82ff7d6e 100644 --- a/dashboard/client/src/common/CollapsibleSection.tsx +++ b/dashboard/client/src/common/CollapsibleSection.tsx @@ -1,6 +1,8 @@ import { createStyles, makeStyles, Typography } from "@material-ui/core"; -import React, { PropsWithChildren, useState } from "react"; -import { RiArrowDownSLine, RiArrowUpSLine } from "react-icons/ri"; +import classNames from "classnames"; +import React, { PropsWithChildren, useEffect, useState } from "react"; +import { RiArrowDownSLine, RiArrowRightSLine } from "react-icons/ri"; +import { ClassNameProps } from "./props"; const useStyles = makeStyles((theme) => createStyles({ @@ -10,6 +12,7 @@ const useStyles = makeStyles((theme) => flexWrap: "nowrap", alignItems: "center", fontWeight: 500, + cursor: "pointer", }, icon: { marginRight: theme.spacing(1), @@ -17,25 +20,42 @@ const useStyles = makeStyles((theme) => height: 24, }, body: { - marginTop: theme.spacing(3), + marginTop: theme.spacing(1), + }, + bodyHidden: { + display: "none", }, }), ); -type CollapsibleSectionProps = PropsWithChildren<{ - title: string; - startExpanded?: boolean; - className?: string; -}>; +type CollapsibleSectionProps = PropsWithChildren< + { + title: string; + startExpanded?: boolean; + /** + * An optimization to not avoid re-rendering the contents of the collapsible section. + * When enabled, we will keep the content around when collapsing but hide it via css. + */ + keepRendered?: boolean; + } & ClassNameProps +>; export const CollapsibleSection = ({ title, startExpanded = false, className, children, + keepRendered, }: CollapsibleSectionProps) => { const classes = useStyles(); const [expanded, setExpanded] = useState(startExpanded); + const [rendered, setRendered] = useState(expanded); + + useEffect(() => { + if (expanded) { + setRendered(true); + } + }, [expanded]); const handleExpandClick = () => { setExpanded(!expanded); @@ -51,11 +71,19 @@ export const CollapsibleSection = ({ {expanded ? ( ) : ( - + )} {title} - {expanded &&
{children}
} + {(expanded || (keepRendered && rendered)) && ( +
+ {children} +
+ )} ); }; diff --git a/dashboard/client/src/pages/job/JobDetail.tsx b/dashboard/client/src/pages/job/JobDetail.tsx index cddca7c6761c9..8f0b6cdf1c21d 100644 --- a/dashboard/client/src/pages/job/JobDetail.tsx +++ b/dashboard/client/src/pages/job/JobDetail.tsx @@ -25,7 +25,13 @@ const useStyle = makeStyles((theme) => ({ }, })); -export const JobDetailChartsPage = () => { +type JobDetailChartsPageProps = { + newIA?: boolean; +}; + +export const JobDetailChartsPage = ({ + newIA = false, +}: JobDetailChartsPageProps) => { const classes = useStyle(); const { job, msg, params } = useJobDetail(); const jobId = params.id; diff --git a/dashboard/client/src/pages/job/JobDetailActorPage.tsx b/dashboard/client/src/pages/job/JobDetailActorPage.tsx new file mode 100644 index 0000000000000..c0fa8735850cb --- /dev/null +++ b/dashboard/client/src/pages/job/JobDetailActorPage.tsx @@ -0,0 +1,37 @@ +import { makeStyles } from "@material-ui/core"; +import React from "react"; + +import TitleCard from "../../components/TitleCard"; +import ActorList from "../actor/ActorList"; +import { MainNavPageInfo } from "../layout/mainNavContext"; +import { useJobDetail } from "./hook/useJobDetail"; + +const useStyle = makeStyles((theme) => ({ + root: { + padding: theme.spacing(2), + }, +})); + +export const JobDetailActorsPage = () => { + const classes = useStyle(); + const { job, params } = useJobDetail(); + + const pageInfo = job + ? { + title: "Actors", + id: "actors", + path: job.job_id ? `/new/jobs/${job.job_id}/actors` : undefined, + } + : { + title: "Actors", + id: "actors", + path: undefined, + }; + + return ( +
+ + {} +
+ ); +}; diff --git a/dashboard/client/src/pages/job/JobDetailLayout.tsx b/dashboard/client/src/pages/job/JobDetailLayout.tsx index 3c65ccc6b42a6..f87915e451308 100644 --- a/dashboard/client/src/pages/job/JobDetailLayout.tsx +++ b/dashboard/client/src/pages/job/JobDetailLayout.tsx @@ -1,5 +1,9 @@ import React from "react"; -import { RiInformationLine, RiLineChartLine } from "react-icons/ri"; +import { + RiGradienterLine, + RiInformationLine, + RiLineChartLine, +} from "react-icons/ri"; import { MainNavPageInfo } from "../layout/mainNavContext"; import { SideTabLayout, SideTabRouteLink } from "../layout/SideTabLayout"; import { useJobDetail } from "./hook/useJobDetail"; @@ -29,6 +33,12 @@ export const JobDetailLayout = () => { title="Charts" Icon={RiLineChartLine} /> + ); }; diff --git a/dashboard/client/src/pages/layout/MainNavLayout.tsx b/dashboard/client/src/pages/layout/MainNavLayout.tsx index 6a001a29eb3b7..85dabc6d97a35 100644 --- a/dashboard/client/src/pages/layout/MainNavLayout.tsx +++ b/dashboard/client/src/pages/layout/MainNavLayout.tsx @@ -88,13 +88,14 @@ const useMainNavBarStyles = makeStyles((theme) => boxShadow: "0px 1px 0px #D2DCE6", }, logo: { - width: 60, display: "flex", justifyContent: "center", + marginLeft: theme.spacing(2), + marginRight: theme.spacing(3), }, navItem: { - marginRight: theme.spacing(2), - fontSize: "1em", + marginRight: theme.spacing(6), + fontSize: "1rem", fontWeight: 500, color: "black", textDecoration: "none", @@ -211,15 +212,21 @@ const MainNavBreadcrumbs = () => { ); if (index === 0) { return ( - + {linkOrText} ); } else { return ( - {"/"} - + + {"/"} + + {linkOrText} diff --git a/dashboard/client/src/pages/log/Logs.tsx b/dashboard/client/src/pages/log/Logs.tsx index 6501a0c8b7786..7a36a1e23c64c 100644 --- a/dashboard/client/src/pages/log/Logs.tsx +++ b/dashboard/client/src/pages/log/Logs.tsx @@ -126,7 +126,7 @@ const Logs = (props: LogsProps) => { setEnd, } = useLogs(props); const { newIA } = props; - let href = newIA ? "#/new/log/" : "#/log/"; + let href = newIA ? "#/new/logs/" : "#/log/"; if (origin) { if (path) { diff --git a/dashboard/client/src/pages/metrics/Metrics.tsx b/dashboard/client/src/pages/metrics/Metrics.tsx index 554990b3250ef..8610f6961622e 100644 --- a/dashboard/client/src/pages/metrics/Metrics.tsx +++ b/dashboard/client/src/pages/metrics/Metrics.tsx @@ -20,9 +20,21 @@ const useStyles = makeStyles((theme) => display: "flex", flexDirection: "row", flexWrap: "wrap", + gap: theme.spacing(3), + }, + chart: { + flex: "1 0 448px", + maxWidth: "100%", + height: 300, + overflow: "hidden", + [theme.breakpoints.up("md")]: { + // Calculate max width based on 1/3 of the total width minus padding between cards + maxWidth: `calc((100% - ${theme.spacing(3)}px * 2) / 3)`, + }, }, grafanaEmbed: { - margin: theme.spacing(1), + width: "100%", + height: "100%", }, topBar: { position: "sticky", @@ -213,15 +225,15 @@ export const Metrics = () => {
{METRICS_CONFIG.map(({ title, path }) => ( -