Skip to content

feat: create dynamic parameter component #17351

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Apr 16, 2025
Prev Previous commit
Next Next commit
chore: remove unused typesParameter.ts
  • Loading branch information
jaaydenh committed Apr 11, 2025
commit 3b8d5a50d0448da7ed84985867b80b3e46b2d20c
124 changes: 0 additions & 124 deletions site/src/api/typesParameter.ts

This file was deleted.

132 changes: 65 additions & 67 deletions site/src/modules/workspaces/DynamicParameter/DynamicParameter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,29 +173,26 @@ const ParameterField: FC<ParameterFieldProps> = ({
<SelectValue placeholder="Select option" />
</SelectTrigger>
<SelectContent>
{parameter.options
.map((option) => (
<SelectItem key={option.value.value} value={option.value.value}>
<OptionDisplay option={option} />
</SelectItem>
))}
{parameter.options.map((option) => (
<SelectItem key={option.value.value} value={option.value.value}>
<OptionDisplay option={option} />
</SelectItem>
))}
</SelectContent>
</Select>
);

case "multi-select": {
// Map parameter options to MultiSelectCombobox options format
const comboboxOptions: Option[] = parameter.options
.map((opt) => ({
value: opt.value.value,
label: opt.name,
disable: false,
}));
const comboboxOptions: Option[] = parameter.options.map((opt) => ({
value: opt.value.value,
label: opt.name,
disable: false,
}));

const defaultOptions: Option[] = JSON.parse(defaultValue).map(
(val: string) => {
const option = parameter.options
.find((o) => o.value.value === val);
const option = parameter.options.find((o) => o.value.value === val);
return {
value: val,
label: option?.name || val,
Expand Down Expand Up @@ -245,21 +242,20 @@ const ParameterField: FC<ParameterFieldProps> = ({
disabled={disabled}
defaultValue={defaultValue}
>
{parameter.options
.map((option) => (
<div
key={option.value.value}
className="flex items-center space-x-2"
>
<RadioGroupItem
id={option.value.value}
value={option.value.value}
/>
<Label htmlFor={option.value.value} className="cursor-pointer">
<OptionDisplay option={option} />
</Label>
</div>
))}
{parameter.options.map((option) => (
<div
key={option.value.value}
className="flex items-center space-x-2"
>
<RadioGroupItem
id={option.value.value}
value={option.value.value}
/>
<Label htmlFor={option.value.value} className="cursor-pointer">
<OptionDisplay option={option} />
</Label>
</div>
))}
</RadioGroup>
);

Expand Down Expand Up @@ -353,20 +349,19 @@ const ParameterDiagnostics: FC<ParameterDiagnosticsProps> = ({
}) => {
return (
<div className="flex flex-col gap-2">
{diagnostics
.map((diagnostic, index) => (
<div
key={`diagnostic-${diagnostic.summary}-${index}`}
className={`text-xs px-1 ${
diagnostic.severity === "error"
? "text-content-destructive"
: "text-content-warning"
}`}
>
<div className="font-medium">{diagnostic.summary}</div>
{diagnostic.detail && <div>{diagnostic.detail}</div>}
</div>
))}
{diagnostics.map((diagnostic, index) => (
<div
key={`diagnostic-${diagnostic.summary}-${index}`}
className={`text-xs px-1 ${
diagnostic.severity === "error"
? "text-content-destructive"
: "text-content-warning"
}`}
>
<div className="font-medium">{diagnostic.summary}</div>
{diagnostic.detail && <div>{diagnostic.detail}</div>}
</div>
))}
</div>
);
};
Expand Down Expand Up @@ -408,8 +403,9 @@ const isValidValue = (
buildParam: WorkspaceBuildParameter,
) => {
if (previewParam.options.length > 0) {
const validValues = previewParam.options
.map((option) => option.value.value);
const validValues = previewParam.options.map(
(option) => option.value.value,
);
return validValues.includes(buildParam.value);
}

Expand Down Expand Up @@ -437,10 +433,12 @@ export const useValidationSchemaForDynamicParameters = (
if (parameter) {
switch (parameter.type) {
case "number": {
const minValidation = parameter.validations
.find((v) => v.validation_min !== null);
const maxValidation = parameter.validations
.find((v) => v.validation_max !== null);
const minValidation = parameter.validations.find(
(v) => v.validation_min !== null,
);
const maxValidation = parameter.validations.find(
(v) => v.validation_max !== null,
);

if (
minValidation &&
Expand Down Expand Up @@ -486,12 +484,11 @@ export const useValidationSchemaForDynamicParameters = (
});
}

const monotonic = parameter.validations
.find(
(v) =>
v.validation_monotonic !== null &&
v.validation_monotonic !== "",
);
const monotonic = parameter.validations.find(
(v) =>
v.validation_monotonic !== null &&
v.validation_monotonic !== "",
);

if (monotonic && lastBuildParameters) {
const lastBuildParameter = lastBuildParameters.find(
Expand Down Expand Up @@ -521,12 +518,10 @@ export const useValidationSchemaForDynamicParameters = (
break;
}
case "string": {
const regex = parameter.validations
.find(
(v) =>
v.validation_regex !== null &&
v.validation_regex !== "",
);
const regex = parameter.validations.find(
(v) =>
v.validation_regex !== null && v.validation_regex !== "",
);
if (!regex || !regex.validation_regex) {
return true;
}
Expand All @@ -552,12 +547,15 @@ const parameterError = (
parameter: PreviewParameter,
value?: string,
): string | undefined => {
const validation_error = parameter.validations
.find((v) => v.validation_error !== null);
const minValidation = parameter.validations
.find((v) => v.validation_min !== null);
const maxValidation = parameter.validations
.find((v) => v.validation_max !== null);
const validation_error = parameter.validations.find(
(v) => v.validation_error !== null,
);
const minValidation = parameter.validations.find(
(v) => v.validation_min !== null,
);
const maxValidation = parameter.validations.find(
(v) => v.validation_max !== null,
);

if (!validation_error || !value) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import {
templateVersionPresets,
} from "api/queries/templates";
import { autoCreateWorkspace, createWorkspace } from "api/queries/workspaces";
import type { Template, Workspace } from "api/typesGenerated";
import type {
DynamicParametersResponse,
Template,
Workspace,
} from "api/typesGenerated";
import { Loader } from "components/Loader/Loader";
import { useAuthenticated } from "contexts/auth/RequireAuth";
import { useEffectEvent } from "hooks/hookPolyfills";
Expand All @@ -27,7 +31,6 @@ import type { AutofillBuildParameter } from "utils/richParameters";
import { CreateWorkspacePageViewExperimental } from "./CreateWorkspacePageViewExperimental";
export const createWorkspaceModes = ["form", "auto", "duplicate"] as const;
export type CreateWorkspaceMode = (typeof createWorkspaceModes)[number];
import type { Response } from "api/typesParameter";
import { useWebSocket } from "hooks/useWebsocket";
import {
type CreateWorkspacePermissions,
Expand All @@ -46,14 +49,11 @@ const CreateWorkspacePageExperimental: FC = () => {
const navigate = useNavigate();
const [searchParams] = useSearchParams();

const [currentResponse, setCurrentResponse] = useState<Response | null>(null);
const [currentResponse, setCurrentResponse] =
useState<DynamicParametersResponse | null>(null);
const [wsResponseId, setWSResponseId] = useState<number>(0);
const { message: webSocketResponse, sendMessage } = useWebSocket<Response>(
wsUrl,
urlTestdata,
"",
"",
);
const { message: webSocketResponse, sendMessage } =
useWebSocket<DynamicParametersResponse>(wsUrl, urlTestdata, "", "");

useEffect(() => {
if (webSocketResponse && webSocketResponse.id >= wsResponseId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,8 @@ export const CreateWorkspacePageViewExperimental: FC<
dismissible
data-testid="duplication-warning"
>
Duplicating a workspace only copies its parameters. No state from the old workspace is copied over.
Duplicating a workspace only copies its parameters. No state from
the old workspace is copied over.
</Alert>
)}

Expand Down
Loading