Skip to content

Commit 17d0dc2

Browse files
committed
feat: add a character counter for fields with length limits
- refactors`getFormHelpers` to accept an options object - adds a `maxLength` option which will display a message and character counter for fields with length limits - set `maxLength` option for template description fields
1 parent 04afb88 commit 17d0dc2

File tree

13 files changed

+205
-127
lines changed

13 files changed

+205
-127
lines changed

site/src/pages/CreateTemplatePage/CreateTemplateForm.tsx

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,9 @@ export const CreateTemplateForm: FC<CreateTemplateFormProps> = (props) => {
337337
/>
338338

339339
<TextField
340-
{...getFieldHelpers("description")}
340+
{...getFieldHelpers("description", {
341+
maxLength: MAX_DESCRIPTION_CHAR_LIMIT,
342+
})}
341343
disabled={isSubmitting}
342344
rows={5}
343345
multiline
@@ -363,10 +365,11 @@ export const CreateTemplateForm: FC<CreateTemplateFormProps> = (props) => {
363365
<FormFields>
364366
<Stack direction="row" css={styles.ttlFields}>
365367
<TextField
366-
{...getFieldHelpers(
367-
"default_ttl_hours",
368-
<DefaultTTLHelperText ttl={form.values.default_ttl_hours} />,
369-
)}
368+
{...getFieldHelpers("default_ttl_hours", {
369+
helperText: (
370+
<DefaultTTLHelperText ttl={form.values.default_ttl_hours} />
371+
),
372+
})}
370373
disabled={isSubmitting}
371374
onChange={onChangeTrimmed(form)}
372375
fullWidth
@@ -377,12 +380,13 @@ export const CreateTemplateForm: FC<CreateTemplateFormProps> = (props) => {
377380

378381
<Stack direction="row" css={styles.ttlFields}>
379382
<TextField
380-
{...getFieldHelpers(
381-
"autostop_requirement_days_of_week",
382-
<AutostopRequirementDaysHelperText
383-
days={form.values.autostop_requirement_days_of_week}
384-
/>,
385-
)}
383+
{...getFieldHelpers("autostop_requirement_days_of_week", {
384+
helperText: (
385+
<AutostopRequirementDaysHelperText
386+
days={form.values.autostop_requirement_days_of_week}
387+
/>
388+
),
389+
})}
386390
disabled={
387391
isSubmitting ||
388392
form.values.use_max_ttl ||
@@ -408,13 +412,14 @@ export const CreateTemplateForm: FC<CreateTemplateFormProps> = (props) => {
408412
</TextField>
409413

410414
<TextField
411-
{...getFieldHelpers(
412-
"autostop_requirement_weeks",
413-
<AutostopRequirementWeeksHelperText
414-
days={form.values.autostop_requirement_days_of_week}
415-
weeks={form.values.autostop_requirement_weeks}
416-
/>,
417-
)}
415+
{...getFieldHelpers("autostop_requirement_weeks", {
416+
helperText: (
417+
<AutostopRequirementWeeksHelperText
418+
days={form.values.autostop_requirement_days_of_week}
419+
weeks={form.values.autostop_requirement_weeks}
420+
/>
421+
),
422+
})}
418423
disabled={
419424
isSubmitting ||
420425
form.values.use_max_ttl ||
@@ -453,17 +458,16 @@ export const CreateTemplateForm: FC<CreateTemplateFormProps> = (props) => {
453458
</Stack>
454459

455460
<TextField
456-
{...getFieldHelpers(
457-
"max_ttl_hours",
458-
allowAdvancedScheduling ? (
461+
{...getFieldHelpers("max_ttl_hours", {
462+
helperText: allowAdvancedScheduling ? (
459463
<MaxTTLHelperText ttl={form.values.max_ttl_hours} />
460464
) : (
461465
<>
462466
You need an enterprise license to use it.{" "}
463467
<Link href={docs("/enterprise")}>Learn more</Link>.
464468
</>
465469
),
466-
)}
470+
})}
467471
disabled={
468472
isSubmitting ||
469473
!form.values.use_max_ttl ||

site/src/pages/CreateUserPage/CreateUserForm.tsx

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,9 @@ export const CreateUserForm: FC<
132132
label={Language.emailLabel}
133133
/>
134134
<TextField
135-
{...getFieldHelpers(
136-
"login_type",
137-
"Authentication method for this user",
138-
)}
135+
{...getFieldHelpers("login_type", {
136+
helperText: "Authentication method for this user",
137+
})}
139138
select
140139
id="login_type"
141140
data-testid="login-type-input"
@@ -180,12 +179,11 @@ export const CreateUserForm: FC<
180179
})}
181180
</TextField>
182181
<TextField
183-
{...getFieldHelpers(
184-
"password",
185-
form.values.login_type === "password"
186-
? ""
187-
: "No password required for this login type",
188-
)}
182+
{...getFieldHelpers("password", {
183+
helperText:
184+
form.values.login_type !== "password" &&
185+
"No password required for this login type",
186+
})}
189187
autoComplete="current-password"
190188
fullWidth
191189
id="password"

site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,10 @@ export const AppearanceSettingsPageView: FC<
214214
/>
215215
<Stack spacing={0}>
216216
<TextField
217-
{...serviceBannerFieldHelpers(
218-
"message",
219-
"Markdown bold, italics, and links are supported.",
220-
)}
217+
{...serviceBannerFieldHelpers("message", {
218+
helperText:
219+
"Markdown bold, italics, and links are supported.",
220+
})}
221221
fullWidth
222222
label="Message"
223223
multiline

site/src/pages/GroupsPage/CreateGroupPageView.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,9 @@ export const CreateGroupPageView: FC<CreateGroupPageViewProps> = ({
5252
label="Name"
5353
/>
5454
<TextField
55-
{...getFieldHelpers(
56-
"display_name",
57-
"Optional: keep empty to default to the name.",
58-
)}
55+
{...getFieldHelpers("display_name", {
56+
helperText: "Optional: keep empty to default to the name.",
57+
})}
5958
fullWidth
6059
label="Display Name"
6160
/>

site/src/pages/GroupsPage/SettingsGroupPageView.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,9 @@ const UpdateGroupForm: FC<UpdateGroupFormProps> = ({
7373
) : (
7474
<>
7575
<TextField
76-
{...getFieldHelpers(
77-
"display_name",
78-
"Optional: keep empty to default to the name.",
79-
)}
76+
{...getFieldHelpers("display_name", {
77+
helperText: "Optional: keep empty to default to the name.",
78+
})}
8079
onChange={onChangeTrimmed(form)}
8180
autoComplete="display_name"
8281
autoFocus
@@ -94,11 +93,10 @@ const UpdateGroupForm: FC<UpdateGroupFormProps> = ({
9493
</>
9594
)}
9695
<TextField
97-
{...getFieldHelpers(
98-
"quota_allowance",
99-
`This group gives ${form.values.quota_allowance} quota credits to each
96+
{...getFieldHelpers("quota_allowance", {
97+
helperText: `This group gives ${form.values.quota_allowance} quota credits to each
10098
of its members.`,
101-
)}
99+
})}
102100
onChange={onChangeTrimmed(form)}
103101
autoFocus
104102
fullWidth

site/src/pages/TemplateSettingsPage/Sidebar.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@ import GeneralIcon from "@mui/icons-material/SettingsOutlined";
44
import SecurityIcon from "@mui/icons-material/LockOutlined";
55
import { type FC } from "react";
66
import type { Template } from "api/typesGenerated";
7-
import { Avatar } from "components/Avatar/Avatar";
7+
import { ExternalAvatar } from "components/Avatar/Avatar";
88
import {
99
Sidebar as BaseSidebar,
1010
SidebarHeader,
1111
SidebarNavItem,
1212
} from "components/Sidebar/Sidebar";
13-
import { ExternalImage } from "components/ExternalImage/ExternalImage";
1413

1514
interface SidebarProps {
1615
template: Template;
@@ -21,9 +20,7 @@ export const Sidebar: FC<SidebarProps> = ({ template }) => {
2120
<BaseSidebar>
2221
<SidebarHeader
2322
avatar={
24-
<Avatar variant="square" fitImage>
25-
<ExternalImage src={template.icon} css={{ width: "100%" }} />
26-
</Avatar>
23+
<ExternalAvatar src={template.icon} variant="square" fitImage />
2724
}
2825
title={template.display_name || template.name}
2926
linkTo={`/templates/${template.name}`}

site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsForm.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,16 @@ import {
2929
import { EnterpriseBadge } from "components/Badges/Badges";
3030

3131
const MAX_DESCRIPTION_CHAR_LIMIT = 128;
32+
const MAX_DESCRIPTION_MESSAGE =
33+
"Please enter a description that is no longer than 128 characters.";
3234

3335
export const getValidationSchema = (): Yup.AnyObjectSchema =>
3436
Yup.object({
3537
name: nameValidator("Name"),
3638
display_name: templateDisplayNameValidator("Display name"),
3739
description: Yup.string().max(
3840
MAX_DESCRIPTION_CHAR_LIMIT,
39-
"Please enter a description that is less than or equal to 128 characters.",
41+
MAX_DESCRIPTION_MESSAGE,
4042
),
4143
allow_user_cancel_workspace_jobs: Yup.boolean(),
4244
icon: iconValidator,
@@ -119,7 +121,9 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
119121
/>
120122

121123
<TextField
122-
{...getFieldHelpers("description")}
124+
{...getFieldHelpers("description", {
125+
maxLength: MAX_DESCRIPTION_CHAR_LIMIT,
126+
})}
123127
multiline
124128
disabled={isSubmitting}
125129
fullWidth

site/src/pages/TemplateSettingsPage/TemplateSchedulePage/TemplateScheduleForm.tsx

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -356,10 +356,11 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
356356
>
357357
<Stack direction="row" css={styles.ttlFields}>
358358
<TextField
359-
{...getFieldHelpers(
360-
"default_ttl_ms",
361-
<DefaultTTLHelperText ttl={form.values.default_ttl_ms} />,
362-
)}
359+
{...getFieldHelpers("default_ttl_ms", {
360+
helperText: (
361+
<DefaultTTLHelperText ttl={form.values.default_ttl_ms} />
362+
),
363+
})}
363364
disabled={isSubmitting}
364365
fullWidth
365366
inputProps={{ min: 0, step: 1 }}
@@ -375,12 +376,13 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
375376
>
376377
<Stack direction="row" css={styles.ttlFields}>
377378
<TextField
378-
{...getFieldHelpers(
379-
"autostop_requirement_days_of_week",
380-
<AutostopRequirementDaysHelperText
381-
days={form.values.autostop_requirement_days_of_week}
382-
/>,
383-
)}
379+
{...getFieldHelpers("autostop_requirement_days_of_week", {
380+
helperText: (
381+
<AutostopRequirementDaysHelperText
382+
days={form.values.autostop_requirement_days_of_week}
383+
/>
384+
),
385+
})}
384386
disabled={isSubmitting || form.values.use_max_ttl}
385387
fullWidth
386388
select
@@ -402,13 +404,14 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
402404
</TextField>
403405

404406
<TextField
405-
{...getFieldHelpers(
406-
"autostop_requirement_weeks",
407-
<AutostopRequirementWeeksHelperText
408-
days={form.values.autostop_requirement_days_of_week}
409-
weeks={form.values.autostop_requirement_weeks}
410-
/>,
411-
)}
407+
{...getFieldHelpers("autostop_requirement_weeks", {
408+
helperText: (
409+
<AutostopRequirementWeeksHelperText
410+
days={form.values.autostop_requirement_days_of_week}
411+
weeks={form.values.autostop_requirement_weeks}
412+
/>
413+
),
414+
})}
412415
disabled={
413416
isSubmitting ||
414417
form.values.use_max_ttl ||
@@ -463,17 +466,16 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
463466
</Stack>
464467

465468
<TextField
466-
{...getFieldHelpers(
467-
"max_ttl_ms",
468-
allowAdvancedScheduling ? (
469+
{...getFieldHelpers("max_ttl_ms", {
470+
helperText: allowAdvancedScheduling ? (
469471
<MaxTTLHelperText ttl={form.values.max_ttl_ms} />
470472
) : (
471473
<>
472474
You need an enterprise license to use it{" "}
473475
<Link href={docs("/enterprise")}>Learn more</Link>.
474476
</>
475477
),
476-
)}
478+
})}
477479
disabled={
478480
isSubmitting ||
479481
!form.values.use_max_ttl ||
@@ -581,10 +583,11 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
581583
label="Enable Failure Cleanup"
582584
/>
583585
<TextField
584-
{...getFieldHelpers(
585-
"failure_ttl_ms",
586-
<FailureTTLHelperText ttl={form.values.failure_ttl_ms} />,
587-
)}
586+
{...getFieldHelpers("failure_ttl_ms", {
587+
helperText: (
588+
<FailureTTLHelperText ttl={form.values.failure_ttl_ms} />
589+
),
590+
})}
588591
disabled={isSubmitting || !form.values.failure_cleanup_enabled}
589592
fullWidth
590593
inputProps={{ min: 0, step: "any" }}
@@ -610,12 +613,13 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
610613
label="Enable Dormancy Threshold"
611614
/>
612615
<TextField
613-
{...getFieldHelpers(
614-
"time_til_dormant_ms",
615-
<DormancyTTLHelperText
616-
ttl={form.values.time_til_dormant_ms}
617-
/>,
618-
)}
616+
{...getFieldHelpers("time_til_dormant_ms", {
617+
helperText: (
618+
<DormancyTTLHelperText
619+
ttl={form.values.time_til_dormant_ms}
620+
/>
621+
),
622+
})}
619623
disabled={
620624
isSubmitting || !form.values.inactivity_cleanup_enabled
621625
}
@@ -643,12 +647,13 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
643647
label="Enable Dormancy Auto-Deletion"
644648
/>
645649
<TextField
646-
{...getFieldHelpers(
647-
"time_til_dormant_autodelete_ms",
648-
<DormancyAutoDeletionTTLHelperText
649-
ttl={form.values.time_til_dormant_autodelete_ms}
650-
/>,
651-
)}
650+
{...getFieldHelpers("time_til_dormant_autodelete_ms", {
651+
helperText: (
652+
<DormancyAutoDeletionTTLHelperText
653+
ttl={form.values.time_til_dormant_autodelete_ms}
654+
/>
655+
),
656+
})}
652657
disabled={
653658
isSubmitting ||
654659
!form.values.dormant_autodeletion_cleanup_enabled

site/src/pages/TemplateSettingsPage/TemplateSettingsLayout.tsx

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,7 @@ export const TemplateSettingsLayout: FC = () => {
5656
</Helmet>
5757

5858
<Margins>
59-
<Stack
60-
css={{
61-
padding: "48px 0",
62-
}}
63-
direction="row"
64-
spacing={10}
65-
>
59+
<Stack css={{ padding: "48px 0" }} direction="row" spacing={10}>
6660
{templateQuery.isError || permissionsQuery.isError ? (
6761
<ErrorAlert error={templateQuery.error} />
6862
) : (
@@ -74,11 +68,7 @@ export const TemplateSettingsLayout: FC = () => {
7468
>
7569
<Sidebar template={templateQuery.data} />
7670
<Suspense fallback={<Loader />}>
77-
<main
78-
css={{
79-
width: "100%",
80-
}}
81-
>
71+
<main css={{ width: "100%" }}>
8272
<Outlet />
8373
</main>
8474
</Suspense>

0 commit comments

Comments
 (0)