diff --git a/site/src/api/api.ts b/site/src/api/api.ts index 70d54e5ea0fee..f7e0cd0889f70 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -1009,6 +1009,32 @@ class ApiMethods { return response.data; }; + templateVersionDynamicParameters = ( + versionId: string, + { + onMessage, + onError, + }: { + onMessage: (response: TypesGen.DynamicParametersResponse) => void; + onError: (error: Error) => void; + }, + ): WebSocket => { + const socket = createWebSocket( + `/api/v2/templateversions/${versionId}/dynamic-parameters`, + ); + + socket.addEventListener("message", (event) => + onMessage(JSON.parse(event.data) as TypesGen.DynamicParametersResponse), + ); + + socket.addEventListener("error", () => { + onError(new Error("Connection for dynamic parameters failed.")); + socket.close(); + }); + + return socket; + }; + /** * @param organization Can be the organization's ID or name */ diff --git a/site/src/modules/workspaces/DynamicParameter/DynamicParameter.tsx b/site/src/modules/workspaces/DynamicParameter/DynamicParameter.tsx index d3f2cbbd69fa6..939316625f3db 100644 --- a/site/src/modules/workspaces/DynamicParameter/DynamicParameter.tsx +++ b/site/src/modules/workspaces/DynamicParameter/DynamicParameter.tsx @@ -1,4 +1,5 @@ import type { + NullHCLString, PreviewParameter, PreviewParameterOption, WorkspaceBuildParameter, @@ -156,10 +157,8 @@ const ParameterField: FC = ({ disabled, id, }) => { - const value = parameter.value.valid ? parameter.value.value : ""; - const defaultValue = parameter.default_value.valid - ? parameter.default_value.value - : ""; + const value = validValue(parameter.value); + const defaultValue = validValue(parameter.default_value); switch (parameter.form_type) { case "dropdown": @@ -376,9 +375,7 @@ export const getInitialParameterValues = ( if (parameter.ephemeral) { return { name: parameter.name, - value: parameter.default_value.valid - ? parameter.default_value.value - : "", + value: validValue(parameter.default_value), }; } @@ -390,15 +387,19 @@ export const getInitialParameterValues = ( name: parameter.name, value: autofillParam && - isValidValue(parameter, autofillParam) && + isValidParameterOption(parameter, autofillParam) && autofillParam.value ? autofillParam.value - : "", + : validValue(parameter.default_value), }; }); }; -const isValidValue = ( +const validValue = (value: NullHCLString) => { + return value.valid ? value.value : ""; +}; + +const isValidParameterOption = ( previewParam: PreviewParameter, buildParam: WorkspaceBuildParameter, ) => { @@ -409,7 +410,7 @@ const isValidValue = ( return validValues.includes(buildParam.value); } - return true; + return false; }; export const useValidationSchemaForDynamicParameters = ( diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageExperimental.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageExperimental.tsx index 14f34a2e29f0b..27d76a23a83cd 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageExperimental.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageExperimental.tsx @@ -9,7 +9,6 @@ import { autoCreateWorkspace, createWorkspace } from "api/queries/workspaces"; import type { DynamicParametersRequest, DynamicParametersResponse, - Template, Workspace, } from "api/typesGenerated"; import { Loader } from "components/Loader/Loader"; @@ -32,6 +31,7 @@ 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 { API } from "api/api"; import { type CreateWorkspacePermissions, createWorkspaceChecks, @@ -47,8 +47,9 @@ const CreateWorkspacePageExperimental: FC = () => { const [currentResponse, setCurrentResponse] = useState(null); - const [wsResponseId, setWSResponseId] = useState(0); - const sendMessage = (message: DynamicParametersRequest) => {}; + const [wsResponseId, setWSResponseId] = useState(-1); + const ws = useRef(null); + const [wsError, setWsError] = useState(null); const customVersionId = searchParams.get("version") ?? undefined; const defaultName = searchParams.get("name"); @@ -80,6 +81,49 @@ const CreateWorkspacePageExperimental: FC = () => { const realizedVersionId = customVersionId ?? templateQuery.data?.active_version_id; + const onMessage = useCallback((response: DynamicParametersResponse) => { + setCurrentResponse((prev) => { + if (prev?.id === response.id) { + return prev; + } + return response; + }); + }, []); + + // Initialize the WebSocket connection when there is a valid template version ID + useEffect(() => { + if (!realizedVersionId) { + return; + } + + const socket = API.templateVersionDynamicParameters(realizedVersionId, { + onMessage, + onError: (error) => { + setWsError(error); + }, + }); + + ws.current = socket; + + return () => { + socket.close(); + }; + }, [realizedVersionId, onMessage]); + + const sendMessage = useCallback((formValues: Record) => { + setWSResponseId((prevId) => { + const request: DynamicParametersRequest = { + id: prevId + 1, + inputs: formValues, + }; + if (ws.current && ws.current.readyState === WebSocket.OPEN) { + ws.current.send(JSON.stringify(request)); + return prevId + 1; + } + return prevId; + }); + }, []); + const organizationId = templateQuery.data?.organization_id; const { @@ -90,7 +134,9 @@ const CreateWorkspacePageExperimental: FC = () => { } = useExternalAuth(realizedVersionId); const isLoadingFormData = - templateQuery.isLoading || permissionsQuery.isLoading; + ws.current?.readyState !== WebSocket.OPEN || + templateQuery.isLoading || + permissionsQuery.isLoading; const loadFormDataError = templateQuery.error ?? permissionsQuery.error; const title = autoCreateWorkspaceMutation.isLoading @@ -189,11 +235,12 @@ const CreateWorkspacePageExperimental: FC = () => { { parameters={sortedParams} presets={templateVersionPresetsQuery.data ?? []} creatingWorkspace={createWorkspaceMutation.isLoading} - setWSResponseId={setWSResponseId} sendMessage={sendMessage} onCancel={() => { navigate(-1); diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx index 49fd6e9188960..86f06b84bfe44 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx @@ -67,8 +67,7 @@ export interface CreateWorkspacePageViewExperimentalProps { owner: TypesGen.User, ) => void; resetMutation: () => void; - sendMessage: (message: DynamicParametersRequest) => void; - setWSResponseId: (value: React.SetStateAction) => void; + sendMessage: (message: Record) => void; startPollingExternalAuth: () => void; } @@ -95,7 +94,6 @@ export const CreateWorkspacePageViewExperimental: FC< onCancel, resetMutation, sendMessage, - setWSResponseId, startPollingExternalAuth, }) => { const [owner, setOwner] = useState(defaultOwner); @@ -222,15 +220,7 @@ export const CreateWorkspacePageViewExperimental: FC< // Update the input for the changed parameter formInputs[parameter.name] = value; - setWSResponseId((prevId) => { - const newId = prevId + 1; - const request: DynamicParametersRequest = { - id: newId, - inputs: formInputs, - }; - sendMessage(request); - return newId; - }); + sendMessage(formInputs); }; const { debounced: handleChangeDebounced } = useDebouncedFunction( @@ -240,7 +230,7 @@ export const CreateWorkspacePageViewExperimental: FC< value: string, ) => { await form.setFieldValue(parameterField, { - name: parameter.form_type, + name: parameter.name, value, }); sendDynamicParamsRequest(parameter, value); @@ -257,7 +247,7 @@ export const CreateWorkspacePageViewExperimental: FC< handleChangeDebounced(parameter, parameterField, value); } else { await form.setFieldValue(parameterField, { - name: parameter.form_type, + name: parameter.name, value, }); sendDynamicParamsRequest(parameter, value); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy