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>
+`;