diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js index ac53b74d44..3b44381408 100644 --- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js +++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js @@ -107,6 +107,10 @@ class GrDashboardView extends GestureEventListeners( attached() { super.attached(); this._loadPreferences(); + this.addEventListener('reload', e => { + e.stopPropagation(); + this._reload(); + }); } _loadPreferences() { diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js index 1cd9f3f8f3..fd563aa19a 100644 --- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js +++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js @@ -532,6 +532,10 @@ class GrChangeView extends KeyboardShortcutMixin( e => this._setActivePrimaryTab(e)); this.addEventListener('show-secondary-tab', e => this._setActiveSecondaryTab(e)); + this.addEventListener('reload', e => { + e.stopPropagation(); + this._reload(); + }); } /** @override */ 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 a2ec48ea93..10ba874dc5 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 @@ -112,6 +112,7 @@ class GrErrorManager extends GestureEventListeners( this.listen(document, 'server-error', '_handleServerError'); this.listen(document, 'network-error', '_handleNetworkError'); this.listen(document, 'show-alert', '_handleShowAlert'); + this.listen(document, 'hide-alert', '_hideAlert'); this.listen(document, 'show-error', '_handleShowErrorDialog'); this.listen(document, 'visibilitychange', '_handleVisibilityChange'); this.listen(document, 'show-auth-required', '_handleAuthRequired'); @@ -130,6 +131,7 @@ class GrErrorManager extends GestureEventListeners( this.unlisten(document, 'server-error', '_handleServerError'); this.unlisten(document, 'network-error', '_handleNetworkError'); this.unlisten(document, 'show-alert', '_handleShowAlert'); + this.unlisten(document, 'hide-alert', '_hideAlert'); this.unlisten(document, 'show-error', '_handleShowErrorDialog'); this.unlisten(document, 'visibilitychange', '_handleVisibilityChange'); this.unlisten(document, 'show-auth-required', '_handleAuthRequired'); diff --git a/polygerrit-ui/app/elements/gr-app-element.js b/polygerrit-ui/app/elements/gr-app-element.js index 3ee67ae8b1..ae2ba6f3cf 100644 --- a/polygerrit-ui/app/elements/gr-app-element.js +++ b/polygerrit-ui/app/elements/gr-app-element.js @@ -176,6 +176,10 @@ class GrAppElement extends KeyboardShortcutMixin( e => this._handleRpcLog(e)); this.addEventListener('shortcut-triggered', e => this._handleShortcutTriggered(e)); + // Ideally individual views should handle this event and respond with a soft + // reload. This is a catch-all for all views that cannot or have not + // implemented that. + this.addEventListener('reload', e => window.location.reload()); } /** @override */ diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.js b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.js index 717a28e812..6530576c16 100644 --- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.js +++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.js @@ -21,7 +21,6 @@ import '../gr-avatar/gr-avatar.js'; import '../gr-button/gr-button.js'; import '../gr-rest-api-interface/gr-rest-api-interface.js'; import {hovercardBehaviorMixin} from '../gr-hovercard/gr-hovercard-behavior.js'; -import {GerritNav} from '../../core/gr-navigation/gr-navigation.js'; import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js'; import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js'; import {PolymerElement} from '@polymer/polymer/polymer-element.js'; @@ -130,7 +129,8 @@ class GrHovercardAccount extends GestureEventListeners( this._reportingDetails()); this.$.restAPI.addToAttentionSet(this.change._number, this.account._account_id, 'manually added').then(obj => { - GerritNav.navigateToChange(this.change); + this.dispatchEventThroughTarget('hide-alert'); + this.dispatchEventThroughTarget('reload'); }); this.hide(); } @@ -148,7 +148,8 @@ class GrHovercardAccount extends GestureEventListeners( this._reportingDetails()); this.$.restAPI.removeFromAttentionSet(this.change._number, this.account._account_id, 'manually removed').then(obj => { - GerritNav.navigateToChange(this.change); + this.dispatchEventThroughTarget('hide-alert'); + this.dispatchEventThroughTarget('reload'); }); this.hide(); } diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.ts b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.ts index 18138c38b0..2ec06270ce 100644 --- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.ts +++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.ts @@ -107,6 +107,7 @@ export const htmlTemplate = html` >
{ ); element.account = Object.assign({}, ACCOUNT); + element._config = { + change: {enable_attention_set: true}, + }; + element.change = { + attention_set: {}, + }; element.show({}); flushAsynchronousOperations(); }); @@ -82,5 +88,72 @@ suite('gr-hovercard-account tests', () => { assert.equal(element.shadowRoot.querySelector('.voteable .value').innerText, element.voteableText); }); + + test('add to attention set', done => { + let apiResolve; + const apiPromise = new Promise(r => { + apiResolve = r; + }); + sinon.stub(element.$.restAPI, 'addToAttentionSet') + .callsFake(() => apiPromise); + element.highlightAttention = true; + element._target = document.createElement('div'); + flushAsynchronousOperations(); + const showAlertListener = sinon.spy(); + const hideAlertListener = sinon.spy(); + const reloadListener = sinon.spy(); + element.addEventListener('show-alert', showAlertListener); + element._target.addEventListener('hide-alert', hideAlertListener); + element._target.addEventListener('reload', reloadListener); + + const button = element.shadowRoot.querySelector('.addToAttentionSet'); + assert.isOk(button); + assert.isTrue(element._isShowing, 'hovercard is showing'); + MockInteractions.tap(button); + + assert.isTrue(showAlertListener.called, 'showAlertListener was called'); + assert.isFalse(element._isShowing, 'hovercard is hidden'); + + apiResolve({}); + flush(() => { + assert.isTrue(hideAlertListener.called, 'hideAlertListener was called'); + assert.isTrue(reloadListener.called, 'reloadListener was called'); + done(); + }); + }); + + test('remove from attention set', done => { + let apiResolve; + const apiPromise = new Promise(r => { + apiResolve = r; + }); + sinon.stub(element.$.restAPI, 'removeFromAttentionSet') + .callsFake(() => apiPromise); + element.highlightAttention = true; + element.change = {attention_set: {31415926535: {}}}; + element._target = document.createElement('div'); + flushAsynchronousOperations(); + const showAlertListener = sinon.spy(); + const hideAlertListener = sinon.spy(); + const reloadListener = sinon.spy(); + element.addEventListener('show-alert', showAlertListener); + element._target.addEventListener('hide-alert', hideAlertListener); + element._target.addEventListener('reload', reloadListener); + + const button = element.shadowRoot.querySelector('.removeFromAttentionSet'); + assert.isOk(button); + assert.isTrue(element._isShowing, 'hovercard is showing'); + MockInteractions.tap(button); + + assert.isTrue(showAlertListener.called, 'showAlertListener was called'); + assert.isFalse(element._isShowing, 'hovercard is hidden'); + + apiResolve({}); + flush(() => { + assert.isTrue(hideAlertListener.called, 'hideAlertListener was called'); + assert.isTrue(reloadListener.called, 'reloadListener was called'); + done(); + }); + }); }); diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.js b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.js index 0d351f6d9b..04c3166dd5 100644 --- a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.js +++ b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.js @@ -160,6 +160,17 @@ export const hovercardBehaviorMixin = superClass => class extends superClass { this.unlisten(this._target, 'click', 'hide'); } + /** + * Hovercard elements are created outside of , so if you want to fire + * events, then you probably want to do that through the target element. + */ + dispatchEventThroughTarget(eventName) { + this._target.dispatchEvent(new CustomEvent(eventName, { + bubbles: true, + composed: true, + })); + } + /** * Returns the target element that the hovercard is anchored to (the `id` of * the `for` property).