Skip to content

Commit c6280ae

Browse files
authored
JSONSchema table - fixes (#5432)
* handle undefined currentValue in slider param Signed-off-by: Antonio Gamez Diaz <[email protected]> * move submitForm to a useEffect Signed-off-by: Antonio Gamez Diaz <[email protected]> * remove "from: true" Signed-off-by: Antonio Gamez Diaz <[email protected]> * fix test Signed-off-by: Antonio Gamez Diaz <[email protected]> Signed-off-by: Antonio Gamez Diaz <[email protected]>
1 parent 7260592 commit c6280ae

File tree

5 files changed

+108
-90
lines changed

5 files changed

+108
-90
lines changed

dashboard/src/components/DeploymentForm/DeploymentForm.test.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -271,9 +271,8 @@ describe("renders an error", () => {
271271
spyOnUseHistory = jest.spyOn(ReactRouter, "useHistory").mockReturnValue({ push } as any);
272272

273273
const appValues = "foo: bar";
274-
const schema = {
275-
properties: { foo: { type: "string", form: true } },
276-
} as unknown as JSONSchemaType<any>;
274+
const newAppValues = "foo: modified";
275+
const schema = { properties: { foo: { type: "string" } } } as unknown as JSONSchemaType<any>;
277276
const selected = { ...defaultSelectedPkg, values: appValues, schema: schema };
278277

279278
const wrapper = mountWrapper(
@@ -289,8 +288,9 @@ describe("renders an error", () => {
289288
const handleValuesChange: (v: string) => void = wrapper
290289
.find(DeploymentFormBody)
291290
.prop("setValues");
291+
292292
act(() => {
293-
handleValuesChange("foo: bar");
293+
handleValuesChange(newAppValues);
294294
});
295295

296296
wrapper
@@ -299,7 +299,7 @@ describe("renders an error", () => {
299299

300300
wrapper.update();
301301

302-
expect(wrapper.find(DeploymentFormBody).prop("appValues")).toBe("foo: bar");
302+
expect(wrapper.find(DeploymentFormBody).prop("appValues")).toBe(newAppValues);
303303
expect(wrapper.find(DeploymentForm).find("#releaseName").prop("value")).toBe(
304304
defaultProps.releaseName,
305305
);
@@ -316,7 +316,7 @@ describe("renders an error", () => {
316316
defaultProps.namespace,
317317
defaultSelectedPkg.availablePackageDetail,
318318
defaultProps.releaseName,
319-
appValues,
319+
newAppValues,
320320
schema,
321321
{} as ReconciliationOptions,
322322
);

dashboard/src/components/DeploymentForm/DeploymentFormBody/BasicDeploymentForm/TabularSchemaEditorTable/Params/SliderParam.tsx

+8-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ export interface ISliderParamProps {
2525
export default function SliderParam(props: ISliderParamProps) {
2626
const { handleBasicFormParamChange, id, label, param, step } = props;
2727

28-
const [currentValue, setCurrentValue] = useState(toNumber(param.currentValue) || param.minimum);
28+
const [currentValue, setCurrentValue] = useState(
29+
toNumber(param.currentValue) || toNumber(param.minimum) || 0,
30+
);
2931
const [isValueModified, setIsValueModified] = useState(false);
3032
const [timeout, setThisTimeout] = useState({} as NodeJS.Timeout);
3133

@@ -45,6 +47,9 @@ export default function SliderParam(props: ISliderParamProps) {
4547
setThisTimeout(setTimeout(() => func(targetCopy), basicFormsDebounceTime));
4648
};
4749

50+
const defaultMin = 0;
51+
const defaultMax = 1000;
52+
4853
const unsavedMessage = isValueModified ? "Unsaved" : "";
4954
const isModified =
5055
isValueModified ||
@@ -57,8 +62,8 @@ export default function SliderParam(props: ISliderParamProps) {
5762
aria-label={label}
5863
id={id + "_range"}
5964
type="range"
60-
min={Math.min(param.minimum || 0, currentValue)}
61-
max={Math.max(param.maximum || 1000, currentValue)}
65+
min={Math.min(param.minimum || defaultMin, currentValue)}
66+
max={Math.max(param.maximum || defaultMax, currentValue)}
6267
step={step}
6368
onChange={onChange}
6469
value={currentValue}

dashboard/src/components/DeploymentForm/DeploymentFormBody/DeploymentFormBody.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ it("should modify the original values of the differential component if parsed as
124124
c: d
125125
`;
126126
const schema = {
127-
properties: { a: { type: "string", form: true } },
127+
properties: { a: { type: "string" } },
128128
} as unknown as JSONSchemaType<any>;
129129
const selected = {
130130
values: oldValues,

dashboard/src/components/DeploymentForm/DeploymentFormBody/DeploymentFormBody.tsx

+35-21
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,13 @@ function DeploymentFormBody({
6464
{} as YAML.Document.Parsed<YAML.ParsedNode>,
6565
);
6666
const [restoreModalIsOpen, setRestoreModalOpen] = useState(false);
67-
const [isLoaded, setIsloaded] = useState(false);
68-
const [isLoading, setIsloading] = useState(true);
67+
const [isLoaded, setIsLoaded] = useState(false);
68+
const [isLoading, setIsLoading] = useState(true);
6969
const [unsavedChangesMap] = useState(new Map<string, any>());
70+
const [shouldSubmitForm, setShouldSubmitForm] = useState(false);
7071

71-
// setBasicFormParameters when basicFormParameters changes
72+
// whenever the parsed values change (for instance, when a new pkg version is selected),
73+
// we need to force a new extraction of the params from the schema
7274
useEffect(() => {
7375
if (!isLoaded && schemaFromTheAvailablePackage && !isEmpty(valuesFromTheParentContainerNodes)) {
7476
const initialParamsFromContainer = retrieveBasicFormParams(
@@ -79,8 +81,8 @@ function DeploymentFormBody({
7981
valuesFromTheDeployedPackageNodes,
8082
);
8183
setParamsFromComponentState(initialParamsFromContainer);
82-
setIsloaded(true);
83-
setIsloading(false);
84+
setIsLoaded(true);
85+
setIsLoading(false);
8486
}
8587
}, [
8688
deploymentEvent,
@@ -92,42 +94,48 @@ function DeploymentFormBody({
9294
valuesFromTheParentContainerNodes,
9395
]);
9496

95-
// setDefaultValues when defaultValues changes
97+
// parse and store in the component state the values from the available package
9698
useEffect(() => {
9799
if (valuesFromTheAvailablePackage) {
98100
setValuesFromTheAvailablePackageNodes(parseToYamlNode(valuesFromTheAvailablePackage));
99101
}
100102
}, [isLoaded, valuesFromTheAvailablePackage]);
101103

104+
// parse and store in the component state the current values (which come from the parent container)
102105
useEffect(() => {
103106
if (valuesFromTheParentContainer) {
104107
setValuesFromTheParentContainerNodes(parseToYamlNode(valuesFromTheParentContainer));
105108
}
106109
}, [isLoaded, valuesFromTheParentContainer]);
107110

111+
// parse and store in the component state the values from the deployed package
108112
useEffect(() => {
109113
if (valuesFromTheDeployedPackage) {
110114
setValuesFromTheDeployedPackageNodes(parseToYamlNode(valuesFromTheDeployedPackage));
111115
}
112116
}, [isLoaded, valuesFromTheDeployedPackage, valuesFromTheParentContainer]);
113117

114-
const handleYAMLEditorChange = (value: string) => {
115-
setValuesFromTheParentContainer(value);
116-
setValuesModified();
117-
};
118-
119-
const forceSubmit = useCallback(() => {
120-
// the API was added recently, but should replace the manual dispatch of a submit event with bubbles:true (react>=17)
121-
formRef?.current?.requestSubmit();
122-
}, [formRef]);
118+
// when the shouldSubmitForm flag is enabled, the form will be submitted, but using a native
119+
// form submit event (to trigger the browser validations) instead of just calling its handler function
120+
useEffect(() => {
121+
if (shouldSubmitForm) {
122+
// the requestSubmit API was added recently,
123+
// but should replace the manual dispatch of a submit event with "bubbles:true" (react>=17)
124+
formRef?.current?.requestSubmit();
125+
setShouldSubmitForm(false);
126+
}
127+
}, [formRef, shouldSubmitForm]);
123128

129+
// for each unsaved change in the component state, we need to update the values,
130+
// so that both the table and the yaml editor get the updated values
124131
const saveAllChanges = () => {
125132
let newValuesFromTheParentContainer, newParamsFromComponentState;
126133
unsavedChangesMap.forEach((value, key) => {
127-
setIsloading(true);
134+
setIsLoading(true);
128135
setValuesModified();
129-
const aa = updateCurrentConfigByKey(paramsFromComponentState, key, value);
130-
newParamsFromComponentState = [...aa];
136+
newParamsFromComponentState = [
137+
...updateCurrentConfigByKey(paramsFromComponentState, key, value),
138+
];
131139
setParamsFromComponentState(newParamsFromComponentState);
132140

133141
newValuesFromTheParentContainer = toStringYamlNode(
@@ -136,13 +144,19 @@ function DeploymentFormBody({
136144
setValuesFromTheParentContainer(newValuesFromTheParentContainer);
137145
});
138146
unsavedChangesMap.clear();
139-
setIsloading(false);
147+
setIsLoading(false);
140148
};
141149

142-
// save the pending changes and fire the submit event (via useEffect, to actually get the saved changes)
150+
// save the pending changes and fire the submit event
151+
// via an useEffect, to actually get the most recent saved changes
143152
const handleDeployClick = () => {
144153
saveAllChanges();
145-
forceSubmit();
154+
setShouldSubmitForm(true);
155+
};
156+
157+
const handleYAMLEditorChange = (value: string) => {
158+
setValuesFromTheParentContainer(value);
159+
setValuesModified();
146160
};
147161

148162
// re-build the table based on the new YAML

0 commit comments

Comments
 (0)