Add submit button to PolyGerrit

+ Lays the groundwork for other actions as well.
+ Another change seemingly unrelated is within gr-reply-dropdown,
  which is in here because when a change is submitted, the
  permittedLabels property on the change goes to {}, which needs
  to be accounted for.

Change-Id: I14c4c62ad7e52df6d56894abb38b708d81964d1b
This commit is contained in:
Andrew Bonventre 2016-01-07 16:38:37 -05:00 committed by Dave Borowitz
parent b3caf48ffa
commit 8f46e03cac
5 changed files with 273 additions and 4 deletions

View File

@ -0,0 +1,138 @@
<!--
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.
-->
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="gr-ajax.html">
<link rel="import" href="gr-request.html">
<dom-module id="gr-change-actions">
<template>
<style>
:host {
display: block;
}
button {
background-color: #448aff;
border: none;
border-radius: 2px;
color: #fff;
cursor: pointer;
font: inherit;
padding: .5em .75em;
}
button[disabled] {
opacity: .5;
}
</style>
<gr-ajax id="actionsXHR"
url="[[_computeActionsPath(changeNum, patchNum)]]"
last-response="{{_actions}}"
loading="{{_loading}}"></gr-ajax>
<div>
<template is="dom-repeat" items="[[_computeActionValues(_actions)]]" as="action">
<button title$="[[action.title]]"
hidden$="[[!action.enabled]]"
data-action-key$="[[action.__key]]"
disabled$="[[_loading]]"
on-tap="_handleActionTap">[[action.label]]</button>
</template>
</div>
</template>
<script>
(function() {
'use strict';
Polymer({
is: 'gr-change-actions',
/**
* Fired when the change should be reloaded.
*
* @event reload-change
*/
properties: {
changeNum: String,
patchNum: String,
_actions: {
type: Object,
observer: '_actionsChanged',
},
_loading: {
type: Boolean,
value: false,
},
},
reload: function() {
if (!!this.changeNum && !!this.patchNum) {
this.$.actionsXHR.generateRequest();
}
},
_actionsChanged: function(actions) {
this.hidden = actions.submit == null;
},
_computeActionsPath: function(changeNum, patchNum) {
return Changes.baseURL(changeNum, patchNum) + '/actions';
},
_computeActionValues: function(actions) {
var result = [];
for (var a in actions) {
// TODO(andybons): Add the rest of the actions.
if (a != 'submit') { continue; }
actions[a].__key = a;
result.push(actions[a]);
}
return result;
},
_handleActionTap: function(e) {
e.preventDefault();
var el = Polymer.dom(e).rootTarget;
var key = el.getAttribute('data-action-key');
if (key == 'submit') {
this._submitChange('/' + key, this._actions[key]);
}
},
_submitChange: function(endpoint, action) {
this._send(action.method, {}, endpoint).then(
function() {
this.fire('reload-change', null, {bubbles: false});
}.bind(this)).catch(function(err) {
alert('Oops. Something went wrong. Check the console and bug the ' +
'PolyGerrit team for assistance.');
throw err;
});
},
_send: function(method, payload, actionEndpoint) {
var xhr = document.createElement('gr-request');
this._xhrPromise = xhr.send({
method: method,
url: Changes.baseURL(this.changeNum, this.patchNum) + actionEndpoint,
body: payload,
});
return this._xhrPromise;
},
});
})();
</script>
</dom-module>

View File

