Merge changes from topic 'registration'
* changes:
Fix misspelling of _shouldSuppressError
Add namespacing for keyboard shortcut disabling
Add account registration dialog to PolyGerrit
Allow anything after "/register/"
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java
index 18445b3..842c575 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java
@@ -92,7 +92,7 @@
serve("/starred").with(query("is:starred"));
serveRegex("^/settings/?$").with(screen(PageLinks.SETTINGS));
- serveRegex("^/register/?$").with(screen(PageLinks.REGISTER + "/"));
+ serveRegex("^/register(/.*)?$").with(registerScreen());
serveRegex("^/([1-9][0-9]*)/?$").with(directChangeById());
serveRegex("^/p/(.*)$").with(queryProjectNew());
serveRegex("^/r/(.+)/?$").with(DirectChangeByCommit.class);
@@ -243,6 +243,18 @@
return srv;
}
+ private Key<HttpServlet> registerScreen() {
+ return key(new HttpServlet() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected void doGet(final HttpServletRequest req,
+ final HttpServletResponse rsp) throws IOException {
+ toGerrit("/register" + req.getPathInfo(), req, rsp);
+ }
+ });
+ }
+
static void toGerrit(final String target, final HttpServletRequest req,
final HttpServletResponse rsp) throws IOException {
final StringBuilder url = new StringBuilder();
diff --git a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior.html b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior.html
index 17acac8..f636650 100644
--- a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior.html
+++ b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior.html
@@ -20,7 +20,9 @@
/** @polymerBehavior Gerrit.KeyboardShortcutBehavior */
var KeyboardShortcutBehavior = {
- enabled: true,
+ // Set of identifiers currently blocking keyboard shortcuts. Stored as
+ // a map of string to the value of true.
+ _disablers: {},
properties: {
keyEventTarget: {
@@ -43,8 +45,12 @@
this.keyEventTarget.removeEventListener('keydown', this._boundKeyHandler);
},
- shouldSupressKeyboardShortcut: function(e) {
- if (!KeyboardShortcutBehavior.enabled) { return true; }
+ shouldSuppressKeyboardShortcut: function(e) {
+ for (var c in KeyboardShortcutBehavior._disablers) {
+ if (KeyboardShortcutBehavior._disablers[c] === true) {
+ return true;
+ }
+ }
var getModifierState = e.getModifierState ?
e.getModifierState.bind(e) :
function() { return false; };
@@ -60,6 +66,14 @@
target.tagName == 'A' ||
target.tagName == 'GR-BUTTON';
},
+
+ disable: function(id) {
+ KeyboardShortcutBehavior._disablers[id] = true;
+ },
+
+ enable: function(id) {
+ delete KeyboardShortcutBehavior._disablers[id];
+ },
};
window.Gerrit = window.Gerrit || {};
diff --git a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior_test.html b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior_test.html
new file mode 100644
index 0000000..5ec4145
--- /dev/null
+++ b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior_test.html
@@ -0,0 +1,78 @@
+<!DOCTYPE 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.
+-->
+
+<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
+<title>keyboard-shortcut-behavior</title>
+
+<script src="../../../bower_components/webcomponentsjs/webcomponents.min.js"></script>
+<script src="../../../bower_components/web-component-tester/browser.js"></script>
+
+<link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
+<link rel="import" href="keyboard-shortcut-behavior.html">
+
+<test-fixture id="basic">
+ <template>
+ <test-element></test-element>
+ </template>
+</test-fixture>
+
+<script>
+ suite('keyboard-shortcut-behavior tests', function() {
+ var element;
+
+ suiteSetup(function() {
+ // Define a Polymer element that uses this behavior.
+ Polymer({
+ is: 'test-element',
+ behaviors: [Gerrit.KeyboardShortcutBehavior],
+ properties: {
+ keyEventTarget: {
+ value: function() { return document.body; },
+ },
+ log: {
+ value: function() { return []; },
+ },
+ },
+
+ _handleKey: function(e) {
+ if (!this.shouldSuppressKeyboardShortcut(e)) {
+ this.log.push(e.keyCode);
+ }
+ },
+ });
+ });
+
+ setup(function() {
+ element = fixture('basic');
+ });
+
+ test('blocks keydown events iff one or more disablers', function() {
+ MockInteractions.pressAndReleaseKeyOn(document.body, 97); // 'a'
+ Gerrit.KeyboardShortcutBehavior.enable('x'); // should have no effect
+ MockInteractions.pressAndReleaseKeyOn(document.body, 98); // 'b'
+ Gerrit.KeyboardShortcutBehavior.disable('x'); // blocking starts here
+ MockInteractions.pressAndReleaseKeyOn(document.body, 99); // 'c'
+ Gerrit.KeyboardShortcutBehavior.disable('y');
+ MockInteractions.pressAndReleaseKeyOn(document.body, 100); // 'd'
+ Gerrit.KeyboardShortcutBehavior.enable('x');
+ MockInteractions.pressAndReleaseKeyOn(document.body, 101); // 'e'
+ Gerrit.KeyboardShortcutBehavior.enable('y'); // blocking ends here
+ MockInteractions.pressAndReleaseKeyOn(document.body, 102); // 'f'
+ assert.deepEqual(element.log, [97, 98, 102]);
+ });
+ });
+</script>
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
index 4e17253..2be0afc 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
@@ -150,7 +150,7 @@
},
_handleKey: function(e) {
- if (this.shouldSupressKeyboardShortcut(e)) { return; }
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
if (this.groups == null) { return; }
var len = 0;
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 3d1cac7e..c794a4e 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
@@ -585,7 +585,7 @@
},
_handleKey: function(e) {
- if (this.shouldSupressKeyboardShortcut(e)) { return; }
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
switch (e.keyCode) {
case 65: // 'a'
if (this._loggedIn && !e.shiftKey) {
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 478faf5..22c82a0 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
@@ -295,7 +295,7 @@
},
_handleKey: function(e) {
- if (this.shouldSupressKeyboardShortcut(e)) { return; }
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
switch (e.keyCode) {
case 37: // left
if (e.shiftKey && this._showInlineDiffs) {
diff --git a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
index a38152a..479f389 100644
--- a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
+++ b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
@@ -39,7 +39,7 @@
this.unlisten(document, 'network-error', '_handleNetworkError');
},
- _shouldSupressError: function(msg) {
+ _shouldSuppressError: function(msg) {
return msg.indexOf(TOO_MANY_FILES) > -1;
},
@@ -54,7 +54,7 @@
}.bind(this));
} else {
e.detail.response.text().then(function(text) {
- if (!this._shouldSupressError(text)) {
+ if (!this._shouldSuppressError(text)) {
this._showAlert('Server error: ' + text);
}
}.bind(this));
diff --git a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js
index 6fc3cc1..2f017de 100644
--- a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js
+++ b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js
@@ -79,6 +79,10 @@
this.unlisten(window, 'location-change', '_handleLocationChange');
},
+ reload: function() {
+ this._loadAccount();
+ },
+
_handleLocationChange: function(e) {
this._loginURL = '/login/' + encodeURIComponent(
window.location.pathname +
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 05b191c..85e72c0 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.js
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
@@ -62,7 +62,7 @@
// In certain login flows the server may redirect to a hash without
// a leading slash, which page.js doesn't handle correctly.
if (data.hash[0] !== '/') {
- data.hash = '/' + data.hash
+ data.hash = '/' + data.hash;
}
page.redirect(data.hash);
return;
@@ -181,6 +181,12 @@
});
});
+ page(/^\/register(\/.*)?/, function(ctx) {
+ app.params = {justRegistered: true};
+ var path = ctx.params[0] || '/';
+ page.show(path);
+ });
+
page.start();
});
})();
diff --git a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js
index 2818121..4fd1e19 100644
--- a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js
+++ b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js
@@ -293,7 +293,7 @@
},
_handleKey: function(e) {
- if (this.shouldSupressKeyboardShortcut(e)) { return; }
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
switch (e.keyCode) {
case 191: // '/' or '?' with shift key.
// TODO(andybons): Localization using e.key/keypress event.
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread.js b/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread.js
index 963084a..90a4be1 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread.js
@@ -89,7 +89,7 @@
},
_handleKey: function(e) {
- if (this.shouldSupressKeyboardShortcut(e)) { return; }
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
if (e.keyCode === 69) { // 'e'
e.preventDefault();
this._expandCollapseComments(e.shiftKey);
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
index c5779a4..3c7fe02 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
@@ -189,7 +189,7 @@
},
_handleKey: function(e) {
- if (this.shouldSupressKeyboardShortcut(e)) { return; }
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
switch (e.keyCode) {
case 37: // left
diff --git a/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box.js b/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box.js
index 29b3c19..568b5e0 100644
--- a/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box.js
+++ b/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box.js
@@ -79,7 +79,7 @@
},
_handleKey: function(e) {
- if (this.shouldSupressKeyboardShortcut(e)) { return; }
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
if (e.keyCode === 67) { // 'c'
if (this._checkForModifiers(e)) { return; }
e.preventDefault();
diff --git a/polygerrit-ui/app/elements/gr-app.html b/polygerrit-ui/app/elements/gr-app.html
index 633e8f2..a403e6c 100644
--- a/polygerrit-ui/app/elements/gr-app.html
+++ b/polygerrit-ui/app/elements/gr-app.html
@@ -28,6 +28,7 @@
<link rel="import" href="./change-list/gr-dashboard-view/gr-dashboard-view.html">
<link rel="import" href="./change/gr-change-view/gr-change-view.html">
<link rel="import" href="./diff/gr-diff-view/gr-diff-view.html">
+<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-overlay/gr-overlay.html">
@@ -86,7 +87,8 @@
color: #b71c1c;
}
</style>
- <gr-main-header search-query="{{params.query}}"></gr-main-header>
+ <gr-main-header id="mainHeader" search-query="{{params.query}}">
+ </gr-main-header>
<main>
<template is="dom-if" if="[[_showChangeListView]]" restamp="true">
<gr-change-list-view
@@ -113,7 +115,9 @@
change-view-state="{{_viewState.changeView}}"></gr-diff-view>
</template>
<template is="dom-if" if="[[_showSettingsView]]" restamp="true">
- <gr-settings-view></gr-settings-view>
+ <gr-settings-view
+ on-account-detail-update="_handleAccountDetailUpdate">
+ </gr-settings-view>
</template>
<div id="errorView" class="errorView" hidden>
<div class="errorEmoji">[[_lastError.emoji]]</div>
@@ -138,6 +142,12 @@
view="[[params.view]]"
on-close="_handleKeyboardShortcutDialogClose"></gr-keyboard-shortcuts-dialog>
</gr-overlay>
+ <gr-overlay id="registration" with-backdrop>
+ <gr-registration-dialog
+ on-account-detail-update="_handleAccountDetailUpdate"
+ on-close="_handleRegistrationDialogClose">
+ </gr-registration-dialog>
+ </gr-overlay>
<gr-error-manager></gr-error-manager>
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
<gr-reporting id="reporting"></gr-reporting>
diff --git a/polygerrit-ui/app/elements/gr-app.js b/polygerrit-ui/app/elements/gr-app.js
index 32130f8..b758ff0 100644
--- a/polygerrit-ui/app/elements/gr-app.js
+++ b/polygerrit-ui/app/elements/gr-app.js
@@ -108,6 +108,9 @@
this.set('_showChangeView', view === 'gr-change-view');
this.set('_showDiffView', view === 'gr-diff-view');
this.set('_showSettingsView', view === 'gr-settings-view');
+ if (this.params.justRegistered) {
+ this.$.registration.open();
+ }
},
_loadPlugins: function(plugins) {
@@ -192,7 +195,7 @@
},
_handleKey: function(e) {
- if (this.shouldSupressKeyboardShortcut(e)) { return; }
+ if (this.shouldSuppressKeyboardShortcut(e)) { return; }
if (e.keyCode === 191 && e.shiftKey) { // '/' or '?' with shift key.
this.$.keyboardShortcuts.open();
@@ -202,5 +205,17 @@
_handleKeyboardShortcutDialogClose: function() {
this.$.keyboardShortcuts.close();
},
+
+ _handleAccountDetailUpdate: function(e) {
+ this.$.mainHeader.reload();
+ if (this.params.view === 'gr-settings-view') {
+ this.$$('gr-settings-view').reloadAccountDetail();
+ }
+ },
+
+ _handleRegistrationDialogClose: function(e) {
+ this.params.justRegistered = false;
+ this.$.registration.close();
+ },
});
})();
diff --git a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.js b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.js
index 3930a78..2704ce5 100644
--- a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.js
+++ b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.js
@@ -17,6 +17,12 @@
Polymer({
is: 'gr-account-info',
+ /**
+ * Fired when account details are changed.
+ *
+ * @event account-detail-update
+ */
+
properties: {
mutable: {
type: Boolean,
@@ -72,6 +78,7 @@
return this.$.restAPI.setAccountName(this._account.name).then(function() {
this.hasUnsavedChanges = false;
this._saving = false;
+ this.fire('account-detail-update');
}.bind(this));
},
diff --git a/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.html b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.html
new file mode 100644
index 0000000..ee358d5
--- /dev/null
+++ b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.html
@@ -0,0 +1,98 @@
+<!--
+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="../../../styles/gr-settings-styles.html">
+<link rel="import" href="../../shared/gr-button/gr-button.html">
+<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
+
+<dom-module id="gr-registration-dialog">
+ <template>
+ <style include="gr-settings-styles"></style>
+ <style>
+ :host {
+ display: block;
+ }
+ main {
+ max-width: 46em;
+ }
+ hr {
+ margin-top: 1em;
+ margin-bottom: 1em;
+ }
+ header {
+ border-bottom: 1px solid #ddd;
+ font-weight: bold;
+ }
+ header,
+ main,
+ footer {
+ padding: .5em .65em;
+ }
+ footer {
+ display: flex;
+ justify-content: space-between;
+ }
+ </style>
+ <main class="gr-settings-styles">
+ <header>Please confirm your contact information</header>
+ <main>
+ <p>
+ The following contact information was automatically obtained when you
+ signed in to the site. This information is used to display who you are
+ to others, and to send updates to code reviews you have either started
+ or subscribed to.
+ </p>
+ <hr>
+ <section>
+ <div class="title">Full Name</div>
+ <input
+ is="iron-input"
+ id="name"
+ bind-value="{{_account.name}}"
+ disabled="[[_saving]]"
+ on-keydown="_handleNameKeydown">
+ </section>
+ <section>
+ <div class="title">Preferred Email</div>
+ <select
+ is="gr-select"
+ id="email"
+ bind-value="{{_account.email}}"
+ disabled="[[_saving]]">
+ <option value="[[_account.email]]">[[_account.email]]</option>
+ <template is="dom-repeat" items="[[_account.secondary_emails]]">
+ <option value="[[item]]">[[item]]</option>
+ </template>
+ </select>
+ </section>
+ </main>
+ <footer>
+ <gr-button
+ id="saveButton"
+ primary
+ disabled="[[_saving]]"
+ on-tap="_handleSave">Save</gr-button>
+ <gr-button
+ id="closeButton"
+ disabled="[[_saving]]"
+ on-tap="_handleClose">Close</gr-button>
+ </footer>
+ </main>
+ <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
+ </template>
+ <script src="gr-registration-dialog.js"></script>
+</dom-module>
diff --git a/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.js b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.js
new file mode 100644
index 0000000..9acdba9
--- /dev/null
+++ b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.js
@@ -0,0 +1,79 @@
+// 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';
+
+ Polymer({
+ is: 'gr-registration-dialog',
+
+ /**
+ * Fired when account details are changed.
+ *
+ * @event account-detail-update
+ */
+
+ /**
+ * Fired when the close button is pressed.
+ *
+ * @event close
+ */
+
+ properties: {
+ _account: Object,
+ _saving: Boolean,
+ },
+
+ hostAttributes: {
+ role: 'dialog',
+ },
+
+ attached: function() {
+ this.$.restAPI.getAccount().then(function(account) {
+ this._account = account;
+ }.bind(this));
+ },
+
+ _handleNameKeydown: function(e) {
+ if (e.keyCode === 13) { // Enter
+ e.stopPropagation();
+ this._save();
+ }
+ },
+
+ _save: function() {
+ this._saving = true;
+ var promises = [
+ this.$.restAPI.setAccountName(this.$.name.value),
+ this.$.restAPI.setPreferredAccountEmail(this.$.email.value),
+ ];
+ return Promise.all(promises).then(function() {
+ this._saving = false;
+ this.fire('account-detail-update');
+ }.bind(this));
+ },
+
+ _handleSave: function(e) {
+ e.preventDefault();
+ this._save().then(function() {
+ this.fire('close');
+ }.bind(this));
+ },
+
+ _handleClose: function(e) {
+ e.preventDefault();
+ this._saving = true; // disable buttons indefinitely
+ this.fire('close');
+ },
+ });
+})();
diff --git a/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog_test.html b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog_test.html
new file mode 100644
index 0000000..0b9dc9c
--- /dev/null
+++ b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog_test.html
@@ -0,0 +1,145 @@
+<!DOCTYPE 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.
+-->
+
+<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
+<title>gr-registration-dialog</title>
+
+<script src="../../../bower_components/webcomponentsjs/webcomponents.min.js"></script>
+<script src="../../../bower_components/web-component-tester/browser.js"></script>
+
+<link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
+<link rel="import" href="gr-registration-dialog.html">
+
+<test-fixture id="basic">
+ <template>
+ <gr-registration-dialog></gr-registration-dialog>
+ </template>
+</test-fixture>
+
+<test-fixture id="blank">
+ <template>
+ <div></div>
+ </template>
+</test-fixture>
+
+<script>
+ suite('gr-registration-dialog tests', function() {
+ var element;
+ var account;
+ var _listeners;
+
+ setup(function(done) {
+ _listeners = {};
+
+ account = {
+ name: 'name',
+ email: 'email',
+ secondary_emails: [
+ 'email2',
+ 'email3',
+ ],
+ };
+
+ stub('gr-rest-api-interface', {
+ getAccount: function() {
+ // Once the account is resolved, we can let the test proceed.
+ flush(done);
+ return Promise.resolve(account);
+ },
+ setAccountName: function(name) {
+ account.name = name;
+ return Promise.resolve();
+ },
+ setPreferredAccountEmail: function(email) {
+ account.email = email;
+ return Promise.resolve();
+ },
+ });
+
+ element = fixture('basic');
+ });
+
+ teardown(function() {
+ for (var eventType in _listeners) {
+ if (_listeners.hasOwnProperty(eventType)) {
+ element.removeEventListener(eventType, _listeners[eventType]);
+ }
+ }
+ });
+
+ function listen(eventType) {
+ return new Promise(function(resolve) {
+ _listeners[eventType] = function() { resolve(); };
+ element.addEventListener(eventType, _listeners[eventType]);
+ });
+ }
+
+ function save(opt_action) {
+ var promise = listen('account-detail-update');
+ if (opt_action) {
+ opt_action();
+ } else {
+ MockInteractions.tap(element.$.saveButton);
+ }
+ return promise;
+ }
+
+ function close(opt_action) {
+ var promise = listen('close');
+ if (opt_action) {
+ opt_action();
+ } else {
+ MockInteractions.tap(element.$.closeButton);
+ }
+ return promise;
+ }
+
+ test('fires the close event on close', function(done) {
+ close().then(done);
+ });
+
+ test('fires the close event on save', function(done) {
+ close(function() {
+ MockInteractions.tap(element.$.saveButton);
+ }).then(done);
+ });
+
+ test('saves name and preferred email', function(done) {
+ element.$.name.value = 'new name';
+ element.$.email.value = 'email3';
+
+ // Nothing should be committed yet.
+ assert.equal(account.name, 'name');
+ assert.equal(account.email, 'email');
+
+ // Save and verify new values are committed.
+ save().then(function() {
+ assert.equal(account.name, 'new name');
+ assert.equal(account.email, 'email3');
+ }).then(done);
+ });
+
+ test('pressing enter saves name', function(done) {
+ element.$.name.value = 'entered name';
+ save(function() {
+ MockInteractions.pressAndReleaseKeyOn(element.$.name, 13); // 'enter'
+ }).then(function() {
+ assert.equal(account.name, 'entered name');
+ }).then(done);
+ });
+ });
+</script>
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
index 6c62408..81a56a1 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
@@ -134,6 +134,13 @@
this.unlisten(window, 'scroll', '_handleBodyScroll');
},
+ reloadAccountDetail: function() {
+ Promise.all([
+ this.$.accountInfo.loadData(),
+ this.$.emailEditor.loadData(),
+ ]);
+ },
+
_handleBodyScroll: function(e) {
if (this._headerHeight === undefined) {
var top = this.$.settingsNav.offsetTop;
diff --git a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.js b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.js
index da28e49..f4a389a 100644
--- a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.js
+++ b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.js
@@ -25,25 +25,24 @@
],
detached: function() {
- // For good measure.
- Gerrit.KeyboardShortcutBehavior.enabled = true;
+ Gerrit.KeyboardShortcutBehavior.enable(this._id());
},
open: function() {
return new Promise(function(resolve) {
- Gerrit.KeyboardShortcutBehavior.enabled = false;
+ Gerrit.KeyboardShortcutBehavior.disable(this._id());
Polymer.IronOverlayBehaviorImpl.open.apply(this, arguments);
this._awaitOpen(resolve);
}.bind(this));
},
close: function() {
- Gerrit.KeyboardShortcutBehavior.enabled = true;
+ Gerrit.KeyboardShortcutBehavior.enable(this._id());
Polymer.IronOverlayBehaviorImpl.close.apply(this, arguments);
},
cancel: function() {
- Gerrit.KeyboardShortcutBehavior.enabled = true;
+ Gerrit.KeyboardShortcutBehavior.enable(this._id());
Polymer.IronOverlayBehaviorImpl.cancel.apply(this, arguments);
},
@@ -72,5 +71,9 @@
}.bind(this);
step.call(this);
},
+
+ _id: function() {
+ return this.getAttribute('id') || 'global';
+ },
});
})();
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 f46404a..91bde6b 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
@@ -239,12 +239,39 @@
setPreferredAccountEmail: function(email, opt_errFn, opt_ctx) {
return this.send('PUT', '/accounts/self/emails/' +
- encodeURIComponent(email) + '/preferred', null, opt_errFn, opt_ctx);
+ encodeURIComponent(email) + '/preferred', null,
+ opt_errFn, opt_ctx).then(function() {
+ // If result of getAccountEmails is in cache, update it in the cache
+ // so we don't have to invalidate it.
+ var cachedEmails = this._cache['/accounts/self/emails'];
+ if (cachedEmails) {
+ var emails = cachedEmails.map(function(entry) {
+ if (entry.email === email) {
+ return {email: email, preferred: true};
+ } else {
+ return {email: email};
+ }
+ });
+ this._cache['/accounts/self/emails'] = emails;
+ }
+ }.bind(this));
},
setAccountName: function(name, opt_errFn, opt_ctx) {
return this.send('PUT', '/accounts/self/name', {name: name}, opt_errFn,
- opt_ctx);
+ opt_ctx).then(function(response) {
+ // If result of getAccount is in cache, update it in the cache
+ // so we don't have to invalidate it.
+ var cachedAccount = this._cache['/accounts/self/detail'];
+ if (cachedAccount) {
+ return this.getResponseObject(response).then(function(newName) {
+ // Replace object in cache with new object to force UI updates.
+ // TODO(logan): Polyfill for Object.assign in IE
+ this._cache['/accounts/self/detail'] = Object.assign(
+ {}, cachedAccount, {name: newName});
+ }.bind(this));
+ }
+ }.bind(this));
},
getAccountGroups: function() {
diff --git a/polygerrit-ui/app/test/index.html b/polygerrit-ui/app/test/index.html
index c5df0a2..a25656f 100644
--- a/polygerrit-ui/app/test/index.html
+++ b/polygerrit-ui/app/test/index.html
@@ -74,6 +74,7 @@
'settings/gr-group-list/gr-group-list_test.html',
'settings/gr-http-password/gr-http-password_test.html',
'settings/gr-menu-editor/gr-menu-editor_test.html',
+ 'settings/gr-registration-dialog/gr-registration-dialog_test.html',
'settings/gr-settings-view/gr-settings-view_test.html',
'settings/gr-ssh-editor/gr-ssh-editor_test.html',
'settings/gr-watched-projects-editor/gr-watched-projects-editor_test.html',