From 1101a0f97496dde0a75b6ca7c840bd0ddd75b6d7 Mon Sep 17 00:00:00 2001 From: Jeremy Ruppel Date: Wed, 1 Jul 2026 16:27:24 -0400 Subject: [PATCH] feat(site/src/pages/TemplateBuilder): add provisioner warning to Template Builder form (#26935) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Show a warning in the Template Builder customizations step when the selected organization has no provisioner daemons connected. This matches the existing behavior in the current `CreateTemplateForm`. ## Changes - Added a `provisionerDaemons` query in `TemplateCustomizationsStep`, gated on the selected org - Renders an `Alert` warning with a link to provisioner docs when no daemons are found - Warning is informational only and does not block form submission
Implementation plan The current `CreateTemplateForm` (used for upload/starter/duplicate flows) shows a warning when the selected organization has no provisioner daemons connected. The new Template Builder wizard (`/templates/new/builder`) had an org picker in `TemplateCustomizationsStep` but did not perform this check. ### What was done 1. Imported `provisionerDaemons` query helper, `Alert`, `Link`, and `docs` utility into `TemplateCustomizationsStep.tsx` 2. Added a `useQuery` call for provisioner daemons, enabled only when an org is selected 3. Computed `showProvisionerWarning` (true when the provisioners list is empty) 4. Added a local `ProvisionerWarning` component rendering the same warning text and docs link as `CreateTemplateForm` 5. Rendered the warning below the `OrganizationAutocomplete` picker ### Design decisions - Warning is informational only (does not block submission), matching the existing form behavior and the TODO rationale: a user may connect a provisioner without refreshing - Used the project's `Link` component (`#/components/Link/Link`) instead of MUI Link - Kept `ProvisionerWarning` as a local component rather than extracting to shared, since the component is small (~8 lines)
> 🤖 Generated by Coder Agents on behalf of @jeremyruppel Screenshot 2026-07-01 at 3 56
58 PM --- .../TemplateCustomizationsStep.tsx | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/site/src/pages/TemplateBuilder/TemplateCustomizationsStep.tsx b/site/src/pages/TemplateBuilder/TemplateCustomizationsStep.tsx index 740e9bc053..16b433cfe4 100644 --- a/site/src/pages/TemplateBuilder/TemplateCustomizationsStep.tsx +++ b/site/src/pages/TemplateBuilder/TemplateCustomizationsStep.tsx @@ -1,16 +1,22 @@ import { type FC, useEffect, useState } from "react"; import { useQuery } from "react-query"; -import { permittedOrganizations } from "#/api/queries/organizations"; +import { + permittedOrganizations, + provisionerDaemons, +} from "#/api/queries/organizations"; import type { Organization } from "#/api/typesGenerated"; +import { Alert } from "#/components/Alert/Alert"; import { IconField } from "#/components/IconField/IconField"; import { Input } from "#/components/Input/Input"; import { Label } from "#/components/Label/Label"; +import { Link } from "#/components/Link/Link"; import { OrganizationAutocomplete } from "#/components/OrganizationAutocomplete/OrganizationAutocomplete"; import { Textarea } from "#/components/Textarea/Textarea"; import { TemplateBuilderSubtitle, TemplateBuilderTitle, } from "#/pages/TemplateBuilder/TemplateBuilderHeader"; +import { docs } from "#/utils/docs"; import type { SelectedBaseMeta, TemplateBuilderWizardState, @@ -37,6 +43,12 @@ export const TemplateCustomizationsStep: FC< const [selectedOrg, setSelectedOrg] = useState(null); + const { data: provisioners } = useQuery({ + ...provisionerDaemons(selectedOrg?.id ?? ""), + enabled: Boolean(selectedOrg), + }); + const showProvisionerWarning = provisioners ? provisioners.length < 1 : false; + // Auto-select when exactly one org is available. useEffect(() => { if (orgOptions.length === 1 && !selectedOrg) { @@ -57,6 +69,8 @@ export const TemplateCustomizationsStep: FC< Add additional configurations. + {showProvisionerWarning && } +
{/* Base template card */} {state.selectedBase && } @@ -142,6 +156,18 @@ export const TemplateCustomizationsStep: FC< ); }; +const ProvisionerWarning: FC = () => { + return ( + + This organization does not have any provisioners. Before you create a + template, you'll need to configure a provisioner.{" "} + + See our documentation + + + ); +}; + const BaseTemplateCard: FC<{ base: SelectedBaseMeta }> = ({ base }) => { return (