Clean up deprecated APIs
All core plugins are already moved away from deprecated methods now.
Also removed relevant sections from the doc.
Change-Id: I17cd77c47d65b6244b7842541fbd7f58f5652b0b
diff --git a/Documentation/pg-plugin-dev.txt b/Documentation/pg-plugin-dev.txt
index adb5d20..91bc476 100644
--- a/Documentation/pg-plugin-dev.txt
+++ b/Documentation/pg-plugin-dev.txt
@@ -375,93 +375,4 @@
Note: TODO
=== url
-`plugin.url(opt_path)`
-
-Note: TODO
-
-[[deprecated-api]]
-== Deprecated APIs
-
-Some of the deprecated APIs have limited implementation in PolyGerrit to serve
-as a "stepping stone" to allow gradual migration.
-
-=== install
-`plugin.deprecated.install()`
-
-.Params:
-- none
-
-Replaces plugin APIs with a deprecated version. This allows use of deprecated
-APIs without changing JS code. For example, `onAction` is not available by
-default, and after `plugin.deprecated.install()` it's accessible via
-`self.onAction()`.
-
-=== onAction
-`plugin.deprecated.onAction(type, view_name, callback)`
-
-.Params:
-- `*string* type` Action type.
-- `*string* view_name` REST API action.
-- `*function(actionContext)* callback` Callback invoked on action button click.
-
-Adds a button to the UI with a click callback. Exact button location depends on
-parameters. Callback is triggered with an instance of
-link:#deprecated-action-context[action context].
-
-Support is limited:
-
-- type is either `change` or `revision`.
-
-See link:js-api.html#self_onAction[self.onAction] for more info.
-
-=== panel
-`plugin.deprecated.panel(extensionpoint, callback)`
-
-.Params:
-- `*string* extensionpoint`
-- `*function(screenContext)* callback`
-
-Adds a UI DOM element and triggers a callback with context to allow direct DOM
-access.
-
-Support is limited:
-
-- extensionpoint is one of the following:
- * CHANGE_SCREEN_BELOW_COMMIT_INFO_BLOCK
- * CHANGE_SCREEN_BELOW_CHANGE_INFO_BLOCK
-
-See link:js-api.html#self_panel[self.panel] for more info.
-
-=== settingsScreen
-`plugin.deprecated.settingsScreent(path, menu, callback)`
-
-.Params:
-- `*string* path` URL path fragment of the screen for direct link.
-- `*string* menu` Menu item title.
-- `*function(settingsScreenContext)* callback`
-
-Adds a settings menu item and a section in the settings screen that is provided
-to plugin for setup.
-
-See link:js-api.html#self_settingsScreen[self.settingsScreen] for more info.
-
-[[deprecated-action-context]]
-=== Action Context (deprecated)
-Instance of Action Context is passed to `onAction()` callback.
-
-Support is limited:
-
-- `popup()`
-- `hide()`
-- `refresh()`
-- `textfield()`
-- `br()`
-- `msg()`
-- `div()`
-- `button()`
-- `checkbox()`
-- `label()`
-- `prependLabel()`
-- `call()`
-
-See link:js-api.html#ActionContext[Action Context] for more info.
+`plugin.url(opt_path)`
\ No newline at end of file
diff --git a/Documentation/pg-plugin-migration.txt b/Documentation/pg-plugin-migration.txt
index bca4b7a..061c687 100644
--- a/Documentation/pg-plugin-migration.txt
+++ b/Documentation/pg-plugin-migration.txt
@@ -79,9 +79,6 @@
<script>
Gerrit.install(plugin => {
// Setup block, is executed before sampleplugin.js
-
- // Install deprecated JS APIs (onAction, popup, etc)
- plugin.deprecated.install();
});
</script>
@@ -105,8 +102,6 @@
- `sampleplugin.js` is loaded since it's referenced in `sampleplugin.html`
- setup script tag code is executed before `sampleplugin.js`
- cleanup script tag code is executed after `sampleplugin.js`
-- `plugin.deprecated.install()` enables deprecated APIs (onAction(), popup(),
-etc) before `sampleplugin.js` is loaded
This means the plugin instance is shared between .html-based and .js-based
code. This allows to gradually and incrementally transfer code to the new API.
diff --git a/polygerrit-ui/app/elements/plugins/gr-plugin-types.ts b/polygerrit-ui/app/elements/plugins/gr-plugin-types.ts
index 538c78a..9eeddcc 100644
--- a/polygerrit-ui/app/elements/plugins/gr-plugin-types.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-plugin-types.ts
@@ -18,7 +18,6 @@
import {GrPluginRestApi} from '../shared/gr-js-api-interface/gr-plugin-rest-api';
import {GrEventHelper} from './gr-event-helper/gr-event-helper';
import {GrPopupInterface} from './gr-popup-interface/gr-popup-interface';
-import {GrPluginActionContext} from '../shared/gr-js-api-interface/gr-plugin-action-context';
import {ConfigInfo} from '../../types/common';
interface GerritElementExtensions {
@@ -85,7 +84,9 @@
export interface PluginApi {
_url?: URL;
- deprecated: PluginDeprecatedApi;
+ popup(): Promise<GrPopupInterface>;
+ popup(moduleName: string): Promise<GrPopupInterface>;
+ popup(moduleName?: string): Promise<GrPopupInterface | null>;
hook(endpointName: string, opt_options?: RegisterOptions): HookApi;
getPluginName(): string;
on(eventName: string, target: any): void;
@@ -93,21 +94,3 @@
restApi(): GrPluginRestApi;
eventHelper(element: Node): GrEventHelper;
}
-
-export interface PluginDeprecatedApi {
- _loadedGwt(): void;
- install: () => void;
- popup(element: Node): GrPopupInterface;
- onAction(
- type: string,
- action: string,
- callback: (ctx: GrPluginActionContext) => void
- ): void;
- panel(extensionpoint: string, callback: (panel: PanelInfo) => void): void;
- screen(pattern: string, callback: (settings: SettingsInfo) => void): void;
- settingsScreen(
- path: string,
- menu: string,
- callback: (settings: SettingsInfo) => void
- ): void;
-}
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.js
index e856788..873cc4b 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.js
@@ -20,7 +20,6 @@
import {GrPopupInterface} from '../../plugins/gr-popup-interface/gr-popup-interface.js';
import {GrSettingsApi} from '../../plugins/gr-settings-api/gr-settings-api.js';
import {EventType} from '../../plugins/gr-plugin-types.js';
-import {GrPluginActionContext} from './gr-plugin-action-context.js';
import {PLUGIN_LOADING_TIMEOUT_MS} from './gr-api-utils.js';
import {getPluginLoader} from './gr-plugin-loader.js';
import {_testOnly_initGerritPluginApi} from './gr-gerrit.js';
@@ -353,15 +352,6 @@
assert.isOk(plugin.attributeHelper());
});
- test('deprecated.install', () => {
- assert.notStrictEqual(plugin.popup, plugin.deprecated.popup);
- assert.notStrictEqual(plugin.onAction, plugin.deprecated.onAction);
- plugin.deprecated.install();
- assert.strictEqual(plugin.popup, plugin.deprecated.popup);
- assert.strictEqual(plugin.onAction, plugin.deprecated.onAction);
- assert.notStrictEqual(plugin.install, plugin.deprecated.install);
- });
-
test('getAdminMenuLinks', () => {
const links = [{text: 'a', url: 'b'}, {text: 'c', url: 'd'}];
const getCallbacksStub = sinon.stub(element, '_getEventCallbacks')
@@ -415,56 +405,6 @@
plugin.popup('some-name');
assert.isTrue(openStub.calledOnce);
});
-
- test('deprecated.popup(element) creates popup with element', () => {
- const el = document.createElement('div');
- el.textContent = 'some text here';
- const openStub = sinon.stub(GrPopupInterface.prototype, 'open');
- openStub.returns(Promise.resolve({
- _getElement() {
- return document.createElement('div');
- }}));
- plugin.deprecated.popup(el);
- assert.isTrue(openStub.calledOnce);
- });
- });
-
- suite('onAction', () => {
- let change;
- let revision;
- let actionDetails;
-
- setup(() => {
- change = {};
- revision = {};
- actionDetails = {__key: 'some'};
- sinon.stub(plugin, 'on').callsArgWith(1, change, revision);
- sinon.stub(plugin, 'changeActions').returns({
- addTapListener: sinon.stub().callsArg(1),
- getActionDetails: () => actionDetails,
- });
- });
-
- test('returns GrPluginActionContext', () => {
- const stub = sinon.stub();
- plugin.deprecated.onAction('change', 'foo', ctx => {
- assert.isTrue(ctx instanceof GrPluginActionContext);
- assert.strictEqual(ctx.change, change);
- assert.strictEqual(ctx.revision, revision);
- assert.strictEqual(ctx.action, actionDetails);
- assert.strictEqual(ctx.plugin, plugin);
- stub();
- });
- assert.isTrue(stub.called);
- });
-
- test('other actions', () => {
- const stub = sinon.stub();
- plugin.deprecated.onAction('project', 'foo', stub);
- plugin.deprecated.onAction('edit', 'foo', stub);
- plugin.deprecated.onAction('branch', 'foo', stub);
- assert.isFalse(stub.called);
- });
});
suite('screen', () => {
@@ -480,18 +420,6 @@
);
});
- test('deprecated works', () => {
- const stub = sinon.stub();
- const hookStub = {onAttached: sinon.stub()};
- sinon.stub(plugin, 'hook').returns(hookStub);
- plugin.deprecated.screen('foo', stub);
- assert.isTrue(plugin.hook.calledWith('testplugin-screen-foo'));
- const fakeEl = {style: {display: ''}};
- hookStub.onAttached.callArgWith(0, fakeEl);
- assert.isTrue(stub.called);
- assert.equal(fakeEl.style.display, 'none');
- });
-
test('works', () => {
sinon.stub(plugin, 'registerCustomComponent');
plugin.screen('foo', 'some-module');
@@ -500,82 +428,11 @@
});
});
- suite('panel', () => {
- let fakeEl;
- let emulateAttached;
-
- setup(()=> {
- fakeEl = {change: {}, revision: {}};
- const hookStub = {onAttached: sinon.stub()};
- sinon.stub(plugin, 'hook').returns(hookStub);
- emulateAttached = () => hookStub.onAttached.callArgWith(0, fakeEl);
- });
-
- test('plugin.panel is deprecated', () => {
- plugin.panel('rubbish');
- assert.isTrue(console.error.called);
- });
-
- [
- ['CHANGE_SCREEN_BELOW_COMMIT_INFO_BLOCK', 'change-view-integration'],
- ['CHANGE_SCREEN_BELOW_CHANGE_INFO_BLOCK', 'change-metadata-item'],
- ].forEach(([panelName, endpointName]) => {
- test(`deprecated.panel works for ${panelName}`, () => {
- const callback = sinon.stub();
- plugin.deprecated.panel(panelName, callback);
- assert.isTrue(plugin.hook.calledWith(endpointName));
- emulateAttached();
- assert.isTrue(callback.called);
- const args = callback.args[0][0];
- assert.strictEqual(args.body, fakeEl);
- assert.strictEqual(args.p.CHANGE_INFO, fakeEl.change);
- assert.strictEqual(args.p.REVISION_INFO, fakeEl.revision);
- });
- });
- });
-
suite('settingsScreen', () => {
- test('plugin.settingsScreen is deprecated', () => {
- plugin.settingsScreen('rubbish');
- assert.isTrue(console.error.called);
- });
-
test('plugin.settings() returns GrSettingsApi', () => {
assert.isOk(plugin.settings());
assert.isTrue(plugin.settings() instanceof GrSettingsApi);
});
-
- test('plugin.deprecated.settingsScreen() works', () => {
- const hookStub = {onAttached: sinon.stub()};
- sinon.stub(plugin, 'hook').returns(hookStub);
- const fakeSettings = {};
- fakeSettings.title = sinon.stub().returns(fakeSettings);
- fakeSettings.token = sinon.stub().returns(fakeSettings);
- fakeSettings.module = sinon.stub().returns(fakeSettings);
- fakeSettings.build = sinon.stub().returns(hookStub);
- sinon.stub(plugin, 'settings').returns(fakeSettings);
- const callback = sinon.stub();
-
- plugin.deprecated.settingsScreen('path', 'menu', callback);
- assert.isTrue(fakeSettings.title.calledWith('menu'));
- assert.isTrue(fakeSettings.token.calledWith('path'));
- assert.isTrue(fakeSettings.module.calledWith('div'));
- assert.equal(fakeSettings.build.callCount, 1);
-
- const fakeBody = {};
- const fakeEl = {
- style: {
- display: '',
- },
- querySelector: sinon.stub().returns(fakeBody),
- };
- // Emulate settings screen attached
- hookStub.onAttached.callArgWith(0, fakeEl);
- assert.isTrue(callback.called);
- const args = callback.args[0][0];
- assert.strictEqual(args.body, fakeBody);
- assert.equal(fakeEl.style.display, 'none');
- });
});
});
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context.ts
index 34ecd9e..4366dd5 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context.ts
@@ -42,7 +42,14 @@
) {}
popup(element: Node) {
- this._popups.push(this.plugin.deprecated.popup(element));
+ this.plugin.popup().then(popApi => {
+ const popupEl = popApi._getElement();
+ if (!popupEl) {
+ throw new Error('Popup element not found');
+ }
+ popupEl.appendChild(element);
+ this._popups.push(popApi);
+ });
}
hide() {
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.js
index e93ffd2..27c9c28 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.js
@@ -33,17 +33,20 @@
instance = new GrPluginActionContext(plugin);
});
- test('popup() and hide()', () => {
+ test('popup() and hide()', done => {
const popupApiStub = {
+ _getElement: sinon.stub().returns(document.createElement('div')),
close: sinon.stub(),
};
- sinon.stub(plugin.deprecated, 'popup').returns(popupApiStub);
- const el = {};
+ sinon.stub(plugin, 'popup').returns(Promise.resolve(popupApiStub));
+ const el = document.createElement('span');
instance.popup(el);
- assert.isTrue(instance.plugin.deprecated.popup.calledWith(el));
-
- instance.hide();
- assert.isTrue(popupApiStub.close.called);
+ flush(() => {
+ assert.isTrue(popupApiStub._getElement.called);
+ instance.hide();
+ assert.isTrue(popupApiStub.close.called);
+ done();
+ });
});
test('textfield', () => {
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.ts
index c6b3485..043293f 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.ts
@@ -31,7 +31,6 @@
import {GrRepoApi} from '../../plugins/gr-repo-api/gr-repo-api';
import {GrSettingsApi} from '../../plugins/gr-settings-api/gr-settings-api';
import {GrStylesApi} from '../../plugins/gr-styles-api/gr-styles-api';
-import {GrPluginActionContext} from './gr-plugin-action-context';
import {getPluginEndpoints} from './gr-plugin-endpoints';
import {PRELOADED_PROTOCOL, getPluginNameFromUrl, send} from './gr-api-utils';
@@ -39,23 +38,15 @@
import {
EventType,
HookApi,
- PanelInfo,
PluginApi,
- PluginDeprecatedApi,
RegisterOptions,
- SettingsInfo,
TargetElement,
} from '../../plugins/gr-plugin-types';
-import {ActionInfo, RequestPayload} from '../../../types/common';
+import {RequestPayload} from '../../../types/common';
import {HttpMethod} from '../../../constants/constants';
import {JsApiService} from './gr-js-api-types';
import {GrChangeActions} from '../../../services/services/gr-rest-api/gr-rest-api';
-const PANEL_ENDPOINTS_MAPPING = {
- CHANGE_SCREEN_BELOW_COMMIT_INFO_BLOCK: 'change-view-integration',
- CHANGE_SCREEN_BELOW_CHANGE_INFO_BLOCK: 'change-metadata-item',
-};
-
/**
* Plugin-provided custom components can affect content in extension
* points using one of following methods:
@@ -77,8 +68,6 @@
export type SendCallback = (response: unknown) => void;
export class Plugin implements PluginApi {
- readonly deprecated: PluginDeprecatedApi;
-
readonly _url?: URL;
private _domHooks: GrDomHooksManager;
@@ -89,25 +78,6 @@
private readonly sharedApiElement: JsApiService;
constructor(url?: string) {
- this.deprecated = {
- _loadedGwt: () => {},
- install: () => this.deprecatedInstall(),
- onAction: (
- type: string,
- action: string,
- callback: (ctx: GrPluginActionContext) => void
- ) => this.deprecatedOnAction(type, action, callback),
- panel: (extensionpoint: string, callback: (panel: PanelInfo) => void) =>
- this.deprecatedPanel(extensionpoint, callback),
- popup: (el: Element) => this.deprecatedPopup(el),
- screen: (pattern: string, callback: (settings: SettingsInfo) => void) =>
- this.deprecatedScreen(pattern, callback),
- settingsScreen: (
- path: string,
- menu: string,
- callback: (settings: SettingsInfo) => void
- ) => this.deprecatedSettingsScreen(path, menu, callback),
- };
this.sharedApiElement = getSharedApiEl();
this._domHooks = new GrDomHooksManager(this);
@@ -327,25 +297,16 @@
return new GrEventHelper(element);
}
- popup(moduleName: string) {
- if (typeof moduleName !== 'string') {
+ popup(): Promise<GrPopupInterface>;
+
+ popup(moduleName: string): Promise<GrPopupInterface>;
+
+ popup(moduleName?: string): Promise<GrPopupInterface | null> {
+ if (moduleName !== undefined && typeof moduleName !== 'string') {
console.error('.popup(element) deprecated, use .popup(moduleName)!');
- return;
+ return Promise.resolve(null);
}
- const api = new GrPopupInterface(this, moduleName);
- return api.open();
- }
-
- panel() {
- console.error(
- '.panel() is deprecated! ' + 'Use registerCustomComponent() instead.'
- );
- }
-
- settingsScreen() {
- console.error(
- '.settingsScreen() is deprecated! ' + 'Use .settings() instead.'
- );
+ return new GrPopupInterface(this, moduleName).open();
}
screen(screenName: string, moduleName?: string) {
@@ -365,142 +326,4 @@
_getScreenName(screenName: string) {
return `${this.getPluginName()}-screen-${screenName}`;
}
-
- // !!! DEPRECATED !!!
- // All methods below are deprecated!
- // TODO: should be removed soon after all core plugins moved away from it.
-
- deprecatedInstall() {
- console.info('Installing deprecated APIs is deprecated!');
- const deprecatedThis = (this as unknown) as PluginDeprecatedApi;
- deprecatedThis._loadedGwt = this.deprecated._loadedGwt;
- deprecatedThis.onAction = this.deprecated.onAction;
- deprecatedThis.panel = this.deprecated.panel;
- deprecatedThis.popup = this.deprecated.popup;
- deprecatedThis.screen = this.deprecated.screen;
- deprecatedThis.settingsScreen = this.deprecated.settingsScreen;
- }
-
- deprecatedPopup(el: Element): GrPopupInterface {
- 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 => {
- const popupEl = api._getElement();
- if (!popupEl) {
- throw new Error('Popup element not found');
- }
- popupEl.appendChild(el);
- });
- return api;
- }
-
- deprecatedOnAction(
- type: string,
- action: string,
- callback: (ctx: GrPluginActionContext) => void
- ) {
- 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(EventType.SHOW_CHANGE, (change, revision) => {
- const details: ActionInfo = this.changeActions().getActionDetails(action);
- if (!details) {
- console.warn(
- `${this.getPluginName()} onAction error: ${action} not found!`
- );
- return;
- }
- if (!details.__key) {
- console.warn(
- `${this.getPluginName()} onAction error: ${action} has no key!`
- );
- return;
- }
- this.changeActions().addTapListener(details.__key, () => {
- callback(new GrPluginActionContext(this, details, change, revision));
- });
- });
- }
-
- deprecatedScreen(
- pattern: string,
- callback: (settings: SettingsInfo) => void
- ) {
- console.warn(
- 'plugin.deprecated.screen is deprecated,' + ' use plugin.screen instead!'
- );
- this.hook(this._getScreenName(pattern)).onAttached(el => {
- el.style.display = 'none';
- callback({
- body: el,
- token: el.token,
- onUnload: () => {},
- setTitle: () => {},
- setWindowTitle: () => {},
- show: () => {
- el.style.display = 'initial';
- },
- });
- });
- }
-
- deprecatedSettingsScreen(
- path: string,
- menu: string,
- callback: (settings: SettingsInfo) => void
- ) {
- 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');
- if (!body) return;
- callback({
- body,
- onUnload: () => {},
- setTitle: () => {},
- setWindowTitle: () => {},
- show: () => {
- el.style.display = 'initial';
- },
- });
- });
- }
-
- deprecatedPanel(
- extensionpoint: string,
- callback: (panel: PanelInfo) => void
- ) {
- console.warn(
- '.panel() is deprecated! ' + 'Use registerCustomComponent() instead.'
- );
- let endpoint;
- for (const [key, value] of Object.entries(PANEL_ENDPOINTS_MAPPING)) {
- if (key === extensionpoint) endpoint = value;
- }
- 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: () => {},
- })
- );
- }
}