diff --git a/site/src/pages/TemplateBuilder/BaseInfraSelectStep.tsx b/site/src/pages/TemplateBuilder/BaseInfraSelectStep.tsx index 9b4b0ee077..f52e856e08 100644 --- a/site/src/pages/TemplateBuilder/BaseInfraSelectStep.tsx +++ b/site/src/pages/TemplateBuilder/BaseInfraSelectStep.tsx @@ -20,6 +20,7 @@ function toSelectedBaseMeta(base: TemplateBuilderBase): SelectedBaseMeta { os: base.os, hasParameters: base.variables.length > 0 && base.variables.some((v) => !v.sensitive), + hasPrerequisites: Boolean(base.prerequisites?.length), }; } diff --git a/site/src/pages/TemplateBuilder/BaseTemplateParametersStep.tsx b/site/src/pages/TemplateBuilder/BaseTemplateParametersStep.tsx index e3d6f509b5..c3d128b467 100644 --- a/site/src/pages/TemplateBuilder/BaseTemplateParametersStep.tsx +++ b/site/src/pages/TemplateBuilder/BaseTemplateParametersStep.tsx @@ -5,6 +5,7 @@ import type { TemplateBuilderBasesResponse, TemplateBuilderModuleVariable, } from "#/api/typesGenerated"; +import { MemoizedMarkdown } from "#/components/Markdown/Markdown"; import type { ConfigurationFieldDefinition } from "./ConfigurationField"; import { TemplateConfiguration } from "./TemplateConfiguration"; @@ -89,6 +90,7 @@ export const BaseTemplateParametersStep: FC< const { data } = useQuery(templateBuilderBases()); const base = data?.bases.find((b) => b.id === baseId); const variables = base?.variables.filter((v) => !v.sensitive) ?? []; + const prerequisites = base?.prerequisites ?? ""; const handleChange = (name: string, value: string) => { onChangeValues({ ...values, [name]: value }); @@ -105,6 +107,12 @@ export const BaseTemplateParametersStep: FC< iconUrl={base?.icon} detailsUrl={detailsUrl(baseId)} fields={fields} - /> + > + {prerequisites && ( +
+ {prerequisites} +
+ )} + ); }; diff --git a/site/src/pages/TemplateBuilder/TemplateConfiguration.tsx b/site/src/pages/TemplateBuilder/TemplateConfiguration.tsx index 33bcab4387..4438230f2d 100644 --- a/site/src/pages/TemplateBuilder/TemplateConfiguration.tsx +++ b/site/src/pages/TemplateBuilder/TemplateConfiguration.tsx @@ -1,16 +1,17 @@ +import type { PropsWithChildren } from "react"; import { Link } from "#/components/Link/Link"; import { ConfigurationField, type ConfigurationFieldDefinition, } from "./ConfigurationField"; -type TemplateConfigurationProps = { +type TemplateConfigurationProps = PropsWithChildren<{ name: string; description: string; iconUrl?: string; detailsUrl?: string; fields?: ConfigurationFieldDefinition[]; -}; +}>; export const TemplateConfiguration: React.FC = ({ name, @@ -18,6 +19,7 @@ export const TemplateConfiguration: React.FC = ({ iconUrl, detailsUrl, fields, + children, }) => { return (
@@ -59,6 +61,7 @@ export const TemplateConfiguration: React.FC = ({ ))} )} + {children}
); }; diff --git a/site/src/pages/TemplateBuilder/steps.test.ts b/site/src/pages/TemplateBuilder/steps.test.ts index b77c09506a..f17645c1e2 100644 --- a/site/src/pages/TemplateBuilder/steps.test.ts +++ b/site/src/pages/TemplateBuilder/steps.test.ts @@ -35,6 +35,7 @@ describe("shouldSkip", () => { id: "docker", name: "Docker", hasParameters: false, + hasPrerequisites: false, }, }); expect(stepById("base-parameters").shouldSkip(noParams)).toBe(true); @@ -46,6 +47,7 @@ describe("shouldSkip", () => { id: "aws-linux", name: "AWS Linux", hasParameters: true, + hasPrerequisites: false, }, }); expect(stepById("base-parameters").shouldSkip(withParams)).toBe(false); @@ -137,6 +139,7 @@ describe("findNextVisibleIndex", () => { id: "docker", name: "Docker", hasParameters: false, + hasPrerequisites: false, }, }); // From base-infra (index 0), next visible should be module-select (index 2). @@ -160,6 +163,7 @@ describe("findNextVisibleIndex", () => { id: "aws-linux", name: "AWS Linux", hasParameters: true, + hasPrerequisites: false, }, selectedModules: [ { @@ -186,6 +190,7 @@ describe("findPrevVisibleIndex", () => { id: "docker", name: "Docker", hasParameters: false, + hasPrerequisites: false, }, }); // From module-select (index 2), prev visible should be base-infra (index 0). @@ -220,6 +225,7 @@ describe("nearestVisible", () => { id: "docker", name: "Docker", hasParameters: false, + hasPrerequisites: false, }, }; // Index 1 (base-parameters) is skipped, nearest backward is 0 (base-infra). diff --git a/site/src/pages/TemplateBuilder/steps.ts b/site/src/pages/TemplateBuilder/steps.ts index bed062caf5..85d26a211d 100644 --- a/site/src/pages/TemplateBuilder/steps.ts +++ b/site/src/pages/TemplateBuilder/steps.ts @@ -40,7 +40,9 @@ export const WIZARD_STEPS: readonly WizardStep[] = [ { id: "base-parameters", group: 1, - shouldSkip: (state) => !state.selectedBase?.hasParameters, + shouldSkip: (state) => + !state.selectedBase?.hasParameters && + !state.selectedBase?.hasPrerequisites, }, { id: "module-select", diff --git a/site/src/pages/TemplateBuilder/wizardState.test.ts b/site/src/pages/TemplateBuilder/wizardState.test.ts index 5d4b7edb1c..dbcfcabaff 100644 --- a/site/src/pages/TemplateBuilder/wizardState.test.ts +++ b/site/src/pages/TemplateBuilder/wizardState.test.ts @@ -26,6 +26,7 @@ describe("wizardReducer", () => { id: "docker", name: "Docker", hasParameters: false, + hasPrerequisites: false, }, }, ]); @@ -37,7 +38,12 @@ describe("wizardReducer", () => { const state = reduce([ { type: "SET_BASE", - base: { id: "docker", name: "Docker", hasParameters: true }, + base: { + id: "docker", + name: "Docker", + hasParameters: true, + hasPrerequisites: false, + }, }, { type: "SET_BASE_VARIABLES", @@ -45,7 +51,12 @@ describe("wizardReducer", () => { }, { type: "SET_BASE", - base: { id: "aws-linux", name: "AWS Linux", hasParameters: true }, + base: { + id: "aws-linux", + name: "AWS Linux", + hasParameters: true, + hasPrerequisites: false, + }, }, ]); expect(state.baseTemplateId).toBe("aws-linux"); @@ -56,7 +67,12 @@ describe("wizardReducer", () => { const state = reduce([ { type: "SET_BASE", - base: { id: "docker", name: "Docker", hasParameters: true }, + base: { + id: "docker", + name: "Docker", + hasParameters: true, + hasPrerequisites: false, + }, }, { type: "SET_BASE_VARIABLES", @@ -64,7 +80,12 @@ describe("wizardReducer", () => { }, { type: "SET_BASE", - base: { id: "docker", name: "Docker", hasParameters: true }, + base: { + id: "docker", + name: "Docker", + hasParameters: true, + hasPrerequisites: false, + }, }, ]); expect(state.baseVariableValues).toEqual({ image: "ubuntu" }); @@ -254,7 +275,12 @@ describe("wizardReducer", () => { const state = reduce([ { type: "SET_BASE", - base: { id: "docker", name: "Docker", hasParameters: true }, + base: { + id: "docker", + name: "Docker", + hasParameters: true, + hasPrerequisites: false, + }, }, { type: "SET_CUSTOMIZATION", diff --git a/site/src/pages/TemplateBuilder/wizardState.ts b/site/src/pages/TemplateBuilder/wizardState.ts index 53ee055091..a2bf362b31 100644 --- a/site/src/pages/TemplateBuilder/wizardState.ts +++ b/site/src/pages/TemplateBuilder/wizardState.ts @@ -15,6 +15,7 @@ export type SelectedBaseMeta = { iconUrl?: string; os?: string; hasParameters: boolean; + hasPrerequisites: boolean; }; /**