PolyGerrit: Add support for moving changes from one branch to another

Bug: Issue 6844
Change-Id: Id9479af9ef81146bdfa9e90671b657d5677dc160
This commit is contained in:
Paladox none 2017-07-25 21:39:13 +00:00
parent c2eb913996
commit 45a857cab0
7 changed files with 317 additions and 0 deletions

View File

@ -29,6 +29,7 @@ limitations under the License.
<link rel="import" href="../gr-confirm-abandon-dialog/gr-confirm-abandon-dialog.html">
<link rel="import" href="../gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.html">
<link rel="import" href="../gr-confirm-move-dialog/gr-confirm-move-dialog.html">
<link rel="import" href="../gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.html">
<link rel="import" href="../gr-confirm-revert-dialog/gr-confirm-revert-dialog.html">
<link rel="import" href="../../../styles/shared-styles.html">
@ -124,6 +125,12 @@ limitations under the License.
on-cancel="_handleConfirmDialogCancel"
project="[[change.project]]"
hidden></gr-confirm-cherrypick-dialog>
<gr-confirm-move-dialog id="confirmMove"
class="confirmDialog"
on-confirm="_handleMoveConfirm"
on-cancel="_handleConfirmDialogCancel"
project="[[change.project]]"
hidden></gr-confirm-move-dialog>
<gr-confirm-revert-dialog id="confirmRevertDialog"
class="confirmDialog"
on-confirm="_handleRevertDialogConfirm"

View File

@ -51,6 +51,7 @@
ABANDON: 'abandon',
DELETE: '/',
IGNORE: 'ignore',
MOVE: 'move',
MUTE: 'mute',
PRIVATE: 'private',
PRIVATE_DELETE: 'private.delete',
@ -75,6 +76,7 @@
abandon: 'Abandoning...',
cherrypick: 'Cherry-Picking...',
delete: 'Deleting...',
move: 'Moving..',
publish: 'Publishing...',
rebase: 'Rebasing...',
restore: 'Restoring...',
@ -216,6 +218,10 @@
type: ActionType.REVISION,
key: RevisionActions.CHERRYPICK,
},
{
type: ActionType.CHANGE,
key: ChangeActions.MOVE,
},
{
type: ActionType.REVISION,
key: RevisionActions.DOWNLOAD,
@ -624,6 +630,9 @@
case ChangeActions.WIP:
this._handleWipTap();
break;
case ChangeActions.MOVE:
this._handleMoveTap();
break;
default:
this._fireAction(this._prependSlash(key), this.actions[key], false);
}
@ -717,6 +726,25 @@
);
},
_handleMoveConfirm() {
const el = this.$.confirmMove;
if (!el.branch) {
this.fire('show-alert', {message: ERR_BRANCH_EMPTY});
return;
}
this.$.overlay.close();
el.hidden = true;
this._fireAction(
'/move',
this.actions.move,
false,
{
destination_branch: el.branch,
message: el.message,
}
);
},
_handleRevertDialogConfirm() {
const el = this.$.confirmRevertDialog;
this.$.overlay.close();
@ -870,6 +898,12 @@
this._showActionDialog(this.$.confirmCherrypick);
},
_handleMoveTap() {
this.$.confirmMove.branch = '';
this.$.confirmMove.message = '';
this._showActionDialog(this.$.confirmMove);
},
_handleDownloadTap() {
this.fire('download-tap', null, {bubbles: false});
},

View File

