From fc96e3e4daa56f22d4da048e596eb4755a4ac58a Mon Sep 17 00:00:00 2001 From: Dhruv Srivastava Date: Tue, 5 Jan 2021 17:08:10 +0100 Subject: [PATCH] Allow users to select which changes to cherry pick When cherry pickinging an entire topic to another branch, there are abandoned/unwanted changes with the same topic name. Allow users to select which changes to cherry pick by showing a checkbox next to each change. Also show the status of each change(Abandoned, Merged, New) to help users select which change to select/remove. Change-Id: I453bf77aa9a6c4ff7c0568c70dad1ee7ba78bc3b --- .../gr-change-actions_test.js | 10 +++--- .../gr-confirm-cherrypick-dialog.ts | 30 ++++++++++++++-- .../gr-confirm-cherrypick-dialog_html.ts | 13 ++++++- .../gr-confirm-cherrypick-dialog_test.js | 35 +++++++++++++++++++ 4 files changed, 80 insertions(+), 8 deletions(-) diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js index da214d947d..0279b7e6a6 100644 --- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js +++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js @@ -742,11 +742,11 @@ suite('gr-change-actions tests', () => { const changes = [ { change_id: '12345678901234', topic: 'T', subject: 'random', - project: 'A', + project: 'A', status: 'MERGED', }, { change_id: '23456', topic: 'T', subject: 'a'.repeat(100), - project: 'B', + project: 'B', status: 'NEW', }, ]; setup(done => { @@ -769,8 +769,8 @@ suite('gr-change-actions tests', () => { flush(() => { const changesTable = dialog.shadowRoot.querySelector('table'); const headers = Array.from(changesTable.querySelectorAll('th')); - const expectedHeadings = ['Change', 'Subject', 'Project', - 'Status', '']; + const expectedHeadings = ['', 'Change', 'Status', 'Subject', + 'Project', 'Progress', '']; const headings = headers.map(header => header.innerText); assert.equal(headings.length, expectedHeadings.length); for (let i = 0; i < headings.length; i++) { @@ -779,7 +779,7 @@ suite('gr-change-actions tests', () => { const changeRows = changesTable.querySelectorAll('tbody > tr'); const change = Array.from(changeRows[0].querySelectorAll('td')) .map(e => e.innerText); - const expectedChange = ['1234567890', 'random', 'A', + const expectedChange = ['', '1234567890', 'MERGED', 'random', 'A', 'NOT STARTED', '']; for (let i = 0; i < change.length; i++) { assert.equal(change[i].trim(), expectedChange[i]); diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts index 6af3be3e83..1195ea65b1 100644 --- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts +++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts @@ -31,6 +31,7 @@ import { RepoName, BranchName, CommitId, + ChangeInfoId, } from '../../../types/common'; import {ReportingService} from '../../../services/gr-reporting/gr-reporting'; import {customElement, property, observe} from '@polymer/decorators'; @@ -40,6 +41,7 @@ import { } from '../../shared/gr-autocomplete/gr-autocomplete'; import {HttpMethod, ChangeStatus} from '../../../constants/constants'; import {hasOwnProperty} from '../../../utils/common-util'; +import {dom, EventApi} from '@polymer/polymer/lib/legacy/polymer.dom'; const SUGGESTIONS_LIMIT = 15; const CHANGE_SUBJECT_LIMIT = 50; @@ -146,6 +148,8 @@ export class GrConfirmCherrypickDialog extends GestureEventListeners( @property({type: Object}) reporting: ReportingService; + private selectedChangeIds = new Set(); + private restApiService = appContext.restApiService; constructor() { @@ -161,6 +165,7 @@ export class GrConfirmCherrypickDialog extends GestureEventListeners( const projects: {[projectName: string]: boolean} = {}; this._duplicateProjectChanges = false; changes.forEach(change => { + this.selectedChangeIds.add(change.id); if (projects[change.project]) { this._duplicateProjectChanges = true; } @@ -178,6 +183,19 @@ export class GrConfirmCherrypickDialog extends GestureEventListeners( ); } + _isChangeSelected(changeId: ChangeInfoId) { + return this.selectedChangeIds.has(changeId); + } + + _toggleChangeSelected(e: Event) { + const changeId = ((dom(e) as EventApi).localTarget as HTMLElement).dataset[ + 'item' + ]! as ChangeInfoId; + if (this.selectedChangeIds.has(changeId)) + this.selectedChangeIds.delete(changeId); + else this.selectedChangeIds.add(changeId); + } + _computeTopicErrorMessage(duplicateProjectChanges: boolean) { if (duplicateProjectChanges) { return 'Two changes cannot be of the same project'; @@ -293,8 +311,16 @@ export class GrConfirmCherrypickDialog extends GestureEventListeners( } _handleCherryPickTopic() { - const topic = this._generateRandomCherryPickTopic(this.changes[0]); - this.changes.forEach(change => { + const changes = this.changes.filter(change => + this.selectedChangeIds.has(change.id) + ); + if (!changes.length) { + const errorSpan = this.shadowRoot?.querySelector('.error-message'); + errorSpan!.innerHTML = 'No change selected'; + return; + } + const topic = this._generateRandomCherryPickTopic(changes[0]); + changes.forEach(change => { this.updateStatus(change, {status: ProgressStatus.RUNNING}); const payload = { destination: this.branch, diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_html.ts b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_html.ts index f784425428..16262c60fd 100644 --- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_html.ts +++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_html.ts @@ -179,10 +179,12 @@ export const htmlTemplate = html` + + - + @@ -190,7 +192,16 @@ export const htmlTemplate = html`
ChangeStatus Subject ProjectStatusProgress