Merge changes Ice480cab,I429e3e10,I4379e493,I592312ed,I69e6d993, ...
* changes:
CommentDetail: Rewrite switch statement in include method with if + else
CommentDetail/PatchScriptFactory: Remove unused AccountInfoCache
EventUtil: Inline AccountJson
Assignee endpoints: Use AccountLoader to populate AccountInfo
Anotate GetPastAssignees as singleton
Assignee endpoints: Use IdentifiedUser#getNameEmail() to format user
diff --git a/polygerrit-ui/app/elements/change/gr-account-entry/gr-account-entry.js b/polygerrit-ui/app/elements/change/gr-account-entry/gr-account-entry.js
index 5dea33d..46f2ed2 100644
--- a/polygerrit-ui/app/elements/change/gr-account-entry/gr-account-entry.js
+++ b/polygerrit-ui/app/elements/change/gr-account-entry/gr-account-entry.js
@@ -69,28 +69,27 @@
},
_makeSuggestion: function(reviewer) {
+ var name;
+ var value;
+ var generateStatusStr = function(account) {
+ return account.status ? ' (' + account.status + ')' : '';
+ };
if (reviewer.account) {
// Reviewer is an account suggestion from getChangeSuggestedReviewers.
- return {
- name: reviewer.account.name + ' (' + reviewer.account.email + ')',
- value: reviewer,
- };
+ name = reviewer.account.name + ' <' + reviewer.account.email + '>' +
+ generateStatusStr(reviewer.account);
+ value = reviewer;
} else if (reviewer.group) {
// Reviewer is a group suggestion from getChangeSuggestedReviewers.
- return {
- name: reviewer.group.name + ' (group)',
- value: reviewer,
- };
+ name = reviewer.group.name + ' (group)';
+ value = reviewer;
} else if (reviewer._account_id) {
// Reviewer is an account suggestion from getSuggestedAccounts.
- return {
- name: reviewer.name + ' (' + reviewer.email + ')',
- value: {
- account: reviewer,
- count: 1,
- },
- };
+ name = reviewer.name + ' <' + reviewer.email + '>' +
+ generateStatusStr(reviewer);
+ value = {account: reviewer, count: 1};
}
+ return {name: name, value: value};
},
_getReviewerSuggestions: function(input) {
@@ -104,7 +103,7 @@
if (!this.filter) { return reviewers.map(this._makeSuggestion); }
return reviewers
.filter(this.filter)
- .map(this._makeSuggestion);
+ .map(this._makeSuggestion.bind(this));
}.bind(this));
},
});
diff --git a/polygerrit-ui/app/elements/change/gr-account-entry/gr-account-entry_test.html b/polygerrit-ui/app/elements/change/gr-account-entry/gr-account-entry_test.html
index a4635d5..71e84d0 100644
--- a/polygerrit-ui/app/elements/change/gr-account-entry/gr-account-entry_test.html
+++ b/polygerrit-ui/app/elements/change/gr-account-entry/gr-account-entry_test.html
@@ -35,12 +35,13 @@
suite('gr-account-entry tests', function() {
var sandbox;
var _nextAccountId = 0;
- var makeAccount = function() {
+ var makeAccount = function(opt_status) {
var accountId = ++_nextAccountId;
return {
_account_id: accountId,
name: 'name ' + accountId,
email: 'email ' + accountId,
+ status: opt_status,
};
};
@@ -97,7 +98,7 @@
var account = makeAccount();
var suggestion = element._makeSuggestion({account: account});
assert.deepEqual(suggestion, {
- name: account.name + ' (' + account.email + ')',
+ name: account.name + ' <' + account.email + '>',
value: {account: account},
});
@@ -110,7 +111,21 @@
suggestion = element._makeSuggestion(account);
assert.deepEqual(suggestion, {
- name: account.name + ' (' + account.email + ')',
+ name: account.name + ' <' + account.email + '>',
+ value: {account: account, count: 1},
+ });
+
+ account = makeAccount('OOO');
+
+ suggestion = element._makeSuggestion({account: account});
+ assert.deepEqual(suggestion, {
+ name: account.name + ' <' + account.email + '> (OOO)',
+ value: {account: account},
+ });
+
+ suggestion = element._makeSuggestion(account);
+ assert.deepEqual(suggestion, {
+ name: account.name + ' <' + account.email + '> (OOO)',
value: {account: account, count: 1},
});
});
diff --git a/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list.html b/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list.html
index 14a7260..08e2e21 100644
--- a/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list.html
+++ b/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list.html
@@ -62,7 +62,9 @@
File comment:
</span>
</a>
- <gr-formatted-text class="message"
+ <gr-formatted-text
+ class="message"
+ no-trailing-margin
content="[[comment.message]]"
config="[[projectConfig.commentlinks]]"></gr-formatted-text>
</div>
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
index bb9cf15..1ab8a77 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
@@ -189,15 +189,15 @@
<div>Files</div>
<div class="rightControls">
<template is="dom-if"
- if="[[_fileListActionsVisible(_numFilesShown, _maxFilesForBulkActions)]]">
+ if="[[_fileListActionsVisible(_shownFiles.*, _maxFilesForBulkActions)]]">
<gr-button link on-tap="_expandAllDiffs">Show diffs</gr-button>
<span class="separator">/</span>
<gr-button link on-tap="_collapseAllDiffs">Hide diffs</gr-button>
</template>
<template is="dom-if"
- if="[[!_fileListActionsVisible(_numFilesShown, _maxFilesForBulkActions)]]">
+ if="[[!_fileListActionsVisible(_shownFiles.*, _maxFilesForBulkActions)]]">
<div class="warning">
- Bulk file list actions disabled for large amounts of files
+ Bulk actions disabled because there are too many files.
</div>
</template>
<span class="separator">/</span>
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
index ec463b6..ca1ffe9 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
@@ -102,7 +102,7 @@
_maxFilesForBulkActions: {
type: Number,
readOnly: true,
- value: 225,
+ value: 50,
},
},
@@ -649,8 +649,9 @@
return 'SIDE_BY_SIDE';
},
- _fileListActionsVisible: function(numFilesShown, maxFilesForBulkActions) {
- return numFilesShown <= maxFilesForBulkActions;
+ _fileListActionsVisible: function(shownFilesRecord,
+ maxFilesForBulkActions) {
+ return shownFilesRecord.base.length <= maxFilesForBulkActions;
},
_computePatchSetDescription: function(revisions, patchNum) {
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
index 28a784d..4c8b4f1 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
@@ -616,15 +616,14 @@
});
test('show/hide diffs disabled for large amounts of files', function(done) {
+ var computeSpy = sandbox.spy(element, '_fileListActionsVisible');
element._files = [];
element.changeNum = '42';
element.patchRange = {
basePatchNum: 'PARENT',
patchNum: '2',
};
- var computeSpy = sandbox.spy(element, '_fileListActionsVisible');
element.$.fileCursor.setCursorAtIndex(0);
- element._numFilesShown = 1;
flush(function() {
assert.isTrue(computeSpy.lastCall.returnValue);
var arr = [];
diff --git a/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password.html b/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password.html
index e58f1f2..d96237e 100644
--- a/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password.html
+++ b/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password.html
@@ -15,7 +15,9 @@
-->
<link rel="import" href="../../../bower_components/polymer/polymer.html">
+<link rel="import" href="../../../styles/gr-settings-styles.html">
<link rel="import" href="../../shared/gr-button/gr-button.html">
+<link rel="import" href="../../shared/gr-overlay/gr-overlay.html">
<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
<dom-module id="gr-http-password">
@@ -24,9 +26,24 @@
.password {
font-family: var(--monospace-font-family);
}
- .noPassword {
- color: #777;
+ #generatedPasswordOverlay {
+ padding: 2em;
+ width: 50em;
+ }
+ #generatedPasswordDisplay {
+ margin: 1em 0;
+ }
+ #generatedPasswordDisplay .value {
+ font-family: var(--monospace-font-family);
+ }
+ #passwordWarning {
font-style: italic;
+ text-align: center;
+ }
+ .closeButton {
+ bottom: 2em;
+ position: absolute;
+ right: 2em;
}
</style>
<style include="gr-settings-styles"></style>
@@ -35,28 +52,28 @@
<span class="title">Username</span>
<span class="value">[[_username]]</span>
</section>
- <section>
- <span class="title">Password</span>
- <span hidden$="[[!_hasPassword]]">
- <span class="value" hidden$="[[_passwordVisible]]">
- <gr-button
- link
- on-tap="_handleViewPasswordTap">Click to view</gr-button>
- </span>
- <span
- class="value password"
- hidden$="[[!_passwordVisible]]">[[_password]]</span>
- </span>
- <span class="value noPassword" hidden$="[[_hasPassword]]">(None)</span>
- </section>
<gr-button
id="generateButton"
on-tap="_handleGenerateTap">Generate New Password</gr-button>
- <gr-button
- id="clearButton"
- on-tap="_handleClearTap"
- disabled="[[!_hasPassword]]">Clear Password</gr-button>
</div>
+ <gr-overlay
+ id="generatedPasswordOverlay"
+ on-iron-overlay-closed="_generatedPasswordOverlayClosed"
+ with-backdrop>
+ <div class="gr-settings-styles">
+ <section id="generatedPasswordDisplay">
+ <span class="title">New Password:</span>
+ <span class="value">[[_generatedPassword]]</span>
+ </section>
+ <section id="passwordWarning">
+ This password will not be displayed again.<br>
+ If you lose it, you will need to generate a new one.
+ </section>
+ <gr-button
+ class="closeButton"
+ on-tap="_closeOverlay">Close</gr-button>
+ </div>
+ </gr-overlay>
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
</template>
<script src="gr-http-password.js"></script>
diff --git a/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password.js b/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password.js
index 9248632..bde36aa 100644
--- a/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password.js
+++ b/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password.js
@@ -17,65 +17,31 @@
Polymer({
is: 'gr-http-password',
- /**
- * Fired when getting the password fails with non-404.
- *
- * @event network-error
- */
-
properties: {
- _serverConfig: Object,
_username: String,
- _password: String,
- _passwordVisible: {
- type: Boolean,
- value: false,
- },
- _hasPassword: Boolean,
+ _generatedPassword: String,
},
loadData: function() {
- var promises = [];
-
- promises.push(this.$.restAPI.getAccount().then(function(account) {
+ return this.$.restAPI.getAccount().then(function(account) {
this._username = account.username;
- }.bind(this)));
-
- promises.push(this.$.restAPI
- .getAccountHttpPassword(this._handleGetPasswordError.bind(this))
- .then(function(pass) {
- this._password = pass;
- this._hasPassword = !!pass;
- }.bind(this)));
-
- return Promise.all(promises);
- },
-
- _handleGetPasswordError: function(response) {
- if (response.status === 404) {
- this._hasPassword = false;
- } else {
- this.fire('network-error', {response: response});
- }
- },
-
- _handleViewPasswordTap: function() {
- this._passwordVisible = true;
+ }.bind(this));
},
_handleGenerateTap: function() {
+ this._generatedPassword = 'Generating...';
+ this.$.generatedPasswordOverlay.open();
this.$.restAPI.generateAccountHttpPassword().then(function(newPassword) {
- this._hasPassword = true;
- this._passwordVisible = true;
- this._password = newPassword;
+ this._generatedPassword = newPassword;
}.bind(this));
},
- _handleClearTap: function() {
- this.$.restAPI.deleteAccountHttpPassword().then(function() {
- this._password = '';
- this._hasPassword = false;
- }.bind(this));
+ _closeOverlay: function() {
+ this.$.generatedPasswordOverlay.close();
+ },
+
+ _generatedPasswordOverlayClosed: function() {
+ this._generatedPassword = null;
},
});
})();
diff --git a/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_test.html b/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_test.html
index 36c9abf..e675de2 100644
--- a/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_test.html
@@ -31,7 +31,7 @@
</test-fixture>
<script>
- suite('gr-http-password tests (already has password)', function() {
+ suite('gr-http-password tests', function() {
var element;
var account;
var password;
@@ -51,106 +51,30 @@
element.loadData().then(function() { flush(done); });
});
- test('loads data', function() {
- assert.equal(element._username, 'user name');
- assert.equal(element._password, 'the password');
- assert.isFalse(element._passwordVisible);
- assert.isTrue(element._hasPassword);
- });
-
- test('view password', function() {
- var button = element.$$('.value gr-button');
- assert.isFalse(element._passwordVisible);
- MockInteractions.tap(button);
- assert.isTrue(element._passwordVisible);
- });
-
test('generate password', function() {
var button = element.$.generateButton;
var nextPassword = 'the new password';
+ var generateResolve;
var generateStub = sinon.stub(element.$.restAPI,
'generateAccountHttpPassword', function() {
- return Promise.resolve(nextPassword);
+ return new Promise(function(resolve) {
+ generateResolve = resolve;
+ });
});
- assert.isTrue(element._hasPassword);
- assert.isFalse(element._passwordVisible);
- assert.equal(element._password, 'the password');
+ assert.isNotOk(element._generatedPassword);
MockInteractions.tap(button);
assert.isTrue(generateStub.called);
+ assert.equal(element._generatedPassword, 'Generating...');
+
+ generateResolve(nextPassword);
+
generateStub.lastCall.returnValue.then(function() {
- assert.isTrue(element._passwordVisible);
- assert.isTrue(element._hasPassword);
- assert.equal(element._password, 'the new password');
- });
- });
-
- test('clear password', function() {
- var button = element.$.clearButton;
- var clearStub = sinon.stub(element.$.restAPI, 'deleteAccountHttpPassword',
- function() { return Promise.resolve(); });
-
- assert.isTrue(element._hasPassword);
- assert.equal(element._password, 'the password');
-
- MockInteractions.tap(button);
-
- assert.isTrue(clearStub.called);
- clearStub.lastCall.returnValue.then(function() {
- assert.isFalse(element._hasPassword);
- assert.equal(element._password, '');
+ assert.equal(element._generatedPassword, nextPassword);
});
});
});
- suite('gr-http-password tests (has no password)', function() {
- var element;
- var account;
-
- setup(function(done) {
- account = {username: 'user name'};
-
- stub('gr-rest-api-interface', {
- getAccount: function() { return Promise.resolve(account); },
- getAccountHttpPassword: function(errFn) {
- errFn({status: 404});
- return Promise.resolve('');
- },
- });
-
- element = fixture('basic');
- element.loadData().then(function() { flush(done); });
- });
-
- test('loads data', function() {
- assert.equal(element._username, 'user name');
- assert.isNotOk(element._password);
- assert.isFalse(element._passwordVisible);
- assert.isFalse(element._hasPassword);
- });
-
- test('generate password', function() {
- var button = element.$.generateButton;
- var nextPassword = 'the new password';
- var generateStub = sinon.stub(element.$.restAPI,
- 'generateAccountHttpPassword', function() {
- return Promise.resolve(nextPassword);
- });
-
- assert.isFalse(element._hasPassword);
- assert.isFalse(element._passwordVisible);
- assert.isNotOk(element._password);
-
- MockInteractions.tap(button);
-
- assert.isTrue(generateStub.called);
- generateStub.lastCall.returnValue.then(function() {
- assert.isTrue(element._passwordVisible);
- assert.isOk(element._hasPassword);
- assert.equal(element._password, 'the new password');
- });
- });
- });
</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.html b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.html
index 1d2beab..43721fe 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.html
+++ b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.html
@@ -44,6 +44,9 @@
<span hidden$="[[!_computeShowEmail(showEmail, account)]]">
[[_computeEmailStr(account)]]
</span>
+ <template is="dom-if" if="[[account.status]]">
+ <span>([[account.status]])</span>
+ </template>
</span>
</span>
</template>
diff --git a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.html b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.html
index 11560f1..8855b0a 100644
--- a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.html
+++ b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.html
@@ -29,6 +29,12 @@
gr-linked-text.pre {
margin: 0 0 1.4em 0;
}
+ :host.noTrailingMargin p:last-child,
+ :host.noTrailingMargin ul:last-child,
+ :host.noTrailingMargin blockquote:last-child,
+ :host.noTrailingMargin gr-linked-text.pre:last-child {
+ margin: 0;
+ }
blockquote {
border-left: 1px solid #aaa;
padding: 0 .7em;
diff --git a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.js b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.js
index 1b129a7..c17e9e4 100644
--- a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.js
+++ b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.js
@@ -22,12 +22,22 @@
properties: {
content: String,
config: Object,
+ noTrailingMargin: {
+ type: Boolean,
+ value: false,
+ },
},
observers: [
'_contentOrConfigChanged(content, config)',
],
+ ready: function() {
+ if (this.noTrailingMargin) {
+ this.classList.add('noTrailingMargin');
+ }
+ },
+
/**
* Get the plain text as it appears in the generated DOM.
*