Add API for defining new admin menu links from plugins
Change-Id: If818b752a2e451cbeeabf3423e56cd5a85141b00
This commit is contained in:
parent
273a0d9a9b
commit
c148593425
17
Documentation/pg-plugin-admin-api.txt
Normal file
17
Documentation/pg-plugin-admin-api.txt
Normal file
@ -0,0 +1,17 @@
|
||||
= Gerrit Code Review - Admin customization API
|
||||
|
||||
This API is provided by link:pg-plugin-dev.html#plugin-admin[plugin.admin()]
|
||||
and provides customization of the admin menu.
|
||||
|
||||
== addMenuLink
|
||||
`adminApi.addMenuLink(text, url, opt_external)`
|
||||
|
||||
Add a new link to the end of the admin navigation menu.
|
||||
|
||||
.Params
|
||||
- *text* String text to appear in the link.
|
||||
- *url* String of the destination URL for the link.
|
||||
|
||||
When adding an external link, the URL provided should be a full URL. Otherwise,
|
||||
a non-external link should be relative beginning with a slash. For example, to
|
||||
create a link to open changes, use the value `/q/status:open`.
|
@ -188,6 +188,15 @@ Note: TODO
|
||||
Plugin instance provides access to number of more specific APIs and methods
|
||||
to be used by plugin authors.
|
||||
|
||||
=== admin
|
||||
`plugin.admin()`
|
||||
|
||||
.Params:
|
||||
- none
|
||||
|
||||
.Returns:
|
||||
- Instance of link:pg-plugin-admin-api.html[GrAdminApi].
|
||||
|
||||
=== changeReply
|
||||
`plugin.changeReply()`
|
||||
|
||||
|
@ -23,6 +23,7 @@ limitations under the License.
|
||||
<link rel="import" href="../../../styles/gr-page-nav-styles.html">
|
||||
<link rel="import" href="../../../styles/shared-styles.html">
|
||||
<link rel="import" href="../../core/gr-navigation/gr-navigation.html">
|
||||
<link rel="import" href="../../shared/gr-js-api-interface/gr-js-api-interface.html">
|
||||
<link rel="import" href="../../shared/gr-page-nav/gr-page-nav.html">
|
||||
<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
|
||||
<link rel="import" href="../gr-admin-group-list/gr-admin-group-list.html">
|
||||
@ -140,6 +141,7 @@ limitations under the License.
|
||||
</main>
|
||||
</template>
|
||||
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
|
||||
<gr-js-api-interface id="jsAPI"></gr-js-api-interface>
|
||||
</template>
|
||||
<script src="gr-admin-view.js"></script>
|
||||
</dom-module>
|
||||
|
@ -102,9 +102,13 @@
|
||||
},
|
||||
|
||||
reload() {
|
||||
return this.$.restAPI.getAccount().then(account => {
|
||||
this._account = account;
|
||||
if (!account) {
|
||||
const promises = [
|
||||
this.$.restAPI.getAccount(),
|
||||
Gerrit.awaitPluginsLoaded(),
|
||||
];
|
||||
return Promise.all(promises).then(result => {
|
||||
this._account = result[0];
|
||||
if (!this._account) {
|
||||
// Return so that account capabilities don't load with no account.
|
||||
return this._filteredLinks = this._filterLinks(link => {
|
||||
return link.viewableToAll;
|
||||
@ -115,7 +119,20 @@
|
||||
},
|
||||
|
||||
_filterLinks(filterFn) {
|
||||
const links = ADMIN_LINKS.filter(filterFn);
|
||||
let links = ADMIN_LINKS.slice(0);
|
||||
|
||||
// Append top-level links that are defined by plugins.
|
||||
links.push(...this.$.jsAPI.getAdminMenuLinks().map(link => ({
|
||||
url: link.url,
|
||||
name: link.text,
|
||||
children: [],
|
||||
noBaseUrl: link.url[0] === '/',
|
||||
view: null,
|
||||
viewableToAll: true,
|
||||
})));
|
||||
|
||||
links = links.filter(filterFn);
|
||||
|
||||
const filteredLinks = [];
|
||||
for (const link of links) {
|
||||
const linkCopy = Object.assign({}, link);
|
||||
@ -184,6 +201,7 @@
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
filteredLinks.push(linkCopy);
|
||||
}
|
||||
return filteredLinks;
|
||||
|
@ -45,6 +45,7 @@ limitations under the License.
|
||||
return Promise.resolve({});
|
||||
},
|
||||
});
|
||||
sandbox.stub(Gerrit, 'awaitPluginsLoaded').returns(Promise.resolve());
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
@ -145,6 +146,32 @@ limitations under the License.
|
||||
});
|
||||
});
|
||||
|
||||
test('_filteredLinks from plugin', () => {
|
||||
sandbox.stub(element.$.jsAPI, 'getAdminMenuLinks').returns([
|
||||
{text: 'internal link text', url: '/internal/link/url'},
|
||||
{text: 'external link text', url: 'http://external/link/url'},
|
||||
]);
|
||||
return element.reload().then(() => {
|
||||
assert.equal(element._filteredLinks.length, 3);
|
||||
assert.deepEqual(element._filteredLinks[1], {
|
||||
url: '/internal/link/url',
|
||||
name: 'internal link text',
|
||||
children: [],
|
||||
noBaseUrl: true,
|
||||
view: null,
|
||||
viewableToAll: true,
|
||||
});
|
||||
assert.deepEqual(element._filteredLinks[2], {
|
||||
url: 'http://external/link/url',
|
||||
name: 'external link text',
|
||||
children: [],
|
||||
noBaseUrl: false,
|
||||
view: null,
|
||||
viewableToAll: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Repo shows up in nav', done => {
|
||||
element._repoName = 'Test Repo';
|
||||
sandbox.stub(element.$.restAPI, 'getAccountCapabilities', () => {
|
||||
|
@ -0,0 +1,18 @@
|
||||
<!--
|
||||
@license
|
||||
Copyright (C) 2018 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.
|
||||
-->
|
||||
|
||||
<script src="gr-admin-api.js"></script>
|
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright (C) 2018 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';
|
||||
|
||||
// Prevent redefinition.
|
||||
if (window.GrAdminApi) { return; }
|
||||
|
||||
function GrAdminApi(plugin) {
|
||||
this.plugin = plugin;
|
||||
plugin.on('admin-menu-links', this);
|
||||
this._menuLinks = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @param {string} url
|
||||
*/
|
||||
GrAdminApi.prototype.addMenuLink = function(text, url) {
|
||||
this._menuLinks.push({text, url});
|
||||
};
|
||||
|
||||
GrAdminApi.prototype.getMenuLinks = function() {
|
||||
return this._menuLinks.slice(0);
|
||||
};
|
||||
|
||||
window.GrAdminApi = GrAdminApi;
|
||||
})(window);
|
@ -0,0 +1,60 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
@license
|
||||
Copyright (C) 2018 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-admin-api</title>
|
||||
|
||||
<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
|
||||
<script src="../../../bower_components/web-component-tester/browser.js"></script>
|
||||
<link rel="import" href="../../../test/common-test-setup.html"/>
|
||||
<link rel="import" href="../../shared/gr-js-api-interface/gr-js-api-interface.html">
|
||||
<link rel="import" href="gr-admin-api.html">
|
||||
|
||||
<script>void(0);</script>
|
||||
|
||||
<script>
|
||||
suite('gr-admin-api tests', () => {
|
||||
let sandbox;
|
||||
let adminApi;
|
||||
|
||||
setup(() => {
|
||||
sandbox = sinon.sandbox.create();
|
||||
let plugin;
|
||||
Gerrit.install(p => { plugin = p; }, '0.1',
|
||||
'http://test.com/plugins/testplugin/static/test.js');
|
||||
sandbox.stub(Gerrit, '_arePluginsLoaded').returns(true);
|
||||
adminApi = plugin.admin();
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
adminApi = null;
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
test('exists', () => {
|
||||
assert.isOk(adminApi);
|
||||
});
|
||||
|
||||
test('addMenuLink', () => {
|
||||
adminApi.addMenuLink('text', 'url');
|
||||
const links = adminApi.getMenuLinks();
|
||||
assert.equal(links.length, 1);
|
||||
assert.deepEqual(links[0], {text: 'text', url: 'url'});
|
||||
});
|
||||
});
|
||||
</script>
|
@ -18,6 +18,7 @@ limitations under the License.
|
||||
<link rel="import" href="../../../behaviors/base-url-behavior/base-url-behavior.html">
|
||||
<link rel="import" href="../../../behaviors/gr-patch-set-behavior/gr-patch-set-behavior.html">
|
||||
<link rel="import" href="../../core/gr-reporting/gr-reporting.html">
|
||||
<link rel="import" href="../../plugins/gr-admin-api/gr-admin-api.html">
|
||||
<link rel="import" href="../../plugins/gr-attribute-helper/gr-attribute-helper.html">
|
||||
<link rel="import" href="../../plugins/gr-dom-hooks/gr-dom-hooks.html">
|
||||
<link rel="import" href="../../plugins/gr-event-helper/gr-event-helper.html">
|
||||
|
@ -27,6 +27,7 @@
|
||||
REVERT: 'revert',
|
||||
POST_REVERT: 'postrevert',
|
||||
ANNOTATE_DIFF: 'annotatediff',
|
||||
ADMIN_MENU_LINKS: 'admin-menu-links',
|
||||
};
|
||||
|
||||
const Element = {
|
||||
@ -212,6 +213,15 @@
|
||||
return layers;
|
||||
},
|
||||
|
||||
getAdminMenuLinks() {
|
||||
const links = [];
|
||||
for (const adminApi of
|
||||
this._getEventCallbacks(EventType.ADMIN_MENU_LINKS)) {
|
||||
links.push(...adminApi.getMenuLinks());
|
||||
}
|
||||
return links;
|
||||
},
|
||||
|
||||
getLabelValuesPostRevert(change) {
|
||||
let labels = {};
|
||||
for (const cb of this._getEventCallbacks(EventType.POST_REVERT)) {
|
||||
|
@ -378,6 +378,20 @@ limitations under the License.
|
||||
assert.notStrictEqual(plugin.install, plugin.deprecated.install);
|
||||
});
|
||||
|
||||
test('getAdminMenuLinks', () => {
|
||||
const links = [{text: 'a', url: 'b'}, {text: 'c', url: 'd'}];
|
||||
const getCallbacksStub = sandbox.stub(element, '_getEventCallbacks')
|
||||
.returns([
|
||||
{getMenuLinks: () => [links[0]]},
|
||||
{getMenuLinks: () => [links[1]]},
|
||||
]);
|
||||
const result = element.getAdminMenuLinks();
|
||||
assert.deepEqual(result, links);
|
||||
assert.isTrue(getCallbacksStub.calledOnce);
|
||||
assert.equal(getCallbacksStub.lastCall.args[0],
|
||||
element.EventType.ADMIN_MENU_LINKS);
|
||||
});
|
||||
|
||||
suite('test plugin with base url', () => {
|
||||
setup(() => {
|
||||
sandbox.stub(Gerrit.BaseUrlBehavior, 'getBaseUrl').returns('/r');
|
||||
|
@ -223,6 +223,10 @@
|
||||
return new GrRepoApi(this);
|
||||
};
|
||||
|
||||
Plugin.prototype.admin = function() {
|
||||
return new GrAdminApi(this);
|
||||
};
|
||||
|
||||
Plugin.prototype.settings = function() {
|
||||
return new GrSettingsApi(this);
|
||||
};
|
||||
|
@ -115,6 +115,7 @@ limitations under the License.
|
||||
'edit/gr-edit-controls/gr-edit-controls_test.html',
|
||||
'edit/gr-edit-file-controls/gr-edit-file-controls_test.html',
|
||||
'edit/gr-editor-view/gr-editor-view_test.html',
|
||||
'plugins/gr-admin-api/gr-admin-api_test.html',
|
||||
'plugins/gr-attribute-helper/gr-attribute-helper_test.html',
|
||||
'plugins/gr-endpoint-decorator/gr-endpoint-decorator_test.html',
|
||||
'plugins/gr-event-helper/gr-event-helper_test.html',
|
||||
|
Loading…
Reference in New Issue
Block a user