|  | /** | 
|  | * @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 PROJECT_PLACEHOLDER_PATTERN = /\$\{project\}/g; | 
|  |  | 
|  | Polymer({ | 
|  | is: 'gr-dashboard-view', | 
|  |  | 
|  | /** | 
|  | * Fired when the title of the page should change. | 
|  | * | 
|  | * @event title-change | 
|  | */ | 
|  |  | 
|  | properties: { | 
|  | account: { | 
|  | type: Object, | 
|  | value: null, | 
|  | }, | 
|  | preferences: Object, | 
|  | /** @type {{ selectedChangeIndex: number }} */ | 
|  | viewState: Object, | 
|  |  | 
|  | /** @type {{ project: string, user: string }} */ | 
|  | params: { | 
|  | type: Object, | 
|  | }, | 
|  |  | 
|  | createChangeTap: { | 
|  | type: Function, | 
|  | value() { | 
|  | return this._createChangeTap.bind(this); | 
|  | }, | 
|  | }, | 
|  |  | 
|  | _results: Array, | 
|  |  | 
|  | /** | 
|  | * For showing a "loading..." string during ajax requests. | 
|  | */ | 
|  | _loading: { | 
|  | type: Boolean, | 
|  | value: true, | 
|  | }, | 
|  |  | 
|  | _showDraftsBanner: { | 
|  | type: Boolean, | 
|  | value: false, | 
|  | }, | 
|  |  | 
|  | _showNewUserHelp: { | 
|  | type: Boolean, | 
|  | value: false, | 
|  | }, | 
|  | }, | 
|  |  | 
|  | observers: [ | 
|  | '_paramsChanged(params.*)', | 
|  | ], | 
|  |  | 
|  | behaviors: [ | 
|  | Gerrit.RESTClientBehavior, | 
|  | ], | 
|  |  | 
|  | get options() { | 
|  | return this.listChangesOptionsToHex( | 
|  | this.ListChangesOption.LABELS, | 
|  | this.ListChangesOption.DETAILED_ACCOUNTS, | 
|  | this.ListChangesOption.REVIEWED | 
|  | ); | 
|  | }, | 
|  |  | 
|  | 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 + suffix).replace( | 
|  | PROJECT_PLACEHOLDER_PATTERN, project), | 
|  | }; | 
|  | }), | 
|  | }; | 
|  | }); | 
|  | }, | 
|  |  | 
|  | _computeTitle(user) { | 
|  | if (!user || user === 'self') { | 
|  | return 'My Reviews'; | 
|  | } | 
|  | return 'Dashboard for ' + user; | 
|  | }, | 
|  |  | 
|  | _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. | 
|  | 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 {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 => { | 
|  | 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)); | 
|  | }); | 
|  | }, | 
|  |  | 
|  | _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(); | 
|  | }, | 
|  | }); | 
|  | })(); |