Files
gerrit/polygerrit-ui/app/elements/gr-related-changes-list.html
Andrew Bonventre 3b29d800e8 Style tweaks on change view
+ Add bottom border on the header.
+ Fix issue with the first related change section having a top margin
  which would cause it to be misaligned with the other columns.
+ Clean up CSS a bit around the columns by adding a changeInfo-column
  class.

Change-Id: I0fd76647c58b57126ca45c3404f3910e76918aa6
2016-02-11 11:05:38 -05:00

364 lines
11 KiB
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.
-->
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../behaviors/rest-client-behavior.html">
<link rel="import" href="gr-ajax.html">
<dom-module id="gr-related-changes-list">
<template>
<style>
:host {
display: block;
}
h3 {
margin: .5em 0 0;
}
section {
margin-bottom: 1em;
}
a {
display: block;
}
.relatedChanges a {
display: inline-block;
}
.strikethrough {
color: #666;
text-decoration: line-through;
}
.status {
color: #666;
font-weight: bold;
}
.notCurrent {
color: #e65100;
}
.indirectAncestor {
color: #33691e;
}
.submittable {
color: #1b5e20;
}
.hidden {
display: none;
}
</style>
<gr-ajax id="relatedXHR"
url="[[_computeRelatedURL(change._number, patchNum)]]"
last-response="{{_relatedResponse}}"></gr-ajax>
<gr-ajax id="submittedTogetherXHR"
url="[[_computeSubmittedTogetherURL(change._number)]]"
last-response="{{_submittedTogether}}"></gr-ajax>
<gr-ajax id="conflictsXHR"
url="/changes/"
params="[[_computeConflictsQueryParams(change._number)]]"
last-response="{{_conflicts}}"></gr-ajax>
<gr-ajax id="cherryPicksXHR"
url="/changes/"
params="[[_computeCherryPicksQueryParams(change.project, change.change_id, change._number)]]"
last-response="{{_cherryPicks}}"></gr-ajax>
<gr-ajax id="sameTopicXHR"
url="/changes/"
params="[[_computeSameTopicQueryParams(change.topic)]]"
last-response="{{_sameTopic}}"></gr-ajax>
<div hidden$="[[!_loading]]">Loading...</div>
<section class="relatedChanges" hidden$="[[!_relatedResponse.changes.length]]" hidden>
<h4>Relation Chain</h4>
<template is="dom-repeat" items="[[_relatedResponse.changes]]" as="change">
<div>
<a href$="[[_computeChangeURL(change._change_number, change._revision_number)]]"
class$="[[_computeLinkClass(change)]]">
[[change.commit.subject]]
</a>
<span class$="[[_computeChangeStatusClass(change)]]">
([[_computeChangeStatus(change)]])
</span>
</div>
</template>
</section>
<section hidden$="[[!_submittedTogether.length]]" hidden>
<h4>Submitted together</h4>
<template is="dom-repeat" items="[[_submittedTogether]]" as="change">
<a href$="[[_computeChangeURL(change._number)]]"
class$="[[_computeLinkClass(change)]]">
[[change.project]]: [[change.branch]]: [[change.subject]]
</a>
</template>
</section>
<section hidden$="[[!_sameTopic.length]]" hidden>
<h4>Same topic</h4>
<template is="dom-repeat" items="[[_sameTopic]]" as="change">
<a href$="[[_computeChangeURL(change._number)]]"
class$="[[_computeLinkClass(change)]]">
[[change.project]]: [[change.branch]]: [[change.subject]]
</a>
</template>
</section>
<section hidden$="[[!_conflicts.length]]" hidden>
<h4>Merge conflicts</h4>
<template is="dom-repeat" items="[[_conflicts]]" as="change">
<a href$="[[_computeChangeURL(change._number)]]"
class$="[[_computeLinkClass(change)]]">
[[change.subject]]
</a>
</template>
</section>
<section hidden$="[[!_cherryPicks.length]]" hidden>
<h4>Cherry picks</h4>
<template is="dom-repeat" items="[[_cherryPicks]]" as="change">
<a href$="[[_computeChangeURL(change._number)]]"
class$="[[_computeLinkClass(change)]]">
[[change.subject]]
</a>
</template>
</section>
</template>
<script>
(function() {
'use strict';
Polymer({
is: 'gr-related-changes-list',
properties: {
change: Object,
patchNum: String,
serverConfig: {
type: Object,
observer: '_serverConfigChanged',
},
hidden: {
type: Boolean,
value: false,
reflectToAttribute: true,
},
_loading: Boolean,
_resolveServerConfigReady: Function,
_serverConfigReady: {
type: Object,
value: function() {
return new Promise(function(resolve) {
this._resolveServerConfigReady = resolve;
}.bind(this));
}
},
_connectedRevisions: {
type: Array,
computed: '_computeConnectedRevisions(change, patchNum, ' +
'_relatedResponse.changes)',
},
_relatedResponse: Object,
_submittedTogether: Array,
_conflicts: Array,
_cherryPicks: Array,
_sameTopic: Array,
},
behaviors: [
Gerrit.RESTClientBehavior,
],
observers: [
'_resultsChanged(_relatedResponse.changes, _submittedTogether, ' +
'_conflicts, _cherryPicks, _sameTopic)',
],
reload: function() {
if (!this.change || !this.patchNum) {
return Promise.resolve();
}
this._loading = true;
var promises = [
this.$.relatedXHR.generateRequest().completes,
this.$.submittedTogetherXHR.generateRequest().completes,
this.$.conflictsXHR.generateRequest().completes,
this.$.cherryPicksXHR.generateRequest().completes,
];
return this._serverConfigReady.then(function() {
if (this.change.topic &&
!this.serverConfig.change.submit_whole_topic) {
return this.$.sameTopicXHR.generateRequest().completes;
} else {
this._sameTopic = [];
}
return Promise.resolve();
}.bind(this)).then(Promise.all(promises)).then(function() {
this._loading = false;
}.bind(this));
},
_computeRelatedURL: function(changeNum, patchNum) {
return this.changeBaseURL(changeNum, patchNum) + '/related';
},
_computeSubmittedTogetherURL: function(changeNum) {
return this.changeBaseURL(changeNum) + '/submitted_together';
},
_computeConflictsQueryParams: function(changeNum) {
var options = this.listChangesOptionsToHex(
this.ListChangesOption.CURRENT_REVISION,
this.ListChangesOption.CURRENT_COMMIT
);
return {
O: options,
q: 'status:open is:mergeable conflicts:' + changeNum,
};
},
_computeCherryPicksQueryParams: function(project, changeID, changeNum) {
var options = this.listChangesOptionsToHex(
this.ListChangesOption.CURRENT_REVISION,
this.ListChangesOption.CURRENT_COMMIT
);
var query = [
'project:' + project,
'change:' + changeID,
'-change:' + changeNum,
'-is:abandoned',
].join(' ');
return {
O: options,
q: query
}
},
_computeSameTopicQueryParams: function(topic) {
var options = this.listChangesOptionsToHex(
this.ListChangesOption.LABELS,
this.ListChangesOption.CURRENT_REVISION,
this.ListChangesOption.CURRENT_COMMIT,
this.ListChangesOption.DETAILED_LABELS
);
return {
O: options,
q: 'status:open topic:' + topic,
};
},
_computeChangeURL: function(changeNum, patchNum) {
var urlStr = '/c/' + changeNum;
if (patchNum != null) {
urlStr += '/' + patchNum;
}
return urlStr;
},
_computeLinkClass: function(change) {
if (change.status == this.ChangeStatus.ABANDONED) {
return 'strikethrough';
}
},
_computeChangeStatusClass: function(change) {
var classes = ['status'];
if (change._revision_number != change._current_revision_number) {
classes.push('notCurrent');
} else if (this._isIndirectAncestor(change)) {
classes.push('indirectAncestor');
} else if (change.submittable) {
classes.push('submittable');
} else if (change.status == this.ChangeStatus.NEW) {
classes.push('hidden');
}
return classes.join(' ');
},
_computeChangeStatus: function(change) {
switch (change.status) {
case this.ChangeStatus.MERGED:
return 'Merged';
case this.ChangeStatus.ABANDONED:
return 'Abandoned';
case this.ChangeStatus.DRAFT:
return 'Draft';
}
if (change._revision_number != change._current_revision_number) {
return 'Not current';
} else if (this._isIndirectAncestor(change)) {
return 'Indirect ancestor';
} else if (change.submittable) {
return 'Submittable';
}
return ''
},
_serverConfigChanged: function(config) {
this._resolveServerConfigReady(config);
},
_resultsChanged: function(related, submittedTogether, conflicts,
cherryPicks, sameTopic) {
var results = [
related,
submittedTogether,
conflicts,
cherryPicks,
sameTopic
];
for (var i = 0; i < results.length; i++) {
if (results[i].length > 0) {
this.hidden = false;
return;
}
}
this.hidden = true;
},
_isIndirectAncestor: function(change) {
return this._connectedRevisions.indexOf(change.commit.commit) == -1;
},
_computeConnectedRevisions: function(change, patchNum, relatedChanges) {
var connected = [];
var changeRevision;
for (var rev in change.revisions) {
if (change.revisions[rev]._number == patchNum) {
changeRevision = rev;
}
}
var commits = relatedChanges.map(function(c) { return c.commit; });
var pos = commits.length - 1;
while (pos >= 0) {
var commit = commits[pos].commit;
connected.push(commit);
if (commit == changeRevision) {
break;
}
pos--;
}
while (pos >= 0) {
for (var i = 0; i < commits[pos].parents.length; i++) {
if (connected.indexOf(commits[pos].parents[i].commit) != -1) {
connected.push(commits[pos].commit);
break;
}
}
--pos;
}
return connected;
},
});
})();
</script>
</dom-module>