Show toast messages for storing diff comment drafts
With this change, toast messages show when diff comments are being saved
and notify when saving is complete, even when the diff view is no-longer
loaded. This signal is intended to encourage users to write diff
comments and feel free to navigate away to view other parts of a change.
With this change, new toast messages are able to replace existing toast
messages.
Feature: Issue 6970
Change-Id: I5973673d85c73b14794cb5e5b21327dd0c27ec1d
diff --git a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
index 0a2b974..ac74ee5 100644
--- a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
+++ b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
@@ -126,7 +126,9 @@
*/
_showAlert(text, opt_actionText, opt_actionCallback,
opt_dismissOnNavigation) {
- if (this._alertElement) { return; }
+ if (this._alertElement) {
+ this._hideAlert();
+ }
this._clearHideAlertHandle();
if (opt_dismissOnNavigation) {
diff --git a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html
index 5d1c461..17fa746 100644
--- a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html
+++ b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html
@@ -272,20 +272,11 @@
});
});
- test('dismissOnNavigation respected', () => {
- const asyncStub = sandbox.stub(element, 'async');
- const hideSpy = sandbox.spy(element, '_hideAlert');
- // No async call when dismissOnNavigation supplied.
- element._showAlert('test', null, null, true);
- assert.isFalse(asyncStub.called);
-
- // When page nav happens, clear alert.
- document.dispatchEvent(new CustomEvent('location-change'));
- assert.isTrue(hideSpy.called);
-
- // When timeout is not supplied, use HIDE_ALERT_TIMEOUT_MS.
- element._showAlert('test');
- assert.isTrue(asyncStub.called);
+ test('_showAlert hides existing alerts', () => {
+ element._alertElement = element._createToastAlert();
+ const hideStub = sandbox.stub(element, '_hideAlert');
+ element._showAlert();
+ assert.isTrue(hideStub.calledOnce);
});
});
</script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.js b/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.js
index 4f0ebcc..bda9a35 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.js
@@ -15,6 +15,12 @@
'use strict';
const STORAGE_DEBOUNCE_INTERVAL = 400;
+ const TOAST_DEBOUNCE_INTERVAL = 200;
+
+ const SAVING_MESSAGE = 'Saving';
+ const DRAFT_SINGULAR = 'draft...';
+ const DRAFT_PLURAL = 'drafts...';
+ const SAVED_MESSAGE = 'All changes saved';
Polymer({
is: 'gr-diff-comment',
@@ -109,6 +115,11 @@
type: Boolean,
observer: '_toggleResolved',
},
+
+ _numPendingDiffRequests: {
+ type: Object,
+ value: {number: 0}, // Intentional to share the object across instances.
+ },
},
observers: [
@@ -424,13 +435,52 @@
});
},
+ _getSavingMessage(numPending) {
+ if (numPending === 0) { return SAVED_MESSAGE; }
+ return [
+ SAVING_MESSAGE,
+ numPending,
+ numPending === 1 ? DRAFT_SINGULAR : DRAFT_PLURAL,
+ ].join(' ');
+ },
+
+ _showStartRequest() {
+ const numPending = ++this._numPendingDiffRequests.number;
+ this._updateRequestToast(numPending);
+ },
+
+ _showEndRequest() {
+ const numPending = --this._numPendingDiffRequests.number;
+ this._updateRequestToast(numPending);
+ },
+
+ _updateRequestToast(numPending) {
+ const message = this._getSavingMessage(numPending);
+ this.debounce('draft-toast', () => {
+ // Note: the event is fired on the body rather than this element because
+ // this element may not be attached by the time this executes, in which
+ // case the event would not bubble.
+ document.body.dispatchEvent(new CustomEvent('show-alert',
+ {detail: {message}, bubbles: true}));
+ }, TOAST_DEBOUNCE_INTERVAL);
+ },
+
_saveDraft(draft) {
- return this.$.restAPI.saveDiffDraft(this.changeNum, this.patchNum, draft);
+ this._showStartRequest();
+ return this.$.restAPI.saveDiffDraft(this.changeNum, this.patchNum, draft)
+ .then(result => {
+ this._showEndRequest();
+ return result;
+ });
},
_deleteDraft(draft) {
+ this._showStartRequest();
return this.$.restAPI.deleteDiffDraft(this.changeNum, this.patchNum,
- draft);
+ draft).then(result => {
+ this._showEndRequest();
+ return result;
+ });
},
_getPatchNum() {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment_test.html b/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment_test.html
index bdbf4f9..2816647 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment_test.html
@@ -602,5 +602,34 @@
element.comment = {unresolved: true};
assert.isFalse(element.$$('.resolve input').checked);
});
+
+ suite('draft saving messages', () => {
+ test('_getSavingMessage', () => {
+ assert.equal(element._getSavingMessage(0), 'All changes saved');
+ assert.equal(element._getSavingMessage(1), 'Saving 1 draft...');
+ assert.equal(element._getSavingMessage(2), 'Saving 2 drafts...');
+ assert.equal(element._getSavingMessage(3), 'Saving 3 drafts...');
+ });
+
+ test('_show{Start,End}Request', () => {
+ const updateStub = sandbox.stub(element, '_updateRequestToast');
+ element._numPendingDiffRequests.number = 1;
+
+ element._showStartRequest();
+ assert.isTrue(updateStub.calledOnce);
+ assert.equal(updateStub.lastCall.args[0], 2);
+ assert.equal(element._numPendingDiffRequests.number, 2);
+
+ element._showEndRequest();
+ assert.isTrue(updateStub.calledTwice);
+ assert.equal(updateStub.lastCall.args[0], 1);
+ assert.equal(element._numPendingDiffRequests.number, 1);
+
+ element._showEndRequest();
+ assert.isTrue(updateStub.calledThrice);
+ assert.equal(updateStub.lastCall.args[0], 0);
+ assert.equal(element._numPendingDiffRequests.number, 0);
+ });
+ });
});
</script>