8000 fix: get presets working correctly with dynamic params (#17923) · coder/coder@dc21016 · GitHub
[go: up one dir, main page]

Skip to content

Commit dc21016

Browse files
authored
fix: get presets working correctly with dynamic params (#17923)
This adds a few fixes to get presets working correctly with dynamic params 1. Changes to preset params need to be rendered and displayed correctly 2. Changes to preset params need to be sent to the websocket 3. Changes to preset params need to be marked as touched so they won't be automatically changed later because of dynamic defaults. Dynamic defaults means any default parameter value can be changed by the websocket response unless edited by the user, set by autofill or set by a preset.
1 parent 9c00046 commit dc21016

File tree

3 files changed

+72
-14
lines changed

3 files changed

+72
-14
lines changed

site/src/modules/workspaces/DynamicParameter/DynamicParameter.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,15 @@ const DebouncedParameterField: FC<DebouncedParameterFieldProps> = ({
222222
const onChangeEvent = useEffectEvent(onChange);
223223
// prevDebouncedValueRef is to prevent calling the onChangeEvent on the initial render
224224
const prevDebouncedValueRef = useRef<string | undefined>();
225+
const prevValueRef = useRef(value);
226+
227+
// This is necessary in the case of fields being set by preset parameters
228+
useEffect(() => {
229+
if (value !== undefined && value !== prevValueRef.current) {
230+
setLocalValue(value);
231+
prevValueRef.current = value;
232+
}
233+
}, [value]);
225234

226235
useEffect(() => {
227236
if (prevDebouncedValueRef.current !== undefined) {
@@ -458,7 +467,7 @@ const ParameterField: FC<ParameterFieldProps> = ({
458467
<Slider
459468
id={id}
460469
className="mt-2"
461-
value={[Number(value)]}
470+
value={[Number.isFinite(Number(value)) ? Number(value) : 0]}
462471
onValueChange={([value]) => {
463472
onChange(value.toString());
464473
}}

site/src/pages/CreateWorkspacePage/CreateWorkspacePageExperimental.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ const CreateWorkspacePageExperimental: FC = () => {
101101
}
102102
}, []);
103103

104-
// On sends all initial parameter values to the websocket
104+
// On page load, sends all initial parameter values to the websocket
105105
// (including defaults and autofilled from the url)
106106
// This ensures the backend has the complete initial state of the form,
107107
// which is vital for correctly rendering dynamic UI elements where parameter visibility

site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -213,39 +213,80 @@ export const CreateWorkspacePageViewExperimental: FC<
213213

214214
setPresetParameterNames(selectedPreset.Parameters.map((p) => p.Name));
215215

216+
const currentValues = form.values.rich_parameter_values ?? [];
217+
218+
const updates: Array<{
219+
field: string;
220+
fieldValue: TypesGen.WorkspaceBuildParameter;
221+
parameter: PreviewParameter;
222+
presetValue: string;
223+
}> = [];
224+
216225
for (const presetParameter of selectedPreset.Parameters) {
217226
const parameterIndex = parameters.findIndex(
218227
(p) => p.name === presetParameter.Name,
219228
);
220229
if (parameterIndex === -1) continue;
221230

222231
const parameterField = `rich_parameter_values.${parameterIndex}`;
232+
const parameter = parameters[parameterIndex];
233+
const currentValue = currentValues.find(
234+
(p) => p.name === presetParameter.Name,
235+
)?.value;
236+
237+
if (currentValue !== presetParameter.Value) {
238+
updates.push({
239+
field: parameterField,
240+
fieldValue: {
241+
name: presetParameter.Name,
242+
value: presetParameter.Value,
243+
},
244+
parameter,
245+
presetValue: presetParameter.Value,
246+
});
247+
}
248+
}
223249

224-
form.setFieldValue(parameterField, {
225-
name: presetParameter.Name,
226-
value: presetParameter.Value,
227-
});
250+
if (updates.length > 0) {
251+
for (const update of updates) {
252+
form.setFieldValue(update.field, update.fieldValue);
253+
form.setFieldTouched(update.parameter.name, true);
254+
}
255+
256+
sendDynamicParamsRequest(
257+
updates.map((update) => ({
258+
parameter: update.parameter,
259+
value: update.presetValue,
260+
})),
261+
);
228262
}
229263
}, [
230264
presetOptions,
231265
selectedPresetIndex,
232266
presets,
233267
form.setFieldValue,
268+
form.setFieldTouched,
234269
parameters,
270+
form.values.rich_parameter_values,
235271
]);
236272

237273
// send the last user modified parameter and all touched parameters to the websocket
238274
const sendDynamicParamsRequest = (
239-
parameter: PreviewParameter,
240-
value: string,
275+
parameters: Array<{ parameter: PreviewParameter; value: string }>,
241276
) => {
242277
const formInputs: Record<string, string> = {};
243-
formInputs[parameter.name] = value;
244-
const parameters = form.values.rich_parameter_values ?? [];
278+
const formParameters = form.values.rich_parameter_values ?? [];
279+
280+
for (const { parameter, value } of parameters) {
281+
formInputs[parameter.name] = value;
282+
}
245283

246284
for (const [fieldName, isTouched] of Object.entries(form.touched)) {
247-
if (isTouched && fieldName !== parameter.name) {
248-
const param = parameters.find((p) => p.name === fieldName);
285+
if (
286+
isTouched &&
287+
!parameters.some((p) => p.parameter.name === fieldName)
288+
) {
289+
const param = formParameters.find((p) => p.name === fieldName);
249290
if (param?.value) {
250291
formInputs[fieldName] = param.value;
251292
}
@@ -260,12 +301,20 @@ export const CreateWorkspacePageViewExperimental: FC<
260301
parameterField: string,
261302
value: string,
262303
) => {
304+
const currentFormValue = form.values.rich_parameter_values?.find(
305+
(p) => p.name === parameter.name,
306+
)?.value;
307+
263308
await form.setFieldValue(parameterField, {
264309
name: parameter.name,
265310
value,
266311
});
267-
form.setFieldTouched(parameter.name, true);
268-
sendDynamicParamsRequest(parameter, value);
312+
313+
// Only send the request if the value has changed from the form value
314+
if (currentFormValue !== value) {
315+
form.setFieldTouched(parameter.name, true);
316+
sendDynamicParamsRequest([{ parameter, value }]);
317+
}
269318
};
270319

271320
useSyncFormParameters({

0 commit comments

Comments
 (0)
0