Merge changes I9f3acf5b,Ia85d8e87
* changes:
[project.config] Replace Guava collections with native Java ones
[project.config] Add tests for reading comment links
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index 5e67b38..0c30a4b 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -301,6 +301,12 @@
link:user-search.html#reviewedby[reviewedby:self].
--
+[[skip_mergeable]]
+--
+* `SKIP_MERGEABLE`: skip the `mergeable` field in
+link:#change-info[ChangeInfo]. For fast moving projects, this field must
+be recomputed often, which is slow for projects with big trees.
+
[[submittable]]
--
* `SUBMITTABLE`: include the `submittable` field in link:#change-info[ChangeInfo],
@@ -5658,7 +5664,8 @@
Not set for merged changes.
|`mergeable` |optional|
Whether the change is mergeable. +
-Not set for merged changes, or if the change has not yet been tested.
+Not set for merged changes, if the change has not yet been tested, or
+if the link:#skip_mergeable[skip_mergeable] option is set.
|`submittable` |optional|
Whether the change has been approved by the project submit rules. +
Only set if link:#submittable[requested].
diff --git a/java/com/google/gerrit/extensions/client/ListChangesOption.java b/java/com/google/gerrit/extensions/client/ListChangesOption.java
index ee7d039..ffc5029 100644
--- a/java/com/google/gerrit/extensions/client/ListChangesOption.java
+++ b/java/com/google/gerrit/extensions/client/ListChangesOption.java
@@ -75,7 +75,10 @@
SUBMITTABLE(20),
/** If tracking Ids are included, include detailed tracking Ids info. */
- TRACKING_IDS(21);
+ TRACKING_IDS(21),
+
+ /** Skip mergeability data */
+ SKIP_MERGEABLE(22);
private final int value;
diff --git a/java/com/google/gerrit/server/change/ChangeJson.java b/java/com/google/gerrit/server/change/ChangeJson.java
index 81558e3..8ba755f 100644
--- a/java/com/google/gerrit/server/change/ChangeJson.java
+++ b/java/com/google/gerrit/server/change/ChangeJson.java
@@ -33,6 +33,7 @@
import static com.google.gerrit.extensions.client.ListChangesOption.PUSH_CERTIFICATES;
import static com.google.gerrit.extensions.client.ListChangesOption.REVIEWED;
import static com.google.gerrit.extensions.client.ListChangesOption.REVIEWER_UPDATES;
+import static com.google.gerrit.extensions.client.ListChangesOption.SKIP_MERGEABLE;
import static com.google.gerrit.extensions.client.ListChangesOption.SUBMITTABLE;
import static com.google.gerrit.extensions.client.ListChangesOption.TRACKING_IDS;
import static com.google.gerrit.extensions.client.ListChangesOption.WEB_LINKS;
@@ -521,7 +522,9 @@
if (str.isOk()) {
out.submitType = str.type;
}
- out.mergeable = cd.isMergeable();
+ if (!has(SKIP_MERGEABLE)) {
+ out.mergeable = cd.isMergeable();
+ }
if (has(SUBMITTABLE)) {
out.submittable = submittable(cd);
}
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
index fa683cf..b770064 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -91,6 +91,7 @@
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.client.Comment.Range;
import com.google.gerrit.extensions.client.InheritableBoolean;
+import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.extensions.client.Side;
import com.google.gerrit.extensions.client.SubmitType;
@@ -237,6 +238,15 @@
}
@Test
+ public void skipMergeable() throws Exception {
+ PushOneCommit.Result r = createChange();
+ String triplet = project.get() + "~master~" + r.getChangeId();
+ ChangeInfo c =
+ gApi.changes().id(triplet).get(ImmutableList.of(ListChangesOption.SKIP_MERGEABLE));
+ assertThat(c.mergeable).isNull();
+ }
+
+ @Test
public void setPrivateByOwner() throws Exception {
TestRepository<InMemoryRepository> userRepo = cloneProject(project, user);
PushOneCommit.Result result =
diff --git a/polygerrit-ui/app/BUILD b/polygerrit-ui/app/BUILD
index ec7efb6..991ce2e 100644
--- a/polygerrit-ui/app/BUILD
+++ b/polygerrit-ui/app/BUILD
@@ -163,7 +163,7 @@
],
),
outs = ["polygerrit_embed_ui.zip"],
- app = "embed/change-diff-views.html",
+ app = "embed/embed.html",
)
filegroup(
diff --git a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.html b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.html
index 4013b37..2294621 100644
--- a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.html
+++ b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.html
@@ -89,11 +89,13 @@
<div class="header">
<span class="title">[[name]]</span>
<div class="right">
- <paper-toggle-button
- id="exclusiveToggle"
- checked="{{permission.value.exclusive}}"
- on-change="_handleValueChange"
- disabled$="[[!editing]]"></paper-toggle-button>Exclusive
+ <template is=dom-if if="[[!_permissionIsOwner(permission.id)]]">
+ <paper-toggle-button
+ id="exclusiveToggle"
+ checked="{{permission.value.exclusive}}"
+ on-change="_handleValueChange"
+ disabled$="[[!editing]]"></paper-toggle-button>Exclusive
+ </template>
<gr-button
link
id="removeBtn"
diff --git a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.js b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.js
index f9c04e60..cfb0ad5 100644
--- a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.js
+++ b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.js
@@ -89,6 +89,10 @@
this._setupValues();
},
+ _permissionIsOwner(permissionId) {
+ return permissionId === 'owner';
+ },
+
_handleEditingChanged(editing, editingOld) {
// Ignore when editing gets set initially.
if (!editingOld) { return; }
diff --git a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_test.html b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_test.html
index b67d705..ec93a5c 100644
--- a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_test.html
@@ -335,7 +335,7 @@
assert.isFalse(element._originalExclusiveValue);
assert.isNotOk(element.permission.value.modified);
- MockInteractions.tap(element.$.exclusiveToggle);
+ MockInteractions.tap(element.$$('#exclusiveToggle'));
flushAsynchronousOperations();
assert.isTrue(element.permission.value.exclusive);
assert.isTrue(element.permission.value.modified);
@@ -353,6 +353,15 @@
assert.isTrue(element.permission.value.modified);
assert.isTrue(modifiedHandler.called);
});
+
+ test('Exclusive hidden for owner permission', () => {
+ assert.equal(getComputedStyle(element.$$('#exclusiveToggle')).display,
+ 'flex');
+ element.set(['permission', 'id'], 'owner');
+ flushAsynchronousOperations();
+ assert.equal(getComputedStyle(element.$$('#exclusiveToggle')).display,
+ 'none');
+ });
});
});
</script>
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.html b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.html
index 481cd76..f3286f2 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.html
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.html
@@ -132,6 +132,7 @@
<gr-overlay id="overlay" with-backdrop>
<gr-confirm-rebase-dialog id="confirmRebase"
class="confirmDialog"
+ change-number="[[change._number]]"
on-confirm="_handleRebaseConfirm"
on-cancel="_handleConfirmDialogCancel"
branch="[[change.branch]]"
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
index b2a6f0d..8e00c06 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
@@ -173,7 +173,7 @@
*/
properties: {
- /** @type {{ branch: string, project: string }} */
+ /** @type {{ _number: number, branch: string, project: string }} */
change: Object,
actions: {
type: Object,
@@ -501,7 +501,7 @@
this.notifyPath('actions.rebaseEdit');
}
} else {
- if (!changeActions.rebasEdit) {
+ if (!changeActions.rebaseEdit) {
this.set('actions.rebaseEdit', REBASE_EDIT);
}
if (changeActions.publishEdit) {
@@ -802,6 +802,7 @@
switch (key) {
case RevisionActions.REBASE:
this._showActionDialog(this.$.confirmRebase);
+ this.$.confirmRebase.fetchRecentChanges();
break;
case RevisionActions.CHERRYPICK:
this._handleCherrypickTap();
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html
index 62b4626..df2fbcb 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html
@@ -306,6 +306,9 @@
test('rebase change', done => {
const fireActionStub = sandbox.stub(element, '_fireAction');
+ const fetchChangesStub = sandbox.stub(element.$.confirmRebase,
+ 'fetchRecentChanges').returns(Promise.resolve([]));
+ element._hasKnownChainState = true;
flush(() => {
const rebaseButton = element.$$('gr-button[data-action-key="rebase"]');
MockInteractions.tap(rebaseButton);
@@ -318,6 +321,7 @@
method: 'POST',
title: 'Rebase onto tip of branch or parent change',
};
+ assert.isTrue(fetchChangesStub.called);
// rebase on other
element.$.confirmRebase.base = '1234';
element._handleRebaseConfirm();
@@ -340,6 +344,22 @@
});
});
+ test(`rebase dialog gets recent changes each time it's opened`, done => {
+ const fetchChangesStub = sandbox.stub(element.$.confirmRebase,
+ 'fetchRecentChanges').returns(Promise.resolve([]));
+ element._hasKnownChainState = true;
+ const rebaseButton = element.$$('gr-button[data-action-key="rebase"]');
+ MockInteractions.tap(rebaseButton);
+ assert.isTrue(fetchChangesStub.calledOnce);
+
+ flush(() => {
+ element.$.confirmRebase.fire('cancel');
+ MockInteractions.tap(rebaseButton);
+ assert.isTrue(fetchChangesStub.calledTwice);
+ done();
+ });
+ });
+
test('two dialogs are not shown at the same time', done => {
element._hasKnownChainState = true;
flush(() => {
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 7e661c7..c2f2f6f 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
@@ -76,7 +76,10 @@
}
gr-change-status {
display: initial;
- margin: .1em .5em .1em 0;
+ margin: .1em .1em .1em .4em;
+ }
+ gr-change-status:first-child {
+ margin-left: 0;
}
.header-title {
align-items: center;
@@ -144,7 +147,9 @@
}
}
.changeStatuses,
- .commitActions {
+ .changeText,
+ .commitActions,
+ .statusText {
align-items: center;
display: flex;
}
@@ -225,6 +230,7 @@
}
gr-commit-info {
display: inline-block;
+ margin-right: -5px;
}
@media screen and (min-width: 80em) {
.commitMessage {
@@ -327,19 +333,22 @@
status="[[status]]"></gr-change-status>
</template>
</div>
+ <div class="statusText">
+ <template
+ is="dom-if"
+ if="[[_computeShowCommitInfo(_changeStatus, _change.current_revision)]]">
+ <span class="text"> as </span>
+ <gr-commit-info
+ change="[[_change]]"
+ commit-info="[[_computeMergedCommitInfo(_change.current_revision, _change.revisions)]]"
+ server-config="[[_serverConfig]]"></gr-commit-info>
+ </template>
+ </div>
+ <span class="separator"></span>
<div class="changeText">
<a aria-label$="[[_computeChangePermalinkAriaLabel(_change._number)]]"
- href$="[[_computeChangeUrl(_change)]]">[[_change._number]]</a><!--
- --><template
- is="dom-if"
- if="[[_computeShowCommitInfo(_changeStatus, _change.current_revision)]]"><!--
- --><span class="text"> ([[_changeStatus]] as </span><!--
- --><gr-commit-info
- change="[[_change]]"
- commit-info="[[_computeMergedCommitInfo(_change.current_revision, _change.revisions)]]"
- server-config="[[_serverConfig]]"></gr-commit-info>)<!--
- --></template><!--
- --><span class="text">: </span><span class="headerSubject">[[_change.subject]]</span>
+ href$="[[_computeChangeUrl(_change)]]">[[_change._number]]</a>
+ <span class="headerSubject">: [[_change.subject]]</span>
</div>
</div><!-- end header-title -->
<div class="commitActions" hidden$="[[!_loggedIn]]">
@@ -370,7 +379,7 @@
server-config="[[_serverConfig]]"
missing-labels="[[_missingLabels]]"
mutable="[[_loggedIn]]"
- parent-is-current="[[!_rebaseOriginallyEnabled]]"
+ parent-is-current="[[_parentIsCurrent]]"
on-show-reply-dialog="_handleShowReplyDialog">
</gr-change-metadata>
<!-- Plugins insert content into following container.
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 fd9a490..1800175 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
@@ -151,17 +151,7 @@
_patchRange: {
type: Object,
},
- // These are kept as separate properties from the patchRange so that the
- // observer can be aware of the previous value. In order to view sub
- // property changes for _patchRange, a complex observer must be used, and
- // that only displays the new value.
- //
- // If a previous value did not exist, the change is not reloaded with the
- // new patches. This is just the initial setting from the change view vs.
- // an update coming from the two way data binding.
- _patchNum: String,
_filesExpanded: String,
- _basePatchNum: String,
_currentRevision: Object,
_currentRevisionActions: Object,
_allPatchSets: {
@@ -224,7 +214,7 @@
value: false,
observer: '_updateToggleContainerClass',
},
- _rebaseOriginallyEnabled: Boolean,
+ _parentIsCurrent: Boolean,
},
behaviors: [
@@ -938,8 +928,10 @@
if (revisionActions && revisionActions.rebase) {
revisionActions.rebase.rebaseOnCurrent =
!!revisionActions.rebase.enabled;
- this._rebaseOriginallyEnabled = !!revisionActions.rebase.enabled;
+ this._parentIsCurrent = !revisionActions.rebase.enabled;
revisionActions.rebase.enabled = true;
+ } else {
+ this._parentIsCurrent = true;
}
return revisionActions;
},
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
index d8367610..7d4a54b 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
@@ -399,6 +399,7 @@
title: 'Rebase onto tip of branch or parent change',
},
};
+ element._parentIsCurrent = undefined;
// Rebase enabled should always end up true.
// When rebase is enabled initially, rebaseOnCurrent should be set to
@@ -408,6 +409,7 @@
assert.isTrue(currentRevisionActions.rebase.enabled);
assert.isTrue(currentRevisionActions.rebase.rebaseOnCurrent);
+ assert.isFalse(element._parentIsCurrent);
delete currentRevisionActions.rebase.enabled;
@@ -418,6 +420,21 @@
assert.isTrue(currentRevisionActions.rebase.enabled);
assert.isFalse(currentRevisionActions.rebase.rebaseOnCurrent);
+ assert.isTrue(element._parentIsCurrent);
+ });
+
+ test('_updateRebaseAction sets _parentIsCurrent on no rebase', () => {
+ const currentRevisionActions = {
+ cherrypick: {
+ enabled: true,
+ label: 'Cherry Pick',
+ method: 'POST',
+ title: 'cherrypick',
+ },
+ };
+ element._parentIsCurrent = undefined;
+ element._updateRebaseAction(currentRevisionActions);
+ assert.isTrue(element._parentIsCurrent);
});
test('_reload is called when an approved label is removed', () => {
diff --git a/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info.html b/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info.html
index 67b54d6..3eaeab25 100644
--- a/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info.html
+++ b/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info.html
@@ -25,9 +25,6 @@
align-items: center;
display: flex;
}
- gr-copy-clipboard {
- padding-left: .5em;
- }
</style>
<div class="container">
<template is="dom-if" if="[[_showWebLink]]">
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.html b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.html
index 582a03c..4370d7e 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.html
+++ b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.html
@@ -15,7 +15,9 @@
-->
<link rel="import" href="../../../bower_components/polymer/polymer.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">
<link rel="import" href="../../../styles/shared-styles.html">
<dom-module id="gr-confirm-rebase-dialog">
@@ -49,6 +51,7 @@
}
</style>
<gr-confirm-dialog
+ id="confirmDialog"
confirm-label="Rebase"
on-confirm="_handleConfirmTap"
on-cancel="_handleCancelTap">
@@ -98,15 +101,18 @@
</label>
</div>
<div class="parentRevisionContainer">
- <input is="iron-input"
- type="text"
+ <gr-autocomplete
id="parentInput"
- bind-value="{{base}}"
+ query="[[_query]]"
+ text="{{_inputText}}"
on-tap="_handleEnterChangeNumberTap"
+ on-commit="_handleBaseSelected"
placeholder="Change number">
+ </gr-autocomplete>
</div>
</div>
</gr-confirm-dialog>
+ <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
</template>
<script src="gr-confirm-rebase-dialog.js"></script>
</dom-module>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.js b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.js
index eb0fa17..e4f6e97 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.js
@@ -36,14 +36,62 @@
* @type {?string} */
base: String,
branch: String,
+ changeNumber: Number,
hasParent: Boolean,
rebaseOnCurrent: Boolean,
+ _inputText: String,
+ _query: {
+ type: Function,
+ value() {
+ return this._getChangeSuggestions.bind(this);
+ },
+ },
+ _recentChanges: Array,
},
observers: [
'_updateSelectedOption(rebaseOnCurrent, hasParent)',
],
+ // This is called by gr-change-actions every time the rebase dialog is
+ // re-opened. Unlike other autocompletes that make a request with each
+ // updated input, this one gets all recent changes once and then filters
+ // them by the input. The query is re-run each time the dialog is opened
+ // in case there are new/updated changes in the generic query since the
+ // last time it was run.
+ fetchRecentChanges() {
+ return this.$.restAPI.getChanges(null, `is:open -age:90d`)
+ .then(response => {
+ const changes = [];
+ for (const key in response) {
+ if (!response.hasOwnProperty(key)) { continue; }
+ changes.push({
+ name: `${response[key]._number}: ${response[key].subject}`,
+ value: response[key]._number,
+ });
+ }
+ this._recentChanges = changes;
+ return this._recentChanges;
+ });
+ },
+
+ _getRecentChanges() {
+ if (this._recentChanges) {
+ return Promise.resolve(this._recentChanges);
+ }
+ return this.fetchRecentChanges();
+ },
+
+ _getChangeSuggestions(input) {
+ return this._getRecentChanges().then(changes =>
+ this._filterChanges(input, changes));
+ },
+
+ _filterChanges(input, changes) {
+ return changes.filter(change => change.name.includes(input) &&
+ change.value !== this.changeNumber);
+ },
+
_displayParentOption(rebaseOnCurrent, hasParent) {
return hasParent && rebaseOnCurrent;
},
@@ -58,11 +106,13 @@
_handleConfirmTap(e) {
e.preventDefault();
+ this._inputText = '';
this.fire('confirm', null, {bubbles: false});
},
_handleCancelTap(e) {
e.preventDefault();
+ this._inputText = '';
this.fire('cancel', null, {bubbles: false});
},
@@ -85,6 +135,10 @@
this.base = null;
},
+ _handleBaseSelected(e) {
+ this.base = e.detail.value;
+ },
+
_handleEnterChangeNumberTap() {
this.$.rebaseOnOtherInput.checked = true;
},
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.html b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.html
index 0ea7c49..ccfc368 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.html
@@ -34,9 +34,15 @@
<script>
suite('gr-confirm-rebase-dialog tests', () => {
let element;
+ let sandbox;
setup(() => {
element = fixture('basic');
+ sandbox = sinon.sandbox.create();
+ });
+
+ teardown(() => {
+ sandbox.restore();
});
test('controls with parent and rebase on current available', () => {
@@ -82,5 +88,88 @@
assert.isTrue(element.$.rebaseOnTip.hasAttribute('hidden'));
assert.isFalse(element.$.tipUpToDateMsg.hasAttribute('hidden'));
});
+
+ test('input cleared on cancel or submit', () => {
+ element._inputText = '123';
+ element.$.confirmDialog.fire('confirm');
+ assert.equal(element._inputText, '');
+
+ element._inputText = '123';
+ element.$.confirmDialog.fire('cancel');
+ assert.equal(element._inputText, '');
+ });
+
+ suite('parent suggestions', () => {
+ let recentChanges;
+ setup(() => {
+ recentChanges = [
+ {
+ name: '123: my first awesome change',
+ value: 123,
+ },
+ {
+ name: '124: my second awesome change',
+ value: 124,
+ },
+ {
+ name: '245: my third awesome change',
+ value: 245,
+ },
+ ];
+
+ sandbox.stub(element.$.restAPI, 'getChanges').returns(Promise.resolve(
+ [
+ {
+ _number: 123,
+ subject: 'my first awesome change',
+ },
+ {
+ _number: 124,
+ subject: 'my second awesome change',
+ },
+ {
+ _number: 245,
+ subject: 'my third awesome change',
+ },
+ ]
+ ));
+ });
+
+ test('_getRecentChanges', () => {
+ sandbox.spy(element, '_getRecentChanges');
+ return element._getRecentChanges().then(() => {
+ assert.deepEqual(element._recentChanges, recentChanges);
+ assert.equal(element.$.restAPI.getChanges.callCount, 1);
+ // When called a second time, should not re-request recent changes.
+ element._getRecentChanges();
+ }).then(() => {
+ assert.equal(element._getRecentChanges.callCount, 2);
+ assert.equal(element.$.restAPI.getChanges.callCount, 1);
+ });
+ });
+
+ test('_filterChanges', () => {
+ assert.equal(element._filterChanges('123', recentChanges).length, 1);
+ assert.equal(element._filterChanges('12', recentChanges).length, 2);
+ assert.equal(element._filterChanges('awesome', recentChanges).length,
+ 3);
+ assert.equal(element._filterChanges('third', recentChanges).length,
+ 1);
+
+ element.changeNumber = 123;
+ assert.equal(element._filterChanges('123', recentChanges).length, 0);
+ assert.equal(element._filterChanges('124', recentChanges).length, 1);
+ assert.equal(element._filterChanges('awesome', recentChanges).length,
+ 2);
+ });
+
+ test('input text change triggers function', () => {
+ sandbox.spy(element, '_getRecentChanges');
+ element._inputText = '1';
+ assert.isTrue(element._getRecentChanges.calledOnce);
+ element._inputText = '12';
+ assert.isTrue(element._getRecentChanges.calledTwice);
+ });
+ });
});
</script>
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 c92919d..4c6b95a 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
@@ -135,6 +135,9 @@
font-family: var(--font-family-bold);
margin-right: 24px;
}
+ gr-commit-info {
+ margin-right: -5px;
+ }
@media screen and (max-width: 50em) {
.patchInfo-header .desktop {
display: none;
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
index 8d91ef8..6a7966b 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
@@ -55,7 +55,7 @@
stub('gr-rest-api-interface', {
getConfig() { return Promise.resolve({}); },
getAccount() { return Promise.resolve({}); },
- getChange() { return Promise.resolve([{}]); },
+ getChange() { return Promise.resolve({}); },
getChangeSuggestedReviewers() { return Promise.resolve([]); },
});
diff --git a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html
index 7b17f22..006b9d9 100644
--- a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html
+++ b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html
@@ -319,10 +319,12 @@
/**
* @param {{ _number: number, project: string }} change The change object.
* @param {string} path The file path.
+ * @param {number=} opt_patchNum
* @return {string}
*/
- getEditUrlForDiff(change, path) {
- return this.getEditUrlForDiffById(change._number, change.project, path);
+ getEditUrlForDiff(change, path, opt_patchNum) {
+ return this.getEditUrlForDiffById(change._number, change.project, path,
+ opt_patchNum);
},
/**
@@ -331,13 +333,13 @@
* @param {string} path The file path.
* @return {string}
*/
- getEditUrlForDiffById(changeNum, project, path) {
+ getEditUrlForDiffById(changeNum, project, path, opt_patchNum) {
return this._getUrlFor({
view: Gerrit.Nav.View.EDIT,
changeNum,
project,
path,
- patchNum: EDIT_PATCHNUM,
+ patchNum: opt_patchNum || EDIT_PATCHNUM,
});
},
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router.js b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
index dc264f2..cc59be8 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.js
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
@@ -114,9 +114,8 @@
// eslint-disable-next-line max-len
CHANGE_OR_DIFF: /^\/c\/(.+)\/\+\/(\d+)(\/?((-?\d+|edit)(\.\.(\d+|edit))?(\/(.+))?))?\/?$/,
- // Matches /c/<project>/+/<changeNum>/edit/<path>,edit
- // eslint-disable-next-line max-len
- DIFF_EDIT: /^\/c\/(.+)\/\+\/(\d+)\/edit\/(.+),edit$/,
+ // Matches /c/<project>/+/<changeNum>/[<patchNum|edit>]/<path>,edit
+ DIFF_EDIT: /^\/c\/(.+)\/\+\/(\d+)\/(\d+|edit)\/(.+),edit$/,
// Matches non-project-relative
// /c/<changeNum>/[<basePatchNum>..]<patchNum>/<path>.
@@ -498,9 +497,12 @@
return this.$.restAPI.getFromProjectLookup(params.changeNum)
.then(project => {
- // Do nothing if the lookup request failed. This avoids an infinite
- // loop of project lookups.
- if (!project) { return; }
+ // Show a 404 and terminate if the lookup request failed. Attempting
+ // to redirect after failing to get the project loops infinitely.
+ if (!project) {
+ this._show404();
+ return;
+ }
params.project = project;
this._normalizePatchRangeParams(params);
@@ -1250,7 +1252,8 @@
this._redirectOrNavigate({
project: ctx.params[0],
changeNum: ctx.params[1],
- path: ctx.params[2],
+ patchNum: ctx.params[2],
+ path: ctx.params[3],
view: Gerrit.Nav.View.EDIT,
});
},
@@ -1333,6 +1336,10 @@
* Catchall route for when no other route is matched.
*/
_handleDefaultRoute() {
+ this._show404();
+ },
+
+ _show404() {
// Note: the app's 404 display is tightly-coupled with catching 404
// network responses, so we simulate a 404 response status to display it.
// TODO: Decouple the gr-app error view from network responses.
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html
index 7011c65..f5a7dd9 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html
@@ -430,11 +430,13 @@
suite('_normalizeLegacyRouteParams', () => {
let rangeStub;
let redirectStub;
+ let show404Stub;
setup(() => {
rangeStub = sandbox.stub(element, '_normalizePatchRangeParams')
.returns(Promise.resolve());
redirectStub = sandbox.stub(element, '_redirect');
+ show404Stub = sandbox.stub(element, '_show404');
});
test('w/o changeNum', () => {
@@ -445,6 +447,7 @@
assert.isFalse(rangeStub.called);
assert.isNotOk(params.project);
assert.isFalse(redirectStub.called);
+ assert.isFalse(show404Stub.called);
});
});
@@ -456,18 +459,19 @@
assert.isTrue(rangeStub.called);
assert.equal(params.project, 'foo/bar');
assert.isTrue(redirectStub.calledOnce);
+ assert.isFalse(show404Stub.called);
});
});
test('halts on project lookup failure', () => {
projectLookupStub.returns(Promise.resolve(undefined));
-
const params = {changeNum: 1234};
return element._normalizeLegacyRouteParams(params).then(() => {
assert.isTrue(projectLookupStub.called);
assert.isFalse(rangeStub.called);
assert.isUndefined(params.project);
assert.isFalse(redirectStub.called);
+ assert.isTrue(show404Stub.calledOnce);
});
});
});
@@ -1313,7 +1317,8 @@
params: [
'foo/bar', // 0 Project
1234, // 1 Change number
- 'foo/bar/baz', // 2 File path
+ 3, // 2 Patch num
+ 'foo/bar/baz', // 3 File path
],
};
const appParams = {
@@ -1321,6 +1326,7 @@
changeNum: 1234,
view: Gerrit.Nav.View.EDIT,
path: 'foo/bar/baz',
+ patchNum: 3,
};
element._handleDiffEditRoute(ctx);
diff --git a/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls.html b/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls.html
index f0d7f6f..96ba196b 100644
--- a/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls.html
+++ b/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls.html
@@ -37,6 +37,12 @@
#more {
margin-right: 1em;
}
+ gr-button,
+ gr-dropdown {
+ --gr-button: {
+ height: 1.8em;
+ }
+ }
gr-dropdown {
--gr-dropdown-item: {
background-color: transparent;
diff --git a/polygerrit-ui/app/elements/gr-app.html b/polygerrit-ui/app/elements/gr-app.html
index ef93794..ced27dd 100644
--- a/polygerrit-ui/app/elements/gr-app.html
+++ b/polygerrit-ui/app/elements/gr-app.html
@@ -55,6 +55,7 @@
<link rel="import" href="./settings/gr-registration-dialog/gr-registration-dialog.html">
<link rel="import" href="./settings/gr-settings-view/gr-settings-view.html">
<link rel="import" href="./shared/gr-fixed-panel/gr-fixed-panel.html">
+<link rel="import" href="./shared/gr-rest-api-interface/gr-rest-api-interface.html">
<script src="../scripts/util.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.html b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.html
index 6d7df94..62da3bb 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.html
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.html
@@ -37,11 +37,8 @@
background-color: #fff;
box-shadow: 0 1px 5px rgba(0, 0, 0, .3);
}
- button {
- background: none;
- border: none;
- font: inherit;
- padding: .3em 0;
+ gr-button {
+ @apply --gr-button;
}
gr-avatar {
height: 2em;
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 b5bb35a..3f19f7e 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
@@ -1993,7 +1993,11 @@
*/
getChange(changeNum, opt_errFn) {
// Cannot use _changeBaseURL, as this function is used by _projectLookup.
- return this.fetchJSON(`/changes/?q=${changeNum}`, opt_errFn);
+ return this.fetchJSON(`/changes/?q=change:${changeNum}`, opt_errFn)
+ .then(res => {
+ if (!res || !res.length) { return null; }
+ return res[0];
+ });
},
/**
@@ -2026,8 +2030,7 @@
this.fire('page-error', {response});
};
- return this.getChange(changeNum, onError).then(res => {
- const change = res[0];
+ return this.getChange(changeNum, onError).then(change => {
if (!change || !change.project) { return; }
this.setInProjectLookup(changeNum, change.project);
return change.project;
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
index a8c09d1..33eb181 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
@@ -1036,7 +1036,7 @@
suite('getFromProjectLookup', () => {
test('getChange fails', () => {
sandbox.stub(element, 'getChange')
- .returns(Promise.resolve([]));
+ .returns(Promise.resolve(null));
return element.getFromProjectLookup().then(val => {
assert.strictEqual(val, undefined);
assert.deepEqual(element._projectLookup, {});
@@ -1044,7 +1044,7 @@
});
test('getChange succeeds, no project', () => {
- sandbox.stub(element, 'getChange').returns(Promise.resolve([]));
+ sandbox.stub(element, 'getChange').returns(Promise.resolve(null));
return element.getFromProjectLookup().then(val => {
assert.strictEqual(val, undefined);
assert.deepEqual(element._projectLookup, {});
@@ -1053,7 +1053,7 @@
test('getChange succeeds with project', () => {
sandbox.stub(element, 'getChange')
- .returns(Promise.resolve([{project: 'project'}]));
+ .returns(Promise.resolve({project: 'project'}));
return element.getFromProjectLookup('test').then(val => {
assert.equal(val, 'project');
assert.deepEqual(element._projectLookup, {test: 'project'});
diff --git a/polygerrit-ui/app/embed/change-diff-views.html b/polygerrit-ui/app/embed/embed.html
similarity index 81%
rename from polygerrit-ui/app/embed/change-diff-views.html
rename to polygerrit-ui/app/embed/embed.html
index 8426585..14b6b66 100644
--- a/polygerrit-ui/app/embed/change-diff-views.html
+++ b/polygerrit-ui/app/embed/embed.html
@@ -16,4 +16,6 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../elements/change/gr-change-view/gr-change-view.html">
<link rel="import" href="../elements/diff/gr-diff-view/gr-diff-view.html">
+<link rel="import" href="../elements/change-list/gr-dashboard-view/gr-dashboard-view.html">
+<link rel="import" href="../elements/change-list/gr-change-list-view/gr-change-list-view.html">
<link rel="import" href="../styles/app-theme.html">
diff --git a/polygerrit-ui/app/embed/embed_test.html b/polygerrit-ui/app/embed/embed_test.html
index 26ea895..80f7e5d 100644
--- a/polygerrit-ui/app/embed/embed_test.html
+++ b/polygerrit-ui/app/embed/embed_test.html
@@ -16,11 +16,11 @@
-->
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>change-diff-views-embed_test</title>
+<title>embed_test</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="../polygerrit_ui/elements/change-diff-views.html"/>
+<link rel="import" href="../polygerrit_ui/elements/embed.html"/>
<script>void(0);</script>
@@ -36,6 +36,18 @@
</template>
</test-fixture>
+<test-fixture id="dashboard-view">
+ <template>
+ <gr-dashboard-view></gr-dashboard-view>
+ </template>
+</test-fixture>
+
+<test-fixture id="change-list-view">
+ <template>
+ <gr-change-list-view></gr-change-list-view>
+ </template>
+</test-fixture>
+
<script>
suite('embed test', () => {
test('gr-change-view is embedded', () => {
@@ -47,5 +59,15 @@
const element = fixture('diff-view');
assert.equal(element.is, 'gr-diff-view');
});
+
+ test('dashboard-view is embedded', () => {
+ const element = fixture('dashboard-view');
+ assert.equal(element.is, 'gr-dashboard-view');
+ });
+
+ test('change-list-view is embedded', () => {
+ const element = fixture('change-list-view');
+ assert.equal(element.is, 'gr-change-list-view');
+ });
});
</script>