diff options
Diffstat (limited to 'polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js')
-rw-r--r-- | polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js | 294 |
1 files changed, 222 insertions, 72 deletions
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 6c5bad35e1..56bc17cf77 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 @@ -1,41 +1,23 @@ -// Copyright (C) 2016 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/** + * @license + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ (function() { 'use strict'; - const DEFAULT_SECTIONS = [ - { - name: 'Work in progress', - query: 'is:open owner:${user} is:wip', - selfOnly: true, - }, - { - name: 'Outgoing reviews', - query: 'is:open owner:${user} -is:wip', - }, - { - name: 'Incoming reviews', - query: 'is:open ((reviewer:${user} -owner:${user} -is:ignored) OR ' + - 'assignee:${user}) -is:wip', - }, - { - name: 'Recently closed', - query: 'is:closed (owner:${user} OR reviewer:${user} OR ' + - 'assignee:${user})', - suffixForDashboard: '-age:4w limit:10', - }, - ]; + const PROJECT_PLACEHOLDER_PATTERN = /\$\{project\}/g; Polymer({ is: 'gr-dashboard-view', @@ -49,20 +31,26 @@ properties: { account: { type: Object, - value() { return {}; }, + value: null, }, + preferences: Object, /** @type {{ selectedChangeIndex: number }} */ viewState: Object, + + /** @type {{ project: string, user: string }} */ params: { type: Object, }, - _results: Array, - _sectionMetadata: { - type: Array, - value() { return DEFAULT_SECTIONS; }, + createChangeTap: { + type: Function, + value() { + return this._createChangeTap.bind(this); + }, }, + _results: Array, + /** * For showing a "loading..." string during ajax requests. */ @@ -70,10 +58,20 @@ type: Boolean, value: true, }, + + _showDraftsBanner: { + type: Boolean, + value: false, + }, + + _showNewUserHelp: { + type: Boolean, + value: false, + }, }, observers: [ - '_userChanged(params.user)', + '_paramsChanged(params.*)', ], behaviors: [ @@ -88,53 +86,205 @@ ); }, + attached() { + this._loadPreferences(); + }, + + _loadPreferences() { + return this.$.restAPI.getLoggedIn().then(loggedIn => { + if (loggedIn) { + this.$.restAPI.getPreferences().then(preferences => { + this.preferences = preferences; + }); + } else { + this.preferences = {}; + } + }); + }, + + _getProjectDashboard(project, dashboard) { + const errFn = response => { + this.fire('page-error', {response}); + }; + return this.$.restAPI.getDashboard( + project, dashboard, errFn).then(response => { + if (!response) { + return; + } + return { + title: response.title, + sections: response.sections.map(section => { + const suffix = response.foreach ? ' ' + response.foreach : ''; + return { + name: section.name, + query: + section.query.replace( + PROJECT_PLACEHOLDER_PATTERN, project) + suffix, + }; + }), + }; + }); + }, + _computeTitle(user) { - if (user === 'self') { + if (!user || user === 'self') { return 'My Reviews'; } return 'Dashboard for ' + user; }, - /** - * Allows a refresh if menu item is selected again. - */ - _userChanged(user) { - if (!user) { return; } + _isViewActive(params) { + return params.view === Gerrit.Nav.View.DASHBOARD; + }, + + _paramsChanged(paramsChangeRecord) { + const params = paramsChangeRecord.base; + + if (!this._isViewActive(params)) { + return Promise.resolve(); + } + + const user = params.user || 'self'; // NOTE: This method may be called before attachment. Fire title-change // in an async so that attachment to the DOM can take place first. - this.async( - () => this.fire('title-change', {title: this._computeTitle(user)})); + const title = params.title || this._computeTitle(user); + this.async(() => this.fire('title-change', {title})); + return this._reload(); + }, + /** + * Reloads the element. + * + * @return {Promise<!Object>} + */ + _reload() { this._loading = true; - const sections = this._sectionMetadata.filter( - section => (user === 'self' || !section.selfOnly)); - const queries = - sections.map( - section => this._dashboardQueryForSection(section, user)); - this.$.restAPI.getChanges(null, queries, null, this.options) - .then(results => { - this._results = sections.map((section, i) => { - return { - sectionName: section.name, - query: queries[i], - results: results[i], - }; - }); - this._loading = false; + const {project, dashboard, title, user, sections} = this.params; + const dashboardPromise = project ? + this._getProjectDashboard(project, dashboard) : + Promise.resolve(Gerrit.Nav.getUserDashboard( + user, + sections, + title || this._computeTitle(user))); + + const checkForNewUser = !project && user === 'self'; + return dashboardPromise + .then(res => this._fetchDashboardChanges(res, checkForNewUser)) + .then(() => { + this._maybeShowDraftsBanner(); + this.$.reporting.dashboardDisplayed(); }).catch(err => { - this._loading = false; - console.warn(err.message); + console.warn(err); + }).then(() => { this._loading = false; }); + }, + + /** + * Fetches the changes for each dashboard section and sets this._results + * with the response. + * + * @param {!Object} res + * @param {boolean} checkForNewUser + * @return {Promise} + */ + _fetchDashboardChanges(res, checkForNewUser) { + if (!res) { return Promise.resolve(); } + + const queries = res.sections + .map(section => section.suffixForDashboard ? + section.query + ' ' + section.suffixForDashboard : + section.query); + + if (checkForNewUser) { + queries.push('owner:self'); + } + + return this.$.restAPI.getChanges(null, queries, null, this.options) + .then(changes => { + if (checkForNewUser) { + // Last set of results is not meant for dashboard display. + const lastResultSet = changes.pop(); + this._showNewUserHelp = lastResultSet.length == 0; + } + this._results = changes.map((results, i) => ({ + sectionName: res.sections[i].name, + query: res.sections[i].query, + results, + isOutgoing: res.sections[i].isOutgoing, + })).filter((section, i) => i < res.sections.length && ( + !res.sections[i].hideIfEmpty || + section.results.length)); }); }, - _dashboardQueryForSection(section, user) { - const query = - section.suffixForDashboard ? - section.query + ' ' + section.suffixForDashboard : - section.query; - return query.replace(/\$\{user\}/g, user); + _computeUserHeaderClass(params) { + if (!params || !!params.project || !params.user + || params.user === 'self') { + return 'hide'; + } + return ''; + }, + + _handleToggleStar(e) { + this.$.restAPI.saveChangeStarred(e.detail.change._number, + e.detail.starred); + }, + + _handleToggleReviewed(e) { + 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(); + }, + + _computeDraftsLink() { + return Gerrit.Nav.getUrlForSearchQuery('has:draft -is:open'); + }, + + _createChangeTap(e) { + this.$.destinationDialog.open(); + }, + + _handleDestinationConfirm(e) { + this.$.commandsDialog.branch = e.detail.branch; + this.$.commandsDialog.open(); + }, }); })(); |