diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceScheduleForm.stories.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceScheduleForm.stories.tsx index 4efc0c3f2df7b..d45e265c42030 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceScheduleForm.stories.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceScheduleForm.stories.tsx @@ -8,20 +8,19 @@ import { emptySchedule, } from "pages/WorkspaceSettingsPage/WorkspaceSchedulePage/schedule"; import { emptyTTL } from "pages/WorkspaceSettingsPage/WorkspaceSchedulePage/ttl"; -import { mockApiError } from "testHelpers/entities"; +import { MockTemplate, mockApiError } from "testHelpers/entities"; import { WorkspaceScheduleForm } from "./WorkspaceScheduleForm"; dayjs.extend(advancedFormat); dayjs.extend(utc); dayjs.extend(timezone); -const meta: Meta = { - title: "pages/WorkspaceSettingsPage/WorkspaceScheduleForm", - component: WorkspaceScheduleForm, - args: { - allowTemplateAutoStart: true, - allowTemplateAutoStop: true, - allowedTemplateAutoStartDays: [ +const mockTemplate = { + ...MockTemplate, + allow_user_autostart: true, + allow_user_autostop: true, + autostart_requirement: { + days_of_week: [ "sunday", "monday", "tuesday", @@ -33,12 +32,20 @@ const meta: Meta = { }, }; +const meta: Meta = { + title: "pages/WorkspaceSettingsPage/WorkspaceScheduleForm", + component: WorkspaceScheduleForm, + args: { + template: mockTemplate, + }, +}; + export default meta; type Story = StoryObj; const defaultInitialValues = { - autostartEnabled: true, ...defaultSchedule(), + autostartEnabled: true, autostopEnabled: true, ttl: 24, }; @@ -51,8 +58,11 @@ export const AllDisabled: Story = { autostopEnabled: false, ttl: emptyTTL, }, - allowTemplateAutoStart: false, - allowTemplateAutoStop: false, + template: { + ...mockTemplate, + allow_user_autostart: false, + allow_user_autostop: false, + }, }, }; @@ -64,7 +74,10 @@ export const Autostart: Story = { autostopEnabled: false, ttl: emptyTTL, }, - allowTemplateAutoStop: false, + template: { + ...mockTemplate, + allow_user_autostop: false, + }, }, }; @@ -90,7 +103,7 @@ export const WithError: Story = { args: { initialValues: { ...defaultInitialValues, ttl: 100 }, initialTouched: { ttl: true }, - submitScheduleError: mockApiError({ + error: mockApiError({ message: "Something went wrong.", validations: [ { field: "ttl_ms", detail: "Invalid time until shutdown." }, diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceScheduleForm.test.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceScheduleForm.test.tsx index 31d8d89637dc0..41cbe7f373e4d 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceScheduleForm.test.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceScheduleForm.test.tsx @@ -4,6 +4,7 @@ import { validationSchema, WorkspaceScheduleFormValues, WorkspaceScheduleForm, + WorkspaceScheduleFormProps, } from "./WorkspaceScheduleForm"; import { timeZones } from "utils/timeZones"; import * as API from "api/api"; @@ -245,8 +246,8 @@ describe("ttlShutdownAt", () => { }); const autoStartDayLabels = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; -const defaultFormProps = { - submitScheduleError: "", +const defaultFormProps: WorkspaceScheduleFormProps = { + error: "", initialValues: { ...defaultSchedule(), autostartEnabled: true, @@ -257,20 +258,28 @@ const defaultFormProps = { defaultTTL: 24, onCancel: () => null, onSubmit: () => null, - allowedTemplateAutoStartDays: autoStartDayLabels, - allowTemplateAutoStart: true, - allowTemplateAutoStop: true, + template: { + ...MockTemplate, + allow_user_autostart: true, + allow_user_autostop: true, + autostart_requirement: { + ...MockTemplate.autostart_requirement, + days_of_week: autoStartDayLabels, + }, + }, }; describe("templateInheritance", () => { it("disables the entire autostart feature appropriately", async () => { jest.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate); - render( - , - ); + const props = { + ...defaultFormProps, + template: { + ...defaultFormProps.template, + allow_user_autostart: false, + }, + }; + render(); const autoStartToggle = await screen.findByLabelText("Enable Autostart"); expect(autoStartToggle).toBeDisabled(); @@ -291,12 +300,18 @@ describe("templateInheritance", () => { const enabledDayLabels = ["Sat", "Sun"]; jest.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate); - render( - , - ); + const props = { + ...defaultFormProps, + template: { + ...defaultFormProps.template, + autostart_requirement: { + ...MockTemplate.autostart_requirement, + days_of_week: ["saturday", "sunday"], + }, + }, + }; + + render(); const autoStartToggle = await screen.findByLabelText("Enable Autostart"); expect(autoStartToggle).toBeEnabled(); @@ -321,13 +336,15 @@ describe("templateInheritance", () => { } }); it("disables the entire autostop feature appropriately", async () => { + const props = { + ...defaultFormProps, + template: { + ...defaultFormProps.template, + allow_user_autostop: false, + }, + }; jest.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate); - render( - , - ); + render(); const autoStopToggle = await screen.findByLabelText("Enable Autostop"); expect(autoStopToggle).toBeDisabled(); @@ -398,17 +415,16 @@ test("form should be enabled when both auto stop and auto start features are dis }); test("form should be disabled when both auto stop and auto start features are disabled at template level", async () => { + const props = { + ...defaultFormProps, + template: { + ...defaultFormProps.template, + allow_user_autostart: false, + allow_user_autostop: false, + }, + }; jest.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate); - render( - , - ); + render(); const submitButton = await screen.findByRole("button", { name: "Submit" }); expect(submitButton).toBeDisabled(); diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceScheduleForm.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceScheduleForm.tsx index 57866aacbc062..a5af7c72f0806 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceScheduleForm.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceScheduleForm.tsx @@ -32,7 +32,7 @@ import { timeZones } from "utils/timeZones"; import Tooltip from "@mui/material/Tooltip"; import { formatDuration, intervalToDuration } from "date-fns"; import { DisabledBadge } from "components/Badges/Badges"; -import { TemplateAutostartRequirement } from "api/typesGenerated"; +import { Template } from "api/typesGenerated"; // REMARK: some plugins depend on utc, so it's listed first. Otherwise they're // sorted alphabetically. @@ -71,12 +71,10 @@ export const Language = { }; export interface WorkspaceScheduleFormProps { - submitScheduleError?: unknown; + template: Template; + error?: unknown; initialValues: WorkspaceScheduleFormValues; isLoading: boolean; - allowedTemplateAutoStartDays: TemplateAutostartRequirement["days_of_week"]; - allowTemplateAutoStop: boolean; - allowTemplateAutoStart: boolean; onCancel: () => void; onSubmit: (values: WorkspaceScheduleFormValues) => void; // for storybook @@ -95,7 +93,6 @@ export interface WorkspaceScheduleFormValues { saturday: boolean; startTime: string; timezone: string; - autostopEnabled: boolean; ttl: number; } @@ -184,16 +181,14 @@ export const validationSchema = Yup.object({ }); export const WorkspaceScheduleForm: FC = ({ - submitScheduleError, + error, initialValues, isLoading, onCancel, onSubmit, initialTouched, defaultTTL, - allowedTemplateAutoStartDays, - allowTemplateAutoStop, - allowTemplateAutoStart, + template, }) => { const form = useFormik({ initialValues, @@ -202,10 +197,7 @@ export const WorkspaceScheduleForm: FC = ({ initialTouched, enableReinitialize: true, }); - const formHelpers = getFormHelpers( - form, - submitScheduleError, - ); + const formHelpers = getFormHelpers(form, error); const checkboxes: Array<{ value: boolean; name: string; label: string }> = [ { @@ -289,7 +281,7 @@ export const WorkspaceScheduleForm: FC = ({ Select the time and days of week on which you want the workspace starting automatically. - {!allowTemplateAutoStart && ( + {!template.allow_user_autostart && ( @@ -301,7 +293,7 @@ export const WorkspaceScheduleForm: FC = ({ = ({ // or if primary feature is toggled off via the switch above disabled={ isLoading || - !allowTemplateAutoStart || + !template.allow_user_autostart || !form.values.autostartEnabled } label={Language.startTimeLabel} @@ -329,7 +321,7 @@ export const WorkspaceScheduleForm: FC = ({ // or if primary feature is toggled off via the switch above disabled={ isLoading || - !allowTemplateAutoStart || + !template.allow_user_autostart || !form.values.autostartEnabled } label={Language.timezoneLabel} @@ -367,8 +359,10 @@ export const WorkspaceScheduleForm: FC = ({ // also disabled if primary feature switch (above) is toggled off disabled={ isLoading || - !allowTemplateAutoStart || - !allowedTemplateAutoStartDays.includes(checkbox.name) || + !template.allow_user_autostart || + !template.autostart_requirement.days_of_week.includes( + checkbox.name, + ) || !form.values.autostartEnabled } onChange={form.handleChange} @@ -396,10 +390,13 @@ export const WorkspaceScheduleForm: FC = ({
Set how many hours should elapse after the workspace started before the workspace automatically shuts down. This will be - extended by 1 hour after last activity in the workspace was - detected. + extended by{" "} + {dayjs + .duration({ milliseconds: template.activity_bump_ms }) + .humanize()}{" "} + after last activity in the workspace was detected.
- {!allowTemplateAutoStop && ( + {!template.allow_user_autostop && ( @@ -414,7 +411,7 @@ export const WorkspaceScheduleForm: FC = ({ name="autostopEnabled" checked={form.values.autostopEnabled} onChange={handleToggleAutostop} - disabled={!allowTemplateAutoStop} + disabled={!template.allow_user_autostop} /> } label={Language.stopSwitch} @@ -428,7 +425,7 @@ export const WorkspaceScheduleForm: FC = ({ // if autostop feature is toggled off via the switch above disabled={ isLoading || - !allowTemplateAutoStop || + !template.allow_user_autostop || !form.values.autostopEnabled } inputProps={{ min: 0, step: "any" }} @@ -443,7 +440,9 @@ export const WorkspaceScheduleForm: FC = ({ isLoading={isLoading} // If both options, autostart and autostop, are disabled at the template // level, the form is disabled. - submitDisabled={!allowTemplateAutoStart && !allowTemplateAutoStop} + submitDisabled={ + !template.allow_user_autostart && !template.allow_user_autostop + } /> ); diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceSchedulePage.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceSchedulePage.tsx index 2c1eefc545aa0..4805566f36382 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceSchedulePage.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceSchedulePage.tsx @@ -101,12 +101,8 @@ export const WorkspaceSchedulePage: FC = () => { {template && (