Add dialogue before relanding

Relanding a change automatically notifies reviewers, even if the change is not ready to review. This option adds a dialogue when relanding to notify reviewers, or to only notify the owner.

Bug:999368
Change-Id: I8dbb1867e8da478502656bc354228d400971254d
diff --git a/src/main/resources/static/reland-button.js b/src/main/resources/static/reland-button.js
index 9c01c07..436b247 100644
--- a/src/main/resources/static/reland-button.js
+++ b/src/main/resources/static/reland-button.js
@@ -5,7 +5,12 @@
 import {REVIEW_LABEL, STATUS_SUBMITTED, getLabelMaxValue, getTrailer,
   isLabelVotePermitted} from './common.js';
 
+import {relandPopupTemplate} from './reland-popup-html.js';
+
 let _CUSTOM_RELAND_KEY = null;
+let _NEW_KEY = null;
+let _CURR_CHANGE = null;
+let _RELAND_POPUP = null;
 
 /**
  * Adds a "Reland" button to the page if appropriate.
@@ -53,48 +58,96 @@
  * action changes
  */
 function installRelandButton(plugin, change, changeActions) {
-  const newKey = changeActions.add(
+  _CURR_CHANGE = change;
+  _NEW_KEY = changeActions.add(
       changeActions.ActionType.CHANGE, 'Create Reland');
-  changeActions.setEnabled(newKey, true);
+  changeActions.setEnabled(_NEW_KEY, true);
   const handler = async function() {
-    changeActions.setEnabled(newKey, false);
-    changeActions.setLabel(newKey, 'Reopening...');
-    const orig = (
-      change.revisions[change.current_revision].commit.message.trim());
-    const subject = 'Reland "' + change.subject + '"\n\n';
-    const disclaimer = (
-      'This is a reland of ' + change.current_revision + '\n\n' +
-        'Original change\'s description:\n');
-    const quote = orig.replace(/^/gm, '> ').replace(/^> $/gm, '>');
-    let message = subject + disclaimer + quote;
-    const bugFooter = getTrailer(orig, 'Bug');
-    const cqFooter = getTrailer(orig, 'Cq-Include-Trybots');
-    if (bugFooter || cqFooter) {
-      message += '\n\n' + bugFooter + cqFooter;
+    if (_RELAND_POPUP) {
+      // Make sure the popup is completely closed before we open it.
+      _RELAND_POPUP.close();
+      _RELAND_POPUP.open();
+    } else {
+      _RELAND_POPUP = await plugin.popup(RelandPopup.is);
     }
-    const url = (
-      '/changes/' + change._number + '/revisions/' +
-        change.revisions[change.current_revision]._number +
-        '/cherrypick');
-    const body = {
-      message: message.trim(),
-      destination: change.branch,
-      keep_reviewers: true,
-    };
-    try {
-      const response = await plugin.restApi().post(url, body);
-      window.location.pathname = '/c/' + response._number;
-    } catch (err) {
-      changeActions.setLabel(newKey, 'Can\'t reland');
-      changeActions.setEnabled(newKey, false);
-      changeActions._el.dispatchEvent(new CustomEvent('show-alert', {
-        detail: {message: 'Cannot reland: ' + err},
-        composed: true,
-        bubbles: true,
-      }));
-      throw err;
-    }
-  };
-  changeActions.addTapListener(newKey, handler);
-  _CUSTOM_RELAND_KEY = newKey;
+  }
+  changeActions.addTapListener(_NEW_KEY, handler);
+  _CUSTOM_RELAND_KEY = _NEW_KEY;
 }
+
+/**
+ * createReland relands a change with a given notification level.
+ * @param {Plugin} plugin: the plugin object
+ * @param {string} notify: the notification level
+ */
+async function createReland(plugin, notify) {
+  const changeActions = plugin.changeActions();
+  changeActions.setEnabled(_NEW_KEY, false);
+  changeActions.setLabel(_NEW_KEY, 'Reopening...');
+  const orig = (
+    _CURR_CHANGE.revisions[_CURR_CHANGE.current_revision].commit.message.trim());
+  const subject = 'Reland "' + _CURR_CHANGE.subject + '"\n\n';
+  const disclaimer = (
+    'This is a reland of ' + _CURR_CHANGE.current_revision + '\n\n' +
+      'Original change\'s description:\n');
+  const quote = orig.replace(/^/gm, '> ').replace(/^> $/gm, '>');
+  let message = subject + disclaimer + quote;
+  const bugFooter = getTrailer(orig, 'Bug');
+  const cqFooter = getTrailer(orig, 'Cq-Include-Trybots');
+  if (bugFooter || cqFooter) {
+    message += '\n\n' + bugFooter + cqFooter;
+  }
+  const url = (
+    '/changes/' + _CURR_CHANGE._number + '/revisions/' +
+    _CURR_CHANGE.revisions[_CURR_CHANGE.current_revision]._number +
+      '/cherrypick');
+  const body = {
+    message: message.trim(),
+    destination: _CURR_CHANGE.branch,
+    notify: notify,
+    keep_reviewers: true,
+  };
+  try {
+    const response = await plugin.restApi().post(url, body);
+    window.location.pathname = '/c/' + response._number;
+  } catch (err) {
+    changeActions.setLabel(_NEW_KEY, 'Can\'t reland');
+    changeActions.setEnabled(_NEW_KEY, false);
+    changeActions._el.dispatchEvent(new CustomEvent('show-alert', {
+      detail: {message: 'Cannot reland: ' + err},
+      composed: true,
+      bubbles: true,
+    }));
+    throw err;
+  }
+}
+
+class RelandPopup extends Polymer.Element {
+  static get template() {
+    return relandPopupTemplate;
+  }
+
+  static get is() {
+    return 'reland-popup';
+  }
+
+  _handleConfirm() {
+    this._createReland("ALL");
+    _RELAND_POPUP.close();
+  }
+
+  _handleCancel() {
+    this._createReland("OWNER");
+    _RELAND_POPUP.close();
+  }
+
+  async _createReland(notify) {
+    try {
+      await createReland(this.plugin, notify);
+    } catch (err) {
+      console.error(err);
+    }
+  }
+}
+
+customElements.define(RelandPopup.is, RelandPopup);
diff --git a/src/main/resources/static/reland-popup-html.js b/src/main/resources/static/reland-popup-html.js
new file mode 100644
index 0000000..936cfa3
--- /dev/null
+++ b/src/main/resources/static/reland-popup-html.js
@@ -0,0 +1,17 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+export const relandPopupTemplate = Polymer.html`
+<gr-dialog
+    id="relandDialog"
+    confirm-label="Notify Reviewers"
+    cancel-label="Reland Without Notifying"
+    on-cancel="_handleCancel"
+    on-confirm="_handleConfirm">
+  <div class="main" slot="main">
+    Click "Notify Reviewers" if you would like to send this<br/>
+    reland to reviewers, or "Reland Without Notifying" if not.<br/>
+  </div>
+</gr-dialog>
+`;