| /** |
| * @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. |
| */ |
| import '../../../styles/shared-styles'; |
| import '../../shared/gr-download-commands/gr-download-commands'; |
| import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners'; |
| import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin'; |
| import {PolymerElement} from '@polymer/polymer/polymer-element'; |
| import {htmlTemplate} from './gr-download-dialog_html'; |
| import {patchNumEquals} from '../../../utils/patch-set-util'; |
| import {changeBaseURL} from '../../../utils/change-util'; |
| import {customElement, property, computed, observe} from '@polymer/decorators'; |
| import {ChangeInfo, ServerInfo, PatchSetNum} from '../../../types/common'; |
| import {RevisionInfo} from '../../shared/revision-info/revision-info'; |
| import {GrDownloadCommands} from '../../shared/gr-download-commands/gr-download-commands'; |
| import {GrButton} from '../../shared/gr-button/gr-button'; |
| import {hasOwnProperty} from '../../../utils/common-util'; |
| import {GrOverlayStops} from '../../shared/gr-overlay/gr-overlay'; |
| |
| export interface GrDownloadDialog { |
| $: { |
| download: HTMLAnchorElement; |
| downloadCommands: GrDownloadCommands; |
| closeButton: GrButton; |
| }; |
| } |
| |
| @customElement('gr-download-dialog') |
| export class GrDownloadDialog extends GestureEventListeners( |
| LegacyElementMixin(PolymerElement) |
| ) { |
| static get template() { |
| return htmlTemplate; |
| } |
| |
| /** |
| * Fired when the user presses the close button. |
| * |
| * @event close |
| */ |
| |
| @property({type: Object}) |
| change: ChangeInfo | undefined; |
| |
| @property({type: Object}) |
| config?: ServerInfo; |
| |
| @property({type: String}) |
| patchNum: PatchSetNum | undefined; |
| |
| @property({type: String}) |
| _selectedScheme?: string; |
| |
| @computed('change', 'patchNum') |
| get _schemes() { |
| // Polymer 2: check for undefined |
| if (this.change === undefined || this.patchNum === undefined) { |
| return []; |
| } |
| |
| for (const rev of Object.values(this.change.revisions || {})) { |
| if (patchNumEquals(rev._number, this.patchNum)) { |
| const fetch = rev.fetch; |
| if (fetch) { |
| return Object.keys(fetch).sort(); |
| } |
| break; |
| } |
| } |
| return []; |
| } |
| |
| /** @override */ |
| ready() { |
| super.ready(); |
| this._ensureAttribute('role', 'dialog'); |
| } |
| |
| focus() { |
| if (this._schemes.length) { |
| this.$.downloadCommands.focusOnCopy(); |
| } else { |
| this.$.download.focus(); |
| } |
| } |
| |
| getFocusStops(): GrOverlayStops { |
| return { |
| start: this.$.downloadCommands.$.downloadTabs, |
| end: this.$.closeButton, |
| }; |
| } |
| |
| _computeDownloadCommands( |
| change?: ChangeInfo, |
| patchNum?: PatchSetNum, |
| selectedScheme?: string |
| ) { |
| let commandObj; |
| if (!change || !selectedScheme) return []; |
| for (const rev of Object.values(change.revisions || {})) { |
| if ( |
| patchNumEquals(rev._number, patchNum) && |
| rev && |
| rev.fetch && |
| hasOwnProperty(rev.fetch, selectedScheme) |
| ) { |
| commandObj = rev.fetch[selectedScheme].commands; |
| break; |
| } |
| } |
| const commands = []; |
| for (const title in commandObj) { |
| if (!commandObj || !hasOwnProperty(commandObj, title)) { |
| continue; |
| } |
| commands.push({ |
| title, |
| command: commandObj[title], |
| }); |
| } |
| return commands; |
| } |
| |
| _computeZipDownloadLink(change?: ChangeInfo, patchNum?: PatchSetNum) { |
| return this._computeDownloadLink(change, patchNum, true); |
| } |
| |
| _computeZipDownloadFilename(change?: ChangeInfo, patchNum?: PatchSetNum) { |
| return this._computeDownloadFilename(change, patchNum, true); |
| } |
| |
| _computeDownloadLink( |
| change?: ChangeInfo, |
| patchNum?: PatchSetNum, |
| zip?: boolean |
| ) { |
| // Polymer 2: check for undefined |
| if (change === undefined || patchNum === undefined) { |
| return ''; |
| } |
| return ( |
| changeBaseURL(change.project, change._number, patchNum) + |
| '/patch?' + |
| (zip ? 'zip' : 'download') |
| ); |
| } |
| |
| _computeDownloadFilename( |
| change?: ChangeInfo, |
| patchNum?: PatchSetNum, |
| zip?: boolean |
| ) { |
| // Polymer 2: check for undefined |
| if (change === undefined || patchNum === undefined) { |
| return ''; |
| } |
| |
| let shortRev = ''; |
| for (const rev in change.revisions) { |
| if (patchNumEquals(change.revisions[rev]._number, patchNum)) { |
| shortRev = rev.substr(0, 7); |
| break; |
| } |
| } |
| return shortRev + '.diff.' + (zip ? 'zip' : 'base64'); |
| } |
| |
| _computeHidePatchFile(change?: ChangeInfo, patchNum?: PatchSetNum) { |
| // Polymer 2: check for undefined |
| if (change === undefined || patchNum === undefined) { |
| return false; |
| } |
| for (const rev of Object.values(change.revisions || {})) { |
| if (patchNumEquals(rev._number, patchNum)) { |
| const parentLength = |
| rev.commit && rev.commit.parents ? rev.commit.parents.length : 0; |
| return parentLength === 0; |
| } |
| } |
| return false; |
| } |
| |
| _computeArchiveDownloadLink( |
| change?: ChangeInfo, |
| patchNum?: PatchSetNum, |
| format?: string |
| ) { |
| // Polymer 2: check for undefined |
| if ( |
| change === undefined || |
| patchNum === undefined || |
| format === undefined |
| ) { |
| return ''; |
| } |
| return ( |
| changeBaseURL(change.project, change._number, patchNum) + |
| '/archive?format=' + |
| format |
| ); |
| } |
| |
| _computePatchSetQuantity(revisions?: {[revisionId: string]: RevisionInfo}) { |
| if (!revisions) { |
| return 0; |
| } |
| return Object.keys(revisions).length; |
| } |
| |
| _handleCloseTap(e: Event) { |
| e.preventDefault(); |
| e.stopPropagation(); |
| this.dispatchEvent( |
| new CustomEvent('close', { |
| composed: true, |
| bubbles: false, |
| }) |
| ); |
| } |
| |
| @observe('_schemes') |
| _schemesChanged(schemes: string[]) { |
| if (schemes.length === 0) { |
| return; |
| } |
| if (!this._selectedScheme || !schemes.includes(this._selectedScheme)) { |
| this._selectedScheme = schemes.sort()[0]; |
| } |
| } |
| |
| _computeShowDownloadCommands(schemes: string[]) { |
| return schemes.length ? '' : 'hidden'; |
| } |
| } |
| |
| declare global { |
| interface HTMLElementTagNameMap { |
| 'gr-download-dialog': GrDownloadDialog; |
| } |
| } |