Skip to content

Commit afdab85

Browse files
committed
chore: move logic for sending initial parameters to websocket
1 parent 03dde8a commit afdab85

File tree

2 files changed

+69
-49
lines changed

2 files changed

+69
-49
lines changed

site/src/pages/CreateWorkspacePage/CreateWorkspacePageExperimental.tsx

Lines changed: 69 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { API } from "api/api";
12
import { type ApiErrorResponse, DetailedError } from "api/errors";
23
import { checkAuthorization } from "api/queries/authCheck";
34
import {
@@ -9,11 +10,13 @@ import { autoCreateWorkspace, createWorkspace } from "api/queries/workspaces";
910
import type {
1011
DynamicParametersRequest,
1112
DynamicParametersResponse,
13+
PreviewParameter,
1214
Workspace,
1315
} from "api/typesGenerated";
1416
import { Loader } from "components/Loader/Loader";
1517
import { useAuthenticated } from "hooks";
1618
import { useEffectEvent } from "hooks/hookPolyfills";
19+
import { getInitialParameterValues } from "modules/workspaces/DynamicParameter/DynamicParameter";
1720
import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName";
1821
import {
1922
type FC,
@@ -29,13 +32,13 @@ import { useNavigate, useParams, useSearchParams } from "react-router-dom";
2932
import { pageTitle } from "utils/page";
3033
import type { AutofillBuildParameter } from "utils/richParameters";
3134
import { CreateWorkspacePageViewExperimental } from "./CreateWorkspacePageViewExperimental";
32-
const createWorkspaceModes = ["form", "auto", "duplicate"] as const;
33-
export type CreateWorkspaceMode = (typeof createWorkspaceModes)[number];
34-
import { API } from "api/api";
3535
import {
3636
type CreateWorkspacePermissions,
3737
createWorkspaceChecks,
3838
} from "./permissions";
39+
40+
const createWorkspaceModes = ["form", "auto", "duplicate"] as const;
41+
export type CreateWorkspaceMode = (typeof createWorkspaceModes)[number];
3942
export type ExternalAuthPollingState = "idle" | "polling" | "abandoned";
4043

4144
const CreateWorkspacePageExperimental: FC = () => {
@@ -50,6 +53,7 @@ const CreateWorkspacePageExperimental: FC = () => {
5053
const [wsResponseId, setWSResponseId] = useState<number>(-1);
5154
const ws = useRef<WebSocket | null>(null);
5255
const [wsError, setWsError] = useState<Error | null>(null);
56+
const initialParamsSentRef = useRef(false);
5357

5458
const customVersionId = searchParams.get("version") ?? undefined;
5559
const defaultName = searchParams.get("name");
@@ -84,15 +88,72 @@ const CreateWorkspacePageExperimental: FC = () => {
8488
const realizedVersionId =
8589
customVersionId ?? templateQuery.data?.active_version_id;
8690

87-
const onMessage = useCallback((response: DynamicParametersResponse) => {
88-
setCurrentResponse((prev) => {
89-
if (prev?.id === response.id) {
90-
return prev;
91+
const autofillParameters = useMemo(
92+
() => getAutofillParameters(searchParams),
93+
[searchParams],
94+
);
95+
96+
const sendMessage = useCallback((formValues: Record<string, string>) => {
97+
setWSResponseId((prevId) => {
98+
const request: DynamicParametersRequest = {
99+
id: prevId + 1,
100+
inputs: formValues,
101+
};
102+
if (ws.current && ws.current.readyState === WebSocket.OPEN) {
103+
ws.current.send(JSON.stringify(request));
104+
return prevId + 1;
91105
}
92-
return response;
106+
return prevId;
93107
});
94108
}, []);
95109

110+
// On sends all initial parameter values to the websocket
111+
// (including defaults and autofilled from the url)
112+
// This ensures the backend has the complete initial state of the form,
113+
// which is vital for correctly rendering dynamic UI elements where parameter visibility
114+
// or options might depend on the initial values of other parameters.
115+
const sendInitialParameters = useEffectEvent(
116+
(parameters: PreviewParameter[]) => {
117+
if (initialParamsSentRef.current) return;
118+
if (parameters.length === 0) return;
119+
120+
const initialFormValues = getInitialParameterValues(
121+
parameters,
122+
autofillParameters,
123+
);
124+
if (initialFormValues.length === 0) return;
125+
126+
const initialParamsToSend: Record<string, string> = {};
127+
for (const param of initialFormValues) {
128+
if (param.name && param.value) {
129+
initialParamsToSend[param.name] = param.value;
130+
}
131+
}
132+
133+
if (Object.keys(initialParamsToSend).length === 0) return;
134+
135+
sendMessage(initialParamsToSend);
136+
initialParamsSentRef.current = true;
137+
},
138+
);
139+
140+
const onMessage = useCallback(
141+
(response: DynamicParametersResponse) => {
142+
setCurrentResponse((prev) => {
143+
if (prev?.id === response.id) {
144+
return prev;
145+
}
146+
147+
if (!initialParamsSentRef.current && response.parameters.length > 0) {
148+
sendInitialParameters([...response.parameters]);
149+
}
150+
151+
return response;
152+
});
153+
},
154+
[sendInitialParameters],
155+
);
156+
96157
// Initialize the WebSocket connection when there is a valid template version ID
97158
useEffect(() => {
98159
if (!realizedVersionId) return;
@@ -127,20 +188,6 @@ const CreateWorkspacePageExperimental: FC = () => {
127188
};
128189
}, [owner.id, realizedVersionId, onMessage]);
129190

130-
const sendMessage = useCallback((formValues: Record<string, string>) => {
131-
setWSResponseId((prevId) => {
132-
const request: DynamicParametersRequest = {
133-
id: prevId + 1,
134-
inputs: formValues,
135-
};
136-
if (ws.current && ws.current.readyState === WebSocket.OPEN) {
137-
ws.current.send(JSON.stringify(request));
138-
return prevId + 1;
139-
}
140-
return prevId;
141-
});
142-
}, []);
143-
144191
const organizationId = templateQuery.data?.organization_id;
145192

146193
const {
@@ -167,9 +214,6 @@ const CreateWorkspacePageExperimental: FC = () => {
167214
[navigate],
168215
);
169216

170-
// Auto fill parameters
171-
const autofillParameters = getAutofillParameters(searchParams);
172-
173217
const autoCreationStartedRef = useRef(false);
174218
const automateWorkspaceCreation = useEffectEvent(async () => {
175219
if (autoCreationStartedRef.current || !organizationId) {

site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -141,30 +141,6 @@ export const CreateWorkspacePageViewExperimental: FC<
141141
},
142142
});
143143

144-
// On component mount, sends all initial parameter values to the websocket
145-
// (including defaults and autofilled from the url)
146-
// This ensures the backend has the complete initial state of the form,
147-
// which is vital for correctly rendering dynamic UI elements where parameter visibility
148-
// or options might depend on the initial values of other parameters.
149-
const hasInitializedWebsocket = useRef(false);
150-
useEffect(() => {
151-
if (hasInitializedWebsocket.current) return;
152-
153-
const formValues = form.values.rich_parameter_values;
154-
if (parameters.length > 0 && formValues && formValues.length > 0) {
155-
const initialParams: Record<string, string> = {};
156-
for (const param of formValues) {
157-
if (param.name && param.value) {
158-
initialParams[param.name] = param.value;
159-
}
160-
}
161-
if (Object.keys(initialParams).length > 0) {
162-
sendMessage(initialParams);
163-
hasInitializedWebsocket.current = true;
164-
}
165-
}
166-
}, [parameters, form.values.rich_parameter_values, sendMessage]);
167-
168144
const autofillByName = Object.fromEntries(
169145
autofillParameters.map((param) => [param.name, param]),
170146
);

0 commit comments

Comments
 (0)
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