@ -398,6 +398,34 @@ limitations under the License.
});
});
suite('move change', () => {
let fireActionStub;
setup(() => {
fireActionStub = sandbox.stub(element, '_fireAction');
sandbox.stub(window, 'alert');
});
test('works', () => {
element._handleMoveTap();
element._handleMoveConfirm();
assert.equal(fireActionStub.callCount, 0);
element.$.confirmMove.branch = 'master';
element._handleMoveConfirm();
assert.equal(fireActionStub.callCount, 1);
});
test('branch name cleared when re-open move', () => {
const emptyBranchName = '';
element.$.confirmMove.branch = 'master';
element._handleMoveTap();
assert.equal(element.$.confirmMove.branch, emptyBranchName);
});
});
test('custom actions', done => {
// Add a button with the same key as a server-based one to ensure
// collisions are taken care of.

View File

@ -0,0 +1,87 @@
<!--
Copyright (C) 2017 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.
-->
<link rel="import" href="../../../bower_components/iron-autogrow-textarea/iron-autogrow-textarea.html">
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../../styles/shared-styles.html">
<link rel="import" href="../../shared/gr-autocomplete/gr-autocomplete.html">
<link rel="import" href="../../shared/gr-confirm-dialog/gr-confirm-dialog.html">
<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
<dom-module id="gr-confirm-move-dialog">
<template>
<style include="shared-styles">
:host {
display: block;
width: 30em;
}
:host([disabled]) {
opacity: .5;
pointer-events: none;
}
label {
cursor: pointer;
}
iron-autogrow-textarea {
padding: 0;
}
.main {
display: flex;
flex-direction: column;
width: 100%;
}
.main label,
.main input[type="text"] {
display: block;
font: inherit;
width: 100%;
}
.main .message {
border: groove;
width: 100%;
}
</style>
<gr-confirm-dialog
confirm-label="Move Change"
on-confirm="_handleConfirmTap"
on-cancel="_handleCancelTap">
<div class="header">Move Change to Another Branch</div>
<div class="main">
<label for="branchInput">
Move change to branch
</label>
<gr-autocomplete
id="branchInput"
text="{{branch}}"
query="[[_query]]"
placeholder="Destination branch">
</gr-autocomplete>
<label for="messageInput">
Move Change Commit Message
</label>
<iron-autogrow-textarea
id="messageInput"
class="message"
autocomplete="on"
rows="4"
max-rows="15"
bind-value="{{message}}"></iron-autogrow-textarea>
</div>
</gr-confirm-dialog>
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
</template>
<script src="gr-confirm-move-dialog.js"></script>
</dom-module>

View File

@ -0,0 +1,79 @@
// Copyright (C) 2017 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 SUGGESTIONS_LIMIT = 15;
Polymer({
is: 'gr-confirm-move-dialog',
/**
* Fired when the confirm button is pressed.
*
* @event confirm
*/
/**
* Fired when the cancel button is pressed.
*
* @event cancel
*/
properties: {
branch: String,
message: String,
project: String,
_query: {
type: Function,
value() {
return this._getProjectBranchesSuggestions.bind(this);
},
},
},
_handleConfirmTap(e) {
e.preventDefault();
this.fire('confirm', null, {bubbles: false});
},
_handleCancelTap(e) {
e.preventDefault();
this.fire('cancel', null, {bubbles: false});
},
_getProjectBranchesSuggestions(input) {
if (input.startsWith('refs/heads/')) {
input = input.substring('refs/heads/'.length);
}
return this.$.restAPI.getProjectBranches(
input, this.project, SUGGESTIONS_LIMIT).then(response => {
const branches = [];
let branch;
for (const key in response) {
if (!response.hasOwnProperty(key)) { continue; }
if (response[key].ref.startsWith('refs/heads/')) {
branch = response[key].ref.substring('refs/heads/'.length);
} else {
branch = response[key].ref;
}
branches.push({
name: branch,
});
}
return branches;
});
},
});
})();

View File

@ -0,0 +1,81 @@
<!DOCTYPE html>
<!--
Copyright (C) 2017 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.
-->
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>gr-confirm-move-dialog</title>
<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
<script src="../../../bower_components/web-component-tester/browser.js"></script>
<link rel="import" href="../../../test/common-test-setup.html"/>
<link rel="import" href="gr-confirm-move-dialog.html">
<script>void(0);</script>
<test-fixture id="basic">
<template>
<gr-confirm-move-dialog></gr-confirm-move-dialog>
</template>
</test-fixture>
<script>
suite('gr-confirm-move-dialog tests', () => {
let element;
setup(() => {
stub('gr-rest-api-interface', {
getProjectBranches(input) {
if (input.startsWith('test')) {
return Promise.resolve([
{
ref: 'refs/heads/test-branch',
revision: '67ebf73496383c6777035e374d2d664009e2aa5c',
can_delete: true,
},
]);
} else {
return Promise.resolve({});
}
},
});
element = fixture('basic');
element.project = 'test-project';
});
test('with updated commit message', () => {
element.branch = 'master';
const myNewMessage = 'updated commit message';
element.message = myNewMessage;
flushAsynchronousOperations();
assert.equal(element.message, myNewMessage);
});
test('_getProjectBranchesSuggestions empty', done => {
element._getProjectBranchesSuggestions('nonexistent').then(branches => {
assert.equal(branches.length, 0);
done();
});
});
test('_getProjectBranchesSuggestions non-empty', done => {
element._getProjectBranchesSuggestions('test-branch').then(branches => {
assert.equal(branches.length, 1);
assert.equal(branches[0].name, 'test-branch');
done();
});
});
});
</script>

View File

@ -51,6 +51,7 @@ limitations under the License.
'change/gr-comment-list/gr-comment-list_test.html',
'change/gr-commit-info/gr-commit-info_test.html',
'change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.html',
'change/gr-confirm-move-dialog/gr-confirm-move-dialog_test.html',
'change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.html',
'change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.html',
'change/gr-download-dialog/gr-download-dialog_test.html',