Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a7e5588

Browse files
refactor: Refactor build page (coder#4815)
* refactor: Improve build page * Add build translation * Add build avatar better props * Get build number from build
1 parent cf794f1 commit a7e5588

File tree

8 files changed

+148
-132
lines changed

8 files changed

+148
-132
lines changed

site/src/components/BuildsTable/BuildAvatar.tsx

+13-5
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,26 @@ const StyledBadge = withStyles((theme) => ({
2525
},
2626
}))(Badge)
2727

28+
interface StyledAvatarProps {
29+
size?: number
30+
}
31+
2832
const StyledAvatar = withStyles((theme) => ({
2933
root: {
3034
background: theme.palette.divider,
3135
color: theme.palette.text.primary,
3236
border: `2px solid ${theme.palette.divider}`,
37+
width: ({ size }: StyledAvatarProps) => size,
38+
height: ({ size }: StyledAvatarProps) => size,
3339

3440
"& svg": {
35-
width: 18,
36-
height: 18,
41+
width: ({ size }: StyledAvatarProps) => (size ? size / 2 : 18),
42+
height: ({ size }: StyledAvatarProps) => (size ? size / 2 : 18),
3743
},
3844
},
3945
}))(Avatar)
4046

41-
export type BuildAvatarProps = {
47+
export interface BuildAvatarProps extends StyledAvatarProps {
4248
build: WorkspaceBuild
4349
}
4450

@@ -48,7 +54,7 @@ const iconByTransition: Record<WorkspaceTransition, JSX.Element> = {
4854
delete: <DeleteOutlined />,
4955
}
5056

51-
export const BuildAvatar: FC<BuildAvatarProps> = ({ build }) => {
57+
export const BuildAvatar: FC<BuildAvatarProps> = ({ build, size }) => {
5258
const theme = useTheme<Theme>()
5359
const displayBuildStatus = getDisplayWorkspaceBuildStatus(theme, build)
5460

@@ -65,7 +71,9 @@ export const BuildAvatar: FC<BuildAvatarProps> = ({ build }) => {
6571
}}
6672
badgeContent={<div></div>}
6773
>
68-
<StyledAvatar>{iconByTransition[build.transition]}</StyledAvatar>
74+
<StyledAvatar size={size}>
75+
{iconByTransition[build.transition]}
76+
</StyledAvatar>
6977
</StyledBadge>
7078
)
7179
}

site/src/components/Logs/Logs.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,6 @@ const useStyles = makeStyles((theme) => ({
5757
userSelect: "none",
5858
width: theme.spacing(12.5),
5959
display: "inline-block",
60+
color: theme.palette.text.secondary,
6061
},
6162
}))

site/src/components/Stats/Stats.tsx

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { makeStyles } from "@material-ui/core/styles"
2+
import { ComponentProps, FC, PropsWithChildren } from "react"
3+
4+
export const Stats: FC<PropsWithChildren<ComponentProps<"div">>> = (props) => {
5+
const styles = useStyles()
6+
return <div className={styles.stats} {...props} />
7+
}
8+
9+
export const StatsItem: FC<{
10+
label: string
11+
value: string | number | JSX.Element
12+
}> = ({ label, value }) => {
13+
const styles = useStyles()
14+
15+
return (
16+
<div className={styles.statItem}>
17+
<span className={styles.statsLabel}>{label}:</span>
18+
<span className={styles.statsValue}>{value}</span>
19+
</div>
20+
)
21+
}
22+
23+
const useStyles = makeStyles((theme) => ({
24+
stats: {
25+
paddingLeft: theme.spacing(2),
26+
paddingRight: theme.spacing(2),
27+
borderRadius: theme.shape.borderRadius,
28+
border: `1px solid ${theme.palette.divider}`,
29+
display: "flex",
30+
alignItems: "center",
31+
color: theme.palette.text.secondary,
32+
margin: "0px",
33+
[theme.breakpoints.down("sm")]: {
34+
display: "block",
35+
},
36+
},
37+
38+
statItem: {
39+
padding: theme.spacing(2),
40+
paddingTop: theme.spacing(1.75),
41+
display: "flex",
42+
alignItems: "baseline",
43+
gap: theme.spacing(1),
44+
},
45+
46+
statsLabel: {
47+
display: "block",
48+
wordWrap: "break-word",
49+
},
50+
51+
statsValue: {
52+
marginTop: theme.spacing(0.25),
53+
display: "block",
54+
wordWrap: "break-word",
55+
color: theme.palette.text.primary,
56+
57+
"& a": {
58+
color: theme.palette.text.primary,
59+
textDecoration: "none",
60+
fontWeight: 600,
61+
62+
"&:hover": {
63+
textDecoration: "underline",
64+
},
65+
},
66+
},
67+
}))

