diff --git a/site/src/pages/WorkspaceSchedulePage/WorkspaceSchedulePage.tsx b/site/src/pages/WorkspaceSchedulePage/WorkspaceSchedulePage.tsx index 492a56ae47aa0..ad48166dea9c7 100644 --- a/site/src/pages/WorkspaceSchedulePage/WorkspaceSchedulePage.tsx +++ b/site/src/pages/WorkspaceSchedulePage/WorkspaceSchedulePage.tsx @@ -4,6 +4,7 @@ import { scheduleToAutoStart } from "pages/WorkspaceSchedulePage/schedule" import { ttlMsToAutoStop } from "pages/WorkspaceSchedulePage/ttl" import React, { useEffect, useState } from "react" import { Navigate, useNavigate, useParams } from "react-router-dom" +import { scheduleChanged } from "util/schedule" import * as TypesGen from "../../api/typesGenerated" import { FullScreenLoader } from "../../components/Loader/FullScreenLoader" import { WorkspaceScheduleForm } from "../../components/WorkspaceScheduleForm/WorkspaceScheduleForm" @@ -108,10 +109,10 @@ export const WorkspaceSchedulePage: React.FC = () => { onSubmit={(values) => { scheduleSend({ type: "SUBMIT_SCHEDULE", - autoStart: values.autoStartEnabled - ? formValuesToAutoStartRequest(values) - : undefined, + autoStart: formValuesToAutoStartRequest(values), ttl: formValuesToTTLRequest(values), + autoStartChanged: scheduleChanged(autoStart, values), + autoStopChanged: scheduleChanged(autoStop, values), }) }} /> diff --git a/site/src/util/schedule.test.ts b/site/src/util/schedule.test.ts index 452727624a4e6..43b0306203490 100644 --- a/site/src/util/schedule.test.ts +++ b/site/src/util/schedule.test.ts @@ -1,5 +1,7 @@ import dayjs from "dayjs" import duration from "dayjs/plugin/duration" +import { emptySchedule } from "pages/WorkspaceSchedulePage/schedule" +import { emptyTTL } from "pages/WorkspaceSchedulePage/ttl" import { Template, Workspace } from "../api/typesGenerated" import * as Mocks from "../testHelpers/entities" import { @@ -12,6 +14,7 @@ import { getMaxDeadlineChange, getMinDeadline, stripTimezone, + scheduleChanged, } from "./schedule" dayjs.extend(duration) @@ -141,3 +144,71 @@ describe("getMaxDeadlineChange", () => { expect(getMaxDeadlineChange(deadline, minDeadline)).toEqual(2) }) }) + +describe("scheduleChanged", () => { + describe("autoStart", () => { + it("should be true if toggle values are different", () => { + const autoStart = { autoStartEnabled: true, ...emptySchedule } + const formValues = { + autoStartEnabled: false, + ...emptySchedule, + autoStopEnabled: false, + ttl: emptyTTL, + } + expect(scheduleChanged(autoStart, formValues)).toBe(true) + }) + it("should be true if schedule values are different", () => { + const autoStart = { autoStartEnabled: true, ...emptySchedule } + const formValues = { + autoStartEnabled: true, + ...{ ...emptySchedule, monday: true, startTime: "09:00" }, + autoStopEnabled: false, + ttl: emptyTTL, + } + expect(scheduleChanged(autoStart, formValues)).toBe(true) + }) + it("should be false if all autostart values are the same", () => { + const autoStart = { autoStartEnabled: true, ...emptySchedule } + const formValues = { + autoStartEnabled: true, + ...emptySchedule, + autoStopEnabled: false, + ttl: emptyTTL, + } + expect(scheduleChanged(autoStart, formValues)).toBe(false) + }) + }) + + describe("autoStop", () => { + it("should be true if toggle values are different", () => { + const autoStop = { autoStopEnabled: true, ttl: 1000 } + const formValues = { + autoStartEnabled: false, + ...emptySchedule, + autoStopEnabled: false, + ttl: 1000, + } + expect(scheduleChanged(autoStop, formValues)).toBe(true) + }) + it("should be true if ttl values are different", () => { + const autoStop = { autoStopEnabled: true, ttl: 1000 } + const formValues = { + autoStartEnabled: false, + ...emptySchedule, + autoStopEnabled: true, + ttl: 2000, + } + expect(scheduleChanged(autoStop, formValues)).toBe(true) + }) + it("should be false if all autostop values are the same", () => { + const autoStop = { autoStopEnabled: true, ttl: 1000 } + const formValues = { + autoStartEnabled: false, + ...emptySchedule, + autoStopEnabled: true, + ttl: 1000, + } + expect(scheduleChanged(autoStop, formValues)).toBe(false) + }) + }) +}) diff --git a/site/src/util/schedule.ts b/site/src/util/schedule.ts index 4070f8101e388..cd325f2006f4c 100644 --- a/site/src/util/schedule.ts +++ b/site/src/util/schedule.ts @@ -1,3 +1,5 @@ +import map from "lodash/map" +import some from "lodash/some" import cronstrue from "cronstrue" import dayjs, { Dayjs } from "dayjs" import advancedFormat from "dayjs/plugin/advancedFormat" @@ -7,6 +9,9 @@ import timezone from "dayjs/plugin/timezone" import utc from "dayjs/plugin/utc" import { Template, Workspace } from "../api/typesGenerated" import { isWorkspaceOn } from "./workspace" +import { WorkspaceScheduleFormValues } from "components/WorkspaceScheduleForm/WorkspaceScheduleForm" +import { AutoStop } from "pages/WorkspaceSchedulePage/ttl" +import { AutoStart } from "pages/WorkspaceSchedulePage/schedule" // REMARK: some plugins depend on utc, so it's listed first. Otherwise they're // sorted alphabetically. @@ -179,3 +184,15 @@ export const getMaxDeadlineChange = ( deadline: dayjs.Dayjs, extremeDeadline: dayjs.Dayjs, ): number => Math.abs(deadline.diff(extremeDeadline, "hours")) + +export const scheduleChanged = ( + initialValues: AutoStart | AutoStop, + formValues: WorkspaceScheduleFormValues, +): boolean => + some( + map( + { ...initialValues }, + (v: boolean | string, k: keyof typeof initialValues) => + formValues[k] !== v, + ), + ) diff --git a/site/src/xServices/workspaceSchedule/workspaceScheduleXService.ts b/site/src/xServices/workspaceSchedule/workspaceScheduleXService.ts index 3d2e7cacfce67..33382097dd535 100644 --- a/site/src/xServices/workspaceSchedule/workspaceScheduleXService.ts +++ b/site/src/xServices/workspaceSchedule/workspaceScheduleXService.ts @@ -45,8 +45,10 @@ export type WorkspaceScheduleEvent = | { type: "GET_WORKSPACE"; username: string; workspaceName: string } | { type: "SUBMIT_SCHEDULE" - autoStart: TypesGen.UpdateWorkspaceAutostartRequest | undefined + autoStart: TypesGen.UpdateWorkspaceAutostartRequest + autoStartChanged: boolean ttl: TypesGen.UpdateWorkspaceTTLRequest + autoStopChanged: boolean } export const workspaceSchedule = createMachine( @@ -195,10 +197,12 @@ export const workspaceSchedule = createMachine( throw new Error("Failed to load workspace.") } - if (event.autoStart?.schedule !== undefined) { + if (event.autoStartChanged) { await API.putWorkspaceAutostart(context.workspace.id, event.autoStart) } - await API.putWorkspaceAutostop(context.workspace.id, event.ttl) + if (event.autoStopChanged) { + await API.putWorkspaceAutostop(context.workspace.id, event.ttl) + } }, }, },