Merge "Fix change-list-item having grown from 28px to 29px height"
diff --git a/polygerrit-ui/app/BUILD b/polygerrit-ui/app/BUILD
index 1038629..5e944c2 100644
--- a/polygerrit-ui/app/BUILD
+++ b/polygerrit-ui/app/BUILD
@@ -94,7 +94,6 @@
# so template tests pass.
# TODO: fix problems reported by template checker in these files.
ignore_templates_list = [
- "elements/admin/gr-admin-view/gr-admin-view_html.ts",
"elements/admin/gr-permission/gr-permission_html.ts",
"elements/admin/gr-repo-access/gr-repo-access_html.ts",
"elements/admin/gr-rule-editor/gr-rule-editor_html.ts",
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.ts b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.ts
index 2c2405b..762bffc 100644
--- a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.ts
+++ b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.ts
@@ -14,9 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import '../../../styles/gr-menu-page-styles';
-import '../../../styles/gr-page-nav-styles';
-import '../../../styles/shared-styles';
+
import '../../shared/gr-dropdown-list/gr-dropdown-list';
import '../../shared/gr-icons/gr-icons';
import '../../shared/gr-page-nav/gr-page-nav';
@@ -31,8 +29,6 @@
import '../gr-repo-dashboards/gr-repo-dashboards';
import '../gr-repo-detail-list/gr-repo-detail-list';
import '../gr-repo-list/gr-repo-list';
-import {PolymerElement} from '@polymer/polymer/polymer-element';
-import {htmlTemplate} from './gr-admin-view_html';
import {getBaseUrl} from '../../../utils/url-util';
import {
GerritNav,
@@ -46,7 +42,6 @@
NavLink,
SubsectionInterface,
} from '../../../utils/admin-nav-util';
-import {customElement, observe, property} from '@polymer/decorators';
import {
AppElementAdminParams,
AppElementGroupParams,
@@ -62,6 +57,11 @@
import {ValueChangeDetail} from '../../shared/gr-dropdown-list/gr-dropdown-list';
import {getAppContext} from '../../../services/app-context';
import {GerritView} from '../../../services/router/router-model';
+import {menuPageStyles} from '../../../styles/gr-menu-page-styles';
+import {pageNavStyles} from '../../../styles/gr-page-nav-styles';
+import {sharedStyles} from '../../../styles/shared-styles';
+import {LitElement, PropertyValues, css, html} from 'lit';
+import {customElement, property, state} from 'lit/decorators';
const INTERNAL_GROUP_REGEX = /^[\da-f]{40}$/;
@@ -90,11 +90,7 @@
}
@customElement('gr-admin-view')
-export class GrAdminView extends PolymerElement {
- static get template() {
- return htmlTemplate;
- }
-
+export class GrAdminView extends LitElement {
private account?: AccountDetailInfo;
@property({type: Object})
@@ -106,68 +102,25 @@
@property({type: String})
adminView?: string;
- @property({type: String})
- _breadcrumbParentName?: string;
+ @state() private breadcrumbParentName?: string;
- @property({type: String})
- _repoName?: RepoName;
+ // private but used in test
+ @state() repoName?: RepoName;
- @property({type: String, observer: '_computeGroupName'})
- _groupId?: GroupId;
+ // private but used in test
+ @state() groupId?: GroupId;
- @property({type: Boolean})
- _groupIsInternal?: boolean;
+ // private but used in test
+ @state() groupIsInternal?: boolean;
- @property({type: String})
- _groupName?: GroupName;
+ // private but used in test
+ @state() groupName?: GroupName;
- @property({type: Boolean})
- _groupOwner = false;
+ // private but used in test
+ @state() subsectionLinks?: AdminSubsectionLink[];
- @property({type: Array})
- _subsectionLinks?: AdminSubsectionLink[];
-
- @property({type: Array})
- _filteredLinks?: NavLink[];
-
- @property({type: Boolean})
- _showDownload = false;
-
- @property({type: Boolean})
- _isAdmin = false;
-
- @property({type: Boolean})
- _showGroup?: boolean;
-
- @property({type: Boolean})
- _showGroupAuditLog?: boolean;
-
- @property({type: Boolean})
- _showGroupList?: boolean;
-
- @property({type: Boolean})
- _showGroupMembers?: boolean;
-
- @property({type: Boolean})
- _showRepoAccess?: boolean;
-
- @property({type: Boolean})
- _showRepoCommands?: boolean;
-
- @property({type: Boolean})
- _showRepoDashboards?: boolean;
-
- @property({type: Boolean})
- _showRepoDetailList?: boolean;
-
- @property({type: Boolean})
- _showRepoMain?: boolean;
-
- @property({type: Boolean})
- _showRepoList?: boolean;
-
- @property({type: Boolean})
- _showPluginList?: boolean;
+ // private but used in test
+ @state() filteredLinks?: NavLink[];
// private but used in the tests
readonly jsAPI = getAppContext().jsApiService;
@@ -179,201 +132,479 @@
this.reload();
}
- reload() {
+ static override get styles() {
+ return [
+ sharedStyles,
+ menuPageStyles,
+ pageNavStyles,
+ css`
+ .breadcrumbText {
+ /* Same as dropdown trigger so chevron spacing is consistent. */
+ padding: 5px 4px;
+ }
+ iron-icon {
+ margin: 0 var(--spacing-xs);
+ }
+ .breadcrumb {
+ align-items: center;
+ display: flex;
+ }
+ .mainHeader {
+ align-items: baseline;
+ border-bottom: 1px solid var(--border-color);
+ display: flex;
+ }
+ .selectText {
+ display: none;
+ }
+ .selectText.show {
+ display: inline-block;
+ }
+ .main.breadcrumbs:not(.table) {
+ margin-top: var(--spacing-l);
+ }
+ `,
+ ];
+ }
+
+ override render() {
+ return html`
+ <gr-page-nav class="navStyles">
+ <ul class="sectionContent">
+ ${this.filteredLinks?.map(item => this.renderAdminNav(item))}
+ </ul>
+ </gr-page-nav>
+ ${this.renderSubsectionLinks()} ${this.renderRepoList()}
+ ${this.renderGroupList()} ${this.renderPluginList()}
+ ${this.renderRepoMain()} ${this.renderGroup()}
+ ${this.renderGroupMembers()} ${this.renderGroupAuditLog()}
+ ${this.renderRepoDetailList()} ${this.renderRepoCommands()}
+ ${this.renderRepoAccess()} ${this.renderRepoDashboards()}
+ `;
+ }
+
+ private renderAdminNav(item: NavLink) {
+ return html`
+ <li class="sectionTitle ${this.computeSelectedClass(item.view)}">
+ <a class="title" href="${this.computeLinkURL(item)}" rel="noopener"
+ >${item.name}</a
+ >
+ </li>
+ ${item.children?.map(child => this.renderAdminNavChild(child))}
+ ${this.renderAdminNavSubsection(item)}
+ `;
+ }
+
+ private renderAdminNavChild(child: SubsectionInterface) {
+ return html`
+ <li class="${this.computeSelectedClass(child.view)}">
+ <a href="${this.computeLinkURL(child)}" rel="noopener">${child.name}</a>
+ </li>
+ `;
+ }
+
+ private renderAdminNavSubsection(item: NavLink) {
+ if (!item.subsection) return;
+
+ return html`
+ <!--If a section has a subsection, render that.-->
+ <li class="${this.computeSelectedClass(item.subsection.view)}">
+ ${this.renderAdminNavSubsectionUrl(item.subsection)}
+ </li>
+ <!--Loop through the links in the sub-section.-->
+ ${item.subsection?.children?.map(child =>
+ this.renderAdminNavSubsectionChild(child)
+ )}
+ `;
+ }
+
+ private renderAdminNavSubsectionUrl(subsection?: SubsectionInterface) {
+ if (!subsection!.url) return html`${subsection!.name}`;
+
+ return html`
+ <a class="title" href="${this.computeLinkURL(subsection)}" rel="noopener">
+ ${subsection!.name}</a
+ >
+ `;
+ }
+
+ private renderAdminNavSubsectionChild(child: SubsectionInterface) {
+ return html`
+ <li
+ class="subsectionItem ${this.computeSelectedClass(
+ child.view,
+ child.detailType
+ )}"
+ >
+ <a href="${this.computeLinkURL(child)}">${child.name}</a>
+ </li>
+ `;
+ }
+
+ private renderSubsectionLinks() {
+ if (!this.subsectionLinks?.length) return;
+
+ return html`
+ <section class="mainHeader">
+ <span class="breadcrumb">
+ <span class="breadcrumbText">${this.breadcrumbParentName}</span>
+ <iron-icon icon="gr-icons:chevron-right"></iron-icon>
+ </span>
+ <gr-dropdown-list
+ id="pageSelect"
+ lowercase
+ value=${this.computeSelectValue()}
+ .items=${this.subsectionLinks}
+ @value-change=${this.handleSubsectionChange}
+ >
+ </gr-dropdown-list>
+ </section>
+ `;
+ }
+
+ private renderRepoList() {
+ const params = this.params as AppElementAdminParams;
+ if (
+ !(
+ params?.view === GerritView.ADMIN &&
+ params?.adminView === 'gr-repo-list'
+ )
+ )
+ return;
+
+ return html`
+ <div class="main table">
+ <gr-repo-list class="table" .params=${params}></gr-repo-list>
+ </div>
+ `;
+ }
+
+ private renderGroupList() {
+ const params = this.params as AppElementAdminParams;
+ if (
+ !(
+ params?.view === GerritView.ADMIN &&
+ params?.adminView === 'gr-admin-group-list'
+ )
+ )
+ return;
+
+ return html`
+ <div class="main table">
+ <gr-admin-group-list class="table" .params=${params}>
+ </gr-admin-group-list>
+ </div>
+ `;
+ }
+
+ private renderPluginList() {
+ const params = this.params as AppElementAdminParams;
+ if (
+ !(
+ params?.view === GerritView.ADMIN &&
+ params?.adminView === 'gr-plugin-list'
+ )
+ )
+ return;
+
+ return html`
+ <div class="main table">
+ <gr-plugin-list class="table" .params=${params}></gr-plugin-list>
+ </div>
+ `;
+ }
+
+ private renderRepoMain() {
+ const params = this.params as AppElementRepoParams;
+ if (
+ !(
+ params?.view === GerritView.REPO &&
+ (!params?.detail || params?.detail === RepoDetailView.GENERAL)
+ )
+ )
+ return;
+
+ return html`
+ <div class="main breadcrumbs">
+ <gr-repo .repo=${params.repo}></gr-repo>
+ </div>
+ `;
+ }
+
+ private renderGroup() {
+ const params = this.params as AppElementGroupParams;
+ if (!(params?.view === GerritView.GROUP && !params?.detail)) return;
+
+ return html`
+ <div class="main breadcrumbs">
+ <gr-group
+ .groupId=${params.groupId}
+ @name-changed=${(e: CustomEvent<GroupNameChangedDetail>) => {
+ this.updateGroupName(e);
+ }}
+ ></gr-group>
+ </div>
+ `;
+ }
+
+ private renderGroupMembers() {
+ const params = this.params as AppElementGroupParams;
+ if (
+ !(
+ params?.view === GerritView.GROUP &&
+ params?.detail === GroupDetailView.MEMBERS
+ )
+ )
+ return;
+
+ return html`
+ <div class="main breadcrumbs">
+ <gr-group-members .groupId=${params.groupId}></gr-group-members>
+ </div>
+ `;
+ }
+
+ private renderGroupAuditLog() {
+ const params = this.params as AppElementGroupParams;
+ if (
+ !(
+ params?.view === GerritView.GROUP &&
+ params?.detail === GroupDetailView.LOG
+ )
+ )
+ return;
+
+ return html`
+ <div class="main table breadcrumbs">
+ <gr-group-audit-log
+ class="table"
+ .groupId=${params.groupId}
+ ></gr-group-audit-log>
+ </div>
+ `;
+ }
+
+ private renderRepoDetailList() {
+ const params = this.params as AppElementRepoParams;
+ if (
+ !(
+ params?.view === GerritView.REPO &&
+ (params?.detail === RepoDetailView.BRANCHES ||
+ params?.detail === RepoDetailView.TAGS)
+ )
+ )
+ return;
+
+ return html`
+ <div class="main table breadcrumbs">
+ <gr-repo-detail-list
+ class="table"
+ .params=${params}
+ ></gr-repo-detail-list>
+ </div>
+ `;
+ }
+
+ private renderRepoCommands() {
+ const params = this.params as AppElementRepoParams;
+ if (
+ !(
+ params?.view === GerritView.REPO &&
+ params?.detail === RepoDetailView.COMMANDS
+ )
+ )
+ return;
+
+ return html`
+ <div class="main breadcrumbs">
+ <gr-repo-commands .repo=${params.repo}></gr-repo-commands>
+ </div>
+ `;
+ }
+
+ private renderRepoAccess() {
+ const params = this.params as AppElementRepoParams;
+ if (
+ !(
+ params?.view === GerritView.REPO &&
+ params?.detail === RepoDetailView.ACCESS
+ )
+ )
+ return;
+
+ return html`
+ <div class="main breadcrumbs">
+ <gr-repo-access
+ .path=${this.path}
+ .repo=${params.repo}
+ ></gr-repo-access>
+ </div>
+ `;
+ }
+
+ private renderRepoDashboards() {
+ const params = this.params as AppElementRepoParams;
+ if (
+ !(
+ params?.view === GerritView.REPO &&
+ params?.detail === RepoDetailView.DASHBOARDS
+ )
+ )
+ return;
+
+ return html`
+ <div class="main table breadcrumbs">
+ <gr-repo-dashboards .repo=${params.repo}></gr-repo-dashboards>
+ </div>
+ `;
+ }
+
+ override willUpdate(changedProperties: PropertyValues) {
+ if (changedProperties.has('params')) {
+ this.paramsChanged();
+ }
+
+ if (changedProperties.has('groupId')) {
+ this.computeGroupName();
+ }
+ }
+
+ async reload() {
const promises: [Promise<AccountDetailInfo | undefined>, Promise<void>] = [
this.restApiService.getAccount(),
getPluginLoader().awaitPluginsLoaded(),
];
- return Promise.all(promises).then(result => {
- this.account = result[0];
- let options: AdminNavLinksOption | undefined = undefined;
- 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,
+ const result = await Promise.all(promises);
+ this.account = result[0];
+ let options: AdminNavLinksOption | undefined = undefined;
+ if (this.repoName) {
+ options = {repoName: this.repoName};
+ } else if (this.groupId) {
+ const isAdmin = await this.restApiService.getIsAdmin();
+ const isOwner = await this.restApiService.getIsGroupOwner(this.groupName);
+ options = {
+ groupId: this.groupId,
+ groupName: this.groupName,
+ groupIsInternal: this.groupIsInternal,
+ isAdmin,
+ groupOwner: isOwner,
+ };
+ }
+
+ const res = await getAdminLinks(
+ this.account,
+ () =>
+ this.restApiService.getAccountCapabilities().then(capabilities => {
+ if (!capabilities) {
+ throw new Error('getAccountCapabilities returns undefined');
+ }
+ return capabilities;
+ }),
+ () => this.jsAPI.getAdminMenuLinks(),
+ options
+ );
+ this.filteredLinks = res.links;
+ this.breadcrumbParentName = res.expandedSection
+ ? res.expandedSection.name
+ : '';
+
+ 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,
};
- }
-
- return getAdminLinks(
- this.account,
- () =>
- this.restApiService.getAccountCapabilities().then(capabilities => {
- if (!capabilities) {
- throw new Error('getAccountCapabilities returns undefined');
- }
- return capabilities;
- }),
- () => this.jsAPI.getAdminMenuLinks(),
- options
- ).then(res => {
- this._filteredLinks = res.links;
- this._breadcrumbParentName = res.expandedSection
- ? res.expandedSection.name
- : '';
-
- 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,
- };
- });
});
- });
}
- _computeSelectValue(params: AdminViewParams) {
- if (!params || !params.view) return;
- return `${params.view}${getAdminViewParamsDetail(params) ?? ''}`;
+ private computeSelectValue() {
+ if (!this.params?.view) return;
+ return `${this.params.view}${getAdminViewParamsDetail(this.params) ?? ''}`;
}
- _selectedIsCurrentPage(selected: AdminSubsectionLink) {
+ // private but used in test
+ selectedIsCurrentPage(selected: AdminSubsectionLink) {
if (!this.params) return false;
return (
- selected.parent === (this._repoName ?? this._groupId) &&
+ selected.parent === (this.repoName ?? this.groupId) &&
selected.view === this.params.view &&
selected.detailType === getAdminViewParamsDetail(this.params)
);
}
- _handleSubsectionChange(e: CustomEvent<ValueChangeDetail>) {
- if (!this._subsectionLinks) return;
+ // private but used in test
+ handleSubsectionChange(e: CustomEvent<ValueChangeDetail>) {
+ if (!this.subsectionLinks) return;
- // The GrDropdownList items are _subsectionLinks, so find(...) always return
- // an item _subsectionLinks and never returns undefined
- const selected = this._subsectionLinks.find(
+ // The GrDropdownList items are subsectionLinks, so find(...) always return
+ // an item subsectionLinks and never returns undefined
+ const selected = this.subsectionLinks.find(
section => section.value === e.detail.value
)!;
// This is when it gets set initially.
- if (this._selectedIsCurrentPage(selected)) return;
+ if (this.selectedIsCurrentPage(selected)) return;
if (selected.url === undefined) return;
GerritNav.navigateToRelativeUrl(selected.url);
}
- @observe('params')
- _paramsChanged(params: AdminViewParams) {
- this.set('_showGroup', params.view === GerritView.GROUP && !params.detail);
- this.set(
- '_showGroupAuditLog',
- params.view === GerritView.GROUP && params.detail === GroupDetailView.LOG
- );
- this.set(
- '_showGroupMembers',
- params.view === GerritView.GROUP &&
- params.detail === GroupDetailView.MEMBERS
- );
+ private async paramsChanged() {
+ if (this.needsReload()) await this.reload();
+ }
- this.set(
- '_showGroupList',
- params.view === GerritView.ADMIN &&
- params.adminView === 'gr-admin-group-list'
- );
+ needsReload() {
+ if (!this.params) return;
- this.set(
- '_showRepoAccess',
- params.view === GerritView.REPO && params.detail === RepoDetailView.ACCESS
- );
- this.set(
- '_showRepoCommands',
- params.view === GerritView.REPO &&
- params.detail === RepoDetailView.COMMANDS
- );
- this.set(
- '_showRepoDetailList',
- params.view === GerritView.REPO &&
- (params.detail === RepoDetailView.BRANCHES ||
- params.detail === RepoDetailView.TAGS)
- );
- this.set(
- '_showRepoDashboards',
- params.view === GerritView.REPO &&
- params.detail === RepoDetailView.DASHBOARDS
- );
- this.set(
- '_showRepoMain',
- params.view === GerritView.REPO &&
- (!params.detail || params.detail === RepoDetailView.GENERAL)
- );
- this.set(
- '_showRepoList',
- params.view === GerritView.ADMIN && params.adminView === 'gr-repo-list'
- );
-
- this.set(
- '_showPluginList',
- params.view === GerritView.ADMIN && params.adminView === 'gr-plugin-list'
- );
-
- let needsReload = false;
const newRepoName =
- params.view === GerritView.REPO ? params.repo : undefined;
- if (newRepoName !== this._repoName) {
- this._repoName = newRepoName;
+ this.params.view === GerritView.REPO ? this.params.repo : undefined;
+ if (newRepoName !== this.repoName) {
+ this.repoName = newRepoName;
// Reloads the admin menu.
- needsReload = true;
+ return true;
}
const newGroupId =
- params.view === GerritView.GROUP ? params.groupId : undefined;
- if (newGroupId !== this._groupId) {
- this._groupId = newGroupId;
+ this.params.view === GerritView.GROUP ? this.params.groupId : undefined;
+ if (newGroupId !== this.groupId) {
+ this.groupId = newGroupId;
// Reloads the admin menu.
- needsReload = true;
+ return true;
}
if (
- this._breadcrumbParentName &&
- (params.view !== GerritView.GROUP || !params.groupId) &&
- (params.view !== GerritView.REPO || !params.repo)
+ this.breadcrumbParentName &&
+ (this.params.view !== GerritView.GROUP || !this.params.groupId) &&
+ (this.params.view !== GerritView.REPO || !this.params.repo)
) {
- needsReload = true;
+ return true;
}
- if (!needsReload) {
- return;
- }
- this.reload();
+
+ return false;
}
- // 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).
- _computeURLHelper(host: string, path: string) {
- return '//' + host + getBaseUrl() + path;
- }
-
- _computeRelativeURL(path: string) {
- const host = window.location.host;
- return this._computeURLHelper(host, path);
- }
-
- _computeLinkURL(link: NavLink | SubsectionInterface) {
+ // private but used in test
+ computeLinkURL(link?: NavLink | SubsectionInterface) {
if (!link || typeof link.url === 'undefined') return '';
if ((link as NavLink).target || !(link as NavLink).noBaseUrl) {
return link.url;
}
- return this._computeRelativeURL(link.url);
+ return `//${window.location.host}${getBaseUrl()}${link.url}`;
}
- _computeSelectedClass(
+ private computeSelectedClass(
itemView?: GerritView,
- params?: AdminViewParams,
detailType?: GroupDetailView | RepoDetailView
) {
+ const params = this.params;
if (!params) return '';
// Group params are structured differently from admin params. Compute
// selected differently for groups.
@@ -410,40 +641,23 @@
: '';
}
- _computeGroupName(groupId?: GroupId) {
- if (!groupId) return;
+ // private but used in test
+ async computeGroupName() {
+ if (!this.groupId) return;
- const promises: Array<Promise<void>> = [];
- this.restApiService.getGroupConfig(groupId).then(group => {
- if (!group || !group.name) {
- return;
- }
+ const group = await this.restApiService.getGroupConfig(this.groupId);
+ if (!group || !group.name) {
+ return;
+ }
- this._groupName = group.name;
- this._groupIsInternal = !!group.id.match(INTERNAL_GROUP_REGEX);
- this.reload();
-
- promises.push(
- this.restApiService.getIsAdmin().then(isAdmin => {
- this._isAdmin = !!isAdmin;
- })
- );
-
- promises.push(
- this.restApiService.getIsGroupOwner(group.name).then(isOwner => {
- this._groupOwner = isOwner;
- })
- );
-
- return Promise.all(promises).then(() => {
- this.reload();
- });
- });
+ this.groupName = group.name;
+ this.groupIsInternal = !!group.id.match(INTERNAL_GROUP_REGEX);
+ await this.reload();
}
- _updateGroupName(e: CustomEvent<GroupNameChangedDetail>) {
- this._groupName = e.detail.name;
- this.reload();
+ private async updateGroupName(e: CustomEvent<GroupNameChangedDetail>) {
+ this.groupName = e.detail.name;
+ await this.reload();
}
}
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_html.ts b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_html.ts
deleted file mode 100644
index a3afc5c..0000000
--- a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_html.ts
+++ /dev/null
@@ -1,181 +0,0 @@
-/**
- * @license
- * Copyright (C) 2020 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.
- */
-import {html} from '@polymer/polymer/lib/utils/html-tag';
-
-export const htmlTemplate = html`
- <style include="shared-styles">
- /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
- </style>
- <style include="gr-menu-page-styles">
- /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
- </style>
- <style include="gr-page-nav-styles">
- .breadcrumbText {
- /* Same as dropdown trigger so chevron spacing is consistent. */
- padding: 5px 4px;
- }
- iron-icon {
- margin: 0 var(--spacing-xs);
- }
- .breadcrumb {
- align-items: center;
- display: flex;
- }
- .mainHeader {
- align-items: baseline;
- border-bottom: 1px solid var(--border-color);
- display: flex;
- }
- .selectText {
- display: none;
- }
- .selectText.show {
- display: inline-block;
- }
- .main.breadcrumbs:not(.table) {
- margin-top: var(--spacing-l);
- }
- </style>
- <gr-page-nav class="navStyles">
- <ul class="sectionContent">
- <template id="adminNav" is="dom-repeat" items="[[_filteredLinks]]">
- <li class$="sectionTitle [[_computeSelectedClass(item.view, params)]]">
- <a class="title" href="[[_computeLinkURL(item)]]" rel="noopener"
- >[[item.name]]</a
- >
- </li>
- <template is="dom-repeat" items="[[item.children]]" as="child">
- <li class$="[[_computeSelectedClass(child.view, params)]]">
- <a href$="[[_computeLinkURL(child)]]" rel="noopener"
- >[[child.name]]</a
- >
- </li>
- </template>
- <template is="dom-if" if="[[item.subsection]]">
- <!--If a section has a subsection, render that.-->
- <li class$="[[_computeSelectedClass(item.subsection.view, params)]]">
- <template is="dom-if" if="[[item.subsection.url]]" as="child">
- <a
- class="title"
- href$="[[_computeLinkURL(item.subsection)]]"
- rel="noopener"
- >
- [[item.subsection.name]]</a
- >
- </template>
- <template is="dom-if" if="[[!item.subsection.url]]" as="child">
- [[item.subsection.name]]
- </template>
- </li>
- <!--Loop through the links in the sub-section.-->
- <template
- is="dom-repeat"
- items="[[item.subsection.children]]"
- as="child"
- >
- <li
- class$="subsectionItem [[_computeSelectedClass(child.view, params, child.detailType)]]"
- >
- <a href$="[[_computeLinkURL(child)]]">[[child.name]]</a>
- </li>
- </template>
- </template>
- </template>
- </ul>
- </gr-page-nav>
- <template is="dom-if" if="[[_subsectionLinks.length]]">
- <section class="mainHeader">
- <span class="breadcrumb">
- <span class="breadcrumbText">[[_breadcrumbParentName]]</span>
- <iron-icon icon="gr-icons:chevron-right"></iron-icon>
- </span>
- <gr-dropdown-list
- lowercase=""
- id="pageSelect"
- value="[[_computeSelectValue(params)]]"
- items="[[_subsectionLinks]]"
- on-value-change="_handleSubsectionChange"
- >
- </gr-dropdown-list>
- </section>
- </template>
- <template is="dom-if" if="[[_showRepoList]]" restamp="true">
- <div class="main table">
- <gr-repo-list class="table" params="[[params]]"></gr-repo-list>
- </div>
- </template>
- <template is="dom-if" if="[[_showGroupList]]" restamp="true">
- <div class="main table">
- <gr-admin-group-list class="table" params="[[params]]">
- </gr-admin-group-list>
- </div>
- </template>
- <template is="dom-if" if="[[_showPluginList]]" restamp="true">
- <div class="main table">
- <gr-plugin-list class="table" params="[[params]]"></gr-plugin-list>
- </div>
- </template>
- <template is="dom-if" if="[[_showRepoMain]]" restamp="true">
- <div class="main breadcrumbs">
- <gr-repo repo="[[params.repo]]"></gr-repo>
- </div>
- </template>
- <template is="dom-if" if="[[_showGroup]]" restamp="true">
- <div class="main breadcrumbs">
- <gr-group
- group-id="[[params.groupId]]"
- on-name-changed="_updateGroupName"
- ></gr-group>
- </div>
- </template>
- <template is="dom-if" if="[[_showGroupMembers]]" restamp="true">
- <div class="main breadcrumbs">
- <gr-group-members group-id="[[params.groupId]]"></gr-group-members>
- </div>
- </template>
- <template is="dom-if" if="[[_showRepoDetailList]]" restamp="true">
- <div class="main table breadcrumbs">
- <gr-repo-detail-list
- params="[[params]]"
- class="table"
- ></gr-repo-detail-list>
- </div>
- </template>
- <template is="dom-if" if="[[_showGroupAuditLog]]" restamp="true">
- <div class="main table breadcrumbs">
- <gr-group-audit-log
- group-id="[[params.groupId]]"
- class="table"
- ></gr-group-audit-log>
- </div>
- </template>
- <template is="dom-if" if="[[_showRepoCommands]]" restamp="true">
- <div class="main breadcrumbs">
- <gr-repo-commands repo="[[params.repo]]"></gr-repo-commands>
- </div>
- </template>
- <template is="dom-if" if="[[_showRepoAccess]]" restamp="true">
- <div class="main breadcrumbs">
- <gr-repo-access path="[[path]]" repo="[[params.repo]]"></gr-repo-access>
- </div>
- </template>
- <template is="dom-if" if="[[_showRepoDashboards]]" restamp="true">
- <div class="main table breadcrumbs">
- <gr-repo-dashboards repo="[[params.repo]]"></gr-repo-dashboards>
- </div>
- </template>
-`;
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.ts b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.ts
index 2c7ea82..5574ad1 100644
--- a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.ts
+++ b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.ts
@@ -47,33 +47,26 @@
const pluginsLoaded = Promise.resolve();
sinon.stub(getPluginLoader(), 'awaitPluginsLoaded').returns(pluginsLoaded);
await pluginsLoaded;
- await flush();
- });
-
- test('_computeURLHelper', () => {
- const path = '/test';
- const host = 'http://www.testsite.com';
- const computedPath = element._computeURLHelper(host, path);
- assert.equal(computedPath, '//http://www.testsite.com/test');
+ await element.updateComplete;
});
test('link URLs', () => {
assert.equal(
- element._computeLinkURL({name: '', url: '/test', noBaseUrl: true}),
+ element.computeLinkURL({name: '', url: '/test', noBaseUrl: true}),
'//' + window.location.host + '/test'
);
stubBaseUrl('/foo');
assert.equal(
- element._computeLinkURL({name: '', url: '/test', noBaseUrl: true}),
+ element.computeLinkURL({name: '', url: '/test', noBaseUrl: true}),
'//' + window.location.host + '/foo/test'
);
assert.equal(
- element._computeLinkURL({name: '', url: '/test', noBaseUrl: false}),
+ element.computeLinkURL({name: '', url: '/test', noBaseUrl: false}),
'/test'
);
assert.equal(
- element._computeLinkURL({
+ element.computeLinkURL({
name: '',
url: '/test',
target: '_blank',
@@ -83,8 +76,8 @@
);
});
- test('current page gets selected and is displayed', () => {
- element._filteredLinks = [
+ test('current page gets selected and is displayed', async () => {
+ element.filteredLinks = [
{
name: 'Repositories',
url: '/admin/repos',
@@ -98,13 +91,13 @@
adminView: 'gr-repo-list',
};
- flush();
+ await element.updateComplete;
assert.equal(queryAll<HTMLLIElement>(element, '.selected').length, 1);
assert.ok(queryAndAssert<GrRepoList>(element, 'gr-repo-list'));
assert.isNotOk(query(element, 'gr-admin-create-repo'));
});
- test('_filteredLinks admin', async () => {
+ test('filteredLinks admin', async () => {
stubRestApi('getAccount').returns(
Promise.resolve({
name: 'test-user',
@@ -115,36 +108,36 @@
Promise.resolve(createAdminCapabilities())
);
await element.reload();
- assert.equal(element._filteredLinks!.length, 3);
+ assert.equal(element.filteredLinks!.length, 3);
// Repos
- assert.isNotOk(element._filteredLinks![0].subsection);
+ assert.isNotOk(element.filteredLinks![0].subsection);
// Groups
- assert.isNotOk(element._filteredLinks![0].subsection);
+ assert.isNotOk(element.filteredLinks![0].subsection);
// Plugins
- assert.isNotOk(element._filteredLinks![0].subsection);
+ assert.isNotOk(element.filteredLinks![0].subsection);
});
- test('_filteredLinks non admin authenticated', async () => {
+ test('filteredLinks non admin authenticated', async () => {
await element.reload();
- assert.equal(element._filteredLinks!.length, 2);
+ assert.equal(element.filteredLinks!.length, 2);
// Repos
- assert.isNotOk(element._filteredLinks![0].subsection);
+ assert.isNotOk(element.filteredLinks![0].subsection);
// Groups
- assert.isNotOk(element._filteredLinks![0].subsection);
+ assert.isNotOk(element.filteredLinks![0].subsection);
});
- test('_filteredLinks non admin unathenticated', async () => {
+ test('filteredLinks non admin unathenticated', async () => {
stubRestApi('getAccount').returns(Promise.resolve(undefined));
await element.reload();
- assert.equal(element._filteredLinks!.length, 1);
+ assert.equal(element.filteredLinks!.length, 1);
// Repos
- assert.isNotOk(element._filteredLinks![0].subsection);
+ assert.isNotOk(element.filteredLinks![0].subsection);
});
- test('_filteredLinks from plugin', () => {
+ test('filteredLinks from plugin', () => {
stubRestApi('getAccount').returns(Promise.resolve(undefined));
sinon.stub(element.jsAPI, 'getAdminMenuLinks').returns([
{capability: null, text: 'internal link text', url: '/internal/link/url'},
@@ -155,8 +148,8 @@
},
]);
return element.reload().then(() => {
- assert.equal(element._filteredLinks!.length, 3);
- assert.deepEqual(element._filteredLinks![1], {
+ assert.equal(element.filteredLinks!.length, 3);
+ assert.deepEqual(element.filteredLinks![1], {
capability: undefined,
url: '/internal/link/url',
name: 'internal link text',
@@ -165,7 +158,7 @@
viewableToAll: true,
target: null,
});
- assert.deepEqual(element._filteredLinks![2], {
+ assert.deepEqual(element.filteredLinks![2], {
capability: undefined,
url: 'http://external/link/url',
name: 'external link text',
@@ -178,7 +171,7 @@
});
test('Repo shows up in nav', async () => {
- element._repoName = 'Test Repo' as RepoName;
+ element.repoName = 'Test Repo' as RepoName;
stubRestApi('getAccount').returns(
Promise.resolve({
name: 'test-user',
@@ -189,7 +182,7 @@
Promise.resolve(createAdminCapabilities())
);
await element.reload();
- await flush();
+ await element.updateComplete;
assert.equal(queryAll<HTMLLIElement>(element, '.sectionTitle').length, 3);
assert.equal(
queryAndAssert<HTMLSpanElement>(element, '.breadcrumbText').innerText,
@@ -202,11 +195,10 @@
});
test('Group shows up in nav', async () => {
- element._groupId = 'a15262' as GroupId;
- element._groupName = 'my-group' as GroupName;
- element._groupIsInternal = true;
- element._isAdmin = true;
- element._groupOwner = false;
+ element.groupId = 'a15262' as GroupId;
+ element.groupName = 'my-group' as GroupName;
+ element.groupIsInternal = true;
+ stubRestApi('getIsAdmin').returns(Promise.resolve(true));
stubRestApi('getAccount').returns(
Promise.resolve({
name: 'test-user',
@@ -217,18 +209,18 @@
Promise.resolve(createAdminCapabilities())
);
await element.reload();
- await flush();
- assert.equal(element._filteredLinks!.length, 3);
+ await element.updateComplete;
+ assert.equal(element.filteredLinks!.length, 3);
// Repos
- assert.isNotOk(element._filteredLinks![0].subsection);
+ 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');
+ 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);
+ assert.isNotOk(element.filteredLinks![2].subsection);
});
- test('Nav is reloaded when repo changes', () => {
+ test('Nav is reloaded when repo changes', async () => {
stubRestApi('getAccountCapabilities').returns(
Promise.resolve(createAdminCapabilities())
);
@@ -240,13 +232,15 @@
);
const reloadStub = sinon.stub(element, 'reload');
element.params = {repo: 'Test Repo' as RepoName, view: GerritView.REPO};
+ await element.updateComplete;
assert.equal(reloadStub.callCount, 1);
element.params = {repo: 'Test Repo 2' as RepoName, view: GerritView.REPO};
+ await element.updateComplete;
assert.equal(reloadStub.callCount, 2);
});
- test('Nav is reloaded when group changes', () => {
- sinon.stub(element, '_computeGroupName');
+ test('Nav is reloaded when group changes', async () => {
+ sinon.stub(element, 'computeGroupName');
stubRestApi('getAccountCapabilities').returns(
Promise.resolve(createAdminCapabilities())
);
@@ -258,20 +252,21 @@
);
const reloadStub = sinon.stub(element, 'reload');
element.params = {groupId: '1' as GroupId, view: GerritView.GROUP};
+ await element.updateComplete;
assert.equal(reloadStub.callCount, 1);
});
test('Nav is reloaded when group name changes', async () => {
const newName = 'newName' as GroupName;
const reloadCalled = mockPromise();
- sinon.stub(element, '_computeGroupName');
+ sinon.stub(element, 'computeGroupName');
sinon.stub(element, 'reload').callsFake(() => {
reloadCalled.resolve();
return Promise.resolve();
});
element.params = {groupId: '1' as GroupId, view: GerritView.GROUP};
- element._groupName = 'oldName' as GroupName;
- await flush();
+ element.groupName = 'oldName' as GroupName;
+ await element.updateComplete;
queryAndAssert<GrGroup>(element, 'gr-group').dispatchEvent(
new CustomEvent('name-changed', {
detail: {name: newName},
@@ -280,12 +275,12 @@
})
);
await reloadCalled;
- assert.equal(element._groupName, newName);
+ assert.equal(element.groupName, newName);
});
- test('dropdown displays if there is a subsection', () => {
+ test('dropdown displays if there is a subsection', async () => {
assert.isNotOk(query(element, '.mainHeader'));
- element._subsectionLinks = [
+ element.subsectionLinks = [
{
text: 'Home',
value: 'repo',
@@ -294,18 +289,15 @@
detailType: undefined,
},
];
- flush();
+ await element.updateComplete;
assert.isOk(query(element, '.mainHeader'));
- element._subsectionLinks = undefined;
- flush();
- assert.equal(
- getComputedStyle(queryAndAssert(element, '.mainHeader')).display,
- 'none'
- );
+ element.subsectionLinks = undefined;
+ await element.updateComplete;
+ assert.isNotOk(query(element, '.mainHeader'));
});
test('Dropdown only triggers navigation on explicit select', async () => {
- element._repoName = 'my-repo' as RepoName;
+ element.repoName = 'my-repo' as RepoName;
element.params = {
repo: 'my-repo' as RepoName,
view: GerritNav.View.REPO,
@@ -320,7 +312,7 @@
registered_on: '2015-03-12 18:32:08.000000000' as Timestamp,
})
);
- await flush();
+ await element.updateComplete;
const expectedFilteredLinks = [
{
name: 'Repositories',
@@ -451,12 +443,12 @@
);
const selectedIsCurrentPageSpy = sinon.spy(
element,
- '_selectedIsCurrentPage'
+ 'selectedIsCurrentPage'
);
- sinon.spy(element, '_handleSubsectionChange');
+ sinon.spy(element, 'handleSubsectionChange');
await element.reload();
- assert.deepEqual(element._filteredLinks, expectedFilteredLinks);
- assert.deepEqual(element._subsectionLinks, expectedSubsectionLinks);
+ assert.deepEqual(element.filteredLinks, expectedFilteredLinks);
+ assert.deepEqual(element.subsectionLinks, expectedSubsectionLinks);
assert.equal(
queryAndAssert<GrDropdownList>(element, '#pageSelect').value,
'repoaccess'
@@ -472,8 +464,8 @@
assert.isTrue(navigateToRelativeUrlStub.calledOnce);
});
- test('_selectedIsCurrentPage', () => {
- element._repoName = 'my-repo' as RepoName;
+ test('selectedIsCurrentPage', () => {
+ element.repoName = 'my-repo' as RepoName;
element.params = {view: GerritView.REPO, repo: 'my-repo' as RepoName};
const selected = {
view: GerritView.REPO,
@@ -481,15 +473,15 @@
value: '',
text: '',
} as AdminSubsectionLink;
- assert.isTrue(element._selectedIsCurrentPage(selected));
+ assert.isTrue(element.selectedIsCurrentPage(selected));
selected.parent = 'my-second-repo' as RepoName;
- assert.isFalse(element._selectedIsCurrentPage(selected));
+ assert.isFalse(element.selectedIsCurrentPage(selected));
selected.detailType = GerritNav.RepoDetailView.GENERAL;
- assert.isFalse(element._selectedIsCurrentPage(selected));
+ assert.isFalse(element.selectedIsCurrentPage(selected));
});
- suite('_computeSelectedClass', () => {
- setup(() => {
+ suite('computeSelectedClass', () => {
+ setup(async () => {
stubRestApi('getAccountCapabilities').returns(
Promise.resolve(createAdminCapabilities())
);
@@ -499,7 +491,7 @@
registered_on: '2015-03-12 18:32:08.000000000' as Timestamp,
})
);
- return element.reload();
+ await element.reload();
});
suite('repos', () => {
@@ -509,67 +501,64 @@
);
});
- test('repo list', () => {
+ test('repo list', async () => {
element.params = {
view: GerritNav.View.ADMIN,
adminView: 'gr-repo-list',
openCreateModal: false,
};
- flush();
+ await element.updateComplete;
const selected = queryAndAssert(element, 'gr-page-nav .selected');
assert.isOk(selected);
assert.equal(selected.textContent!.trim(), 'Repositories');
});
- test('repo', () => {
+ test('repo', async () => {
element.params = {
view: GerritNav.View.REPO,
repo: 'foo' as RepoName,
};
- element._repoName = 'foo' as RepoName;
- return element.reload().then(() => {
- flush();
- const selected = queryAndAssert(element, 'gr-page-nav .selected');
- assert.isOk(selected);
- assert.equal(selected.textContent!.trim(), 'foo');
- });
+ element.repoName = 'foo' as RepoName;
+ await element.reload();
+ await element.updateComplete;
+ const selected = queryAndAssert(element, 'gr-page-nav .selected');
+ assert.isOk(selected);
+ assert.equal(selected.textContent!.trim(), 'foo');
});
- test('repo access', () => {
+ test('repo access', async () => {
element.params = {
view: GerritNav.View.REPO,
detail: GerritNav.RepoDetailView.ACCESS,
repo: 'foo' as RepoName,
};
- element._repoName = 'foo' as RepoName;
- return element.reload().then(() => {
- flush();
- const selected = queryAndAssert(element, 'gr-page-nav .selected');
- assert.isOk(selected);
- assert.equal(selected.textContent!.trim(), 'Access');
- });
+ element.repoName = 'foo' as RepoName;
+ await element.reload();
+ await element.updateComplete;
+ const selected = queryAndAssert(element, 'gr-page-nav .selected');
+ assert.isOk(selected);
+ assert.equal(selected.textContent!.trim(), 'Access');
});
- test('repo dashboards', () => {
+ test('repo dashboards', async () => {
element.params = {
view: GerritNav.View.REPO,
detail: GerritNav.RepoDetailView.DASHBOARDS,
repo: 'foo' as RepoName,
};
- element._repoName = 'foo' as RepoName;
- return element.reload().then(() => {
- flush();
- const selected = queryAndAssert(element, 'gr-page-nav .selected');
- assert.isOk(selected);
- assert.equal(selected.textContent!.trim(), 'Dashboards');
- });
+ element.repoName = 'foo' as RepoName;
+ await element.reload();
+ await element.updateComplete;
+ const selected = queryAndAssert(element, 'gr-page-nav .selected');
+ assert.isOk(selected);
+ assert.equal(selected.textContent!.trim(), 'Dashboards');
});
});
suite('groups', () => {
let getGroupConfigStub: sinon.SinonStub;
- setup(() => {
+ setup(async () => {
stub('gr-group', 'loadGroup').callsFake(() => Promise.resolve());
stub('gr-group-members', 'loadGroupDetails').callsFake(() =>
Promise.resolve()
@@ -583,42 +572,41 @@
})
);
stubRestApi('getIsGroupOwner').returns(Promise.resolve(true));
- return element.reload();
+ await element.reload();
});
- test('group list', () => {
+ test('group list', async () => {
element.params = {
view: GerritNav.View.ADMIN,
adminView: 'gr-admin-group-list',
openCreateModal: false,
};
- flush();
+ await element.updateComplete;
const selected = queryAndAssert(element, 'gr-page-nav .selected');
assert.isOk(selected);
assert.equal(selected.textContent!.trim(), 'Groups');
});
- test('internal group', () => {
+ test('internal group', async () => {
element.params = {
view: GerritNav.View.GROUP,
groupId: '1234' as GroupId,
};
- element._groupName = 'foo' as GroupName;
- return element.reload().then(() => {
- flush();
- const subsectionItems = queryAll<HTMLLIElement>(
- element,
- '.subsectionItem'
- );
- assert.equal(subsectionItems.length, 2);
- assert.isTrue(element._groupIsInternal);
- const selected = queryAndAssert(element, 'gr-page-nav .selected');
- assert.isOk(selected);
- assert.equal(selected.textContent!.trim(), 'foo');
- });
+ element.groupName = 'foo' as GroupName;
+ await element.reload();
+ await element.updateComplete;
+ const subsectionItems = queryAll<HTMLLIElement>(
+ element,
+ '.subsectionItem'
+ );
+ assert.equal(subsectionItems.length, 2);
+ assert.isTrue(element.groupIsInternal);
+ const selected = queryAndAssert(element, 'gr-page-nav .selected');
+ assert.isOk(selected);
+ assert.equal(selected.textContent!.trim(), 'foo');
});
- test('external group', () => {
+ test('external group', async () => {
getGroupConfigStub.returns(
Promise.resolve({
name: 'foo',
@@ -629,34 +617,32 @@
view: GerritNav.View.GROUP,
groupId: '1234' as GroupId,
};
- element._groupName = 'foo' as GroupName;
- return element.reload().then(() => {
- flush();
- const subsectionItems = queryAll<HTMLLIElement>(
- element,
- '.subsectionItem'
- );
- assert.equal(subsectionItems.length, 0);
- assert.isFalse(element._groupIsInternal);
- const selected = queryAndAssert(element, 'gr-page-nav .selected');
- assert.isOk(selected);
- assert.equal(selected.textContent!.trim(), 'foo');
- });
+ element.groupName = 'foo' as GroupName;
+ await element.reload();
+ await element.updateComplete;
+ const subsectionItems = queryAll<HTMLLIElement>(
+ element,
+ '.subsectionItem'
+ );
+ assert.equal(subsectionItems.length, 0);
+ assert.isFalse(element.groupIsInternal);
+ const selected = queryAndAssert(element, 'gr-page-nav .selected');
+ assert.isOk(selected);
+ assert.equal(selected.textContent!.trim(), 'foo');
});
- test('group members', () => {
+ test('group members', async () => {
element.params = {
view: GerritNav.View.GROUP,
detail: GerritNav.GroupDetailView.MEMBERS,
groupId: '1234' as GroupId,
};
- element._groupName = 'foo' as GroupName;
- return element.reload().then(() => {
- flush();
- const selected = queryAndAssert(element, 'gr-page-nav .selected');
- assert.isOk(selected);
- assert.equal(selected.textContent!.trim(), 'Members');
- });
+ element.groupName = 'foo' as GroupName;
+ await element.reload();
+ await element.updateComplete;
+ const selected = queryAndAssert(element, 'gr-page-nav .selected');
+ assert.isOk(selected);
+ assert.equal(selected.textContent!.trim(), 'Members');
});
});
});
diff --git a/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list.ts b/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list.ts
index 0db155d..3393596 100644
--- a/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list.ts
+++ b/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list.ts
@@ -22,7 +22,7 @@
import {ErrorCallback} from '../../../api/rest';
import {encodeURL, getBaseUrl} from '../../../utils/url-util';
import {SHOWN_ITEMS_COUNT} from '../../../constants/constants';
-import {ListViewParams} from '../../gr-app-types';
+import {AppElementAdminParams} from '../../gr-app-types';
import {tableStyles} from '../../../styles/gr-table-styles';
import {sharedStyles} from '../../../styles/shared-styles';
import {LitElement, PropertyValues, css, html} from 'lit';
@@ -41,7 +41,7 @@
* URL params passed from the router.
*/
@property({type: Object})
- params?: ListViewParams;
+ params?: AppElementAdminParams;
/**
* Offset of currently visible query results.
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-impl.ts b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-impl.ts
index 221797c..f20b5a0 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-impl.ts
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-impl.ts
@@ -501,7 +501,8 @@
});
}
- getIsGroupOwner(groupName: GroupName): Promise<boolean> {
+ getIsGroupOwner(groupName?: GroupName): Promise<boolean> {
+ if (!groupName) return Promise.resolve(false);
const encodeName = encodeURIComponent(groupName);
const req = {
url: `/groups/?owned&g=${encodeName}`,
diff --git a/polygerrit-ui/app/services/gr-rest-api/gr-rest-api.ts b/polygerrit-ui/app/services/gr-rest-api/gr-rest-api.ts
index ba94929..7c35222 100644
--- a/polygerrit-ui/app/services/gr-rest-api/gr-rest-api.ts
+++ b/polygerrit-ui/app/services/gr-rest-api/gr-rest-api.ts
@@ -319,7 +319,7 @@
getIsAdmin(): Promise<boolean | undefined>;
- getIsGroupOwner(groupName: GroupName): Promise<boolean>;
+ getIsGroupOwner(groupName?: GroupName): Promise<boolean>;
saveGroupName(
groupId: GroupId | GroupName,
diff --git a/polygerrit-ui/app/utils/admin-nav-util.ts b/polygerrit-ui/app/utils/admin-nav-util.ts
index 86a3682..6688c19 100644
--- a/polygerrit-ui/app/utils/admin-nav-util.ts
+++ b/polygerrit-ui/app/utils/admin-nav-util.ts
@@ -258,4 +258,5 @@
capability?: string;
target?: string | null;
subsection?: SubsectionInterface;
+ children?: SubsectionInterface[];
}