Skip to content

Commit 1e23793

Browse files
mvollmermartinpitt
authored andcommitted
storage: Don't change dialog state during input validation
1 parent 675f9d3 commit 1e23793

File tree

2 files changed

+25
-11
lines changed

2 files changed

+25
-11
lines changed

pkg/storaged/dialog.jsx

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -420,11 +420,11 @@ export const dialog_open = (def) => {
420420
function run_action(progress_callback, variant) {
421421
const func = () => {
422422
return validate(variant)
423-
.then(() => {
423+
.then(validated_values => {
424424
const visible_values = { variant };
425425
fields.forEach(f => {
426426
if (is_visible(f, values))
427-
visible_values[f.tag] = values[f.tag];
427+
visible_values[f.tag] = validated_values[f.tag];
428428
});
429429
if (def.Action.wrapper)
430430
return def.Action.wrapper(visible_values, progress_callback,
@@ -506,16 +506,32 @@ export const dialog_open = (def) => {
506506
};
507507

508508
const validate = (variant) => {
509+
// The validation functions sometimes change the dialog values
510+
// for the benefit of the action functions. For example, a
511+
// SizeSlider will convert from "text plus unit" to a numeric
512+
// value during validation.
513+
//
514+
// However, if the action fails, we don't want the values in
515+
// the dialog to change. The SizeSlider would convert back
516+
// from a numeric value to "text plus unit", for example, and
517+
// that conversion might change what the user had type.
518+
//
519+
// So we make a copy of the dialog state and let the validate
520+
// and action functions work with that.
521+
//
522+
const validated_values = { ...values };
523+
509524
return Promise.all(fields.map(f => {
510525
if (is_visible(f, values) && f.options && f.options.validate)
511-
return f.options.validate(values[f.tag], values, variant);
526+
return f.options.validate(validated_values[f.tag], validated_values, variant);
512527
else
513528
return null;
514529
})).then(results => {
515530
const errors = { };
516531
fields.forEach((f, i) => { if (results[i]) errors[f.tag] = results[i]; });
517532
if (Object.keys(errors).length > 0)
518533
return Promise.reject(errors);
534+
return validated_values;
519535
});
520536
};
521537

test/verify/check-storage-partitions

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,23 +93,21 @@ class TestStoragePartitions(storagelib.StorageCase):
9393

9494
# Switch the dialog into the mode where it stores separate text and unit
9595
# instead of a numeric value.
96-
self.dialog_set_val("size", 26.2)
97-
98-
# Change to GB
99-
unit = "1000000000"
100-
b.select_from_dropdown(".size-unit > select", unit)
96+
b.set_input_text(".size-text > input", "26.200001")
97+
b.select_from_dropdown(".size-unit > select", "1000000000") # GB
10198

10299
# Apply the dialog. This will convert from text+unit back to a
103100
# correctly rounded numeric value (which is too large).
104101

105102
self.dialog_apply()
106103
self.dialog_wait_error("size", "Size is too large")
107104

105+
# The text in the input field must not have changed
106+
b.wait_val(".size-text > input", "26.200001")
107+
108108
# Change unit back to MB. (This must round again, which it
109109
# didn't always do.)
110-
111-
unit = "1000000"
112-
b.select_from_dropdown(".size-unit > select", unit)
110+
b.select_from_dropdown(".size-unit > select", "1000000") # MB
113111

114112
self.dialog_apply()
115113
self.dialog_wait_close()

0 commit comments

Comments
 (0)