Merge "Allow for bulk deletion of draft comments"
This commit is contained in:
@@ -20,6 +20,9 @@ limitations under the License.
|
||||
<link rel="import" href="../../../styles/shared-styles.html">
|
||||
<link rel="import" href="../../change-list/gr-change-list/gr-change-list.html">
|
||||
<link rel="import" href="../../core/gr-reporting/gr-reporting.html">
|
||||
<link rel="import" href="../../shared/gr-button/gr-button.html">
|
||||
<link rel="import" href="../../shared/gr-dialog/gr-dialog.html">
|
||||
<link rel="import" href="../../shared/gr-overlay/gr-overlay.html">
|
||||
<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
|
||||
<link rel="import" href="../gr-user-header/gr-user-header.html">
|
||||
|
||||
@@ -37,18 +40,42 @@ limitations under the License.
|
||||
gr-change-list {
|
||||
width: 100%;
|
||||
}
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
gr-user-header {
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
.banner {
|
||||
align-items: center;
|
||||
background-color: var(--comment-background-color);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: .25em var(--default-horizontal-margin);
|
||||
}
|
||||
.banner gr-button {
|
||||
--gr-button: {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
}
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
@media only screen and (max-width: 50em) {
|
||||
.loading {
|
||||
padding: 0 var(--default-horizontal-margin);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div class$="banner [[_computeBannerClass(_showDraftsBanner)]]">
|
||||
<div>
|
||||
You have draft comments on closed changes.
|
||||
</div>
|
||||
<div>
|
||||
<gr-button
|
||||
class="delete"
|
||||
link
|
||||
on-tap="_handleOpenDeleteDialog">Delete All</gr-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="loading" hidden$="[[!_loading]]">Loading...</div>
|
||||
<div hidden$="[[_loading]]" hidden>
|
||||
<gr-user-header
|
||||
@@ -64,6 +91,21 @@ limitations under the License.
|
||||
on-toggle-star="_handleToggleStar"
|
||||
on-toggle-reviewed="_handleToggleReviewed"></gr-change-list>
|
||||
</div>
|
||||
<gr-overlay id="confirmDeleteOverlay" with-backdrop>
|
||||
<gr-dialog
|
||||
id="confirmDeleteDialog"
|
||||
confirm-label="Delete"
|
||||
on-confirm="_handleConfirmDelete"
|
||||
on-cancel="_closeConfirmDeleteOverlay">
|
||||
<div class="header" slot="header">
|
||||
Delete comments
|
||||
</div>
|
||||
<div class="main" slot="main">
|
||||
Are you sure you want to delete all your draft comments in closed changes? This action
|
||||
cannot be undone.
|
||||
</div>
|
||||
</gr-dialog>
|
||||
</gr-overlay>
|
||||
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
|
||||
<gr-reporting id="reporting"></gr-reporting>
|
||||
</template>
|
||||
|
@@ -51,6 +51,11 @@
|
||||
type: Boolean,
|
||||
value: true,
|
||||
},
|
||||
|
||||
_showDraftsBanner: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
|
||||
observers: [
|
||||
@@ -153,6 +158,7 @@
|
||||
|
||||
return dashboardPromise.then(this._fetchDashboardChanges.bind(this))
|
||||
.then(() => {
|
||||
this._maybeShowDraftsBanner();
|
||||
this.$.reporting.dashboardDisplayed();
|
||||
}).catch(err => {
|
||||
console.warn(err);
|
||||
@@ -199,5 +205,44 @@
|
||||
this.$.restAPI.saveChangeReviewed(e.detail.change._number,
|
||||
e.detail.reviewed);
|
||||
},
|
||||
|
||||
/**
|
||||
* Banner is shown if a user is on their own dashboard and they have draft
|
||||
* comments on closed changes.
|
||||
*/
|
||||
_maybeShowDraftsBanner() {
|
||||
this._showDraftsBanner = false;
|
||||
if (!(this.params.user === 'self')) { return; }
|
||||
|
||||
const draftSection = this._results
|
||||
.find(section => section.query === 'has:draft');
|
||||
if (!draftSection || !draftSection.results.length) { return; }
|
||||
|
||||
const closedChanges = draftSection.results
|
||||
.filter(change => !this.changeIsOpen(change.status));
|
||||
if (!closedChanges.length) { return; }
|
||||
|
||||
this._showDraftsBanner = true;
|
||||
},
|
||||
|
||||
_computeBannerClass(show) {
|
||||
return show ? '' : 'hide';
|
||||
},
|
||||
|
||||
_handleOpenDeleteDialog() {
|
||||
this.$.confirmDeleteOverlay.open();
|
||||
},
|
||||
|
||||
_handleConfirmDelete() {
|
||||
this.$.confirmDeleteDialog.disabled = true;
|
||||
return this.$.restAPI.deleteDraftComments('-is:open').then(() => {
|
||||
this._closeConfirmDeleteOverlay();
|
||||
this._reload();
|
||||
});
|
||||
},
|
||||
|
||||
_closeConfirmDeleteOverlay() {
|
||||
this.$.confirmDeleteOverlay.close();
|
||||
},
|
||||
});
|
||||
})();
|
||||
|
@@ -63,6 +63,85 @@ limitations under the License.
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
suite('drafts banner functionality', () => {
|
||||
suite('_maybeShowDraftsBanner', () => {
|
||||
test('not dashboard/self', () => {
|
||||
element.params = {user: 'notself'};
|
||||
element._maybeShowDraftsBanner();
|
||||
assert.isFalse(element._showDraftsBanner);
|
||||
});
|
||||
|
||||
test('no drafts at all', () => {
|
||||
element.params = {user: 'self'};
|
||||
element._results = [];
|
||||
element._maybeShowDraftsBanner();
|
||||
assert.isFalse(element._showDraftsBanner);
|
||||
});
|
||||
|
||||
test('no drafts on open changes', () => {
|
||||
element.params = {user: 'self'};
|
||||
element._results = [{query: 'has:draft', results: [{status: '_'}]}];
|
||||
sandbox.stub(element, 'changeIsOpen').returns(true);
|
||||
element._maybeShowDraftsBanner();
|
||||
assert.isFalse(element._showDraftsBanner);
|
||||
});
|
||||
|
||||
test('no drafts on open changes', () => {
|
||||
element.params = {user: 'self'};
|
||||
element._results = [{query: 'has:draft', results: [{status: '_'}]}];
|
||||
sandbox.stub(element, 'changeIsOpen').returns(false);
|
||||
element._maybeShowDraftsBanner();
|
||||
assert.isTrue(element._showDraftsBanner);
|
||||
});
|
||||
});
|
||||
|
||||
test('_showDraftsBanner', () => {
|
||||
element._showDraftsBanner = false;
|
||||
flushAsynchronousOperations();
|
||||
assert.isTrue(isHidden(element.$$('.banner')));
|
||||
|
||||
element._showDraftsBanner = true;
|
||||
flushAsynchronousOperations();
|
||||
assert.isFalse(isHidden(element.$$('.banner')));
|
||||
});
|
||||
|
||||
test('delete tap opens dialog', () => {
|
||||
sandbox.stub(element, '_handleOpenDeleteDialog');
|
||||
element._showDraftsBanner = true;
|
||||
flushAsynchronousOperations();
|
||||
|
||||
MockInteractions.tap(element.$$('.banner .delete'));
|
||||
assert.isTrue(element._handleOpenDeleteDialog.called);
|
||||
});
|
||||
|
||||
test('delete comments flow', async () => {
|
||||
sandbox.spy(element, '_handleConfirmDelete');
|
||||
sandbox.stub(element, '_reload');
|
||||
|
||||
// Set up control over timing of when RPC resolves.
|
||||
let deleteDraftCommentsPromiseResolver;
|
||||
const deleteDraftCommentsPromise = new Promise(resolve => {
|
||||
deleteDraftCommentsPromiseResolver = resolve;
|
||||
});
|
||||
sandbox.stub(element.$.restAPI, 'deleteDraftComments')
|
||||
.returns(deleteDraftCommentsPromise);
|
||||
|
||||
// Open confirmation dialog and tap confirm button.
|
||||
await element.$.confirmDeleteOverlay.open();
|
||||
MockInteractions.tap(element.$.confirmDeleteDialog.$.confirm);
|
||||
flushAsynchronousOperations();
|
||||
assert.isTrue(element.$.restAPI.deleteDraftComments
|
||||
.calledWithExactly('-is:open'));
|
||||
assert.isTrue(element.$.confirmDeleteDialog.disabled);
|
||||
assert.equal(element._reload.callCount, 0);
|
||||
|
||||
// Verify state after RPC resolves.
|
||||
deleteDraftCommentsPromiseResolver([]);
|
||||
await deleteDraftCommentsPromise;
|
||||
assert.equal(element._reload.callCount, 1);
|
||||
});
|
||||
});
|
||||
|
||||
test('_computeTitle', () => {
|
||||
assert.equal(element._computeTitle('self'), 'My Reviews');
|
||||
assert.equal(element._computeTitle('not self'), 'Dashboard for not self');
|
||||
|
@@ -2925,5 +2925,13 @@
|
||||
reportEndpointAsIs: true,
|
||||
});
|
||||
},
|
||||
|
||||
deleteDraftComments(query) {
|
||||
return this._send({
|
||||
method: 'POST',
|
||||
url: '/accounts/self/drafts:delete',
|
||||
query,
|
||||
});
|
||||
},
|
||||
});
|
||||
})();
|
||||
|
Reference in New Issue
Block a user