
* stable-3.0: Update git submodules Update git submodules Update git submodules Fix documentation of UI selection Set version to 2.16.12-SNAPSHOT Set version to 2.16.11 Update git submodules Revert "GerritServer: Silence non-critical logs from JGit's FileSnapshot" Revert "GerritServer: Silence non-critical logs from JGit's FS" Revert "Upgrade JGit to 5.1.10.201908230655-r" Revert "Stop using deprecated DirCacheEntry#setLastModified(long)" Update git submodules Update git submodules Update git submodules Update git submodules Update git submodules Update git submodules Set version to 2.15.17-SNAPSHOT Update git submodules Update git submodules Revert "Upgrade JGit to 5.3.4.201908231101-r" Set version to 2.15.16 Revert "CreateAccount: Fail early when invalid SSH key is given" Update git submodules tools/eclipse/project.py: Fix typo of bazelisk Set XSRF on '/' under PolyGerrit Migrate from old-style legacy .java provider to the new JavaInfo. Remove deleted rules for the new added section Support bazelisk or bazel in tools/eclipse/project.py Rework imports in project.py Update project.py to use argparse AccountIT: Test that account is not created with invalid email CreateAccount: Fail early when invalid SSH key is given Update git submodules GerritServer: Silence non-critical logs from JGit's FS GerritServer: Silence non-critical logs from JGit's FileSnapshot Stop using deprecated DirCacheEntry#setLastModified(long) ProjectState: Fix 'invalid type qualification' javadoc warning Upgrade JGit to 5.3.4.201908231101-r Documentation: refresh IntelliJ IDEA developer documentation Documentation: update external links to Bazel Use base url for commentlink Update git submodules Update git submodules Don't store LabelTypes in ProjectState Upgrade highlight.js to latest master revision Update git submodules Update git submodules Update git submodules StarredChangesUtil: Stop using deprecated RefDatabase.getRef Suppress warnings about deprecated BaseReceivePack DeleteRef: Stop using deprecated RefDatabase.getRef Upgrade elasticsearch-rest-client to 7.3.1 Add .gitreview file Remove vestigal GWT plugin loading hooks Upgrade JGit to 5.1.10.201908230655-r DeleteDraftComments: Don't update change modified timestamp ChangeIT: set submittableAfterLosingPermissions private Rebase: Don't swallow caught exception Output NoteDb migration progress to Flogger Update git submodules Remove AccountPatchReview data when change gets auto-abandoned DefaultChangeReportFormatter: Make constructor and urlFormatter visible StarredChangesUtil: Fix NPE when ref to be deleted doesn't exist StarredChangesUtil: Throw LockFailureException on LOCK_FAILURE Add test for creating a change on a non-existing base change Rebase: Do not fail with 500 ISE if non-existing change is given as base Fix detecting changes of parent trees when computing change kind for merge commit Remove duplicate descriptions of fields in Requirement JSON entity Allow to set content type in the plugin REST API interface InternalAccountQuery: Add back the oneByExternalId method Set version to 2.16.11-SNAPSHOT Revert "Migrate from old-style legacy .java provider to the new JavaInfo." Catch all exceptions for reporting on Schema_130 migration Update git submodules Migrate from old-style legacy .java provider to the new JavaInfo. Update git submodules Update git submodules AuthRequest: Fix Javadoc for return values ChangeApi: Add methods to get change comments/drafts as list Update git submodules ListChangeComments: Extend ListChangeDrafts Upgrade Go Bazel rules to the latest version detach -> detached Fix anchor tag for settings page Add support for Elasticsearch version 7.3.* PrologEnvironment: Reduce "setting reductionLimit" log spam ElasticContainer: Upgrade to 6.8.2 image for V6_8 tests Fix typo: program Fix email token routing Clarify usage of 'parent' option in list files API Remove unused Skylark patch file Files: Use Gerrit API to get revision parents Fix broken link for rest-api-projects.html#commentlink-info Add support for Elasticsearch version 6.8.x Upgrade elasticsearch-rest-client to 7.2.1 Add support for "Link Another Identity" in gr-identities Update git submodules CommitApi: Add method to get commit info Consolidate all CommitApi tests into a single class Files: Validate parent option to prevent internal server error RevisionIT: Assert that files(base) only works for patch set revisions Fix and expand documentation of REST API to get revision files RevisionIT#files: Simplify assertion Update git submodules Update git submodules Update git submodules Update git submodules Remove default bug tracker from _feedbackUrl PG: Add shortcuts for dashboard and watched changes PG: Allow empty label values Remove token param from getCapabilities Add an extension point to show a small banner next to the search bar Fix gr-group-audit-log to use tbody Change-Id: Iaf877b737f115d4fe95af74f8284eec19112a21d
691 lines
21 KiB
JavaScript
691 lines
21 KiB
JavaScript
/**
|
|
* @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(window) {
|
|
'use strict';
|
|
|
|
/**
|
|
* Hash of loaded and installed plugins, name to Plugin object.
|
|
*/
|
|
const _plugins = {};
|
|
|
|
/**
|
|
* Array of plugin URLs to be loaded, name to url.
|
|
*/
|
|
let _pluginsPending = {};
|
|
|
|
let _pluginsInstalled = [];
|
|
|
|
let _pluginsPendingCount = -1;
|
|
|
|
const PRELOADED_PROTOCOL = 'preloaded:';
|
|
|
|
const UNKNOWN_PLUGIN = 'unknown';
|
|
|
|
const PANEL_ENDPOINTS_MAPPING = {
|
|
CHANGE_SCREEN_BELOW_COMMIT_INFO_BLOCK: 'change-view-integration',
|
|
CHANGE_SCREEN_BELOW_CHANGE_INFO_BLOCK: 'change-metadata-item',
|
|
};
|
|
|
|
const PLUGIN_LOADING_TIMEOUT_MS = 10000;
|
|
|
|
let _restAPI;
|
|
|
|
const getRestAPI = () => {
|
|
if (!_restAPI) {
|
|
_restAPI = document.createElement('gr-rest-api-interface');
|
|
}
|
|
return _restAPI;
|
|
};
|
|
|
|
let _reporting;
|
|
const getReporting = () => {
|
|
if (!_reporting) {
|
|
_reporting = document.createElement('gr-reporting');
|
|
}
|
|
return _reporting;
|
|
};
|
|
|
|
// TODO (viktard): deprecate in favor of GrPluginRestApi.
|
|
function send(method, url, opt_callback, opt_payload) {
|
|
return getRestAPI().send(method, url, opt_payload).then(response => {
|
|
if (response.status < 200 || response.status >= 300) {
|
|
return response.text().then(text => {
|
|
if (text) {
|
|
return Promise.reject(text);
|
|
} else {
|
|
return Promise.reject(response.status);
|
|
}
|
|
});
|
|
} else {
|
|
return getRestAPI().getResponseObject(response);
|
|
}
|
|
}).then(response => {
|
|
if (opt_callback) {
|
|
opt_callback(response);
|
|
}
|
|
return response;
|
|
});
|
|
}
|
|
|
|
const API_VERSION = '0.1';
|
|
|
|
/**
|
|
* Plugin-provided custom components can affect content in extension
|
|
* points using one of following methods:
|
|
* - DECORATE: custom component is set with `content` attribute and may
|
|
* decorate (e.g. style) DOM element.
|
|
* - REPLACE: contents of extension point are replaced with the custom
|
|
* component.
|
|
* - STYLE: custom component is a shared styles module that is inserted
|
|
* into the extension point.
|
|
*/
|
|
const EndpointType = {
|
|
DECORATE: 'decorate',
|
|
REPLACE: 'replace',
|
|
STYLE: 'style',
|
|
};
|
|
|
|
function flushPreinstalls() {
|
|
if (window.Gerrit.flushPreinstalls) {
|
|
window.Gerrit.flushPreinstalls();
|
|
}
|
|
}
|
|
|
|
function installPreloadedPlugins() {
|
|
if (!Gerrit._preloadedPlugins) { return; }
|
|
for (const name in Gerrit._preloadedPlugins) {
|
|
if (!Gerrit._preloadedPlugins.hasOwnProperty(name)) { continue; }
|
|
const callback = Gerrit._preloadedPlugins[name];
|
|
Gerrit.install(callback, API_VERSION, PRELOADED_PROTOCOL + name);
|
|
}
|
|
}
|
|
|
|
function getPluginNameFromUrl(url) {
|
|
if (!(url instanceof URL)) {
|
|
try {
|
|
url = new URL(url);
|
|
} catch (e) {
|
|
console.warn(e);
|
|
return null;
|
|
}
|
|
}
|
|
if (url.protocol === PRELOADED_PROTOCOL) {
|
|
return url.pathname;
|
|
}
|
|
const base = Gerrit.BaseUrlBehavior.getBaseUrl();
|
|
const pathname = url.pathname.replace(base, '');
|
|
// Site theme is server from predefined path.
|
|
if (pathname === '/static/gerrit-theme.html') {
|
|
return 'gerrit-theme';
|
|
} else if (!pathname.startsWith('/plugins')) {
|
|
console.warn('Plugin not being loaded from /plugins base path:',
|
|
url.href, '— Unable to determine name.');
|
|
return;
|
|
}
|
|
// Pathname should normally look like this:
|
|
// /plugins/PLUGINNAME/static/SCRIPTNAME.html
|
|
// Or, for app/samples:
|
|
// /plugins/PLUGINNAME.html
|
|
return pathname.split('/')[2].split('.')[0];
|
|
}
|
|
|
|
function Plugin(opt_url) {
|
|
this._domHooks = new GrDomHooksManager(this);
|
|
|
|
if (!opt_url) {
|
|
console.warn('Plugin not being loaded from /plugins base path.',
|
|
'Unable to determine name.');
|
|
return;
|
|
}
|
|
this.deprecated = {
|
|
_loadedGwt: deprecatedAPI._loadedGwt.bind(this),
|
|
install: deprecatedAPI.install.bind(this),
|
|
onAction: deprecatedAPI.onAction.bind(this),
|
|
panel: deprecatedAPI.panel.bind(this),
|
|
popup: deprecatedAPI.popup.bind(this),
|
|
screen: deprecatedAPI.screen.bind(this),
|
|
settingsScreen: deprecatedAPI.settingsScreen.bind(this),
|
|
};
|
|
|
|
this._url = new URL(opt_url);
|
|
this._name = getPluginNameFromUrl(this._url);
|
|
if (this._url.protocol === PRELOADED_PROTOCOL) {
|
|
// Original plugin URL is used in plugin assets URLs calculation.
|
|
const assetsBaseUrl = window.ASSETS_PATH ||
|
|
(window.location.origin + Gerrit.BaseUrlBehavior.getBaseUrl());
|
|
this._url = new URL(assetsBaseUrl + '/plugins/' + this._name +
|
|
'/static/' + this._name + '.js');
|
|
}
|
|
}
|
|
|
|
Plugin._sharedAPIElement = document.createElement('gr-js-api-interface');
|
|
|
|
Plugin.prototype._name = '';
|
|
|
|
Plugin.prototype.getPluginName = function() {
|
|
return this._name;
|
|
};
|
|
|
|
Plugin.prototype.registerStyleModule = function(endpointName, moduleName) {
|
|
Gerrit._endpoints.registerModule(
|
|
this, endpointName, EndpointType.STYLE, moduleName);
|
|
};
|
|
|
|
/**
|
|
* Registers an endpoint for the plugin.
|
|
*/
|
|
Plugin.prototype.registerCustomComponent = function(
|
|
endpointName, opt_moduleName, opt_options) {
|
|
return this._registerCustomComponent(endpointName, opt_moduleName,
|
|
opt_options);
|
|
};
|
|
|
|
/**
|
|
* Registers a dynamic endpoint for the plugin.
|
|
*
|
|
* Dynamic plugins are registered by specific prefix, such as
|
|
* 'change-list-header'.
|
|
*/
|
|
Plugin.prototype.registerDynamicCustomComponent = function(
|
|
endpointName, opt_moduleName, opt_options) {
|
|
const fullEndpointName = `${endpointName}-${this.getPluginName()}`;
|
|
return this._registerCustomComponent(fullEndpointName, opt_moduleName,
|
|
opt_options, endpointName);
|
|
};
|
|
|
|
Plugin.prototype._registerCustomComponent = function(
|
|
endpointName, opt_moduleName, opt_options, dynamicEndpoint) {
|
|
const type = opt_options && opt_options.replace ?
|
|
EndpointType.REPLACE : EndpointType.DECORATE;
|
|
const hook = this._domHooks.getDomHook(endpointName, opt_moduleName);
|
|
const moduleName = opt_moduleName || hook.getModuleName();
|
|
Gerrit._endpoints.registerModule(
|
|
this, endpointName, type, moduleName, hook, dynamicEndpoint);
|
|
return hook.getPublicAPI();
|
|
};
|
|
|
|
/**
|
|
* Returns instance of DOM hook API for endpoint. Creates a placeholder
|
|
* element for the first call.
|
|
*/
|
|
Plugin.prototype.hook = function(endpointName, opt_options) {
|
|
return this.registerCustomComponent(endpointName, undefined, opt_options);
|
|
};
|
|
|
|
Plugin.prototype.getServerInfo = function() {
|
|
return document.createElement('gr-rest-api-interface').getConfig();
|
|
};
|
|
|
|
Plugin.prototype.on = function(eventName, callback) {
|
|
Plugin._sharedAPIElement.addEventCallback(eventName, callback);
|
|
};
|
|
|
|
Plugin.prototype.url = function(opt_path) {
|
|
const relPath = '/plugins/' + this._name + (opt_path || '/');
|
|
if (window.location.origin === this._url.origin) {
|
|
// Plugin loaded from the same origin as gr-app, getBaseUrl in effect.
|
|
return this._url.origin + Gerrit.BaseUrlBehavior.getBaseUrl() + relPath;
|
|
} else {
|
|
// Plugin loaded from assets bundle, expect assets placed along with it.
|
|
return this._url.href.split('/plugins/' + this._name)[0] + relPath;
|
|
}
|
|
};
|
|
|
|
Plugin.prototype.screenUrl = function(opt_screenName) {
|
|
const origin = this._url.origin;
|
|
const base = Gerrit.BaseUrlBehavior.getBaseUrl();
|
|
const tokenPart = opt_screenName ? '/' + opt_screenName : '';
|
|
return `${origin}${base}/x/${this.getPluginName()}${tokenPart}`;
|
|
};
|
|
|
|
Plugin.prototype._send = function(method, url, opt_callback, opt_payload) {
|
|
return send(method, this.url(url), opt_callback, opt_payload);
|
|
};
|
|
|
|
Plugin.prototype.get = function(url, opt_callback) {
|
|
console.warn('.get() is deprecated! Use .restApi().get()');
|
|
return this._send('GET', url, opt_callback);
|
|
};
|
|
|
|
Plugin.prototype.post = function(url, payload, opt_callback) {
|
|
console.warn('.post() is deprecated! Use .restApi().post()');
|
|
return this._send('POST', url, opt_callback, payload);
|
|
};
|
|
|
|
Plugin.prototype.put = function(url, payload, opt_callback) {
|
|
console.warn('.put() is deprecated! Use .restApi().put()');
|
|
return this._send('PUT', url, opt_callback, payload);
|
|
};
|
|
|
|
Plugin.prototype.delete = function(url, opt_callback) {
|
|
return Gerrit.delete(this.url(url), opt_callback);
|
|
};
|
|
|
|
Plugin.prototype.annotationApi = function() {
|
|
return new GrAnnotationActionsInterface(this);
|
|
};
|
|
|
|
Plugin.prototype.changeActions = function() {
|
|
return new GrChangeActionsInterface(this,
|
|
Plugin._sharedAPIElement.getElement(
|
|
Plugin._sharedAPIElement.Element.CHANGE_ACTIONS));
|
|
};
|
|
|
|
Plugin.prototype.changeReply = function() {
|
|
return new GrChangeReplyInterface(this,
|
|
Plugin._sharedAPIElement.getElement(
|
|
Plugin._sharedAPIElement.Element.REPLY_DIALOG));
|
|
};
|
|
|
|
Plugin.prototype.changeView = function() {
|
|
return new GrChangeViewApi(this);
|
|
};
|
|
|
|
Plugin.prototype.theme = function() {
|
|
return new GrThemeApi(this);
|
|
};
|
|
|
|
Plugin.prototype.project = function() {
|
|
return new GrRepoApi(this);
|
|
};
|
|
|
|
Plugin.prototype.changeMetadata = function() {
|
|
return new GrChangeMetadataApi(this);
|
|
};
|
|
|
|
Plugin.prototype.admin = function() {
|
|
return new GrAdminApi(this);
|
|
};
|
|
|
|
Plugin.prototype.settings = function() {
|
|
return new GrSettingsApi(this);
|
|
};
|
|
|
|
Plugin.prototype.styles = function() {
|
|
return new GrStylesApi();
|
|
};
|
|
|
|
/**
|
|
* To make REST requests for plugin-provided endpoints, use
|
|
* @example
|
|
* const pluginRestApi = plugin.restApi(plugin.url());
|
|
*
|
|
* @param {string} Base url for subsequent .get(), .post() etc requests.
|
|
*/
|
|
Plugin.prototype.restApi = function(opt_prefix) {
|
|
return new GrPluginRestApi(opt_prefix);
|
|
};
|
|
|
|
Plugin.prototype.attributeHelper = function(element) {
|
|
return new GrAttributeHelper(element);
|
|
};
|
|
|
|
Plugin.prototype.eventHelper = function(element) {
|
|
return new GrEventHelper(element);
|
|
};
|
|
|
|
Plugin.prototype.popup = function(moduleName) {
|
|
if (typeof moduleName !== 'string') {
|
|
console.error('.popup(element) deprecated, use .popup(moduleName)!');
|
|
return;
|
|
}
|
|
const api = new GrPopupInterface(this, moduleName);
|
|
return api.open();
|
|
};
|
|
|
|
Plugin.prototype.panel = function() {
|
|
console.error('.panel() is deprecated! ' +
|
|
'Use registerCustomComponent() instead.');
|
|
};
|
|
|
|
Plugin.prototype.settingsScreen = function() {
|
|
console.error('.settingsScreen() is deprecated! ' +
|
|
'Use .settings() instead.');
|
|
};
|
|
|
|
Plugin.prototype.screen = function(screenName, opt_moduleName) {
|
|
if (opt_moduleName && typeof opt_moduleName !== 'string') {
|
|
console.error('.screen(pattern, callback) deprecated, use ' +
|
|
'.screen(screenName, opt_moduleName)!');
|
|
return;
|
|
}
|
|
return this.registerCustomComponent(
|
|
Gerrit._getPluginScreenName(this.getPluginName(), screenName),
|
|
opt_moduleName);
|
|
};
|
|
|
|
const deprecatedAPI = {
|
|
_loadedGwt: ()=> {},
|
|
|
|
install() {
|
|
console.log('Installing deprecated APIs is deprecated!');
|
|
for (const method in this.deprecated) {
|
|
if (method === 'install') continue;
|
|
this[method] = this.deprecated[method];
|
|
}
|
|
},
|
|
|
|
popup(el) {
|
|
console.warn('plugin.deprecated.popup() is deprecated, ' +
|
|
'use plugin.popup() insted!');
|
|
if (!el) {
|
|
throw new Error('Popup contents not found');
|
|
}
|
|
const api = new GrPopupInterface(this);
|
|
api.open().then(api => api._getElement().appendChild(el));
|
|
return api;
|
|
},
|
|
|
|
onAction(type, action, callback) {
|
|
console.warn('plugin.deprecated.onAction() is deprecated,' +
|
|
' use plugin.changeActions() instead!');
|
|
if (type !== 'change' && type !== 'revision') {
|
|
console.warn(`${type} actions are not supported.`);
|
|
return;
|
|
}
|
|
this.on('showchange', (change, revision) => {
|
|
const details = this.changeActions().getActionDetails(action);
|
|
if (!details) {
|
|
console.warn(
|
|
`${this.getPluginName()} onAction error: ${action} not found!`);
|
|
return;
|
|
}
|
|
this.changeActions().addTapListener(details.__key, () => {
|
|
callback(new GrPluginActionContext(this, details, change, revision));
|
|
});
|
|
});
|
|
},
|
|
|
|
screen(pattern, callback) {
|
|
console.warn('plugin.deprecated.screen is deprecated,' +
|
|
' use plugin.screen instead!');
|
|
if (pattern instanceof RegExp) {
|
|
console.error('deprecated.screen() does not support RegExp. ' +
|
|
'Please use strings for patterns.');
|
|
return;
|
|
}
|
|
this.hook(Gerrit._getPluginScreenName(this.getPluginName(), pattern))
|
|
.onAttached(el => {
|
|
el.style.display = 'none';
|
|
callback({
|
|
body: el,
|
|
token: el.token,
|
|
onUnload: () => {},
|
|
setTitle: () => {},
|
|
setWindowTitle: () => {},
|
|
show: () => {
|
|
el.style.display = 'initial';
|
|
},
|
|
});
|
|
});
|
|
},
|
|
|
|
settingsScreen(path, menu, callback) {
|
|
console.warn('.settingsScreen() is deprecated! Use .settings() instead.');
|
|
const hook = this.settings()
|
|
.title(menu)
|
|
.token(path)
|
|
.module('div')
|
|
.build();
|
|
hook.onAttached(el => {
|
|
el.style.display = 'none';
|
|
const body = el.querySelector('div');
|
|
callback({
|
|
body,
|
|
onUnload: () => {},
|
|
setTitle: () => {},
|
|
setWindowTitle: () => {},
|
|
show: () => {
|
|
el.style.display = 'initial';
|
|
},
|
|
});
|
|
});
|
|
},
|
|
|
|
panel(extensionpoint, callback) {
|
|
console.warn('.panel() is deprecated! ' +
|
|
'Use registerCustomComponent() instead.');
|
|
const endpoint = PANEL_ENDPOINTS_MAPPING[extensionpoint];
|
|
if (!endpoint) {
|
|
console.warn(`.panel ${extensionpoint} not supported!`);
|
|
return;
|
|
}
|
|
this.hook(endpoint).onAttached(el => callback({
|
|
body: el,
|
|
p: {
|
|
CHANGE_INFO: el.change,
|
|
REVISION_INFO: el.revision,
|
|
},
|
|
onUnload: () => {},
|
|
}));
|
|
},
|
|
};
|
|
|
|
flushPreinstalls();
|
|
|
|
window.Gerrit = window.Gerrit || {};
|
|
const Gerrit = window.Gerrit;
|
|
|
|
let _resolveAllPluginsLoaded = null;
|
|
let _allPluginsPromise = null;
|
|
|
|
Gerrit._endpoints = new GrPluginEndpoints();
|
|
|
|
// Provide reset plugins function to clear installed plugins between tests.
|
|
const app = document.querySelector('#app');
|
|
if (!app) {
|
|
// No gr-app found (running tests)
|
|
Gerrit._installPreloadedPlugins = installPreloadedPlugins;
|
|
Gerrit._flushPreinstalls = flushPreinstalls;
|
|
Gerrit._resetPlugins = () => {
|
|
_allPluginsPromise = null;
|
|
_pluginsInstalled = [];
|
|
_pluginsPending = {};
|
|
_pluginsPendingCount = -1;
|
|
_reporting = null;
|
|
_resolveAllPluginsLoaded = null;
|
|
_restAPI = null;
|
|
Gerrit._endpoints = new GrPluginEndpoints();
|
|
for (const k of Object.keys(_plugins)) {
|
|
delete _plugins[k];
|
|
}
|
|
};
|
|
}
|
|
|
|
Gerrit.getPluginName = function() {
|
|
console.warn('Gerrit.getPluginName is not supported in PolyGerrit.',
|
|
'Please use plugin.getPluginName() instead.');
|
|
};
|
|
|
|
/**
|
|
* @deprecated Use plugin.styles().css(rulesStr) instead. Please, consult
|
|
* the documentation how to replace it accordingly.
|
|
*/
|
|
Gerrit.css = function(rulesStr) {
|
|
console.warn('Gerrit.css(rulesStr) is deprecated!',
|
|
'Use plugin.styles().css(rulesStr)');
|
|
if (!Gerrit._customStyleSheet) {
|
|
const styleEl = document.createElement('style');
|
|
document.head.appendChild(styleEl);
|
|
Gerrit._customStyleSheet = styleEl.sheet;
|
|
}
|
|
|
|
const name = '__pg_js_api_class_' +
|
|
Gerrit._customStyleSheet.cssRules.length;
|
|
Gerrit._customStyleSheet.insertRule('.' + name + '{' + rulesStr + '}', 0);
|
|
return name;
|
|
};
|
|
|
|
Gerrit.install = function(callback, opt_version, opt_src) {
|
|
// HTML import polyfill adds __importElement pointing to the import tag.
|
|
const script = document.currentScript &&
|
|
(document.currentScript.__importElement || document.currentScript);
|
|
|
|
let src = opt_src || (script && script.src);
|
|
if (!src || src.startsWith('data:')) {
|
|
src = script && script.baseURI;
|
|
}
|
|
const name = getPluginNameFromUrl(src);
|
|
|
|
if (opt_version && opt_version !== API_VERSION) {
|
|
Gerrit._pluginInstallError(`Plugin ${name} install error: only version ` +
|
|
API_VERSION + ' is supported in PolyGerrit. ' + opt_version +
|
|
' was given.');
|
|
return;
|
|
}
|
|
|
|
const existingPlugin = _plugins[name];
|
|
const plugin = existingPlugin || new Plugin(src);
|
|
try {
|
|
callback(plugin);
|
|
if (name) {
|
|
_plugins[name] = plugin;
|
|
}
|
|
if (!existingPlugin) {
|
|
Gerrit._pluginInstalled(src);
|
|
}
|
|
} catch (e) {
|
|
Gerrit._pluginInstallError(`${e.name}: ${e.message}`);
|
|
}
|
|
};
|
|
|
|
Gerrit.getLoggedIn = function() {
|
|
console.warn('Gerrit.getLoggedIn() is deprecated! ' +
|
|
'Use plugin.restApi().getLoggedIn()');
|
|
return document.createElement('gr-rest-api-interface').getLoggedIn();
|
|
};
|
|
|
|
Gerrit.get = function(url, callback) {
|
|
console.warn('.get() is deprecated! Use plugin.restApi().get()');
|
|
send('GET', url, callback);
|
|
};
|
|
|
|
Gerrit.post = function(url, payload, callback) {
|
|
console.warn('.post() is deprecated! Use plugin.restApi().post()');
|
|
send('POST', url, callback, payload);
|
|
};
|
|
|
|
Gerrit.put = function(url, payload, callback) {
|
|
console.warn('.put() is deprecated! Use plugin.restApi().put()');
|
|
send('PUT', url, callback, payload);
|
|
};
|
|
|
|
Gerrit.delete = function(url, opt_callback) {
|
|
console.warn('.delete() is deprecated! Use plugin.restApi().delete()');
|
|
return getRestAPI().send('DELETE', url).then(response => {
|
|
if (response.status !== 204) {
|
|
return response.text().then(text => {
|
|
if (text) {
|
|
return Promise.reject(text);
|
|
} else {
|
|
return Promise.reject(response.status);
|
|
}
|
|
});
|
|
}
|
|
if (opt_callback) {
|
|
opt_callback(response);
|
|
}
|
|
return response;
|
|
});
|
|
};
|
|
|
|
Gerrit.awaitPluginsLoaded = function() {
|
|
if (!_allPluginsPromise) {
|
|
if (Gerrit._arePluginsLoaded()) {
|
|
_allPluginsPromise = Promise.resolve();
|
|
} else {
|
|
let timeoutId;
|
|
_allPluginsPromise =
|
|
Promise.race([
|
|
new Promise(resolve => _resolveAllPluginsLoaded = resolve),
|
|
new Promise(resolve => timeoutId = setTimeout(
|
|
Gerrit._pluginLoadingTimeout, PLUGIN_LOADING_TIMEOUT_MS)),
|
|
]).then(() => clearTimeout(timeoutId));
|
|
}
|
|
}
|
|
return _allPluginsPromise;
|
|
};
|
|
|
|
Gerrit._pluginLoadingTimeout = function() {
|
|
console.error(`Failed to load plugins: ${Object.keys(_pluginsPending)}`);
|
|
Gerrit._setPluginsPending([]);
|
|
};
|
|
|
|
Gerrit._setPluginsPending = function(plugins) {
|
|
_pluginsPending = plugins.reduce((o, url) => {
|
|
// TODO(viktard): Remove guard (@see Issue 8962)
|
|
o[getPluginNameFromUrl(url) || UNKNOWN_PLUGIN] = url;
|
|
return o;
|
|
}, {});
|
|
Gerrit._setPluginsCount(Object.keys(_pluginsPending).length);
|
|
};
|
|
|
|
Gerrit._setPluginsCount = function(count) {
|
|
_pluginsPendingCount = count;
|
|
if (Gerrit._arePluginsLoaded()) {
|
|
getReporting().pluginsLoaded(_pluginsInstalled);
|
|
if (_resolveAllPluginsLoaded) {
|
|
_resolveAllPluginsLoaded();
|
|
}
|
|
}
|
|
};
|
|
|
|
Gerrit._pluginInstallError = function(message) {
|
|
document.dispatchEvent(new CustomEvent('show-alert', {
|
|
detail: {
|
|
message: `Plugin install error: ${message}`,
|
|
},
|
|
}));
|
|
console.info(`Plugin install error: ${message}`);
|
|
Gerrit._setPluginsCount(_pluginsPendingCount - 1);
|
|
};
|
|
|
|
Gerrit._pluginInstalled = function(url) {
|
|
const name = getPluginNameFromUrl(url) || UNKNOWN_PLUGIN;
|
|
if (!_pluginsPending[name]) {
|
|
console.warn(`Unexpected plugin ${name} installed from ${url}.`);
|
|
} else {
|
|
delete _pluginsPending[name];
|
|
_pluginsInstalled.push(name);
|
|
Gerrit._setPluginsCount(_pluginsPendingCount - 1);
|
|
getReporting().pluginLoaded(name);
|
|
console.log(`Plugin ${name} installed.`);
|
|
}
|
|
};
|
|
|
|
Gerrit._arePluginsLoaded = function() {
|
|
return _pluginsPendingCount === 0;
|
|
};
|
|
|
|
Gerrit._getPluginScreenName = function(pluginName, screenName) {
|
|
return `${pluginName}-screen-${screenName}`;
|
|
};
|
|
|
|
Gerrit._isPluginPreloaded = function(url) {
|
|
const name = getPluginNameFromUrl(url);
|
|
if (name && Gerrit._preloadedPlugins) {
|
|
return name in Gerrit._preloadedPlugins;
|
|
} else {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
// Preloaded plugins should be installed after Gerrit.install() is set,
|
|
// since plugin preloader substitutes Gerrit.install() temporarily.
|
|
installPreloadedPlugins();
|
|
})(window);
|