Make improvements to RB.DialogView
Review Request #10820 — Created Jan. 13, 2020 and submitted
This review request changes makes improvements to
RB.DialogView.
It introduces a property on
RB.DialogView
which is a map of buttons in the dialog from buttonid
s to
button elements. Theid
field of aRB.DialogView
button is now required so that
buttons can be referenced by their id in the map. In addition,disabled
andclass
are added as button keys so that buttons can be created with initial state set to disabled
and with classes set, respectively.
Unit tests:
- new dialog view button properties (id, class, disabled)
Description | From | Last Updated |
---|---|---|
In your description, we don't need to talk about browsers without JS--Review Board really isn't usable if JS is turned … |
david | |
Thanks for working on this, Hannah! Reversing the order of buttons may fix it, but I think only accidentally (and … |
chipx86 | |
Just curious, can you test what happens when esc is pressed? |
david | |
Oh, one last thing. May have mentioned this before, but we now effectively have two distinct changes tangled up here: … |
chipx86 | |
We should call this only if there's an id set. I'd make this its own statement, wrapped in an if … |
chipx86 | |
Rather than define these, let's use the definitions that already exist: $.ui.keyCode.ENTER and $.ui.keyCode.ESCAPE. |
chipx86 | |
Let's pull buttons[0] into a variable and then test against that. It'll be a little faster (avoids repeated index lookups). |
chipx86 | |
Jasmine has a handy .toBeFalse() and .toBeTrue(), which is more correct in these cases. |
chipx86 | |
You'll want to do this right at the class level, like: events: _.extend({ 'change #path': '.....', }, RB.DialogView.prototype.events), |
chipx86 | |
So something that I noticed when I looked at the original code we had earlier is that we're playing with … |
chipx86 | |
This is still best done in render. It's kind of like initialize but for the initial display, so it's the … |
chipx86 | |
Is there a reason why we're using !!buttonInfo.danger instead of just simply buttonInfo.danger? |
bui1 | |
Col: 37 ['testid'] is better written in dot notation. |
reviewbot | |
Col: 37 ['testid'] is better written in dot notation. |
reviewbot | |
Col: 37 ['testid'] is better written in dot notation. |
reviewbot | |
Col: 37 ['testid'] is better written in dot notation. |
reviewbot | |
Col: 41 ['testid'] is better written in dot notation. |
reviewbot | |
Col: 41 ['testid'] is better written in dot notation. |
reviewbot | |
Col: 41 ['upload'] is better written in dot notation. |
reviewbot | |
We like to keep these in alphabetical order, but have completely failed to do so here. Doh. Can you shuffle … |
chipx86 | |
"ID" should be capitalized in sentences. |
chipx86 | |
I think we only want to do this inside of the code building the body and modalBox. Otherwise, a second … |
chipx86 | |
I think this should probably go right before modalBox(), so we're not at risk of page elements jumping around or … |
chipx86 | |
So the biggest thing I'm noticing is that we're now returning a mapping exclusively. The issue is that we're no … |
chipx86 | |
We can just set this to true directly, since we already know that's the value. |
chipx86 | |
toggleClass isn't very useful here, since we already know we want to enable these classes. It's actually a bit slower, … |
chipx86 | |
I mentioned this in a reply to Monica's review, but we don't need to use reduce here. Even though there's … |
chipx86 | |
I think this can now be this.$('.js-path') (and you could remove the id="path" on the element). If we can remove … |
chipx86 |
Change Summary:
Fix description.
Description: |
|
---|
-
-
Thanks for working on this, Hannah!
Reversing the order of buttons may fix it, but I think only accidentally (and I don't like having to shuffle around UI to make something work). Since the Upload button is disabled by default, I don't believe we're guaranteed that all browsers will treat it as the primary button.
It's always better to be explicit in how a bug gets fixed, particularly when we're dependent on browser behavior. Also, we're going to encounter this in other dialogs as well, which may have even more buttons and more complicated button layouts.
modalBox is ooooold
So this is old code. We actually have this far-nicer thing called
RB.DialogView
, which we'd like to port code to. It has a concept of primary buttons, too.It's a bit newer, and it might need some improvement, but that's where any work toward doing this correctly should go.
So I'd suggest changing this code to not call
.modalBox()
directly (okay,RB.DialogView
does call this, but don't worry about that). You can create the element for the contents of the dialog and instantiate using:const dialogView = new RB.DialogView({ title: ..., body: yourElement, buttons: [ { label: gettext('Upload'), primary: true, onClick: () => this.send(), }, { label: gettext('Cancel'), } ], });
Something like that.
Now, this probably won't fix it directly, but here's where phase 2 comes in! You can modify
reviewboard/static/rb/js/ui/views/dialogView.es6.js
to register a key event for Enter and a key event for Escape and hook those up, like:RB.DialogView = Backbone.View.extend({ events: { 'keypress': _onKeyPress, }, ... _onKeyPress(e) { /* Check for Enter and Escape here */ } });
If Enter, activate the primary button if we have one (loop through
this.options
, look forprimary
).If Escape, just call
this.hide()
.I think this would be fantastic addition, and would solve the bug cleanly!
Make sure that you write unit tests, though. Check out
ui/views/tests/dialogView.es6.js
. You'll want to simulate key events. Here's how:const evt = $.Event('keypress') evt.which = $.ui.keyCode.ENTER; dialogView.$el.trigger(evt);
Change Summary:
Fix issues from review and start writing tests
Summary: |
|
||||
---|---|---|---|---|---|
Commit: |
|
||||
Diff: |
Revision 2 (+124 -37) |
Checks run (2 succeeded)
-
-
reviewboard/static/rb/js/ui/views/dialogView.es6.js (Diff revision 2) We should call this only if there's an
id
set. I'd make this its own statement, wrapped in anif
that checks for it.(Frankly, we should probably be doing that with all the things we're adding -- we're cheating a bit with the
toggleClass
thing, and it's not as performant as just anif
withaddClass
.) -
reviewboard/static/rb/js/ui/views/dialogView.es6.js (Diff revision 2) Rather than define these, let's use the definitions that already exist:
$.ui.keyCode.ENTER
and$.ui.keyCode.ESCAPE
. -
reviewboard/static/rb/js/ui/views/tests/dialogViewTests.js (Diff revision 2) Let's pull
buttons[0]
into a variable and then test against that. It'll be a little faster (avoids repeated index lookups). -
reviewboard/static/rb/js/ui/views/tests/dialogViewTests.js (Diff revision 2) Jasmine has a handy
.toBeFalse()
and.toBeTrue()
, which is more correct in these cases. -
reviewboard/static/rb/js/views/uploadAttachmentView.js (Diff revision 2) You'll want to do this right at the class level, like:
events: _.extend({ 'change #path': '.....', }, RB.DialogView.prototype.events),
-
reviewboard/static/rb/js/views/uploadAttachmentView.js (Diff revision 2) So something that I noticed when I looked at the original code we had earlier is that we're playing with fire using these IDs.
#upload
and#path
are wayyyyy too generic, and are bound to conflict. There should never be more than one element with an ID, and if there is, bad things can happen with event handling and such.So what I'd suggest doing is two things:
- Adding support for CSS classes instead of or in addition to IDs, when registering buttons.
- Using our CSS standard naming scheme to come up with suitable classes.
For the latter, I don't want to have you pour too much more work into this, because this can get out of control, so instead of revamping the entire CSS for this dialog, we can make use of these handy
js-
-prefixed classes. So,js-path
andjs-upload-button
.What
js-
means is "I'm a thing owned by some JavaScript, and nothing but the thing that owns me should deal with me." So no custom styling, so page-wide DOM queries, nothing. It's good for this purpose.By using those instead of hard-coded IDs, we'll avoid potentially weird bugs down the line.
-
reviewboard/static/rb/js/views/uploadAttachmentView.js (Diff revision 2) This is still best done in
render
. It's kind of likeinitialize
but for the initial display, so it's the right place to pull out variables. We then don't have to defineshow()
, letting us just take advantage of the parent class's version, and trusting that we'll be pulling out variables before it's actually shown.Make sure though, especially with the above
js-
prefixes I mentioned, to isolate the lookup to this element. You can use a shorthand available to views:this._$path = this.$('.js-path'); this._$uploadBtn = this.$('.js-upload-button');
Change Summary:
Fixed more issues from review and finished writing tests
Summary: |
|
|||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Description: |
|
|||||||||||||||||||||||||||||||||
Testing Done: |
|
|||||||||||||||||||||||||||||||||
Commit: |
|
|||||||||||||||||||||||||||||||||
Diff: |
Revision 3 (+217 -56) |
Checks run (2 succeeded)
Change Summary:
Make selectors more specific
Commit: |
|
||||
---|---|---|---|---|---|
Diff: |
Revision 4 (+217 -56) |
Checks run (2 succeeded)
-
-
reviewboard/static/rb/js/ui/views/dialogView.es6.js (Diff revision 4) Is there a reason why we're using
!!buttonInfo.danger
instead of just simplybuttonInfo.danger
? -
reviewboard/static/rb/js/ui/views/dialogView.es6.js (Diff revision 4) Just a question out of curiousity but what will happen to the dialogue if neither enter/esc is pressed on the keyboard but rather another keyCode like any of the digits/alphabet etc?
Will the dialogue stay open and not produce any errors? Does the dialogue just ignore those key inputs?
-
reviewboard/static/rb/js/views/uploadAttachmentView.js (Diff revision 4) Also wondering why 'send' is used for onClick instead of a function that would trigger an event that would allow the user to upload their file?
Change Summary:
Remove bug fix and make this review request just do the refactoring for RB.UploadAttachmentView - bug fix to come in another rb
Summary: |
|
||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Description: |
|
||||||||||||||||||||||||||||||||||||||||||||||||
Testing Done: |
|
||||||||||||||||||||||||||||||||||||||||||||||||
Commit: |
|
||||||||||||||||||||||||||||||||||||||||||||||||
Diff: |
Revision 5 (+139 -69) |
Checks run (1 failed, 1 succeeded)
JSHint
-
reviewboard/static/rb/js/ui/views/tests/dialogViewTests.js (Diff revision 5) Col: 37 ['testid'] is better written in dot notation.
-
reviewboard/static/rb/js/ui/views/tests/dialogViewTests.js (Diff revision 5) Col: 37 ['testid'] is better written in dot notation.
-
reviewboard/static/rb/js/ui/views/tests/dialogViewTests.js (Diff revision 5) Col: 37 ['testid'] is better written in dot notation.
-
reviewboard/static/rb/js/ui/views/tests/dialogViewTests.js (Diff revision 5) Col: 37 ['testid'] is better written in dot notation.
-
reviewboard/static/rb/js/ui/views/tests/dialogViewTests.js (Diff revision 5) Col: 41 ['testid'] is better written in dot notation.
-
reviewboard/static/rb/js/ui/views/tests/dialogViewTests.js (Diff revision 5) Col: 41 ['testid'] is better written in dot notation.
-
reviewboard/static/rb/js/views/uploadAttachmentView.js (Diff revision 5) Col: 41 ['upload'] is better written in dot notation.
Change Summary:
Fix JSHint errors
Commit: |
|
||||
---|---|---|---|---|---|
Diff: |
Revision 6 (+139 -69) |
Checks run (2 succeeded)
-
Changes look really good! Only have one small comment that I'm not too sure about
-
reviewboard/static/rb/js/ui/views/dialogView.es6.js (Diff revision 6) I really like how simple it is to read the reduce function callback.
More for a question for any mentor/maintainer reviewing this, are reduce functions allowed for es6 files? I've looked through https://www.notion.so/reviewboard/JavaScript-ES6-Guidelines-a5d6efb850d24ac295e1b8792cecdd25
but couldn't find anything on it
-
-
reviewboard/static/rb/js/ui/views/dialogView.es6.js (Diff revision 6) We like to keep these in alphabetical order, but have completely failed to do so here. Doh.
Can you shuffle these around so they're in order?
-
reviewboard/static/rb/js/ui/views/dialogView.es6.js (Diff revision 6) "ID" should be capitalized in sentences.
-
reviewboard/static/rb/js/ui/views/dialogView.es6.js (Diff revision 6) I think we only want to do this inside of the code building the body and
modalBox
. Otherwise, a second call would replace our button map. -
reviewboard/static/rb/js/ui/views/dialogView.es6.js (Diff revision 6) I think this should probably go right before
modalBox()
, so we're not at risk of page elements jumping around ormodalBox
's size calculations being incorrect as things re-render. -
reviewboard/static/rb/js/ui/views/dialogView.es6.js (Diff revision 6) So the biggest thing I'm noticing is that we're now returning a mapping exclusively. The issue is that we're no longer going to have ordering information preserved, so we're browser-dependent. This could cause buttons to swap around.
We're going to want to ultimately end up having two pieces of information calculated:
- A list of button elements (to pass to
modalBox
) -- let's call thisthis.$buttonList
. - A mapping of button elements, for
render()
to reference. -- let's call thisthis.$buttonsMap
, for consistency.
How about we rename this to
_makeButtons()
, and we just populate both of those attributes instead of returning anything? Then it behaves the way thatshow()
now uses it, and it gives us public attributes for both of these useful bits of state.It'll be important to start the function off by clearing both of those attributes before we do anything.
- A list of button elements (to pass to
-
reviewboard/static/rb/js/ui/views/dialogView.es6.js (Diff revision 6) We can just set this to
true
directly, since we already know that's the value. -
reviewboard/static/rb/js/ui/views/dialogView.es6.js (Diff revision 6) toggleClass
isn't very useful here, since we already know we want to enable these classes. It's actually a bit slower, since it's first going to split the existing class list from a string and do a search in there. So instead, let's just useaddClass()
with the class name we want. -
reviewboard/static/rb/js/ui/views/dialogView.es6.js (Diff revision 6) I mentioned this in a reply to Monica's review, but we don't need to use
reduce
here. Even though there's so few buttons in practice, we want to avoid a second loop (and all the function calls that come from each iteration of areduce
call).Instead, let's just set the entry in the map up above, after we've set all the button state (so after the
if (buttonInfo.onClick) { ... }
block).
Change Summary:
Fix issues from review
Commit: |
|
||||
---|---|---|---|---|---|
Diff: |
Revision 7 (+156 -85) |
Checks run (2 succeeded)
-
This looks just about done! One tiny thing (and you can also close the opened issue -- you got it right!).
-
reviewboard/static/rb/js/views/uploadAttachmentView.js (Diff revision 7) I think this can now be
this.$('.js-path')
(and you could remove theid="path"
on the element). If we can remove the IDs on the elements in this dialog, we'll reduce the risk of hard-to-diagnose conflicts.
-
-
Oh, one last thing. May have mentioned this before, but we now effectively have two distinct changes tangled up here:
- A set of improvements to
RB.DialogView
, which are independent of the changes toRB.UploadAttachmentView
. - The fixes to
RB.UploadAttachmentView
and making it a subclass ofRB.DialogView
.
So I'd suggest repurposing this change for the
RB.DialogView
cahnges and describing them, and then having a follow-up review request just for theUploadAttachmentView
changes.It's helpful for a variety of reasons to keep each review request/commit focused like that, so we encourage it where possible.
- A set of improvements to
Change Summary:
Remove path id
Commit: |
|
||||
---|---|---|---|---|---|
Diff: |
Revision 8 (+156 -85) |
Checks run (2 succeeded)
Change Summary:
Remove fixes for UploadAttachmentView - to be moved to another review request.
Summary: |
|
||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Description: |
|
||||||||||||||||||||||||
Testing Done: |
|
||||||||||||||||||||||||
Bugs: |
|
||||||||||||||||||||||||
Commit: |
|
||||||||||||||||||||||||
Diff: |
Revision 9 (+122 -48) |