From cad4bf8108d1dc9d06796043f262cc1fe2362c1d Mon Sep 17 00:00:00 2001 From: Becky Siegel Date: Wed, 18 Apr 2018 16:43:05 +0200 Subject: [PATCH] Introduce gr-admin-nav-behavior and use in gr-admin-view gr-admin-nav-behavior will also be used by the main header. For this change, the behavior replaces work previously done in gr-admin-view. In a follow-up change, gr-admin-view will display the current section's options in a gr-dropdown-list and the gr-main-header will display top level admin links in a dropdown menu. Change-Id: Ief0ca439528929f35335309c292512579bb696c3 --- .../gr-admin-nav-behavior.html | 203 ++++++++++++ .../gr-admin-nav-behavior_test.html | 303 ++++++++++++++++++ .../admin/gr-admin-view/gr-admin-view.html | 1 + .../admin/gr-admin-view/gr-admin-view.js | 175 +++------- .../gr-admin-view/gr-admin-view_test.html | 66 +++- polygerrit-ui/app/test/index.html | 1 + 6 files changed, 608 insertions(+), 141 deletions(-) create mode 100644 polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior.html create mode 100644 polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior_test.html diff --git a/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior.html b/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior.html new file mode 100644 index 0000000000..ac6889607f --- /dev/null +++ b/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior.html @@ -0,0 +1,203 @@ + + diff --git a/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior_test.html b/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior_test.html new file mode 100644 index 0000000000..3e1b868f58 --- /dev/null +++ b/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior_test.html @@ -0,0 +1,303 @@ + + + + +keyboard-shortcut-behavior + + + + + + + + + + + diff --git a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.html b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.html index e43f22089f..3a54152c72 100644 --- a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.html +++ b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.html @@ -18,6 +18,7 @@ limitations under the License. + diff --git a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.js b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.js index 66f017a769..f04fafb27e 100644 --- a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.js +++ b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.js @@ -17,35 +17,9 @@ (function() { 'use strict'; - // Note: noBaseUrl: true is set on entries where the URL is not yet supported - // by router abstraction. - const ADMIN_LINKS = [{ - name: 'Repositories', - noBaseUrl: true, - url: '/admin/repos', - view: 'gr-repo-list', - viewableToAll: true, - children: [], - }, { - name: 'Groups', - section: 'Groups', - noBaseUrl: true, - url: '/admin/groups', - view: 'gr-admin-group-list', - children: [], - }, { - name: 'Plugins', - capability: 'viewPlugins', - section: 'Plugins', - noBaseUrl: true, - url: '/admin/plugins', - view: 'gr-plugin-list', - }]; const INTERNAL_GROUP_REGEX = /^[\da-f]{40}$/; - const ACCOUNT_CAPABILITIES = ['createProject', 'createGroup', 'viewPlugins']; - Polymer({ is: 'gr-admin-view', @@ -66,6 +40,7 @@ type: Boolean, value: false, }, + _subsectionLinks: Array, _filteredLinks: Array, _showDownload: { type: Boolean, @@ -89,6 +64,7 @@ }, behaviors: [ + Gerrit.AdminNavBehavior, Gerrit.BaseUrlBehavior, Gerrit.URLEncodingBehavior, ], @@ -108,113 +84,54 @@ ]; 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; - }); + let options; + if (this._repoName) { + options = {repoName: this._repoName}; + } else if (this._groupId) { + options = { + groupId: this._groupId, + groupName: this._groupName, + groupIsInternal: this._groupIsInternal, + isAdmin: this._isAdmin, + groupOwner: this._groupOwner, + }; } - this._loadAccountCapabilities(); + + return this.getAdminLinks(this._account, + this.$.restAPI.getAccountCapabilities.bind(this.$.restAPI), + this.$.jsAPI.getAdminMenuLinks.bind(this.$.jsAPI), + options) + .then(res => { + this._filteredLinks = res.links; + + if (!res.expandedSection) { + this._subsectionLinks = []; + return; + } + this._subsectionLinks = [res.expandedSection] + .concat(res.expandedSection.children).map(section => { + return { + text: !section.detailType ? 'Home' : section.name, + value: section.view + section.detailType, + view: section.view, + url: section.url, + detailType: section.detailType, + parent: this._groupId || this._repoName || '', + }; + }); + }); }); }, - _filterLinks(filterFn) { - let links = ADMIN_LINKS.slice(0); + _handleSubsectionChange(e) { + const selected = this._subsectionLinks + .find(section => section.value === e.detail.value); - // 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); - linkCopy.children = linkCopy.children ? - linkCopy.children.filter(filterFn) : []; - if (linkCopy.name === 'Repositories' && this._repoName) { - linkCopy.subsection = { - name: this._repoName, - view: Gerrit.Nav.View.REPO, - url: Gerrit.Nav.getUrlForRepo(this._repoName), - children: [{ - name: 'Access', - view: Gerrit.Nav.View.REPO, - detailType: Gerrit.Nav.RepoDetailView.ACCESS, - url: Gerrit.Nav.getUrlForRepoAccess(this._repoName), - }, - { - name: 'Commands', - view: Gerrit.Nav.View.REPO, - detailType: Gerrit.Nav.RepoDetailView.COMMANDS, - url: Gerrit.Nav.getUrlForRepoCommands(this._repoName), - }, - { - name: 'Branches', - view: Gerrit.Nav.View.REPO, - detailType: Gerrit.Nav.RepoDetailView.BRANCHES, - url: Gerrit.Nav.getUrlForRepoBranches(this._repoName), - }, - { - name: 'Tags', - view: Gerrit.Nav.View.REPO, - detailType: Gerrit.Nav.RepoDetailView.TAGS, - url: Gerrit.Nav.getUrlForRepoTags(this._repoName), - }, - { - name: 'Dashboards', - view: Gerrit.Nav.View.REPO, - detailType: Gerrit.Nav.RepoDetailView.DASHBOARDS, - url: Gerrit.Nav.getUrlForRepoDashboards(this._repoName), - }], - }; - } - if (linkCopy.name === 'Groups' && this._groupId && this._groupName) { - linkCopy.subsection = { - name: this._groupName, - view: Gerrit.Nav.View.GROUP, - url: Gerrit.Nav.getUrlForGroup(this._groupId), - children: [], - }; - if (this._groupIsInternal) { - linkCopy.subsection.children.push({ - name: 'Members', - detailType: Gerrit.Nav.GroupDetailView.MEMBERS, - view: Gerrit.Nav.View.GROUP, - url: Gerrit.Nav.getUrlForGroupMembers(this._groupId), - }); - } - if (this._groupIsInternal && (this._isAdmin || this._groupOwner)) { - linkCopy.subsection.children.push( - { - name: 'Audit Log', - detailType: Gerrit.Nav.GroupDetailView.LOG, - view: Gerrit.Nav.View.GROUP, - url: Gerrit.Nav.getUrlForGroupLog(this._groupId), - } - ); - } - } - - filteredLinks.push(linkCopy); + // This is when it gets set initially. + if (this._selectedIsCurrentPage(selected)) { + return; } - return filteredLinks; - }, - - _loadAccountCapabilities() { - return this.$.restAPI.getAccountCapabilities(ACCOUNT_CAPABILITIES) - .then(capabilities => { - this._filteredLinks = this._filterLinks(link => { - return !link.capability || - capabilities.hasOwnProperty(link.capability); - }); - }); + Gerrit.Nav.navigateToRelativeUrl(selected.url); }, _paramsChanged(params) { @@ -260,6 +177,10 @@ } }, + _computeSelectedTitle(params) { + return this.getSelectedTitle(params.view); + }, + // TODO (beckysiegel): Update these functions after router abstraction is // updated. They are currently copied from gr-dropdown (and should be // updated there as well once complete). diff --git a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.html b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.html index ad1fe46404..9148da15d4 100644 --- a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.html +++ b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.html @@ -95,6 +95,9 @@ limitations under the License. }); test('_filteredLinks admin', done => { + sandbox.stub(element.$.restAPI, 'getAccount').returns(Promise.resolve({ + name: 'test-user', + })); sandbox.stub(element.$.restAPI, 'getAccountCapabilities', () => { return Promise.resolve({ createGroup: true, @@ -102,35 +105,36 @@ limitations under the License. viewPlugins: true, }); }); - element._loadAccountCapabilities().then(() => { + element.reload().then(() => { assert.equal(element._filteredLinks.length, 3); // Repos - assert.equal(element._filteredLinks[0].children.length, 0); assert.isNotOk(element._filteredLinks[0].subsection); // Groups - assert.equal(element._filteredLinks[1].children.length, 0); + assert.isNotOk(element._filteredLinks[0].subsection); // Plugins - assert.equal(element._filteredLinks[2].children.length, 0); + assert.isNotOk(element._filteredLinks[0].subsection); done(); }); }); test('_filteredLinks non admin authenticated', done => { + sandbox.stub(element.$.restAPI, 'getAccount').returns(Promise.resolve({ + name: 'test-user', + })); sandbox.stub(element.$.restAPI, 'getAccountCapabilities', () => { return Promise.resolve({}); }); - element._loadAccountCapabilities().then(() => { + element.reload().then(() => { assert.equal(element._filteredLinks.length, 2); // Repos - assert.equal(element._filteredLinks[0].children.length, 0); assert.isNotOk(element._filteredLinks[0].subsection); // Groups - assert.equal(element._filteredLinks[1].children.length, 0); + assert.isNotOk(element._filteredLinks[0].subsection); done(); }); }); @@ -140,7 +144,6 @@ limitations under the License. assert.equal(element._filteredLinks.length, 1); // Repos - assert.equal(element._filteredLinks[0].children.length, 0); assert.isNotOk(element._filteredLinks[0].subsection); done(); }); @@ -156,7 +159,6 @@ limitations under the License. assert.deepEqual(element._filteredLinks[1], { url: '/internal/link/url', name: 'internal link text', - children: [], noBaseUrl: true, view: null, viewableToAll: true, @@ -164,7 +166,6 @@ limitations under the License. assert.deepEqual(element._filteredLinks[2], { url: 'http://external/link/url', name: 'external link text', - children: [], noBaseUrl: false, view: null, viewableToAll: true, @@ -174,6 +175,9 @@ limitations under the License. test('Repo shows up in nav', done => { element._repoName = 'Test Repo'; + sandbox.stub(element.$.restAPI, 'getAccount').returns(Promise.resolve({ + name: 'test-user', + })); sandbox.stub(element.$.restAPI, 'getAccountCapabilities', () => { return Promise.resolve({ createGroup: true, @@ -181,18 +185,52 @@ limitations under the License. viewPlugins: true, }); }); - element._loadAccountCapabilities().then(() => { + element.reload().then(() => { + flushAsynchronousOperations(); assert.equal(element._filteredLinks.length, 3); // Repos - assert.equal(element._filteredLinks[0].children.length, 0); + assert.equal(element._filteredLinks[0].subsection.children.length, 5); assert.equal(element._filteredLinks[0].subsection.name, 'Test Repo'); // Groups - assert.equal(element._filteredLinks[1].children.length, 0); + assert.isNotOk(element._filteredLinks[1].subsection); // Plugins - assert.equal(element._filteredLinks[2].children.length, 0); + assert.isNotOk(element._filteredLinks[2].subsection); + done(); + }); + }); + + test('Group shows up in nav', done => { + element._groupId = 'a15262'; + element._groupName = 'my-group'; + element._groupIsInternal = true; + element._isAdmin = true; + element._groupOwner = false; + sandbox.stub(element.$.restAPI, 'getAccount').returns(Promise.resolve({ + name: 'test-user', + })); + sandbox.stub(element.$.restAPI, 'getAccountCapabilities', () => { + return Promise.resolve({ + createGroup: true, + createProject: true, + viewPlugins: true, + }); + }); + element.reload().then(() => { + flushAsynchronousOperations(); + assert.equal(element._filteredLinks.length, 3); + + // Repos + assert.isNotOk(element._filteredLinks[0].subsection); + + // Groups + assert.equal(element._filteredLinks[1].subsection.children.length, 2); + assert.equal(element._filteredLinks[1].subsection.name, 'my-group'); + + // Plugins + assert.isNotOk(element._filteredLinks[2].subsection); done(); }); }); diff --git a/polygerrit-ui/app/test/index.html b/polygerrit-ui/app/test/index.html index e7c3747d65..6cf674a2ef 100644 --- a/polygerrit-ui/app/test/index.html +++ b/polygerrit-ui/app/test/index.html @@ -196,6 +196,7 @@ limitations under the License. 'keyboard-shortcut-behavior/keyboard-shortcut-behavior_test.html', 'rest-client-behavior/rest-client-behavior_test.html', 'gr-access-behavior/gr-access-behavior_test.html', + 'gr-admin-nav-behavior/gr-admin-nav-behavior_test.html', 'gr-anonymous-name-behavior/gr-anonymous-name-behavior_test.html', 'gr-change-table-behavior/gr-change-table-behavior_test.html', 'gr-patch-set-behavior/gr-patch-set-behavior_test.html',