blob: 04b9bb591086e85272eca253bf4cc74ba41b9f54 [file] [log] [blame]
// 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';
// TODO(davido): Add the rest of the change actions.
var ChangeActions = {
ABANDON: 'abandon',
DELETE: '/',
RESTORE: 'restore',
};
// TODO(andybons): Add the rest of the revision actions.
var RevisionActions = {
CHERRYPICK: 'cherrypick',
DELETE: '/',
PUBLISH: 'publish',
REBASE: 'rebase',
SUBMIT: 'submit',
};
Polymer({
is: 'gr-change-actions',
/**
* Fired when the change should be reloaded.
*
* @event reload-change
*/
properties: {
actions: {
type: Object,
},
changeNum: String,
patchNum: String,
commitMessage: String,
_loading: {
type: Boolean,
value: true,
},
_revisionActions: Object,
},
behaviors: [
Gerrit.RESTClientBehavior,
],
observers: [
'_actionsChanged(actions, _revisionActions)',
],
reload: function() {
if (!this.changeNum || !this.patchNum) {
return Promise.resolve();
}
return this.$.actionsXHR.generateRequest().completes;
},
_actionsChanged: function(actions, revisionActions) {
this.hidden = actions.length == 0 && revisionActions.length == 0;
},
_computeRevisionActionsPath: function(changeNum, patchNum) {
return this.changeBaseURL(changeNum, patchNum) + '/actions';
},
_getValuesFor: function(obj) {
return Object.keys(obj).map(function(key) {
return obj[key];
});
},
_computeActionValues: function(actions, type) {
var result = [];
var values = this._getValuesFor(
type == 'change' ? ChangeActions : RevisionActions);
for (var a in actions) {
if (values.indexOf(a) == -1) { continue; }
actions[a].__key = a;
actions[a].__type = type;
result.push(actions[a]);
}
return result;
},
_computeLoadingLabel: function(action) {
return {
'cherrypick': 'Cherry-Picking...',
'rebase': 'Rebasing...',
'submit': 'Submitting...',
}[action];
},
_computePrimary: function(actionKey) {
return actionKey == 'submit';
},
_computeButtonClass: function(action) {
if ([RevisionActions.SUBMIT,
RevisionActions.PUBLISH].indexOf(action) != -1) {
return 'primary';
}
return '';
},
_handleActionTap: function(e) {
e.preventDefault();
var el = Polymer.dom(e).rootTarget;
var key = el.getAttribute('data-action-key');
var type = el.getAttribute('data-action-type');
if (type == 'revision') {
if (key == RevisionActions.REBASE) {
this._showActionDialog(this.$.confirmRebase);
return;
} else if (key == RevisionActions.CHERRYPICK) {
this._showActionDialog(this.$.confirmCherrypick);
return;
}
this._fireRevisionAction(this._prependSlash(key),
this._revisionActions[key]);
} else {
this._fireChangeAction(this._prependSlash(key), this.actions[key]);
}
},
_prependSlash: function(key) {
return key == '/' ? key : '/' + key;
},
_handleConfirmDialogCancel: function() {
var dialogEls =
Polymer.dom(this.root).querySelectorAll('.confirmDialog');
for (var i = 0; i < dialogEls.length; i++) {
dialogEls[i].hidden = true;
}
this.$.overlay.close();
},
_handleRebaseConfirm: function() {
var payload = {};
var el = this.$.confirmRebase;
if (el.clearParent) {
// There is a subtle but important difference between setting the base
// to an empty string and omitting it entirely from the payload. An
// empty string implies that the parent should be cleared and the
// change should be rebased on top of the target branch. Leaving out
// the base implies that it should be rebased on top of its current
// parent.
payload.base = '';
} else if (el.base && el.base.length > 0) {
payload.base = el.base;
}
this.$.overlay.close();
el.hidden = false;
this._fireRevisionAction('/rebase', this._revisionActions.rebase,
payload);
},
_handleCherrypickConfirm: function() {
var el = this.$.confirmCherrypick;
if (!el.branch) {
// TODO(davido): Fix error handling
alert('The destination branch can’t be empty.');
return;
}
if (!el.message) {
alert('The commit message can’t be empty.');
return;
}
this.$.overlay.close();
el.hidden = false;
this._fireRevisionAction('/cherrypick',
this._revisionActions.cherrypick,
{
destination: el.branch,
message: el.message,
}
);
},
_fireChangeAction: function(endpoint, action) {
this._send(action.method, {}, endpoint).then(
function() {
// We can’t reload a change that was deleted.
if (endpoint == ChangeActions.DELETE) {
page.show('/');
} else {
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;
});
},
_fireRevisionAction: function(endpoint, action, opt_payload) {
var buttonEl = this.$$('[data-action-key="' + action.__key + '"]');
buttonEl.setAttribute('loading', true);
buttonEl.disabled = true;
function enableButton() {
buttonEl.removeAttribute('loading');
buttonEl.disabled = false;
}
this._send(action.method, opt_payload, endpoint, true).then(
function(req) {
if (action.__key == RevisionActions.CHERRYPICK) {
page.show(this.changePath(req.response._number));
} else {
this.fire('reload-change', null, {bubbles: false});
}
enableButton();
}.bind(this)).catch(function(err) {
// TODO(andybons): Handle merge conflict (409 status);
alert('Oops. Something went wrong. Check the console and bug the ' +
'PolyGerrit team for assistance.');
enableButton();
throw err;
});
},
_showActionDialog: function(dialog) {
dialog.hidden = false;
this.$.overlay.open();
},
_send: function(method, payload, actionEndpoint, revisionAction) {
var xhr = document.createElement('gr-request');
this._xhrPromise = xhr.send({
method: method,
url: this.changeBaseURL(this.changeNum,
revisionAction ? this.patchNum : null) + actionEndpoint,
body: payload,
});
return this._xhrPromise;
},
});
})();