mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix(site): disable auto fields when they are disabled in the template settings (#10022)
- Disable form inputs - Add disable badge + tooltip with more info <img width="1679" alt="Screen Shot 2023-10-03 at 14 20 26" src="https://github.com/coder/coder/assets/3165839/7555eb77-19d9-4a13-965e-6d40c3b852dd"> Fix https://github.com/coder/coder/issues/9820
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { type FC, type ReactNode, useMemo } from "react";
|
||||
import { type FC, type ReactNode, useMemo, forwardRef } from "react";
|
||||
import { css, type Interpolation, type Theme, useTheme } from "@emotion/react";
|
||||
import { colors } from "theme/colors";
|
||||
|
||||
@@ -44,61 +44,71 @@ const themeStyles =
|
||||
};
|
||||
};
|
||||
|
||||
export const Pill: FC<PillProps> = (props) => {
|
||||
const { lightBorder, icon, text = null, type = "neutral", ...attrs } = props;
|
||||
const theme = useTheme();
|
||||
export const Pill: FC<PillProps> = forwardRef<HTMLDivElement, PillProps>(
|
||||
(props, ref) => {
|
||||
const {
|
||||
lightBorder,
|
||||
icon,
|
||||
text = null,
|
||||
type = "neutral",
|
||||
...attrs
|
||||
} = props;
|
||||
const theme = useTheme();
|
||||
|
||||
const typeStyles = useMemo(() => {
|
||||
if (type in themeOverrides) {
|
||||
return themeOverrides[type as keyof typeof themeOverrides](lightBorder);
|
||||
}
|
||||
return themeStyles(type, lightBorder);
|
||||
}, [type, lightBorder]);
|
||||
const typeStyles = useMemo(() => {
|
||||
if (type in themeOverrides) {
|
||||
return themeOverrides[type as keyof typeof themeOverrides](lightBorder);
|
||||
}
|
||||
return themeStyles(type, lightBorder);
|
||||
}, [type, lightBorder]);
|
||||
|
||||
return (
|
||||
<div
|
||||
css={[
|
||||
{
|
||||
display: "inline-flex",
|
||||
alignItems: "center",
|
||||
borderWidth: 1,
|
||||
borderStyle: "solid",
|
||||
borderRadius: 99999,
|
||||
fontSize: 12,
|
||||
color: "#FFF",
|
||||
height: theme.spacing(3),
|
||||
paddingLeft: icon ? theme.spacing(0.75) : theme.spacing(1.5),
|
||||
paddingRight: theme.spacing(1.5),
|
||||
whiteSpace: "nowrap",
|
||||
fontWeight: 400,
|
||||
},
|
||||
typeStyles,
|
||||
]}
|
||||
role="status"
|
||||
{...attrs}
|
||||
>
|
||||
{icon && (
|
||||
<div
|
||||
css={css`
|
||||
margin-right: ${theme.spacing(0.5)};
|
||||
width: ${theme.spacing(1.75)};
|
||||
height: ${theme.spacing(1.75)};
|
||||
line-height: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
& > img,
|
||||
& > svg {
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
css={[
|
||||
{
|
||||
cursor: "default",
|
||||
display: "inline-flex",
|
||||
alignItems: "center",
|
||||
borderWidth: 1,
|
||||
borderStyle: "solid",
|
||||
borderRadius: 99999,
|
||||
fontSize: 12,
|
||||
color: "#FFF",
|
||||
height: theme.spacing(3),
|
||||
paddingLeft: icon ? theme.spacing(0.75) : theme.spacing(1.5),
|
||||
paddingRight: theme.spacing(1.5),
|
||||
whiteSpace: "nowrap",
|
||||
fontWeight: 400,
|
||||
},
|
||||
typeStyles,
|
||||
]}
|
||||
role="status"
|
||||
{...attrs}
|
||||
>
|
||||
{icon && (
|
||||
<div
|
||||
css={css`
|
||||
margin-right: ${theme.spacing(0.5)};
|
||||
width: ${theme.spacing(1.75)};
|
||||
height: ${theme.spacing(1.75)};
|
||||
}
|
||||
`}
|
||||
>
|
||||
{icon}
|
||||
</div>
|
||||
)}
|
||||
{text}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
line-height: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
& > img,
|
||||
& > svg {
|
||||
width: ${theme.spacing(1.75)};
|
||||
height: ${theme.spacing(1.75)};
|
||||
}
|
||||
`}
|
||||
>
|
||||
{icon}
|
||||
</div>
|
||||
)}
|
||||
{text}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
+7
@@ -18,6 +18,10 @@ dayjs.extend(timezone);
|
||||
const meta: Meta<typeof WorkspaceScheduleForm> = {
|
||||
title: "components/WorkspaceScheduleForm",
|
||||
component: WorkspaceScheduleForm,
|
||||
args: {
|
||||
enableAutoStart: true,
|
||||
enableAutoStop: true,
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
@@ -38,6 +42,8 @@ export const AllDisabled: Story = {
|
||||
autostopEnabled: false,
|
||||
ttl: emptyTTL,
|
||||
},
|
||||
enableAutoStart: false,
|
||||
enableAutoStop: false,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -49,6 +55,7 @@ export const Autostart: Story = {
|
||||
autostopEnabled: false,
|
||||
ttl: emptyTTL,
|
||||
},
|
||||
enableAutoStop: false,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
+36
-2
@@ -30,6 +30,8 @@ import { ChangeEvent, FC } from "react";
|
||||
import * as Yup from "yup";
|
||||
import { getFormHelpers } from "utils/formUtils";
|
||||
import { timeZones } from "utils/timeZones";
|
||||
import { Pill } from "components/Pill/Pill";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
|
||||
// REMARK: some plugins depend on utc, so it's listed first. Otherwise they're
|
||||
// sorted alphabetically.
|
||||
@@ -76,6 +78,8 @@ export interface WorkspaceScheduleFormProps {
|
||||
submitScheduleError?: unknown;
|
||||
initialValues: WorkspaceScheduleFormValues;
|
||||
isLoading: boolean;
|
||||
enableAutoStop: boolean;
|
||||
enableAutoStart: boolean;
|
||||
onCancel: () => void;
|
||||
onSubmit: (values: WorkspaceScheduleFormValues) => void;
|
||||
// for storybook
|
||||
@@ -193,6 +197,8 @@ export const WorkspaceScheduleForm: FC<
|
||||
onSubmit,
|
||||
initialTouched,
|
||||
defaultTTL,
|
||||
enableAutoStop,
|
||||
enableAutoStart,
|
||||
}) => {
|
||||
const styles = useStyles();
|
||||
|
||||
@@ -284,12 +290,25 @@ export const WorkspaceScheduleForm: FC<
|
||||
<HorizontalForm onSubmit={form.handleSubmit}>
|
||||
<FormSection
|
||||
title="Autostart"
|
||||
description="Select the time and days of week on which you want the workspace starting automatically."
|
||||
description={
|
||||
<>
|
||||
<div css={{ marginBottom: 16 }}>
|
||||
Select the time and days of week on which you want the workspace
|
||||
starting automatically.
|
||||
</div>
|
||||
{!enableAutoStart && (
|
||||
<Tooltip title="This option can be enabled in the template settings">
|
||||
<Pill text="Disabled" />
|
||||
</Tooltip>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
>
|
||||
<FormFields>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
disabled={!enableAutoStart}
|
||||
name="autostartEnabled"
|
||||
checked={form.values.autostartEnabled}
|
||||
onChange={handleToggleAutostart}
|
||||
@@ -352,7 +371,21 @@ export const WorkspaceScheduleForm: FC<
|
||||
|
||||
<FormSection
|
||||
title="Autostop"
|
||||
description="Set how many hours should elapse after a workspace is started before it automatically shuts down. If workspace connection activity is detected, the autostop timer will be bumped by this value."
|
||||
description={
|
||||
<>
|
||||
<div css={{ marginBottom: 16 }}>
|
||||
Set how many hours should elapse after a workspace is started
|
||||
before it automatically shuts down. If workspace connection
|
||||
activity is detected, the autostop timer will be bumped by this
|
||||
value.
|
||||
</div>
|
||||
{!enableAutoStop && (
|
||||
<Tooltip title="This option can be enabled in the template settings">
|
||||
<Pill text="Disabled" />
|
||||
</Tooltip>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
>
|
||||
<FormFields>
|
||||
<FormControlLabel
|
||||
@@ -361,6 +394,7 @@ export const WorkspaceScheduleForm: FC<
|
||||
name="autostopEnabled"
|
||||
checked={form.values.autostopEnabled}
|
||||
onChange={handleToggleAutostop}
|
||||
disabled={!enableAutoStop}
|
||||
/>
|
||||
}
|
||||
label={Language.stopSwitch}
|
||||
|
||||
@@ -83,6 +83,8 @@ export const WorkspaceSchedulePage: FC = () => {
|
||||
(scheduleState.matches("presentForm") ||
|
||||
scheduleState.matches("submittingSchedule")) && (
|
||||
<WorkspaceScheduleForm
|
||||
enableAutoStart={template.allow_user_autostart}
|
||||
enableAutoStop={template.allow_user_autostop}
|
||||
submitScheduleError={submitScheduleError}
|
||||
initialValues={{
|
||||
...getAutostart(workspace),
|
||||
|
||||
@@ -450,8 +450,8 @@ export const MockTemplate: TypesGen.Template = {
|
||||
failure_ttl_ms: 0,
|
||||
time_til_dormant_ms: 0,
|
||||
time_til_dormant_autodelete_ms: 0,
|
||||
allow_user_autostart: false,
|
||||
allow_user_autostop: false,
|
||||
allow_user_autostart: true,
|
||||
allow_user_autostop: true,
|
||||
};
|
||||
|
||||
export const MockTemplateVersionFiles: TemplateVersionFiles = {
|
||||
|
||||
Reference in New Issue
Block a user