diff --git a/Documentation/pg-plugin-dev.txt b/Documentation/pg-plugin-dev.txt
index dc6b2b3d94..fc704a1b21 100644
--- a/Documentation/pg-plugin-dev.txt
+++ b/Documentation/pg-plugin-dev.txt
@@ -311,6 +311,21 @@ screen.
.Returns:
- Absolute URL for the screen, e.g. `http://localhost/base/x/pluginname/screenname`
+[[plugin-settings]]
+=== settings
+`plugin.settings()`
+
+.Params:
+- none
+
+.Returns:
+- Instance of link:pg-plugin-settings-api.html[GrSettingsApi].
+
+=== settingsScreen
+`plugin.settingsScreen(path, menu, callback)`
+
+Deprecated. Use link:#plugin-settings[`plugin.settings()`] instead.
+
=== theme
`plugin.theme()`
@@ -374,6 +389,19 @@ Support is limited:
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.
diff --git a/Documentation/pg-plugin-settings-api.txt b/Documentation/pg-plugin-settings-api.txt
new file mode 100644
index 0000000000..985809da50
--- /dev/null
+++ b/Documentation/pg-plugin-settings-api.txt
@@ -0,0 +1,40 @@
+= Gerrit Code Review - Settings admin customization API
+
+This API is provided by link:pg-plugin-dev.html#plugin-settings[plugin.settings()]
+and provides customization to settings page.
+
+== title
+`settingsApi.title(title)`
+
+.Params
+- `*string* title` Menu item and settings section title
+
+.Returns
+- `GrSettingsApi` for chaining.
+
+== token
+`settingsApi.token(token)`
+
+.Params
+- `*string* token` URL path fragment of the screen for direct link, e.g.
+`settings/#x/some-plugin/*token*`
+
+.Returns
+- `GrSettingsApi` for chaining.
+
+== module
+`settingsApi.module(token)`
+
+.Params
+- `*string* module` Custom element name for instantiating in the settings plugin
+area.
+
+.Returns
+- `GrSettingsApi` for chaining.
+
+== build
+
+.Params
+- none
+
+Apply all other configuration parameters and create required UI elements.
diff --git a/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api.html b/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api.html
new file mode 100644
index 0000000000..4c57daf0fc
--- /dev/null
+++ b/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api.js b/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api.js
new file mode 100644
index 0000000000..f33b683fed
--- /dev/null
+++ b/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api.js
@@ -0,0 +1,62 @@
+// Copyright (C) 2017 The Android Open Source Settings
+//
+// 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';
+
+ function GrSettingsApi(plugin) {
+ this._title = '(no title)';
+ // Generate default screen URL token, specific to plugin, and unique(ish).
+ this._token =
+ plugin.getPluginName() + Math.random().toString(36).substr(5);
+ this.plugin = plugin;
+ }
+
+ GrSettingsApi.prototype.title = function(title) {
+ this._title = title;
+ return this;
+ };
+
+ GrSettingsApi.prototype.token = function(token) {
+ this._token = token;
+ return this;
+ };
+
+ GrSettingsApi.prototype.module = function(moduleName) {
+ this._moduleName = moduleName;
+ return this;
+ };
+
+ GrSettingsApi.prototype.build = function() {
+ if (!this._moduleName) {
+ throw new Error('Settings screen custom element not defined!');
+ }
+ const token = `x/${this.plugin.getPluginName()}/${this._token}`;
+ this.plugin.hook('settings-menu-item').onAttached(el => {
+ const menuItem = document.createElement('gr-settings-menu-item');
+ menuItem.title = this._title;
+ menuItem.href = `#${token}`;
+ el.appendChild(menuItem);
+ });
+
+ return this.plugin.hook('settings-screen').onAttached(el => {
+ const item = document.createElement('gr-settings-item');
+ item.title = this._title;
+ item.anchor = token;
+ item.appendChild(document.createElement(this._moduleName));
+ el.appendChild(item);
+ });
+ };
+
+ window.GrSettingsApi = GrSettingsApi;
+})(window);
diff --git a/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api_test.html b/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api_test.html
new file mode 100644
index 0000000000..cbe71fec4a
--- /dev/null
+++ b/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api_test.html
@@ -0,0 +1,82 @@
+
+
+
+
+
gr-settings-api
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-item.html b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-item.html
new file mode 100644
index 0000000000..97fbf0a322
--- /dev/null
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-item.html
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+ [[title]]
+
+
+
+
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-item.js b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-item.js
new file mode 100644
index 0000000000..e4f5d24723
--- /dev/null
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-item.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2017 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-settings-item',
+ properties: {
+ anchor: String,
+ title: String,
+ },
+ });
+})();
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-menu-item.html b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-menu-item.html
new file mode 100644
index 0000000000..ff71d3f573
--- /dev/null
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-menu-item.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-menu-item.js b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-menu-item.js
new file mode 100644
index 0000000000..797990daca
--- /dev/null
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-menu-item.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2017 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-settings-menu-item',
+ properties: {
+ href: String,
+ title: String,
+ },
+ });
+})();
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html
index ea1f03f1c7..8aae460415 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html
@@ -15,12 +15,12 @@ limitations under the License.
-->
-
-
+
-
+
+
@@ -79,6 +79,8 @@ limitations under the License.
Mail Filters
+
+
@@ -480,6 +482,8 @@ limitations under the License.
+
+
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.html
index 60b291ae24..a489e2cc53 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.html
@@ -22,6 +22,7 @@ limitations under the License.
+
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html
index 6147e682f1..5f91be786f 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html
@@ -518,5 +518,49 @@ limitations under the License.
});
});
});
+
+ 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: sandbox.stub()};
+ sandbox.stub(plugin, 'hook').returns(hookStub);
+ const fakeSettings = {};
+ fakeSettings.title = sandbox.stub().returns(fakeSettings);
+ fakeSettings.token = sandbox.stub().returns(fakeSettings);
+ fakeSettings.module = sandbox.stub().returns(fakeSettings);
+ fakeSettings.build = sandbox.stub().returns(hookStub);
+ sandbox.stub(plugin, 'settings').returns(fakeSettings);
+ const callback = sandbox.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: sandbox.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-public-js-api.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
index a36b898d90..3958cec8db 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
@@ -23,7 +23,7 @@
*/
const plugins = {};
- const stubbedMethods = ['_loadedGwt', 'settingsScreen'];
+ const stubbedMethods = ['_loadedGwt'];
const GWT_PLUGIN_STUB = {};
for (const name of stubbedMethods) {
GWT_PLUGIN_STUB[name] = warnNotSupported.bind(null, name);
@@ -118,6 +118,7 @@
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);
@@ -228,6 +229,10 @@
return new GrRepoApi(this);
};
+ Plugin.prototype.settings = function() {
+ return new GrSettingsApi(this);
+ };
+
/**
* To make REST requests for plugin-provided endpoints, use
* @example
@@ -260,6 +265,11 @@
'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') {
throw new Error('deprecated, use deprecated.screen');
@@ -333,6 +343,28 @@
});
},
+ 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.');
diff --git a/polygerrit-ui/app/test/index.html b/polygerrit-ui/app/test/index.html
index ca662ddcd5..ecbd86afb6 100644
--- a/polygerrit-ui/app/test/index.html
+++ b/polygerrit-ui/app/test/index.html
@@ -116,6 +116,7 @@ limitations under the License.
'plugins/gr-popup-interface/gr-plugin-popup_test.html',
'plugins/gr-popup-interface/gr-popup-interface_test.html',
'plugins/gr-repo-api/gr-repo-api_test.html',
+ 'plugins/gr-settings-api/gr-settings-api_test.html',
'settings/gr-account-info/gr-account-info_test.html',
'settings/gr-change-table-editor/gr-change-table-editor_test.html',
'settings/gr-email-editor/gr-email-editor_test.html',