site/src/components/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { makeStyles } from "@material-ui/core/styles"
22
import dayjs from "dayjs"
3-
import { FC } from "react"
3+
import { FC, Fragment } from "react"
44
import { ProvisionerJobLog } from "../../api/typesGenerated"
55
import { MONOSPACE_FONT_FAMILY } from "../../theme/constants"
66
import { Logs } from "../Logs/Logs"
@@ -59,7 +59,7 @@ export const WorkspaceBuildLogs: FC<WorkspaceBuildLogsProps> = ({ logs }) => {
5959
const shouldDisplayDuration = duration !== undefined
6060

6161
return (
62-
<div key={stage}>
62+
<Fragment key={stage}>
6363
<div className={styles.header}>
6464
<div>{stage}</div>
6565
{shouldDisplayDuration && (
@@ -69,7 +69,7 @@ export const WorkspaceBuildLogs: FC<WorkspaceBuildLogsProps> = ({ logs }) => {
6969
)}
7070
</div>
7171
{!isEmpty && <Logs lines={lines} className={styles.codeBlock} />}
72-
</div>
72+
</Fragment>
7373
)
7474
})}
7575
</div>
@@ -84,14 +84,27 @@ const useStyles = makeStyles((theme) => ({
8484
},
8585

8686
header: {
87-
fontSize: theme.typography.body1.fontSize,
87+
fontSize: 14,
8888
padding: theme.spacing(2),
8989
paddingLeft: theme.spacing(4),
9090
paddingRight: theme.spacing(4),
9191
borderBottom: `1px solid ${theme.palette.divider}`,
9292
backgroundColor: theme.palette.background.paper,
9393
display: "flex",
9494
alignItems: "center",
95+
fontFamily: "Inter",
96+
97+
"&:first-child": {
98+
borderTopLeftRadius: theme.shape.borderRadius,
99+
borderTopRightRadius: theme.shape.borderRadius,
100+
},
101+
102+
"&:last-child": {
103+
borderBottom: 0,
104+
borderTop: `1px solid ${theme.palette.divider}`,
105+
borderBottomLeftRadius: theme.shape.borderRadius,
106+
borderBottomRightRadius: theme.shape.borderRadius,
107+
},
95108
},
96109

97110
duration: {
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
1-
import Link from "@material-ui/core/Link"
2-
import { makeStyles, useTheme } from "@material-ui/core/styles"
1+
import { Stats, StatsItem } from "components/Stats/Stats"
32
import { FC } from "react"
4-
import { Link as RouterLink } from "react-router-dom"
3+
import { useTranslation } from "react-i18next"
4+
import { Link } from "react-router-dom"
55
import { WorkspaceBuild } from "../../api/typesGenerated"
6-
import { MONOSPACE_FONT_FAMILY } from "../../theme/constants"
7-
import { combineClasses } from "../../util/combineClasses"
8-
import {
9-
displayWorkspaceBuildDuration,
10-
getDisplayWorkspaceBuildInitiatedBy,
11-
getDisplayWorkspaceBuildStatus,
12-
} from "../../util/workspace"
6+
import { displayWorkspaceBuildDuration } from "../../util/workspace"
137

148
export interface WorkspaceBuildStatsProps {
159
build: WorkspaceBuild
@@ -18,116 +12,27 @@ export interface WorkspaceBuildStatsProps {
1812
export const WorkspaceBuildStats: FC<WorkspaceBuildStatsProps> = ({
1913
build,
2014
}) => {
21-
const styles = useStyles()
22-
const theme = useTheme()
23-
const status = getDisplayWorkspaceBuildStatus(theme, build)
24-
const initiatedBy = getDisplayWorkspaceBuildInitiatedBy(build)
15+
const { t } = useTranslation("buildPage")
2516

2617
return (
27-
<div className={styles.stats}>
28-
<div className={styles.statItem}>
29-
<span className={styles.statsLabel}>Workspace Name</span>
30-
<Link
31-
component={RouterLink}
32-
to={`/@${build.workspace_owner_name}/${build.workspace_name}`}
33-
className={combineClasses([styles.statsValue, styles.link])}
34-
>
35-
{build.workspace_name}
36-
</Link>
37-
</div>
38-
<div className={styles.statsDivider} />
39-
40-
<div className={styles.statItem}>
41-
<span className={styles.statsLabel}>Duration</span>
42-
<span className={styles.statsValue}>
43-
{displayWorkspaceBuildDuration(build)}
44-
</span>
45-
</div>
46-
<div className={styles.statsDivider} />
47-
<div className={styles.statItem}>
48-
<span className={styles.statsLabel}>Started at</span>
49-
<span className={styles.statsValue}>
50-
{new Date(build.created_at).toLocaleString()}
51-
</span>
52-
</div>
53-
<div className={styles.statsDivider} />
54-
<div className={styles.statItem}>
55-
<span className={styles.statsLabel}>Status</span>
56-
<span className={styles.statsValue}>
57-
<span style={{ color: status.color }}>{status.status}</span>
58-
</span>
59-
</div>
60-
<div className={styles.statsDivider} />
61-
<div className={styles.statItem}>
62-
<span className={styles.statsLabel}>Action</span>
63-
<span
64-
className={combineClasses([styles.statsValue, styles.capitalize])}
65-
>
66-
{build.transition}
67-
</span>
68-
</div>
69-
<div className={styles.statsDivider} />
70-
<div className={styles.statItem}>
71-
<span className={styles.statsLabel}>Initiated by</span>
72-
<span className={styles.statsValue}>{initiatedBy}</span>
73-
</div>
74-
</div>
18+
<Stats>
19+
<StatsItem
20+
label={t("stats.workspace")}
21+
value={
22+
<Link to={`/@${build.workspace_owner_name}/${build.workspace_name}`}>
23+
{build.workspace_name}
24+
</Link>
25+
}
26+
/>
27+
<StatsItem
28+
label={t("stats.duration")}
29+
value={displayWorkspaceBuildDuration(build)}
30+
/>
31+
<StatsItem
32+
label={t("stats.startedAt")}
33+
value={new Date(build.created_at).toLocaleString()}
34+
/>
35+
<StatsItem label={t("stats.action")} value={build.transition} />
36+
</Stats>
7537
)
7638
}
77-
78-
const useStyles = makeStyles((theme) => ({
79-
stats: {
80-
paddingLeft: theme.spacing(2),
81-
paddingRight: theme.spacing(2),
82-
backgroundColor: theme.palette.background.paper,
83-
borderRadius: theme.shape.borderRadius,
84-
display: "flex",
85-
alignItems: "center",
86-
color: theme.palette.text.secondary,
87-
fontFamily: MONOSPACE_FONT_FAMILY,
88-
border: `1px solid ${theme.palette.divider}`,
89-
[theme.breakpoints.down("sm")]: {
90-
display: "block",
91-
},
92-
},
93-
94-
statItem: {
95-
minWidth: "13%",
96-
padding: theme.spacing(2),
97-
paddingTop: theme.spacing(1.75),
98-
},
99-
100-
statsLabel: {
101-
fontSize: 12,
102-
textTransform: "uppercase",
103-
display: "block",
104-
fontWeight: 600,
105-
wordWrap: "break-word",
106-
},
107-
108-
statsValue: {
109-
fontSize: 16,
110-
marginTop: theme.spacing(0.25),
111-
display: "block",
112-
wordWrap: "break-word",
113-
},
114-
115-
statsDivider: {
116-
width: 1,
117-
height: theme.spacing(5),
118-
backgroundColor: theme.palette.divider,
119-
marginRight: theme.spacing(2),
120-
[theme.breakpoints.down("sm")]: {
121-
display: "none",
122-
},
123-
},
124-
125-
capitalize: {
126-
textTransform: "capitalize",
127-
},
128-
129-
link: {
130-
color: theme.palette.text.primary,
131-
fontWeight: 600,
132-
},
133-
}))

site/src/i18n/en/buildPage.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"stats": {
3+
"workspace": "Workspace",
4+
"duration": "Duration",
5+
"startedAt": "Started at",
6+
"action": "Action"
7+
}
8+
}

site/src/i18n/en/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import templatePage from "./templatePage.json"
55
import templatesPage from "./templatesPage.json"
66
import workspacePage from "./workspacePage.json"
77
import agent from "./agent.json"
8+
import buildPage from "./buildPage.json"
89

910
export const en = {
1011
common,
@@ -14,4 +15,5 @@ export const en = {
1415
templatesPage,
1516
createWorkspacePage,
1617
agent,
18+
buildPage,
1719
}

site/src/pages/WorkspaceBuildPage/WorkspaceBuildPageView.tsx

+16-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
import { BuildAvatar } from "components/BuildsTable/BuildAvatar"
12
import { FC } from "react"
23
import { ProvisionerJobLog, WorkspaceBuild } from "../../api/typesGenerated"
34
import { Loader } from "../../components/Loader/Loader"
45
import { Margins } from "../../components/Margins/Margins"
56
import {
67
PageHeader,
8+
PageHeaderSubtitle,
79
PageHeaderTitle,
810
} from "../../components/PageHeader/PageHeader"
911
import { Stack } from "../../components/Stack/Stack"
@@ -29,11 +31,21 @@ export const WorkspaceBuildPageView: FC<WorkspaceBuildPageViewProps> = ({
2931
}) => {
3032
return (
3133
<Margins>
32-
<PageHeader>
33-
<PageHeaderTitle>Logs</PageHeaderTitle>
34-
</PageHeader>
34+
{build && (
35+
<PageHeader>
36+
<Stack direction="row" alignItems="center" spacing={3}>
37+
<BuildAvatar build={build} size={48} />
38+
<div>
39+
<PageHeaderTitle>Build #{build.build_number}</PageHeaderTitle>
40+
<PageHeaderSubtitle condensed>
41+
{build.initiator_name}
42+
</PageHeaderSubtitle>
43+
</div>
44+
</Stack>
45+
</PageHeader>
46+
)}
3547

36-
<Stack>
48+
<Stack spacing={4}>
3749
{build &&
3850
build.transition === "delete" &&
3951
build.job.status === "failed" && (

0 commit comments

Comments
 (0)