|  | /** | 
|  | * @license | 
|  | * Copyright 2018 Google LLC | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  | import { | 
|  | RepoName, | 
|  | GroupId, | 
|  | AccountDetailInfo, | 
|  | AccountCapabilityInfo, | 
|  | } from '../types/common'; | 
|  | import {hasOwnProperty} from './common-util'; | 
|  | import {GerritView} from '../services/router/router-model'; | 
|  | import {MenuLink} from '../api/admin'; | 
|  | import {AdminChildView} from '../models/views/admin'; | 
|  | import {createGroupUrl, GroupDetailView} from '../models/views/group'; | 
|  | import {createRepoUrl, RepoDetailView} from '../models/views/repo'; | 
|  |  | 
|  | const ADMIN_LINKS: NavLink[] = [ | 
|  | { | 
|  | name: 'Repositories', | 
|  | noBaseUrl: true, | 
|  | url: '/admin/repos', | 
|  | view: 'gr-repo-list' as GerritView, | 
|  | viewableToAll: true, | 
|  | }, | 
|  | { | 
|  | name: 'Groups', | 
|  | section: 'Groups', | 
|  | noBaseUrl: true, | 
|  | url: '/admin/groups', | 
|  | view: 'gr-admin-group-list' as GerritView, | 
|  | }, | 
|  | { | 
|  | name: 'Plugins', | 
|  | capability: 'viewPlugins', | 
|  | section: 'Plugins', | 
|  | noBaseUrl: true, | 
|  | url: '/admin/plugins', | 
|  | view: 'gr-plugin-list' as GerritView, | 
|  | }, | 
|  | ]; | 
|  |  | 
|  | export interface AdminLink { | 
|  | url: string; | 
|  | text: string; | 
|  | capability: string | null; | 
|  | noBaseUrl: boolean; | 
|  | view: null; | 
|  | viewableToAll: boolean; | 
|  | target: '_blank' | null; | 
|  | } | 
|  |  | 
|  | export interface AdminLinks { | 
|  | links: NavLink[]; | 
|  | expandedSection?: SubsectionInterface; | 
|  | } | 
|  |  | 
|  | export function getAdminLinks( | 
|  | account: AccountDetailInfo | undefined, | 
|  | getAccountCapabilities: () => Promise<AccountCapabilityInfo>, | 
|  | getAdminMenuLinks: () => MenuLink[], | 
|  | options?: AdminNavLinksOption | 
|  | ): Promise<AdminLinks> { | 
|  | if (!account) { | 
|  | return Promise.resolve( | 
|  | _filterLinks(link => !!link.viewableToAll, getAdminMenuLinks, options) | 
|  | ); | 
|  | } | 
|  | return getAccountCapabilities().then(capabilities => | 
|  | _filterLinks( | 
|  | link => !link.capability || hasOwnProperty(capabilities, link.capability), | 
|  | getAdminMenuLinks, | 
|  | options | 
|  | ) | 
|  | ); | 
|  | } | 
|  |  | 
|  | function _filterLinks( | 
|  | filterFn: (link: NavLink) => boolean, | 
|  | getAdminMenuLinks: () => MenuLink[], | 
|  | options?: AdminNavLinksOption | 
|  | ): AdminLinks { | 
|  | let links: NavLink[] = ADMIN_LINKS.slice(0); | 
|  | let expandedSection: SubsectionInterface | undefined = undefined; | 
|  |  | 
|  | const isExternalLink = (link: MenuLink) => link.url[0] !== '/'; | 
|  |  | 
|  | // Append top-level links that are defined by plugins. | 
|  | links.push( | 
|  | ...getAdminMenuLinks().map((link: MenuLink) => { | 
|  | return { | 
|  | url: link.url, | 
|  | name: link.text, | 
|  | capability: link.capability || undefined, | 
|  | noBaseUrl: !isExternalLink(link), | 
|  | view: undefined, | 
|  | viewableToAll: !link.capability, | 
|  | target: isExternalLink(link) ? '_blank' : null, | 
|  | }; | 
|  | }) | 
|  | ); | 
|  |  | 
|  | links = links.filter(filterFn); | 
|  |  | 
|  | const filteredLinks: NavLink[] = []; | 
|  | const repoName = options && options.repoName; | 
|  | const groupId = options && options.groupId; | 
|  | const groupName = options && options.groupName; | 
|  | const groupIsInternal = options && options.groupIsInternal; | 
|  | const isAdmin = options && options.isAdmin; | 
|  | const groupOwner = options && options.groupOwner; | 
|  |  | 
|  | // Don't bother to get sub-navigation items if only the top level links | 
|  | // are needed. This is used by the main header dropdown. | 
|  | if (!repoName && !groupId) { | 
|  | return {links, expandedSection}; | 
|  | } | 
|  |  | 
|  | // Otherwise determine the full set of links and return both the full | 
|  | // set in addition to the subsection that should be displayed if it | 
|  | // exists. | 
|  | for (const link of links) { | 
|  | const linkCopy = {...link}; | 
|  | if (linkCopy.name === 'Repositories' && repoName) { | 
|  | linkCopy.subsection = getRepoSubsections(repoName); | 
|  | expandedSection = linkCopy.subsection; | 
|  | } else if (linkCopy.name === 'Groups' && groupId && groupName) { | 
|  | linkCopy.subsection = getGroupSubsections( | 
|  | groupId, | 
|  | groupName, | 
|  | groupIsInternal, | 
|  | isAdmin, | 
|  | groupOwner | 
|  | ); | 
|  | expandedSection = linkCopy.subsection; | 
|  | } | 
|  | filteredLinks.push(linkCopy); | 
|  | } | 
|  | return {links: filteredLinks, expandedSection}; | 
|  | } | 
|  |  | 
|  | export function getGroupSubsections( | 
|  | groupId: GroupId, | 
|  | groupName: string, | 
|  | groupIsInternal?: boolean, | 
|  | isAdmin?: boolean, | 
|  | groupOwner?: boolean | 
|  | ) { | 
|  | const children: SubsectionInterface[] = []; | 
|  | const subsection: SubsectionInterface = { | 
|  | name: groupName, | 
|  | view: GerritView.GROUP, | 
|  | url: createGroupUrl({groupId}), | 
|  | children, | 
|  | }; | 
|  | if (groupIsInternal) { | 
|  | children.push({ | 
|  | name: 'Members', | 
|  | detailType: GroupDetailView.MEMBERS, | 
|  | view: GerritView.GROUP, | 
|  | url: createGroupUrl({groupId, detail: GroupDetailView.MEMBERS}), | 
|  | }); | 
|  | } | 
|  | if (groupIsInternal && (isAdmin || groupOwner)) { | 
|  | children.push({ | 
|  | name: 'Audit Log', | 
|  | detailType: GroupDetailView.LOG, | 
|  | view: GerritView.GROUP, | 
|  | url: createGroupUrl({groupId, detail: GroupDetailView.LOG}), | 
|  | }); | 
|  | } | 
|  | return subsection; | 
|  | } | 
|  |  | 
|  | export function getRepoSubsections(repo: RepoName) { | 
|  | return { | 
|  | name: repo, | 
|  | view: GerritView.REPO, | 
|  | children: [ | 
|  | { | 
|  | name: 'General', | 
|  | view: GerritView.REPO, | 
|  | detailType: RepoDetailView.GENERAL, | 
|  | url: createRepoUrl({repo, detail: RepoDetailView.GENERAL}), | 
|  | }, | 
|  | { | 
|  | name: 'Access', | 
|  | view: GerritView.REPO, | 
|  | detailType: RepoDetailView.ACCESS, | 
|  | url: createRepoUrl({repo, detail: RepoDetailView.ACCESS}), | 
|  | }, | 
|  | { | 
|  | name: 'Commands', | 
|  | view: GerritView.REPO, | 
|  | detailType: RepoDetailView.COMMANDS, | 
|  | url: createRepoUrl({repo, detail: RepoDetailView.COMMANDS}), | 
|  | }, | 
|  | { | 
|  | name: 'Branches', | 
|  | view: GerritView.REPO, | 
|  | detailType: RepoDetailView.BRANCHES, | 
|  | url: createRepoUrl({repo, detail: RepoDetailView.BRANCHES}), | 
|  | }, | 
|  | { | 
|  | name: 'Tags', | 
|  | view: GerritView.REPO, | 
|  | detailType: RepoDetailView.TAGS, | 
|  | url: createRepoUrl({repo, detail: RepoDetailView.TAGS}), | 
|  | }, | 
|  | { | 
|  | name: 'Dashboards', | 
|  | view: GerritView.REPO, | 
|  | detailType: RepoDetailView.DASHBOARDS, | 
|  | url: createRepoUrl({repo, detail: RepoDetailView.DASHBOARDS}), | 
|  | }, | 
|  | ], | 
|  | }; | 
|  | } | 
|  |  | 
|  | export interface SubsectionInterface { | 
|  | name: string; | 
|  | view: GerritView; | 
|  | detailType?: RepoDetailView | GroupDetailView; | 
|  | url?: string; | 
|  | children?: SubsectionInterface[]; | 
|  | } | 
|  |  | 
|  | export interface AdminNavLinksOption { | 
|  | repoName?: RepoName; | 
|  | groupId?: GroupId; | 
|  | groupName?: string; | 
|  | groupIsInternal?: boolean; | 
|  | isAdmin?: boolean; | 
|  | groupOwner?: boolean; | 
|  | } | 
|  |  | 
|  | export interface NavLink { | 
|  | name: string; | 
|  | noBaseUrl: boolean; | 
|  | url: string; | 
|  | view?: GerritView | AdminChildView; | 
|  | viewableToAll?: boolean; | 
|  | section?: string; | 
|  | capability?: string; | 
|  | target?: string | null; | 
|  | subsection?: SubsectionInterface; | 
|  | children?: SubsectionInterface[]; | 
|  | } |