Skip to content

Commit 250ee53

Browse files
committed
chore: update for types from typesGenerated
1 parent 24be8bf commit 250ee53

File tree

2 files changed

+178
-138
lines changed

2 files changed

+178
-138
lines changed

site/src/modules/workspaces/DynamicParameter/DynamicParameter.tsx

+160-86
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import type { WorkspaceBuildParameter } from "api/typesGenerated";
21
import type {
3-
Parameter,
4-
ParameterOption,
5-
ParameterValidation,
6-
} from "api/typesParameter";
2+
PreviewParameter,
3+
PreviewParameterOption,
4+
WorkspaceBuildParameter,
5+
} from "api/typesGenerated";
76
import { Badge } from "components/Badge/Badge";
87
import { Checkbox } from "components/Checkbox/Checkbox";
98
import { ExternalImage } from "components/ExternalImage/ExternalImage";
@@ -31,10 +30,11 @@ import {
3130
} from "components/Tooltip/Tooltip";
3231
import { Info, Settings, TriangleAlert } from "lucide-react";
3332
import { type FC, useId } from "react";
33+
import type { AutofillBuildParameter } from "utils/richParameters";
3434
import * as Yup from "yup";
3535

3636
export interface DynamicParameterProps {
37-
parameter: Parameter;
37+
parameter: PreviewParameter;
3838
onChange: (value: string) => void;
3939
disabled?: boolean;
4040
isPreset?: boolean;
@@ -68,7 +68,7 @@ export const DynamicParameter: FC<DynamicParameterProps> = ({
6868
};
6969

7070
interface ParameterLabelProps {
71-
parameter: Parameter;
71+
parameter: PreviewParameter;
7272
isPreset?: boolean;
7373
}
7474

@@ -144,7 +144,7 @@ const ParameterLabel: FC<ParameterLabelProps> = ({ parameter, isPreset }) => {
144144
};
145145

146146
interface ParameterFieldProps {
147-
parameter: Parameter;
147+
parameter: PreviewParameter;
148148
onChange: (value: string) => void;
149149
disabled?: boolean;
150150
id: string;
@@ -173,26 +173,35 @@ const ParameterField: FC<ParameterFieldProps> = ({
173173
<SelectValue placeholder="Select option" />
174174
</SelectTrigger>
175175
<SelectContent>
176-
{parameter.options.map((option) => (
177-
<SelectItem key={option.value.value} value={option.value.value}>
178-
<OptionDisplay option={option} />
179-
</SelectItem>
180-
))}
176+
{parameter.options
177+
.filter(
178+
(option): option is NonNullable<typeof option> =>
179+
option !== null,
180+
)
181+
.map((option) => (
182+
<SelectItem key={option.value.value} value={option.value.value}>
183+
<OptionDisplay option={option} />
184+
</SelectItem>
185+
))}
181186
</SelectContent>
182187
</Select>
183188
);
184189

185190
case "multi-select": {
186191
// Map parameter options to MultiSelectCombobox options format
187-
const comboboxOptions: Option[] = parameter.options.map((opt) => ({
188-
value: opt.value.value,
189-
label: opt.name,
190-
disable: false,
191-
}));
192+
const comboboxOptions: Option[] = parameter.options
193+
.filter((opt): opt is NonNullable<typeof opt> => opt !== null)
194+
.map((opt) => ({
195+
value: opt.value.value,
196+
label: opt.name,
197+
disable: false,
198+
}));
192199

193200
const defaultOptions: Option[] = JSON.parse(defaultValue).map(
194201
(val: string) => {
195-
const option = parameter.options.find((o) => o.value.value === val);
202+
const option = parameter.options
203+
.filter((o): o is NonNullable<typeof o> => o !== null)
204+
.find((o) => o.value.value === val);
196205
return {
197206
value: val,
198207
label: option?.name || val,
@@ -242,20 +251,24 @@ const ParameterField: FC<ParameterFieldProps> = ({
242251
disabled={disabled}
243252
defaultValue={defaultValue}
244253
>
245-
{parameter.options.map((option) => (
246-
<div
247-
key={option.value.value}
248-
className="flex items-center space-x-2"
249-
>
250-
<RadioGroupItem
251-
id={option.value.value}
252-
value={option.value.value}
253-
/>
254-
<Label htmlFor={option.value.value} className="cursor-pointer">
255-
<OptionDisplay option={option} />
256-
</Label>
257-
</div>
258-
))}
254+
{parameter.options
255+
.filter(
256+
(option): option is NonNullable<typeof option> => option !== null,
257+
)
258+
.map((option) => (
259+
<div
260+
key={option.value.value}
261+
className="flex items-center space-x-2"
262+
>
263+
<RadioGroupItem
264+
id={option.value.value}
265+
value={option.value.value}
266+
/>
267+
<Label htmlFor={option.value.value} className="cursor-pointer">
268+
<OptionDisplay option={option} />
269+
</Label>
270+
</div>
271+
))}
259272
</RadioGroup>
260273
);
261274

@@ -281,7 +294,10 @@ const ParameterField: FC<ParameterFieldProps> = ({
281294
const inputProps: Record<string, unknown> = {};
282295

283296
if (parameter.type === "number") {
284-
const validations = parameter.validations[0] || {};
297+
const validations =
298+
parameter.validations.filter(
299+
(v): v is NonNullable<typeof v> => v !== null,
300+
)[0] || {};
285301
const { validation_min, validation_max } = validations;
286302

287303
if (validation_min !== null) {
@@ -310,7 +326,7 @@ const ParameterField: FC<ParameterFieldProps> = ({
310326
};
311327

312328
interface OptionDisplayProps {
313-
option: ParameterOption;
329+
option: PreviewParameterOption;
314330
}
315331

316332
const OptionDisplay: FC<OptionDisplayProps> = ({ option }) => {
@@ -341,33 +357,84 @@ const OptionDisplay: FC<OptionDisplayProps> = ({ option }) => {
341357
};
342358

343359
interface ParameterDiagnosticsProps {
344-
diagnostics: Parameter["diagnostics"];
360+
diagnostics: PreviewParameter["diagnostics"];
345361
}
346362

347363
const ParameterDiagnostics: FC<ParameterDiagnosticsProps> = ({
348364
diagnostics,
349365
}) => {
350366
return (
351367
<div className="flex flex-col gap-2">
352-
{diagnostics.map((diagnostic, index) => (
353-
<div
354-
key={`diagnostic-${diagnostic.summary}-${index}`}
355-
className={`text-xs px-1 ${
356-
diagnostic.severity === "error"
357-
? "text-content-destructive"
358-
: "text-content-warning"
359-
}`}
360-
>
361-
<div className="font-medium">{diagnostic.summary}</div>
362-
{diagnostic.detail && <div>{diagnostic.detail}</div>}
363-
</div>
364-
))}
368+
{diagnostics
369+
.filter(
370+
(diagnostic): diagnostic is NonNullable<typeof diagnostic> =>
371+
diagnostic !== null,
372+
)
373+
.map((diagnostic, index) => (
374+
<div
375+
key={`diagnostic-${diagnostic.summary}-${index}`}
376+
className={`text-xs px-1 ${
377+
diagnostic.severity === "error"
378+
? "text-content-destructive"
379+
: "text-content-warning"
380+
}`}
381+
>
382+
<div className="font-medium">{diagnostic.summary}</div>
383+
{diagnostic.detail && <div>{diagnostic.detail}</div>}
384+
</div>
385+
))}
365386
</div>
366387
);
367388
};
368389

390+
export const getInitialParameterValues = (
391+
params: PreviewParameter[],
392+
autofillParams?: AutofillBuildParameter[],
393+
): WorkspaceBuildParameter[] => {
394+
return params.map((parameter) => {
395+
// Short-circuit for ephemeral parameters, which are always reset to
396+
// the template-defined default.
397+
if (parameter.ephemeral) {
398+
return {
399+
name: parameter.name,
400+
value: parameter.default_value.valid
401+
? parameter.default_value.value
402+
: "",
403+
};
404+
}
405+
406+
const autofillParam = autofillParams?.find(
407+
({ name }) => name === parameter.name,
408+
);
409+
410+
return {
411+
name: parameter.name,
412+
value:
413+
autofillParam &&
414+
isValidValue(parameter, autofillParam) &&
415+
autofillParam.value
416+
? autofillParam.value
417+
: "",
418+
};
419+
});
420+
};
421+
422+
const isValidValue = (
423+
previewParam: PreviewParameter,
424+
buildParam: WorkspaceBuildParameter,
425+
) => {
426+
if (previewParam.options.length > 0) {
427+
const validValues = previewParam.options
428+
.filter((option): option is NonNullable<typeof option> => option !== null)
429+
.map((option) => option.value.value);
430+
return validValues.includes(buildParam.value);
431+
}
432+
433+
return true;
434+
};
435+
369436
export const useValidationSchemaForDynamicParameters = (
370-
parameters?: Parameter[],
437+
parameters?: PreviewParameter[],
371438
lastBuildParameters?: WorkspaceBuildParameter[],
372439
): Yup.AnySchema => {
373440
if (!parameters) {
@@ -387,15 +454,16 @@ export const useValidationSchemaForDynamicParameters = (
387454
if (parameter) {
388455
switch (parameter.type) {
389456
case "number": {
390-
const minValidation = parameter.validations.find(
391-
(v) => v.validation_min !== null,
392-
);
393-
const maxValidation = parameter.validations.find(
394-
(v) => v.validation_max !== null,
395-
);
457+
const minValidation = parameter.validations
458+
.filter((v): v is NonNullable<typeof v> => v !== null)
459+
.find((v) => v.validation_min !== null);
460+
const maxValidation = parameter.validations
461+
.filter((v): v is NonNullable<typeof v> => v !== null)
462+
.find((v) => v.validation_max !== null);
396463

397464
if (
398-
minValidation?.validation_min &&
465+
minValidation &&
466+
minValidation.validation_min !== null &&
399467
!maxValidation &&
400468
Number(val) < minValidation.validation_min
401469
) {
@@ -409,7 +477,8 @@ export const useValidationSchemaForDynamicParameters = (
409477

410478
if (
411479
!minValidation &&
412-
maxValidation?.validation_max &&
480+
maxValidation &&
481+
maxValidation.validation_max !== null &&
413482
Number(val) > maxValidation.validation_max
414483
) {
415484
return ctx.createError({
@@ -421,8 +490,10 @@ export const useValidationSchemaForDynamicParameters = (
421490
}
422491

423492
if (
424-
minValidation?.validation_min &&
425-
maxValidation?.validation_max &&
493+
minValidation &&
494+
minValidation.validation_min !== null &&
495+
maxValidation &&
496+
maxValidation.validation_max !== null &&
426497
(Number(val) < minValidation.validation_min ||
427498
Number(val) > maxValidation.validation_max)
428499
) {
@@ -434,18 +505,20 @@ export const useValidationSchemaForDynamicParameters = (
434505
});
435506
}
436507

437-
const monotonicValidation = parameter.validations.find(
438-
(v) => v.validation_monotonic !== null,
439-
);
440-
if (
441-
monotonicValidation?.validation_monotonic &&
442-
lastBuildParameters
443-
) {
508+
const monotonic = parameter.validations
509+
.filter((v): v is NonNullable<typeof v> => v !== null)
510+
.find(
511+
(v) =>
512+
v.validation_monotonic !== null &&
513+
v.validation_monotonic !== "",
514+
);
515+
516+
if (monotonic && lastBuildParameters) {
444517
const lastBuildParameter = lastBuildParameters.find(
445518
(last: { name: string }) => last.name === name,
446519
);
447520
if (lastBuildParameter) {
448-
switch (monotonicValidation.validation_monotonic) {
521+
switch (monotonic.validation_monotonic) {
449522
case "increasing":
450523
if (Number(lastBuildParameter.value) > Number(val)) {
451524
return ctx.createError({
@@ -468,17 +541,18 @@ export const useValidationSchemaForDynamicParameters = (
468541
break;
469542
}
470543
case "string": {
471-
const regexValidation = parameter.validations.find(
472-
(v) => v.validation_regex !== null,
473-
);
474-
if (!regexValidation?.validation_regex) {
544+
const regex = parameter.validations
545+
.filter((v): v is NonNullable<typeof v> => v !== null)
546+
.find(
547+
(v) =>
548+
v.validation_regex !== null &&
549+
v.validation_regex !== "",
550+
);
551+
if (!regex || !regex.validation_regex) {
475552
return true;
476553
}
477554

478-
if (
479-
val &&
480-
!new RegExp(regexValidation.validation_regex).test(val)
481-
) {
555+
if (val && !new RegExp(regex.validation_regex).test(val)) {
482556
return ctx.createError({
483557
path: ctx.path,
484558
message: parameterError(parameter, val),
@@ -496,18 +570,18 @@ export const useValidationSchemaForDynamicParameters = (
496570
};
497571

498572
const parameterError = (
499-
parameter: Parameter,
573+
parameter: PreviewParameter,
500574
value?: string,
501575
): string | undefined => {
502-
const validation_error = parameter.validations.find(
503-
(v) => v.validation_error !== null,
504-
);
505-
const minValidation = parameter.validations.find(
506-
(v) => v.validation_min !== null,
507-
);
508-
const maxValidation = parameter.validations.find(
509-
(v) => v.validation_max !== null,
510-
);
576+
const validation_error = parameter.validations
577+
.filter((v): v is NonNullable<typeof v> => v !== null)
578+
.find((v) => v.validation_error !== null);
579+
const minValidation = parameter.validations
580+
.filter((v): v is NonNullable<typeof v> => v !== null)
581+
.find((v) => v.validation_min !== null);
582+
const maxValidation = parameter.validations
583+
.filter((v): v is NonNullable<typeof v> => v !== null)
584+
.find((v) => v.validation_max !== null);
511585

512586
if (!validation_error || !value) {
513587
return;

0 commit comments

Comments
 (0)