diff --git a/site/src/components/BuildsTable/BuildAvatar.tsx b/site/src/components/BuildsTable/BuildAvatar.tsx index d4976d0e2a984..c891aeaca95be 100644 --- a/site/src/components/BuildsTable/BuildAvatar.tsx +++ b/site/src/components/BuildsTable/BuildAvatar.tsx @@ -25,20 +25,26 @@ const StyledBadge = withStyles((theme) => ({ }, }))(Badge) +interface StyledAvatarProps { + size?: number +} + const StyledAvatar = withStyles((theme) => ({ root: { background: theme.palette.divider, color: theme.palette.text.primary, border: `2px solid ${theme.palette.divider}`, + width: ({ size }: StyledAvatarProps) => size, + height: ({ size }: StyledAvatarProps) => size, "& svg": { - width: 18, - height: 18, + width: ({ size }: StyledAvatarProps) => (size ? size / 2 : 18), + height: ({ size }: StyledAvatarProps) => (size ? size / 2 : 18), }, }, }))(Avatar) -export type BuildAvatarProps = { +export interface BuildAvatarProps extends StyledAvatarProps { build: WorkspaceBuild } @@ -48,7 +54,7 @@ const iconByTransition: Record = { delete: , } -export const BuildAvatar: FC = ({ build }) => { +export const BuildAvatar: FC = ({ build, size }) => { const theme = useTheme() const displayBuildStatus = getDisplayWorkspaceBuildStatus(theme, build) @@ -65,7 +71,9 @@ export const BuildAvatar: FC = ({ build }) => { }} badgeContent={
} > - {iconByTransition[build.transition]} + + {iconByTransition[build.transition]} + ) } diff --git a/site/src/components/Logs/Logs.tsx b/site/src/components/Logs/Logs.tsx index f992eb2b8af4c..d5fd60d037c6c 100644 --- a/site/src/components/Logs/Logs.tsx +++ b/site/src/components/Logs/Logs.tsx @@ -57,5 +57,6 @@ const useStyles = makeStyles((theme) => ({ userSelect: "none", width: theme.spacing(12.5), display: "inline-block", + color: theme.palette.text.secondary, }, })) diff --git a/site/src/components/Stats/Stats.tsx b/site/src/components/Stats/Stats.tsx new file mode 100644 index 0000000000000..1cb05d554bc8d --- /dev/null +++ b/site/src/components/Stats/Stats.tsx @@ -0,0 +1,67 @@ +import { makeStyles } from "@material-ui/core/styles" +import { ComponentProps, FC, PropsWithChildren } from "react" + +export const Stats: FC>> = (props) => { + const styles = useStyles() + return
+} + +export const StatsItem: FC<{ + label: string + value: string | number | JSX.Element +}> = ({ label, value }) => { + const styles = useStyles() + + return ( +
+ {label}: + {value} +
+ ) +} + +const useStyles = makeStyles((theme) => ({ + stats: { + paddingLeft: theme.spacing(2), + paddingRight: theme.spacing(2), + borderRadius: theme.shape.borderRadius, + border: `1px solid ${theme.palette.divider}`, + display: "flex", + alignItems: "center", + color: theme.palette.text.secondary, + margin: "0px", + [theme.breakpoints.down("sm")]: { + display: "block", + }, + }, + + statItem: { + padding: theme.spacing(2), + paddingTop: theme.spacing(1.75), + display: "flex", + alignItems: "baseline", + gap: theme.spacing(1), + }, + + statsLabel: { + display: "block", + wordWrap: "break-word", + }, + + statsValue: { + marginTop: theme.spacing(0.25), + display: "block", + wordWrap: "break-word", + color: theme.palette.text.primary, + + "& a": { + color: theme.palette.text.primary, + textDecoration: "none", + fontWeight: 600, + + "&:hover": { + textDecoration: "underline", + }, + }, + }, +})) diff --git a/site/src/components/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx b/site/src/components/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx index f0dc70c5609bc..edf9aaeed5626 100644 --- a/site/src/components/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx +++ b/site/src/components/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx @@ -1,6 +1,6 @@ import { makeStyles } from "@material-ui/core/styles" import dayjs from "dayjs" -import { FC } from "react" +import { FC, Fragment } from "react" import { ProvisionerJobLog } from "../../api/typesGenerated" import { MONOSPACE_FONT_FAMILY } from "../../theme/constants" import { Logs } from "../Logs/Logs" @@ -59,7 +59,7 @@ export const WorkspaceBuildLogs: FC = ({ logs }) => { const shouldDisplayDuration = duration !== undefined return ( -
+
{stage}
{shouldDisplayDuration && ( @@ -69,7 +69,7 @@ export const WorkspaceBuildLogs: FC = ({ logs }) => { )}
{!isEmpty && } -
+ ) })}
@@ -84,7 +84,7 @@ const useStyles = makeStyles((theme) => ({ }, header: { - fontSize: theme.typography.body1.fontSize, + fontSize: 14, padding: theme.spacing(2), paddingLeft: theme.spacing(4), paddingRight: theme.spacing(4), @@ -92,6 +92,19 @@ const useStyles = makeStyles((theme) => ({ backgroundColor: theme.palette.background.paper, display: "flex", alignItems: "center", + fontFamily: "Inter", + + "&:first-child": { + borderTopLeftRadius: theme.shape.borderRadius, + borderTopRightRadius: theme.shape.borderRadius, + }, + + "&:last-child": { + borderBottom: 0, + borderTop: `1px solid ${theme.palette.divider}`, + borderBottomLeftRadius: theme.shape.borderRadius, + borderBottomRightRadius: theme.shape.borderRadius, + }, }, duration: { diff --git a/site/src/components/WorkspaceBuildStats/WorkspaceBuildStats.tsx b/site/src/components/WorkspaceBuildStats/WorkspaceBuildStats.tsx index 10a16dc1d5f4f..6399570f5799a 100644 --- a/site/src/components/WorkspaceBuildStats/WorkspaceBuildStats.tsx +++ b/site/src/components/WorkspaceBuildStats/WorkspaceBuildStats.tsx @@ -1,15 +1,9 @@ -import Link from "@material-ui/core/Link" -import { makeStyles, useTheme } from "@material-ui/core/styles" +import { Stats, StatsItem } from "components/Stats/Stats" import { FC } from "react" -import { Link as RouterLink } from "react-router-dom" +import { useTranslation } from "react-i18next" +import { Link } from "react-router-dom" import { WorkspaceBuild } from "../../api/typesGenerated" -import { MONOSPACE_FONT_FAMILY } from "../../theme/constants" -import { combineClasses } from "../../util/combineClasses" -import { - displayWorkspaceBuildDuration, - getDisplayWorkspaceBuildInitiatedBy, - getDisplayWorkspaceBuildStatus, -} from "../../util/workspace" +import { displayWorkspaceBuildDuration } from "../../util/workspace" export interface WorkspaceBuildStatsProps { build: WorkspaceBuild @@ -18,116 +12,27 @@ export interface WorkspaceBuildStatsProps { export const WorkspaceBuildStats: FC = ({ build, }) => { - const styles = useStyles() - const theme = useTheme() - const status = getDisplayWorkspaceBuildStatus(theme, build) - const initiatedBy = getDisplayWorkspaceBuildInitiatedBy(build) + const { t } = useTranslation("buildPage") return ( -
-
- Workspace Name - - {build.workspace_name} - -
-
- -
- Duration - - {displayWorkspaceBuildDuration(build)} - -
-
-
- Started at - - {new Date(build.created_at).toLocaleString()} - -
-
-
- Status - - {status.status} - -
-
-
- Action - - {build.transition} - -
-
-
- Initiated by - {initiatedBy} -
-
+ + + {build.workspace_name} + + } + /> + + + + ) } - -const useStyles = makeStyles((theme) => ({ - stats: { - paddingLeft: theme.spacing(2), - paddingRight: theme.spacing(2), - backgroundColor: theme.palette.background.paper, - borderRadius: theme.shape.borderRadius, - display: "flex", - alignItems: "center", - color: theme.palette.text.secondary, - fontFamily: MONOSPACE_FONT_FAMILY, - border: `1px solid ${theme.palette.divider}`, - [theme.breakpoints.down("sm")]: { - display: "block", - }, - }, - - statItem: { - minWidth: "13%", - padding: theme.spacing(2), - paddingTop: theme.spacing(1.75), - }, - - statsLabel: { - fontSize: 12, - textTransform: "uppercase", - display: "block", - fontWeight: 600, - wordWrap: "break-word", - }, - - statsValue: { - fontSize: 16, - marginTop: theme.spacing(0.25), - display: "block", - wordWrap: "break-word", - }, - - statsDivider: { - width: 1, - height: theme.spacing(5), - backgroundColor: theme.palette.divider, - marginRight: theme.spacing(2), - [theme.breakpoints.down("sm")]: { - display: "none", - }, - }, - - capitalize: { - textTransform: "capitalize", - }, - - link: { - color: theme.palette.text.primary, - fontWeight: 600, - }, -})) diff --git a/site/src/i18n/en/buildPage.json b/site/src/i18n/en/buildPage.json new file mode 100644 index 0000000000000..134c040e9f65f --- /dev/null +++ b/site/src/i18n/en/buildPage.json @@ -0,0 +1,8 @@ +{ + "stats": { + "workspace": "Workspace", + "duration": "Duration", + "startedAt": "Started at", + "action": "Action" + } +} diff --git a/site/src/i18n/en/index.ts b/site/src/i18n/en/index.ts index f5a8efe7f2be2..653ac3ed8553b 100644 --- a/site/src/i18n/en/index.ts +++ b/site/src/i18n/en/index.ts @@ -5,6 +5,7 @@ import templatePage from "./templatePage.json" import templatesPage from "./templatesPage.json" import workspacePage from "./workspacePage.json" import agent from "./agent.json" +import buildPage from "./buildPage.json" export const en = { common, @@ -14,4 +15,5 @@ export const en = { templatesPage, createWorkspacePage, agent, + buildPage, } diff --git a/site/src/pages/WorkspaceBuildPage/WorkspaceBuildPageView.tsx b/site/src/pages/WorkspaceBuildPage/WorkspaceBuildPageView.tsx index a690697684cd4..17cfb72e0c12f 100644 --- a/site/src/pages/WorkspaceBuildPage/WorkspaceBuildPageView.tsx +++ b/site/src/pages/WorkspaceBuildPage/WorkspaceBuildPageView.tsx @@ -1,9 +1,11 @@ +import { BuildAvatar } from "components/BuildsTable/BuildAvatar" import { FC } from "react" import { ProvisionerJobLog, WorkspaceBuild } from "../../api/typesGenerated" import { Loader } from "../../components/Loader/Loader" import { Margins } from "../../components/Margins/Margins" import { PageHeader, + PageHeaderSubtitle, PageHeaderTitle, } from "../../components/PageHeader/PageHeader" import { Stack } from "../../components/Stack/Stack" @@ -29,11 +31,21 @@ export const WorkspaceBuildPageView: FC = ({ }) => { return ( - - Logs - + {build && ( + + + +
+ Build #{build.build_number} + + {build.initiator_name} + +
+
+
+ )} - + {build && build.transition === "delete" && build.job.status === "failed" && (