@ -17,6 +17,7 @@ limitations under the License.
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
<link rel="import" href="gr-ajax.html">
<link rel="import" href="gr-change-actions.html">
<link rel="import" href="gr-date-formatter.html">
<link rel="import" href="gr-file-list.html">
<link rel="import" href="gr-linked-text.html">
@ -112,6 +113,9 @@ limitations under the License.
.notApproved {
background-color: #ffd4d4;
}
gr-change-actions {
margin-top: 1em;
}
.summary {
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
@ -229,6 +233,10 @@ limitations under the License.
</tr>
</template>
</table>
<gr-change-actions id="actions"
change-num="[[_changeNum]]"
patch-num="[[_patchNum]]"
on-reload-change="_reload"></gr-change-actions>
</section>
<section class="summary">
<gr-linked-text pre
@ -457,16 +465,17 @@ limitations under the License.
_reload: function() {
var detailCompletes = this.$.detailXHR.generateRequest().completes;
this.$.commentsXHR.generateRequest();
var reloadCommitInfoAndFileList = function() {
var reloadPatchNumDependentResources = function() {
this.$.commitInfoXHR.generateRequest();
this.$.actions.reload();
this.$.fileList.reload();
}.bind(this);
if (this._patchNum) {
reloadCommitInfoAndFileList();
reloadPatchNumDependentResources();
} else {
// The patch number is reliant on the change detail request.
detailCompletes.then(reloadCommitInfoAndFileList);
detailCompletes.then(reloadPatchNumDependentResources);
}
},

View File

@ -249,7 +249,9 @@ limitations under the License.
}
}
for (var i = 0; i < permittedLabels[labelName].length; i++) {
var len = permittedLabels[labelName] != null ?
permittedLabels[labelName].length : 0;
for (var i = 0; i < len; i++) {
var val = parseInt(permittedLabels[labelName][i], 10);
if (val == labelValue) {
return i;

View File

@ -0,0 +1,119 @@
<!DOCTYPE html>
<!--
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.
-->
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>gr-change-actions</title>
<script src="../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
<script src="../../bower_components/web-component-tester/browser.js"></script>
<script src="../scripts/changes.js"></script>
<script src="../scripts/util.js"></script>
<link rel="import" href="../../bower_components/iron-test-helpers/iron-test-helpers.html">
<link rel="import" href="../elements/gr-change-actions.html">
<test-fixture id="basic">
<template>
<gr-change-actions></gr-change-actions>
</template>
</test-fixture>
<script>
suite('gr-change-actions tests', function() {
var element;
var server;
setup(function() {
element = fixture('basic');
server = sinon.fakeServer.create();
server.respondWith(
'GET',
'/changes/42/revisions/2/actions',
[
200,
{ 'Content-Type': 'application/json' },
')]}\'\n' +
JSON.stringify({
cherrypick: {
method: 'POST',
label: 'Cherry Pick',
title: 'Cherry pick change to a different branch',
enabled: true
},
rebase: {
method: 'POST',
label: 'Rebase',
title: 'Rebase onto tip of branch or parent change'
},
submit: {
method: 'POST',
label: 'Submit',
title: 'Submit patch set 1 into master',
enabled: true
}
}),
]
);
server.respondWith(
'POST',
'/changes/42/revisions/2/submit',
[
200,
{ 'Content-Type': 'application/json' },
')]}\'\n{}', // The response is not used by the element.
]
);
});
test('submit button shows', function(done) {
element.changeNum = '42';
element.patchNum = '2';
element.reload();
server.respond();
element.async(function() {
var buttonEls = Polymer.dom(element.root).querySelectorAll('button');
assert.equal(buttonEls.length, 1);
assert.isFalse(element.hidden);
done();
}, 1);
});
test('submit change', function(done) {
element.changeNum = '42';
element.patchNum = '2';
element.reload();
server.respond();
element.async(function() {
var submitButton = element.$$('button[data-action-key="submit"]');
assert.ok(submitButton);
MockInteractions.tap(submitButton);
server.respond();
// Upon success it should fire the reload-change event.
element.addEventListener('reload-change', function(e) {
done();
});
}, 1);
});
});
</script>

View File

@ -24,6 +24,7 @@ limitations under the License.
var testFiles = [];
[ 'gr-account-dropdown-test.html',
'gr-change-actions-test.html',
'gr-change-list-item-test.html',
'gr-change-list-test.html',
'gr-change-view-test.html',