Add confirmation dialog for post-commit review requests on web UI

Review Request #10148 — Created Sept. 17, 2018 and submitted

Review Board
reviewboard, students

When a user is scrolling through the changeset (post commit review) to
make a new review request on the web UI, clicking on the row of a
commit makes a new review request, which can be done accidentally very

I added a confirmation dialog when creating post-commit review requests
on web UI so the user can confirm that they want to create a new review
request from that commit. Clicking 'cancel' closes the dialog and takes
no further action, clicking 'create' creates a new review request.

Ran JS tests (all of which pass).

Tested behaviour in Chrome, Safari, and Firefox with the following

  1. Click on commit, click cancel on confirmation dialog
  2. Click on commit with no diff with master, click confirm, see error
  3. Click on commit with diff with master, click confirm, see review
    request created
Loading file attachments...

  • 0
  • 0
  • 33
  • 1
  • 34
Description From Last Updated
  2. Could you add a screen shot of your work?

  3. Can you wrap your summary at 72 characters, but ideally 52 characters. Commit summaries needn't end in a period.

  4. Can you wrap your description at 72 characters?

    1. You wrapped your description and testing done at 52, which just the 1-line summary needs to be wrapped at.

  5. You can have your testing done render a list using:

    Tested behaviour in Chrome, Safari in Firefox:
    1. Something
    2. Another thing
    3. Yet another thing.
  6. The issue was originally filed against reviewboard 2.5.x.

    Can you apply your patch on that branch, test, and re-post?


    To get Reviewboard 2.5.x to work, you will need a new virtual environment with Review Board at release-2.5.x and Djblets at release-0.9.x. You do not need another source checkout of RB or Djblets -- another virtualenv will suffice.

  7. How about:

    "The confirmation dialog will allow the user to cancel the creation of the review request."

  8. We may want to add more context to the message here, something like:

    You are creating a new review request from a commit that has already been published. Are you sure you want to continue?
  9. This string needs to be marked for translation with gettext().

  10. This string needs to be marked for translation with gettext().

    Missing trailing comma.

  11. This string needs to be marked for translation with gettext().

  12. Unfortunately, we can't use ES6 arrow functions here. We'll have to do _.bind(this._createNewReviewRequest, this) instead.

    This is because we have customers on older versions of IE (I know :( ). We do allow arrow functions in .es6.js files, which are transpiled with Babel to ES5 that can run on all these browsers.

    However, since this patch will be backported to 2.5.x, we don't be able to use that. Sorry.

  2. Ideally this long message would be in the body of the dialog instead of the title

    1. I tried one approach by adding a 'body' option to the dialogView class to make this change. I'm not sure if this is what you were expecting based on our conversation in Slack, but continuing to use the dialogView class allowed me to take advantage of the existing functionality to set the button list correctly for modalBox. I added a new screenshot of what it looks like now. Let me know what you think.

  3. Instead of doing this, lets define a subclass that will display this content. We can refactor it out into a generic class at a later date.

    If you wrap the contents of the file in an IIFE, we can have it local to the file.

    1. Can you elaborate on this a bit? I'm not sure I understand exactly what you mean here...

    2. You can ignore this. Your approach is better.

  2. Can you add body and title here?

    The title should be something like "Are you sure?" or "Create review request?"

  3. reviewboard/static/rb/js/ui/views/dialogView.js (Diff revision 3)

    This should really be in the default impl of render above. Also, doing _.result twice may result in us calling an expensive function twice. Lets do:

    var body;
    /* snip */
    body = _.result(this, 'body');
    if (body !== undefined) {
  2. Title case: Create Review Request?

  3. reviewboard/static/rb/js/ui/views/dialogView.js (Diff revision 4)

    While you're here, would you mind updating the doc comment to take the following format:

     * Initialze the view.
     * Args:
     *     options (object):
     *         Options for the view.
     * Option Args:
     *     body (string or function, optional):
     *         <Description of body.>
     *     title (string, optional):
     *         <Description of title.>
     *     buttons (object, optional):
     *         <Description of buttons.>
    1. If you can take a look at what I did, do you think I need to put the parameters of the buttons here like I did even though it's duplicating the description at the top of the file?

  4. Need a var body statement at the top of the function.

  2. One more request to add to the design of this: can we include the commit summary in the text of the dialog, so people can verify that they clicked on the one they intended to?

    1. I added a screenshot of my changes. I also added the first few characters of the commit id like in the commit view in the list. Let me know what you think.

  2. reviewboard/static/rb/js/ui/views/dialogView.js (Diff revision 6)

    Instead of duplicating this I would just do

    See the :js:class:`class-level documentation <RB.DialogView>` for the keys that this object accepts.
  1. Just a few tiny nits left.

  2. reviewboard/static/rb/css/common.less (Diff revision 7)

    Let's sort these alphabetically.

  3. Please put a blank line between these two.

  4. Instead of <b>, let's just use <span> and then put font-weight: bold in the CSS.

  5. Because this is an ES5 file, no trailing comma on the last item in an object.

    1. In the first review Barret gave me he said I was missing trailing commas so I added them everywhere. So I shouldn't add them unless it's an es6.js file?

    2. That was my bad. I forgot trailing commas in objects aren't an ES5 thing. Sorry 😦

  6. Because this is an ES5 file, no trailing comma on the last item in an object.

    1. Same thing, in the first review Barret gave me he said I was missing trailing commas so I added them everywhere. So I shouldn't add them unless it's an es6.js file?

  2. A few things here. Wrapping everything in gettext wont work. gettext() requires the value to a be a string literal, otherwise the code that looks for things to translate won't be able to parse this.

    Also, we want to avoid using inline styles when possible. This should be included in the rules for .summary in the LESS file.

    Instead, lets use a template on the class:

        _dialogTemplate: _.template([
            '<p><%- prefixText %></p>',
            '<p class="summary">',
            ' <%- commitID %>: <%- summary %>',
            '<p><%- suffixText %></p>',

    For more details on _.template, check out the docs.

    Then we can use it like so:

    var dialogView = new RB.DialogView({
        title: gettext('Create Review Request?'),
        body: this._dialogTemplate({
            prefixText: gettext('You are creating a new review request from the following published commit:'),
            suffixText: gettext('Are you sure you want to continue?'),
        buttons: [ /* ... */ ]

    This allows us to only mark the string literals for translation. Additionally, lets use <p> tags for content separation instead of <br>, as that is what they exist for.

  1. Two minor nits, but otherwise looks good to me!

  2. While you're here, can you change this to /**? Otherwise it doesn't get picked up by the documentation generation tool

    1. I changed this for all the functions I touched. Should I fix it for the rest or leave them for now (i.e. it should be in a different patch)

    2. Just the ones you touched are fine. Cleanup can be a different patch.

  2. Tiny nit: summaries don't need a period.

  3. Also your summary should be in the imperitive mood as if it were an order. If you substitute your sumamry into the following sentence it should make sense:

    This patch will <summary>

    So Add confirmation dialog ... would work or similar.

  2. This is only used once, so instead of defining a variable, you could do it inline:

    body: this._dialogBodyTemplate({
        prefixText: gettext('...'),
        commitID: commitID,
        summary: this.model.get('summary'),
        suffixText: ...
  3. In ES5, all variables need to be defined at the top of the function. So:

    var commitID = this.model.get('id'),
    if (commitID.length > 7) {
        commitID = commitID.slice(0, 7);
    dialogView = new RB.DialogView({
  4. Wrap to 79 columns.

  1. Ship It!
  1. Ship It!
Review request changed

Status: Closed (submitted)

Change Summary:

Pushed to release-3.0.x (7746104)