Skip to content

Commit 0156cc6

Browse files
greyscaledkylecarbs
authored andcommitted
feat: edit workspace schedule page (#1701)
Resolves: #1455 Resolves: #1456 Summary: Adds a page (accessible from Workspace Schedule section on a workspace) to edit a schedule. Impact: General parity with CLI for autostart/autostop: that is you can update your schedule from the UI
1 parent 6a37ae2 commit 0156cc6

File tree

11 files changed

+877
-112
lines changed

11 files changed

+877
-112
lines changed

site/src/AppRouter.tsx

+9
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { CreateUserPage } from "./pages/UsersPage/CreateUserPage/CreateUserPage"
1717
import { UsersPage } from "./pages/UsersPage/UsersPage"
1818
import { WorkspaceBuildPage } from "./pages/WorkspaceBuildPage/WorkspaceBuildPage"
1919
import { WorkspacePage } from "./pages/WorkspacePage/WorkspacePage"
20+
import { WorkspaceSchedulePage } from "./pages/WorkspaceSchedulePage/WorkspaceSchedulePage"
2021
import { WorkspaceSettingsPage } from "./pages/WorkspaceSettingsPage/WorkspaceSettingsPage"
2122

2223
const TerminalPage = React.lazy(() => import("./pages/TerminalPage/TerminalPage"))
@@ -83,6 +84,14 @@ export const AppRouter: React.FC = () => (
8384
</AuthAndFrame>
8485
}
8586
/>
87+
<Route
88+
path="schedule"
89+
element={
90+
<RequireAuth>
91+
<WorkspaceSchedulePage />
92+
</RequireAuth>
93+
}
94+
/>
8695
</Route>
8796
</Route>
8897

site/src/components/WorkspaceSchedule/WorkspaceSchedule.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import dayjs from "dayjs"
77
import duration from "dayjs/plugin/duration"
88
import relativeTime from "dayjs/plugin/relativeTime"
99
import React from "react"
10+
import { Link as RouterLink } from "react-router-dom"
1011
import { Workspace } from "../../api/typesGenerated"
1112
import { MONOSPACE_FONT_FAMILY } from "../../theme/constants"
1213
import { extractTimezone, stripTimezone } from "../../util/schedule"
@@ -78,7 +79,9 @@ export const WorkspaceSchedule: React.FC<WorkspaceScheduleProps> = ({ workspace
7879
<span className={styles.scheduleValue}>{Language.autoStopDisplay(workspace)}</span>
7980
</div>
8081
<div>
81-
<Link className={styles.scheduleAction}>{Language.editScheduleLink}</Link>
82+
<Link className={styles.scheduleAction} component={RouterLink} to={`/workspaces/${workspace.id}/schedule`}>
83+
{Language.editScheduleLink}
84+
</Link>
8285
</div>
8386
</Stack>
8487
</div>

site/src/components/WorkspaceStats/WorkspaceScheduleForm.stories.tsx

+1-4
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,5 @@ const Template: Story<WorkspaceScheduleFormProps> = (args) => <WorkspaceSchedule
1313
export const Example = Template.bind({})
1414
Example.args = {
1515
onCancel: () => action("onCancel"),
16-
onSubmit: () => {
17-
action("onSubmit")
18-
return Promise.resolve()
19-
},
16+
onSubmit: () => action("onSubmit"),
2017
}

site/src/components/WorkspaceStats/WorkspaceScheduleForm.test.ts

+58-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const valid: WorkspaceScheduleFormValues = {
1010
saturday: false,
1111

1212
startTime: "09:30",
13+
timezone: "Canada/Eastern",
1314
ttl: 120,
1415
}
1516

@@ -25,14 +26,15 @@ describe("validationSchema", () => {
2526
saturday: false,
2627

2728
startTime: "",
29+
timezone: "",
2830
ttl: 0,
2931
}
3032
const validate = () => validationSchema.validateSync(values)
3133
expect(validate).not.toThrow()
3234
})
3335

3436
it("disallows ttl to be negative", () => {
35-
const values = {
37+
const values: WorkspaceScheduleFormValues = {
3638
...valid,
3739
ttl: -1,
3840
}
@@ -41,7 +43,7 @@ describe("validationSchema", () => {
4143
})
4244

4345
it("disallows all days-of-week to be false when startTime is set", () => {
44-
const values = {
46+
const values: WorkspaceScheduleFormValues = {
4547
...valid,
4648
sunday: false,
4749
monday: false,
@@ -54,4 +56,58 @@ describe("validationSchema", () => {
5456
const validate = () => validationSchema.validateSync(values)
5557
expect(validate).toThrowError(Language.errorNoDayOfWeek)
5658
})
59+
60+
it("allows startTime 16:20", () => {
61+
const values: WorkspaceScheduleFormValues = {
62+
...valid,
63+
startTime: "16:20",
64+
}
65+
const validate = () => validationSchema.validateSync(values)
66+
expect(validate).not.toThrow()
67+
})
68+
69+
it("disallows startTime to be H:mm", () => {
70+
const values: WorkspaceScheduleFormValues = {
71+
...valid,
72+
startTime: "9:30",
73+
}
74+
const validate = () => validationSchema.validateSync(values)
75+
expect(validate).toThrowError(Language.errorTime)
76+
})
77+
78+
it("disallows startTime to be HH:m", () => {
79+
const values: WorkspaceScheduleFormValues = {
80+
...valid,
81+
startTime: "09:5",
82+
}
83+
const validate = () => validationSchema.validateSync(values)
84+
expect(validate).toThrowError(Language.errorTime)
85+
})
86+
87+
it("disallows an invalid startTime 24:01", () => {
88+
const values: WorkspaceScheduleFormValues = {
89+
...valid,
90+
startTime: "24:01",
91+
}
92+
const validate = () => validationSchema.validateSync(values)
93+
expect(validate).toThrowError(Language.errorTime)
94+
})
95+
96+
it("disallows an invalid startTime 09:60", () => {
97+
const values: WorkspaceScheduleFormValues = {
98+
...valid,
99+
startTime: "09:60",
100+
}
101+
const validate = () => validationSchema.validateSync(values)
102+
expect(validate).toThrowError(Language.errorTime)
103+
})
104+
105+
it("disallows an invalid timezone Canada/North", () => {
106+
const values: WorkspaceScheduleFormValues = {
107+
...valid,
108+
timezone: "Canada/North",
109+
}
110+
const validate = () => validationSchema.validateSync(values)
111+
expect(validate).toThrowError(Language.errorTimezone)
112+
})
57113
})

0 commit comments

Comments
 (0)