Merge "Fix javascript errors in gr-admin-view components"
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
index 8d5f759..bfa174b 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
@@ -44,6 +44,7 @@
<link rel="import" href="../gr-download-dialog/gr-download-dialog.html">
<link rel="import" href="../gr-file-list-header/gr-file-list-header.html">
<link rel="import" href="../gr-file-list/gr-file-list.html">
+<link rel="import" href="../gr-included-in-dialog/gr-included-in-dialog.html">
<link rel="import" href="../gr-messages-list/gr-messages-list.html">
<link rel="import" href="../gr-related-changes-list/gr-related-changes-list.html">
<link rel="import" href="../gr-reply-dialog/gr-reply-dialog.html">
@@ -256,6 +257,9 @@
#messageList.visible {
display: block;
}
+ #includedInOverlay {
+ width: 65em;
+ }
@media screen and (min-width: 80em) {
.commitMessage {
max-width: var(--commit-message-max-width, 100ch);
@@ -513,6 +517,7 @@
files-expanded="[[_filesExpanded]]"
on-open-diff-prefs="_handleOpenDiffPrefs"
on-open-download-dialog="_handleOpenDownloadDialog"
+ on-open-included-in-dialog="_handleOpenIncludedInDialog"
on-expand-diffs="_expandAllDiffs"
on-collapse-diffs="_collapseAllDiffs">
</gr-file-list-header>
@@ -582,6 +587,12 @@
config="[[_serverConfig.download]]"
on-close="_handleDownloadDialogClose"></gr-download-dialog>
</gr-overlay>
+ <gr-overlay id="includedInOverlay" with-backdrop>
+ <gr-included-in-dialog
+ id="includedInDialog"
+ change-num="[[_changeNum]]"
+ on-close="_handleIncludedInDialogClose"></gr-included-in-dialog>
+ </gr-overlay>
<gr-overlay id="replyOverlay"
class="scrollable"
no-cancel-on-outside-click
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
index 20ae258..e552dd1 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
@@ -526,6 +526,18 @@
this.$.fileList.openDiffPrefs();
},
+ _handleOpenIncludedInDialog() {
+ this.$.includedInDialog.loadData().then(() => {
+ Polymer.dom.flush();
+ this.$.includedInOverlay.refit();
+ });
+ this.$.includedInOverlay.open();
+ },
+
+ _handleIncludedInDialogClose(e) {
+ this.$.includedInOverlay.close();
+ },
+
_handleOpenDownloadDialog() {
this.$.downloadOverlay.open().then(() => {
this.$.downloadOverlay
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.html b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.html
index d02a189..54f271a 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.html
@@ -80,6 +80,12 @@
.downloadContainer {
margin-right: 16px;
}
+ .includedInContainer {
+ margin-right: 16px;
+ }
+ .includedInContainer.hide {
+ display: none;
+ }
.rightControls {
align-self: flex-end;
margin: auto 0 auto auto;
@@ -209,6 +215,11 @@
class="download"
on-tap="_handleDownloadTap">Download</gr-button>
</span>
+ <span class$="includedInContainer [[_hideIncludedIn(change)]] desktop">
+ <gr-button link
+ class="includedIn"
+ on-tap="_handleIncludedInTap">Included In</gr-button>
+ </span>
<template is="dom-if"
if="[[_fileListActionsVisible(shownFileCount, _maxFilesForBulkActions)]]">
<gr-button
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.js b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.js
index 84add8a..93f010a 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.js
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.js
@@ -149,7 +149,7 @@
.then(res => {
if (res.ok) {
if (target) { target.disabled = false; }
- this.set(['_change', 'revisions', sha, 'description'], desc);
+ this.set(['change', 'revisions', sha, 'description'], desc);
this._patchsetDescription = desc;
}
}).catch(err => {
@@ -179,6 +179,11 @@
this.fire('open-diff-prefs');
},
+ _handleIncludedInTap(e) {
+ e.preventDefault();
+ this.fire('open-included-in-dialog');
+ },
+
_handleDownloadTap(e) {
e.preventDefault();
this.fire('open-download-dialog');
@@ -199,5 +204,9 @@
_getRevisionInfo(change) {
return new Gerrit.RevisionInfo(change);
},
+
+ _hideIncludedIn(change) {
+ return change && change.status === 'MERGED' ? '' : 'hide';
+ },
});
})();
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.html b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.html
index a92d783..f7056dc 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.html
@@ -134,6 +134,7 @@
// The API stub should be called with an empty string for the new
// description.
assert.equal(putDescStub.lastCall.args[2], '');
+ assert.equal(element.change.revisions.rev1.description, '');
flushAsynchronousOperations();
// The editable label should now be visible and the chip hidden.
@@ -154,6 +155,7 @@
}).then(() => {
flushAsynchronousOperations();
// The chip should be visible again, and the label hidden.
+ assert.equal(element.change.revisions.rev1.description, 'test2');
assert.equal(getComputedStyle(label).display, 'none');
assert.notEqual(getComputedStyle(chip).display, 'none');
});
diff --git a/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.html b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.html
new file mode 100644
index 0000000..c3d5808
--- /dev/null
+++ b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.html
@@ -0,0 +1,100 @@
+<!--
+Copyright (C) 2018 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="../../../styles/shared-styles.html">
+<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
+
+<dom-module id="gr-included-in-dialog">
+ <template>
+ <style include="shared-styles">
+ :host {
+ display: block;
+ max-height: 80vh;
+ overflow-y: auto;
+ padding: 4.5em 1em 1em 1em;
+ }
+ header {
+ background: #fff;
+ border-bottom: 1px solid #cdcdcd;
+ left: 0;
+ padding: 1em;
+ position: absolute;
+ right: 0;
+ top: 0;
+ }
+ #title {
+ display: inline-block;
+ font-size: 1.2rem;
+ margin-top: .2em;
+ }
+ h2 {
+ font-size: 1rem;
+ }
+ #filterInput {
+ display: inline-block;
+ float: right;
+ margin: 0 1em;
+ padding: .2em;
+ }
+ .closeButtonContainer {
+ float: right;
+ }
+ ul {
+ margin-bottom: 1em;
+ }
+ ul li {
+ border-radius: .2em;
+ background: #eee;
+ display: inline-block;
+ margin: 0 .2em .4em .2em;
+ padding: .2em .4em;
+ }
+ .loading.loaded {
+ display: none;
+ }
+ </style>
+ <header>
+ <h1 id="title">Included In:</h1>
+ <span class="closeButtonContainer">
+ <gr-button id="closeButton"
+ link
+ on-tap="_handleCloseTap">Close</gr-button>
+ </span>
+ <input
+ id="filterInput"
+ is="iron-input"
+ placeholder="Filter"
+ on-bind-value-changed="_onFilterChanged">
+ </header>
+ <div class$="[[_computeLoadingClass(_loaded)]]">Loading...</div>
+ <template
+ is="dom-repeat"
+ items="[[_computeGroups(_includedIn, _filterText)]]"
+ as="group">
+ <div>
+ <h2>[[group.title]]:</h2>
+ <ul>
+ <template is="dom-repeat" items="[[group.items]]">
+ <li>[[item]]</li>
+ </template>
+ </ul>
+ </div>
+ </template>
+ <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
+ </template>
+ <script src="gr-included-in-dialog.js"></script>
+</dom-module>
diff --git a/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.js b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.js
new file mode 100644
index 0000000..93e644e
--- /dev/null
+++ b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.js
@@ -0,0 +1,96 @@
+// Copyright (C) 2018 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';
+
+ Polymer({
+ is: 'gr-included-in-dialog',
+
+ /**
+ * Fired when the user presses the close button.
+ *
+ * @event close
+ */
+
+ properties: {
+ /** @type {?} */
+ changeNum: {
+ type: Object,
+ observer: '_resetData',
+ },
+ /** @type {?} */
+ _includedIn: Object,
+ _loaded: {
+ type: Boolean,
+ value: false,
+ },
+ _filterText: {
+ type: String,
+ value: '',
+ },
+ },
+
+ loadData() {
+ if (!this.changeNum) { return; }
+ this._filterText = '';
+ return this.$.restAPI.getChangeIncludedIn(this.changeNum).then(
+ configs => {
+ if (!configs) { return; }
+ this._includedIn = configs;
+ this._loaded = true;
+ });
+ },
+
+ _resetData() {
+ this._includedIn = null;
+ this._loaded = false;
+ },
+
+ _computeGroups(includedIn, filterText) {
+ if (!includedIn) { return []; }
+
+ const filter = item => !filterText.length ||
+ item.toLowerCase().indexOf(filterText.toLowerCase()) !== -1;
+
+ const groups = [
+ {title: 'Branches', items: includedIn.branches.filter(filter)},
+ {title: 'Tags', items: includedIn.tags.filter(filter)},
+ ];
+ if (includedIn.external) {
+ for (const externalKey of Object.keys(includedIn.external)) {
+ groups.push({
+ title: externalKey,
+ items: includedIn.external[externalKey].filter(filter),
+ });
+ }
+ }
+ return groups.filter(g => g.items.length);
+ },
+
+ _handleCloseTap(e) {
+ e.preventDefault();
+ this.fire('close', null, {bubbles: false});
+ },
+
+ _computeLoadingClass(loaded) {
+ return loaded ? 'loading loaded' : 'loading';
+ },
+
+ _onFilterChanged() {
+ this.debounce('filter-change', () => {
+ this._filterText = this.$.filterInput.bindValue;
+ }, 100);
+ },
+ });
+})();
diff --git a/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog_test.html b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog_test.html
new file mode 100644
index 0000000..1f7af38
--- /dev/null
+++ b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog_test.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<!--
+Copyright (C) 2018 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-included-in-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-included-in-dialog.html">
+
+<script>void(0);</script>
+
+<test-fixture id="basic">
+ <template>
+ <gr-included-in-dialog></gr-included-in-dialog>
+ </template>
+</test-fixture>
+
+<script>
+ suite('gr-included-in-dialog', () => {
+ let element;
+ let sandbox;
+
+ setup(() => {
+ sandbox = sinon.sandbox.create();
+ element = fixture('basic');
+ });
+
+ teardown(() => { sandbox.restore(); });
+
+ test('_computeGroups', () => {
+ const includedIn = {branches: [], tags: []};
+ let filterText = '';
+ assert.deepEqual(element._computeGroups(includedIn, filterText), []);
+
+ includedIn.branches.push('master', 'development', 'stable-2.0');
+ includedIn.tags.push('v1.9', 'v2.0', 'v2.1');
+ assert.deepEqual(element._computeGroups(includedIn, filterText), [
+ {title: 'Branches', items: ['master', 'development', 'stable-2.0']},
+ {title: 'Tags', items: ['v1.9', 'v2.0', 'v2.1']},
+ ]);
+
+ includedIn.external = {};
+ assert.deepEqual(element._computeGroups(includedIn, filterText), [
+ {title: 'Branches', items: ['master', 'development', 'stable-2.0']},
+ {title: 'Tags', items: ['v1.9', 'v2.0', 'v2.1']},
+ ]);
+
+ includedIn.external.foo = ['abc', 'def', 'ghi'];
+ assert.deepEqual(element._computeGroups(includedIn, filterText), [
+ {title: 'Branches', items: ['master', 'development', 'stable-2.0']},
+ {title: 'Tags', items: ['v1.9', 'v2.0', 'v2.1']},
+ {title: 'foo', items: ['abc', 'def', 'ghi']},
+ ]);
+
+ filterText = 'v2';
+ assert.deepEqual(element._computeGroups(includedIn, filterText), [
+ {title: 'Tags', items: ['v2.0', 'v2.1']},
+ ]);
+
+ // Filtering is case-insensitive.
+ filterText = 'V2';
+ assert.deepEqual(element._computeGroups(includedIn, filterText), [
+ {title: 'Tags', items: ['v2.0', 'v2.1']},
+ ]);
+ });
+ });
+</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
index daa2a4f..88faaba 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
@@ -1107,6 +1107,13 @@
opt_errFn, null, params);
},
+ /**
+ * @param {number|string} changeNum
+ */
+ getChangeIncludedIn(changeNum) {
+ return this._getChangeURLAndFetch(changeNum, '/in', null);
+ },
+
_computeFilter(filter) {
if (filter && filter.startsWith('^')) {
filter = '&r=' + encodeURIComponent(filter);
diff --git a/polygerrit-ui/app/test/index.html b/polygerrit-ui/app/test/index.html
index 2bb8b2e..f0500ee 100644
--- a/polygerrit-ui/app/test/index.html
+++ b/polygerrit-ui/app/test/index.html
@@ -73,6 +73,7 @@
'change/gr-download-dialog/gr-download-dialog_test.html',
'change/gr-file-list-header/gr-file-list-header_test.html',
'change/gr-file-list/gr-file-list_test.html',
+ 'change/gr-included-in-dialog/gr-included-in-dialog_test.html',
'change/gr-label-score-row/gr-label-score-row_test.html',
'change/gr-label-scores/gr-label-scores_test.html',
'change/gr-message/gr-message_test.html',