blob: a66c38d8defa770f4835802e06195f3eab9f491b [file] [log] [blame]
/**
* @license
* 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';
const PREFS_SECTION_FIELDS = [
'changes_per_page',
'date_format',
'time_format',
'email_strategy',
'diff_view',
'publish_comments_on_push',
'work_in_progress_by_default',
'default_base_for_merges',
'signed_off_by',
'email_format',
'size_bar_in_change_table',
'relative_date_in_change_table',
];
const GERRIT_DOCS_BASE_URL = 'https://gerrit-review.googlesource.com/' +
'Documentation';
const GERRIT_DOCS_FILTER_PATH = '/user-notify.html';
const ABSOLUTE_URL_PATTERN = /^https?:/;
const TRAILING_SLASH_PATTERN = /\/$/;
const RELOAD_MESSAGE = 'Reloading...';
const HTTP_AUTH = [
'HTTP',
'HTTP_LDAP',
];
Polymer({
is: 'gr-settings-view',
_legacyUndefinedCheck: true,
/**
* Fired when the title of the page should change.
*
* @event title-change
*/
/**
* Fired with email confirmation text, or when the page reloads.
*
* @event show-alert
*/
properties: {
prefs: {
type: Object,
value() { return {}; },
},
params: {
type: Object,
value() { return {}; },
},
_accountNameMutable: Boolean,
_accountInfoChanged: Boolean,
_changeTableColumnsNotDisplayed: Array,
/** @type {?} */
_localPrefs: {
type: Object,
value() { return {}; },
},
_localChangeTableColumns: {
type: Array,
value() { return []; },
},
_localMenu: {
type: Array,
value() { return []; },
},
_loading: {
type: Boolean,
value: true,
},
_changeTableChanged: {
type: Boolean,
value: false,
},
_prefsChanged: {
type: Boolean,
value: false,
},
/** @type {?} */
_diffPrefsChanged: Boolean,
/** @type {?} */
_editPrefsChanged: Boolean,
_menuChanged: {
type: Boolean,
value: false,
},
_watchedProjectsChanged: {
type: Boolean,
value: false,
},
_keysChanged: {
type: Boolean,
value: false,
},
_gpgKeysChanged: {
type: Boolean,
value: false,
},
_newEmail: String,
_addingEmail: {
type: Boolean,
value: false,
},
_lastSentVerificationEmail: {
type: String,
value: null,
},
/** @type {?} */
_serverConfig: Object,
/** @type {?string} */
_docsBaseUrl: String,
_emailsChanged: Boolean,
/**
* For testing purposes.
*/
_loadingPromise: Object,
_showNumber: Boolean,
_isDark: {
type: Boolean,
value: false,
},
},
behaviors: [
Gerrit.DocsUrlBehavior,
Gerrit.ChangeTableBehavior,
],
observers: [
'_handlePrefsChanged(_localPrefs.*)',
'_handleMenuChanged(_localMenu.splices)',
'_handleChangeTableChanged(_localChangeTableColumns, _showNumber)',
],
attached() {
// Polymer 2: anchor tag won't work on shadow DOM
// we need to manually calling scrollIntoView when hash changed
this.listen(window, 'location-change', '_handleLocationChange');
this.fire('title-change', {title: 'Settings'});
this._isDark = !!window.localStorage.getItem('dark-theme');
const promises = [
this.$.accountInfo.loadData(),
this.$.watchedProjectsEditor.loadData(),
this.$.groupList.loadData(),
this.$.identities.loadData(),
this.$.editPrefs.loadData(),
this.$.diffPrefs.loadData(),
];
promises.push(this.$.restAPI.getPreferences().then(prefs => {
this.prefs = prefs;
this._showNumber = !!prefs.legacycid_in_change_table;
this._copyPrefs('_localPrefs', 'prefs');
this._cloneMenu(prefs.my);
this._cloneChangeTableColumns();
}));
promises.push(this.$.restAPI.getConfig().then(config => {
this._serverConfig = config;
const configPromises = [];
if (this._serverConfig && this._serverConfig.sshd) {
configPromises.push(this.$.sshEditor.loadData());
}
if (this._serverConfig &&
this._serverConfig.receive &&
this._serverConfig.receive.enable_signed_push) {
configPromises.push(this.$.gpgEditor.loadData());
}
configPromises.push(
this.getDocsBaseUrl(config, this.$.restAPI)
.then(baseUrl => { this._docsBaseUrl = baseUrl; }));
return Promise.all(configPromises);
}));
if (this.params.emailToken) {
promises.push(this.$.restAPI.confirmEmail(this.params.emailToken).then(
message => {
if (message) {
this.fire('show-alert', {message});
}
this.$.emailEditor.loadData();
}));
} else {
promises.push(this.$.emailEditor.loadData());
}
this._loadingPromise = Promise.all(promises).then(() => {
this._loading = false;
// Handle anchor tag for initial load
this._handleLocationChange();
});
},
detached() {
this.unlisten(window, 'location-change', '_handleLocationChange');
},
_handleLocationChange() {
// Handle anchor tag after dom attached
const urlHash = window.location.hash;
if (urlHash) {
// Use shadowRoot for Polymer 2
const elem = (this.shadowRoot || document).querySelector(urlHash);
if (elem) {
elem.scrollIntoView();
}
}
},
reloadAccountDetail() {
Promise.all([
this.$.accountInfo.loadData(),
this.$.emailEditor.loadData(),
]);
},
_isLoading() {
return this._loading || this._loading === undefined;
},
_copyPrefs(to, from) {
for (let i = 0; i < PREFS_SECTION_FIELDS.length; i++) {
this.set([to, PREFS_SECTION_FIELDS[i]],
this[from][PREFS_SECTION_FIELDS[i]]);
}
},
_cloneMenu(prefs) {
const menu = [];
for (const item of prefs) {
menu.push({
name: item.name,
url: item.url,
target: item.target,
});
}
this._localMenu = menu;
},
_cloneChangeTableColumns() {
let columns = this.getVisibleColumns(this.prefs.change_table);
if (columns.length === 0) {
columns = this.columnNames;
this._changeTableColumnsNotDisplayed = [];
} else {
this._changeTableColumnsNotDisplayed = this.getComplementColumns(
this.prefs.change_table);
}
this._localChangeTableColumns = columns;
},
_formatChangeTableColumns(changeTableArray) {
return changeTableArray.map(item => {
return {column: item};
});
},
_handleChangeTableChanged() {
if (this._isLoading()) { return; }
this._changeTableChanged = true;
},
_handlePrefsChanged(prefs) {
if (this._isLoading()) { return; }
this._prefsChanged = true;
},
_handleRelativeDateInChangeTable() {
this.set('_localPrefs.relative_date_in_change_table',
this.$.relativeDateInChangeTable.checked);
},
_handleShowSizeBarsInFileListChanged() {
this.set('_localPrefs.size_bar_in_change_table',
this.$.showSizeBarsInFileList.checked);
},
_handlePublishCommentsOnPushChanged() {
this.set('_localPrefs.publish_comments_on_push',
this.$.publishCommentsOnPush.checked);
},
_handleWorkInProgressByDefault() {
this.set('_localPrefs.work_in_progress_by_default',
this.$.workInProgressByDefault.checked);
},
_handleInsertSignedOff() {
this.set('_localPrefs.signed_off_by', this.$.insertSignedOff.checked);
},
_handleMenuChanged() {
if (this._isLoading()) { return; }
this._menuChanged = true;
},
_handleSaveAccountInfo() {
this.$.accountInfo.save();
},
_handleSavePreferences() {
this._copyPrefs('prefs', '_localPrefs');
return this.$.restAPI.savePreferences(this.prefs).then(() => {
this._prefsChanged = false;
});
},
_handleSaveChangeTable() {
this.set('prefs.change_table', this._localChangeTableColumns);
this.set('prefs.legacycid_in_change_table', this._showNumber);
this._cloneChangeTableColumns();
return this.$.restAPI.savePreferences(this.prefs).then(() => {
this._changeTableChanged = false;
});
},
_handleSaveDiffPreferences() {
this.$.diffPrefs.save();
},
_handleSaveEditPreferences() {
this.$.editPrefs.save();
},
_handleSaveMenu() {
this.set('prefs.my', this._localMenu);
this._cloneMenu(this.prefs.my);
return this.$.restAPI.savePreferences(this.prefs).then(() => {
this._menuChanged = false;
});
},
_handleResetMenuButton() {
return this.$.restAPI.getDefaultPreferences().then(data => {
if (data && data.my) {
this._cloneMenu(data.my);
}
});
},
_handleSaveWatchedProjects() {
this.$.watchedProjectsEditor.save();
},
_computeHeaderClass(changed) {
return changed ? 'edited' : '';
},
_handleSaveEmails() {
this.$.emailEditor.save();
},
_handleNewEmailKeydown(e) {
if (e.keyCode === 13) { // Enter
e.stopPropagation();
this._handleAddEmailButton();
}
},
_isNewEmailValid(newEmail) {
return newEmail.includes('@');
},
_computeAddEmailButtonEnabled(newEmail, addingEmail) {
return this._isNewEmailValid(newEmail) && !addingEmail;
},
_handleAddEmailButton() {
if (!this._isNewEmailValid(this._newEmail)) { return; }
this._addingEmail = true;
this.$.restAPI.addAccountEmail(this._newEmail).then(response => {
this._addingEmail = false;
// If it was unsuccessful.
if (response.status < 200 || response.status >= 300) { return; }
this._lastSentVerificationEmail = this._newEmail;
this._newEmail = '';
});
},
_getFilterDocsLink(docsBaseUrl) {
let base = docsBaseUrl;
if (!base || !ABSOLUTE_URL_PATTERN.test(base)) {
base = GERRIT_DOCS_BASE_URL;
}
// Remove any trailing slash, since it is in the GERRIT_DOCS_FILTER_PATH.
base = base.replace(TRAILING_SLASH_PATTERN, '');
return base + GERRIT_DOCS_FILTER_PATH;
},
_handleToggleDark() {
if (this._isDark) {
window.localStorage.removeItem('dark-theme');
} else {
window.localStorage.setItem('dark-theme', 'true');
}
this.dispatchEvent(new CustomEvent('show-alert', {
detail: {message: RELOAD_MESSAGE},
bubbles: true,
}));
this.async(() => {
window.location.reload();
}, 1);
},
_showHttpAuth(config) {
if (config && config.auth &&
config.auth.git_basic_auth_policy) {
return HTTP_AUTH.includes(
config.auth.git_basic_auth_policy.toUpperCase());
}
return false;
},
});
})();