-
Notifications
You must be signed in to change notification settings - Fork 90
nics: Reimplement dialogs with new framework #2425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
nics: Reimplement dialogs with new framework #2425
Conversation
cockpituous
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are more than 10 code coverage comments, see the full report here.
9a5d9ae to
c463979
Compare
cockpituous
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are more than 10 code coverage comments, see the full report here.
c463979 to
35fcd29
Compare
cockpituous
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are more than 10 code coverage comments, see the full report here.
e565eab to
aeac367
Compare
cockpituous
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are more than 10 code coverage comments, see the full report here.
|
Things that stick out in the dialogs that I would like to improve:
The IDs are used by the tests but also to associate labels for input elements. Clicking the FormGroup label will focus the corresponding text input, and clicking a label for a checkbox should toggle that checkbox. Using IDs for each and every thing in a dialog feels too much, but the alternative would be to use "data-ouia" things or similar, and that isn't really any better, is it? So let's have a method for generating IDs for dialog values, and some Python helpers to work with them from the tests. |
1fff60d to
899c38e
Compare
cockpituous
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are more than 10 code coverage comments, see the full report here.
cockpituous
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are more than 10 code coverage comments, see the full report here.
bbe24e2 to
0ece715
Compare
cockpituous
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are more than 10 code coverage comments, see the full report here.
0ece715 to
ee50fd0
Compare
cockpituous
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are more than 10 code coverage comments, see the full report here.
4545de5 to
26d2c33
Compare
cockpituous
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are more than 10 code coverage comments, see the full report here.
To have only one dialog value instead of three (plus assorted props). The goal is to put the initialization knowledge in the component itself, and to not have any extra arguments for the validation function. This gives this component the "standard" API.
26d2c33 to
e6e7919
Compare
cockpituous
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are more than 10 code coverage comments, see the full report here.
| set_aux(val: T): void { | ||
| this.#setter(val, true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These 2 added lines are not executed by any test. Details
| if (Array.isArray(val)) { | ||
| return val.map((_, i) => func(this.sub(i as keyof T) as DialogValue<ArrayElement<T>>, i)); | ||
| } else | ||
| return []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This added line is not executed by any test. Details
| const val = this.get(); | ||
| if (Array.isArray(val)) { | ||
| for (let j = index; j < val.length - 1; j++) | ||
| this.#dialog._rename_validation_state(this.#path, j + 1, j); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This added line is not executed by any test. Details
| at<TT extends T>(witness: TT): DialogValue<TT> { | ||
| cockpit.assert(Object.is(witness, this.get())); | ||
| return new DialogValue<TT>( | ||
| this.#dialog, | ||
| () => this.get() as TT, | ||
| (val, is_aux) => { | ||
| this.#setter(val, is_aux); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These 7 added lines are not executed by any test. Details
| (val, is_aux) => { | ||
| this.#setter(val, is_aux); | ||
| }, | ||
| this.#path, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This added line is not executed by any test. Details
| validate_async(debounce: number, func: (val: T) => Promise<string | undefined>): void { | ||
| const val = this.get(); | ||
| if (!this.#dialog._probe_validation_cache(this.#path, val)) { | ||
| console.log("START VALIDATE ASYNC", this.#path, val); | ||
| this.#dialog._set_validation_timeout( | ||
| this.#path, | ||
| val, | ||
| debounce, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These 8 added lines are not executed by any test. Details
| console.log("BEGIN VALIDATE ASYNC", this.#path, val); | ||
| const prom = | ||
| func(val) | ||
| .catch( | ||
| ex => { | ||
| console.error(ex); | ||
| return undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These 7 added lines are not executed by any test. Details
| .then( | ||
| result => { | ||
| if (this.#dialog._validation_state_is_current(this.#path, prom)) { | ||
| console.log("DONE VALIDATE ASYNC", this.#path, result); | ||
| this.#dialog._set_validation_result(this.#path, val, result); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These 5 added lines are not executed by any test. Details
| console.log("DONE VALIDATE ASYNC", this.#path, result); | ||
| this.#dialog._set_validation_result(this.#path, val, result); | ||
| } else { | ||
| console.log("OUTDATED", this.#path); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This added line is not executed by any test. Details
| } | ||
| } | ||
| ); | ||
| this.#dialog._set_validation_promise(this.#path, val, prom); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This added line is not executed by any test. Details
| const Dialogs = useDialogs(); | ||
| function init(): LoggerValues = { | ||
| text: "", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops, "return" missing.
And introduce the framework at the same time.
Some noteworthy things:
It might be hard to see from the diff, but: the rewrite was very straightforward and it's nice that the "hairy" parts have disappeared, especially the untypable
onValuesChangedmethods. The code has become much less strongly coupled by that. Reusing components likeNetworkModelRowis now feasible and doesn't expect the parent component to have a specific state structure.This is as far as I think I want to go in this PR.
There is more to be done to make them "state of the art", but that requires actual changes to behavior. For example, the "Mac" text input in the Edit dialog could be a clean
DialogTextInput, but it is sometimes disabled with a funny tooltip on the whole text input. I don't think this is a "best practice", it looks funny, I haven't seen it anywhere else, and I think we should reduce the use of tooltips in general. So instead of makingDialogTextInputconfigurable for all these one-off "experiences", I think we should change the dialog to use a helper text to explain why the input is disabled. Likewise, I think we should change how the dialog handles types that have no sources. Etc. I'll continue in nics: Improve the dialog experience with new framework components #2435.Here is the 1000 meter view of the framework API:
DialogState<MyValues>object with the initial values:use_DialogState. Don't worry too much why it needs to be written like this.