fix(site): match activity bump text with template settings (#12170)

Close https://github.com/coder/coder/issues/12130
This commit is contained in:
Bruno Quaresma
2024-02-16 09:33:15 -03:00
committed by GitHub
parent 99dbeb4a85
commit df297627c2
4 changed files with 102 additions and 78 deletions
@@ -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<typeof WorkspaceScheduleForm> = {
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<typeof WorkspaceScheduleForm> = {
},
};
const meta: Meta<typeof WorkspaceScheduleForm> = {
title: "pages/WorkspaceSettingsPage/WorkspaceScheduleForm",
component: WorkspaceScheduleForm,
args: {
template: mockTemplate,
},
};
export default meta;
type Story = StoryObj<typeof WorkspaceScheduleForm>;
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." },
@@ -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(
<WorkspaceScheduleForm
{...defaultFormProps}
allowTemplateAutoStart={false}
/>,
);
const props = {
...defaultFormProps,
template: {
...defaultFormProps.template,
allow_user_autostart: false,
},
};
render(<WorkspaceScheduleForm {...props} />);
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(
<WorkspaceScheduleForm
{...defaultFormProps}
allowedTemplateAutoStartDays={["saturday", "sunday"]}
/>,
);
const props = {
...defaultFormProps,
template: {
...defaultFormProps.template,
autostart_requirement: {
...MockTemplate.autostart_requirement,
days_of_week: ["saturday", "sunday"],
},
},
};
render(<WorkspaceScheduleForm {...props} />);
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(
<WorkspaceScheduleForm
{...defaultFormProps}
allowTemplateAutoStop={false}
/>,
);
render(<WorkspaceScheduleForm {...props} />);
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(
<WorkspaceScheduleForm
{...defaultFormProps}
allowTemplateAutoStart={false}
allowTemplateAutoStop={false}
initialValues={{
...defaultFormProps.initialValues,
}}
/>,
);
render(<WorkspaceScheduleForm {...props} />);
const submitButton = await screen.findByRole("button", { name: "Submit" });
expect(submitButton).toBeDisabled();
@@ -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<WorkspaceScheduleFormProps> = ({
submitScheduleError,
error,
initialValues,
isLoading,
onCancel,
onSubmit,
initialTouched,
defaultTTL,
allowedTemplateAutoStartDays,
allowTemplateAutoStop,
allowTemplateAutoStart,
template,
}) => {
const form = useFormik<WorkspaceScheduleFormValues>({
initialValues,
@@ -202,10 +197,7 @@ export const WorkspaceScheduleForm: FC<WorkspaceScheduleFormProps> = ({
initialTouched,
enableReinitialize: true,
});
const formHelpers = getFormHelpers<WorkspaceScheduleFormValues>(
form,
submitScheduleError,
);
const formHelpers = getFormHelpers<WorkspaceScheduleFormValues>(form, error);
const checkboxes: Array<{ value: boolean; name: string; label: string }> = [
{
@@ -289,7 +281,7 @@ export const WorkspaceScheduleForm: FC<WorkspaceScheduleFormProps> = ({
Select the time and days of week on which you want the workspace
starting automatically.
</div>
{!allowTemplateAutoStart && (
{!template.allow_user_autostart && (
<Tooltip title="This option can be enabled in the template settings">
<DisabledBadge />
</Tooltip>
@@ -301,7 +293,7 @@ export const WorkspaceScheduleForm: FC<WorkspaceScheduleFormProps> = ({
<FormControlLabel
control={
<Switch
disabled={!allowTemplateAutoStart}
disabled={!template.allow_user_autostart}
name="autostartEnabled"
checked={form.values.autostartEnabled}
onChange={handleToggleAutostart}
@@ -316,7 +308,7 @@ export const WorkspaceScheduleForm: FC<WorkspaceScheduleFormProps> = ({
// 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<WorkspaceScheduleFormProps> = ({
// 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<WorkspaceScheduleFormProps> = ({
// 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<WorkspaceScheduleFormProps> = ({
<div css={{ marginBottom: 16 }}>
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.
</div>
{!allowTemplateAutoStop && (
{!template.allow_user_autostop && (
<Tooltip title="This option can be enabled in the template settings">
<DisabledBadge />
</Tooltip>
@@ -414,7 +411,7 @@ export const WorkspaceScheduleForm: FC<WorkspaceScheduleFormProps> = ({
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<WorkspaceScheduleFormProps> = ({
// 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<WorkspaceScheduleFormProps> = ({
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
}
/>
</HorizontalForm>
);
@@ -101,12 +101,8 @@ export const WorkspaceSchedulePage: FC = () => {
{template && (
<WorkspaceScheduleForm
allowedTemplateAutoStartDays={
template.autostart_requirement.days_of_week
}
allowTemplateAutoStart={template.allow_user_autostart}
allowTemplateAutoStop={template.allow_user_autostop}
submitScheduleError={submitScheduleMutation.error}
template={template}
error={submitScheduleMutation.error}
initialValues={{
...getAutostart(workspace),
...getAutostop(workspace),