Skip to content

Commit 12cdd47

Browse files
committed
fix: handle workspace errors
1 parent 6e63487 commit 12cdd47

File tree

5 files changed

+70
-21
lines changed

5 files changed

+70
-21
lines changed

site/src/api/errors.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,6 @@ export const getValidationErrorMessage = (error: Error | ApiError | unknown): st
8686

8787
export const getErrorDetail = (error: Error | ApiError | unknown): string | undefined | null =>
8888
isApiError(error) ? error.response.data.detail : error instanceof Error ? error.stack : null
89+
90+
export const getErrorIfErrorType = (error: Error | unknown): Error | undefined =>
91+
error instanceof Error ? error : undefined

site/src/components/Resources/Resources.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import TableContainer from "@material-ui/core/TableContainer"
66
import TableHead from "@material-ui/core/TableHead"
77
import TableRow from "@material-ui/core/TableRow"
88
import useTheme from "@material-ui/styles/useTheme"
9+
import { ErrorSummary } from "components/ErrorSummary/ErrorSummary"
910
import { FC } from "react"
1011
import { Workspace, WorkspaceResource } from "../../api/typesGenerated"
1112
import { AvatarData } from "../../components/AvatarData/AvatarData"
@@ -45,7 +46,7 @@ export const Resources: FC<ResourcesProps> = ({
4546
return (
4647
<div aria-label={Language.resources} className={styles.wrapper}>
4748
{getResourcesError ? (
48-
{ getResourcesError }
49+
<ErrorSummary error={getResourcesError} />
4950
) : (
5051
<TableContainer className={styles.tableContainer}>
5152
<Table>

site/src/components/Workspace/Workspace.tsx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { makeStyles } from "@material-ui/core/styles"
2+
import { ErrorSummary } from "components/ErrorSummary/ErrorSummary"
23
import { WorkspaceStatusBadge } from "components/WorkspaceStatusBadge/WorkspaceStatusBadge"
34
import { FC } from "react"
45
import { useNavigate } from "react-router-dom"
@@ -15,6 +16,13 @@ import { WorkspaceScheduleButton } from "../WorkspaceScheduleButton/WorkspaceSch
1516
import { WorkspaceSection } from "../WorkspaceSection/WorkspaceSection"
1617
import { WorkspaceStats } from "../WorkspaceStats/WorkspaceStats"
1718

19+
export enum WorkspaceErrors {
20+
GET_RESOURCES_ERROR = "getResourcesError",
21+
GET_BUILDS_ERROR = "getBuildsError",
22+
BUILD_ERROR = "buildError",
23+
CANCELLATION_MESSAGE = "cancellationMessage",
24+
}
25+
1826
export interface WorkspaceProps {
1927
bannerProps: {
2028
isLoading?: boolean
@@ -31,9 +39,9 @@ export interface WorkspaceProps {
3139
handleCancel: () => void
3240
workspace: TypesGen.Workspace
3341
resources?: TypesGen.WorkspaceResource[]
34-
getResourcesError?: Error
3542
builds?: TypesGen.WorkspaceBuild[]
3643
canUpdateWorkspace: boolean
44+
workspaceErrors: Partial<Record<WorkspaceErrors, Error>>
3745
}
3846

3947
/**
@@ -49,15 +57,23 @@ export const Workspace: FC<WorkspaceProps> = ({
4957
handleCancel,
5058
workspace,
5159
resources,
52-
getResourcesError,
5360
builds,
5461
canUpdateWorkspace,
62+
workspaceErrors,
5563
}) => {
5664
const styles = useStyles()
5765
const navigate = useNavigate()
5866

5967
return (
6068
<Margins>
69+
<Stack spacing={1}>
70+
{workspaceErrors[WorkspaceErrors.BUILD_ERROR] && (
71+
<ErrorSummary error={workspaceErrors[WorkspaceErrors.BUILD_ERROR]} dismissible />
72+
)}
73+
{workspaceErrors[WorkspaceErrors.CANCELLATION_MESSAGE] && (
74+
<ErrorSummary error={workspaceErrors[WorkspaceErrors.CANCELLATION_MESSAGE]} dismissible />
75+
)}
76+
</Stack>
6177
<PageHeader
6278
actions={
6379
<Stack direction="row" spacing={1} className={styles.actions}>
@@ -101,14 +117,18 @@ export const Workspace: FC<WorkspaceProps> = ({
101117
{!!resources && !!resources.length && (
102118
<Resources
103119
resources={resources}
104-
getResourcesError={getResourcesError}
120+
getResourcesError={workspaceErrors[WorkspaceErrors.GET_RESOURCES_ERROR]}
105121
workspace={workspace}
106122
canUpdateWorkspace={canUpdateWorkspace}
107123
/>
108124
)}
109125

110126
<WorkspaceSection title="Logs" contentsProps={{ className: styles.timelineContents }}>
111-
<BuildsTable builds={builds} className={styles.timelineTable} />
127+
{workspaceErrors[WorkspaceErrors.GET_BUILDS_ERROR] ? (
128+
<ErrorSummary error={workspaceErrors[WorkspaceErrors.GET_BUILDS_ERROR]} />
129+
) : (
130+
<BuildsTable builds={builds} className={styles.timelineTable} />
131+
)}
112132
</WorkspaceSection>
113133
</Stack>
114134
</Stack>

site/src/pages/WorkspacePage/WorkspacePage.tsx

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import { makeStyles } from "@material-ui/core/styles"
12
import { useMachine, useSelector } from "@xstate/react"
3+
import { getErrorIfErrorType } from "api/errors"
24
import dayjs from "dayjs"
35
import minMax from "dayjs/plugin/minMax"
46
import React, { useContext, useEffect } from "react"
@@ -7,7 +9,7 @@ import { useParams } from "react-router-dom"
79
import { DeleteWorkspaceDialog } from "../../components/DeleteWorkspaceDialog/DeleteWorkspaceDialog"
810
import { ErrorSummary } from "../../components/ErrorSummary/ErrorSummary"
911
import { FullScreenLoader } from "../../components/Loader/FullScreenLoader"
10-
import { Workspace } from "../../components/Workspace/Workspace"
12+
import { Workspace, WorkspaceErrors } from "../../components/Workspace/Workspace"
1113
import { firstOrItem } from "../../util/array"
1214
import { pageTitle } from "../../util/page"
1315
import { getFaviconByStatus } from "../../util/workspace"
@@ -31,13 +33,26 @@ export const WorkspacePage: React.FC = () => {
3133
userId: me?.id,
3234
},
3335
})
34-
const { workspace, resources, getWorkspaceError, getResourcesError, builds, permissions } =
35-
workspaceState.context
36+
const {
37+
workspace,
38+
getWorkspaceError,
39+
resources,
40+
getResourcesError,
41+
builds,
42+
getBuildsError,
43+
permissions,
44+
checkPermissionsError,
45+
buildError,
46+
cancellationMessage,
47+
} = workspaceState.context
3648

49+
console.log(cancellationMessage)
3750
const canUpdateWorkspace = !!permissions?.updateWorkspace
3851

3952
const [bannerState, bannerSend] = useMachine(workspaceScheduleBannerMachine)
4053

54+
const styles = useStyles()
55+
4156
/**
4257
* Get workspace, template, and organization on mount and whenever workspaceId changes.
4358
* workspaceSend should not change.
@@ -47,7 +62,12 @@ export const WorkspacePage: React.FC = () => {
4762
}, [username, workspaceName, workspaceSend])
4863

4964
if (workspaceState.matches("error")) {
50-
return <ErrorSummary error={getWorkspaceError} />
65+
return (
66+
<div className={styles.error}>
67+
{getWorkspaceError && <ErrorSummary error={getWorkspaceError} />}
68+
{checkPermissionsError && <ErrorSummary error={checkPermissionsError} />}
69+
</div>
70+
)
5171
} else if (!workspace) {
5272
return <FullScreenLoader />
5373
} else {
@@ -100,9 +120,14 @@ export const WorkspacePage: React.FC = () => {
100120
handleUpdate={() => workspaceSend("UPDATE")}
101121
handleCancel={() => workspaceSend("CANCEL")}
102122
resources={resources}
103-
getResourcesError={getResourcesError instanceof Error ? getResourcesError : undefined}
104123
builds={builds}
105124
canUpdateWorkspace={canUpdateWorkspace}
125+
workspaceErrors={{
126+
[WorkspaceErrors.GET_RESOURCES_ERROR]: getErrorIfErrorType(getResourcesError),
127+
[WorkspaceErrors.GET_BUILDS_ERROR]: getErrorIfErrorType(getBuildsError),
128+
[WorkspaceErrors.BUILD_ERROR]: getErrorIfErrorType(buildError),
129+
[WorkspaceErrors.CANCELLATION_MESSAGE]: getErrorIfErrorType(cancellationMessage),
130+
}}
106131
/>
107132
<DeleteWorkspaceDialog
108133
isOpen={workspaceState.matches({ ready: { build: "askingDelete" } })}
@@ -121,3 +146,9 @@ export const boundedDeadline = (newDeadline: dayjs.Dayjs, now: dayjs.Dayjs): day
121146
const maxDeadline = now.add(24, "hours")
122147
return dayjs.min(dayjs.max(minDeadline, newDeadline), maxDeadline)
123148
}
149+
150+
const useStyles = makeStyles((theme) => ({
151+
error: {
152+
margin: theme.spacing(2),
153+
},
154+
}))

site/src/xServices/workspace/workspaceXService.ts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export interface WorkspaceContext {
3535
builds?: TypesGen.WorkspaceBuild[]
3636
getBuildsError?: Error | unknown
3737
loadMoreBuildsError?: Error | unknown
38-
cancellationMessage: string
38+
cancellationMessage: Types.Message
3939
// permissions
4040
permissions?: Permissions
4141
checkPermissionsError?: Error | unknown
@@ -213,7 +213,7 @@ export const workspaceMachine = createMachine(
213213
},
214214
onError: {
215215
target: "idle",
216-
actions: ["assignBuildError", "displayBuildError"],
216+
actions: ["assignBuildError"],
217217
},
218218
},
219219
},
@@ -228,7 +228,7 @@ export const workspaceMachine = createMachine(
228228
},
229229
onError: {
230230
target: "idle",
231-
actions: ["assignBuildError", "displayBuildError"],
231+
actions: ["assignBuildError"],
232232
},
233233
},
234234
},
@@ -243,7 +243,7 @@ export const workspaceMachine = createMachine(
243243
},
244244
onError: {
245245
target: "idle",
246-
actions: ["assignBuildError", "displayBuildError"],
246+
actions: ["assignBuildError"],
247247
},
248248
},
249249
},
@@ -258,7 +258,7 @@ export const workspaceMachine = createMachine(
258258
},
259259
onError: {
260260
target: "idle",
261-
actions: ["assignCancellationMessage", "displayCancellationError"],
261+
actions: ["assignCancellationMessage"],
262262
},
263263
},
264264
},
@@ -395,9 +395,6 @@ export const workspaceMachine = createMachine(
395395
assign({
396396
buildError: event.data,
397397
}),
398-
displayBuildError: () => {
399-
displayError(Language.buildError)
400-
},
401398
clearBuildError: (_) =>
402399
assign({
403400
buildError: undefined,
@@ -410,9 +407,6 @@ export const workspaceMachine = createMachine(
410407
assign({
411408
cancellationMessage: undefined,
412409
}),
413-
displayCancellationError: (context) => {
414-
displayError(context.cancellationMessage)
415-
},
416410
assignRefreshWorkspaceError: (_, event) =>
417411
assign({
418412
refreshWorkspaceError: event.data,

0 commit comments

Comments
 (0)