import type { TabRoute } from "./tab-layout"; import "./sidebar.scss"; import React from "react"; import { computed, observable, reaction } from "mobx"; import { observer } from "mobx-react"; import { matchPath, NavLink } from "react-router-dom"; import { Trans } from "@lingui/macro"; import { createStorage, cssNames } from "../../utils"; import { Icon } from "../icon"; import { workloadsRoute, workloadsURL } from "../+workloads/workloads.route"; import { namespacesURL } from "../+namespaces/namespaces.route"; import { nodesURL } from "../+nodes/nodes.route"; import { usersManagementRoute, usersManagementURL } from "../+user-management/user-management.route"; import { networkRoute, networkURL } from "../+network/network.route"; import { storageRoute, storageURL } from "../+storage/storage.route"; import { clusterURL } from "../+cluster"; import { Config, configRoute, configURL } from "../+config"; import { eventRoute, eventsURL } from "../+events"; import { Apps, appsRoute, appsURL } from "../+apps"; import { namespaceStore } from "../+namespaces/namespace.store"; import { Workloads } from "../+workloads"; import { UserManagement } from "../+user-management"; import { Storage } from "../+storage"; import { Network } from "../+network"; import { crdStore } from "../+custom-resources/crd.store"; import { CrdList, crdResourcesRoute, crdRoute, crdURL } from "../+custom-resources"; import { CustomResources } from "../+custom-resources/custom-resources"; import { navigation } from "../../navigation"; import { isAllowedResource } from "../../../common/rbac" import { pageRegistry } from "../../../extensions/registries/page-registry"; const SidebarContext = React.createContext({ pinned: false }); type SidebarContextValue = { pinned: boolean; }; interface Props { className?: string; isPinned: boolean; toggle(): void; } @observer export class Sidebar extends React.Component { async componentDidMount() { if (!crdStore.isLoaded && isAllowedResource("customresourcedefinitions")) { crdStore.loadAll(); } } renderCustomResources() { return Object.entries(crdStore.groups).map(([group, crds]) => { const submenus = crds.map((crd) => { return { title: crd.getResourceKind(), component: CrdList, url: crd.getResourceUrl(), path: crdResourcesRoute.path, }; }); return ( ); }); } render() { const { toggle, isPinned, className } = this.props; const query = namespaceStore.getContextParams(); return (
Lens
Compact view} material={isPinned ? "keyboard_arrow_left" : "keyboard_arrow_right"} onClick={toggle} focusable={false} />
Cluster} icon={} /> Nodes} icon={} /> Workloads} icon={} /> Configuration} icon={} /> Network} icon={} /> } text={Storage} /> } text={Namespaces} /> } text={Events} /> } text={Apps} /> } text={Access Control} /> } text={Custom Resources} > {this.renderCustomResources()} {pageRegistry.clusterPages.map(({ path, title, url = String(path), components: { MenuIcon } }) => { if (!MenuIcon) return; return ( } /> ) })}
); } } interface SidebarNavItemProps { id: string; url: string; text: React.ReactNode | string; className?: string; icon?: React.ReactNode; isHidden?: boolean; routePath?: string | string[]; subMenus?: TabRoute[]; } const navItemStorage = createStorage<[string, boolean][]>("sidebar_menu_item", []); const navItemState = observable.map(navItemStorage.get()); reaction( () => [...navItemState], (value) => navItemStorage.set(value) ); @observer class SidebarNavItem extends React.Component { static contextType = SidebarContext; public context: SidebarContextValue; @computed get isExpanded() { return navItemState.get(this.props.id); } toggleSubMenu = () => { navItemState.set(this.props.id, !this.isExpanded); }; isActive = () => { const { routePath, url } = this.props; const { pathname } = navigation.location; return !!matchPath(pathname, { path: routePath || url, }); }; render() { const { id, isHidden, subMenus = [], icon, text, url, children, className } = this.props; if (isHidden) { return null; } const extendedView = (subMenus.length > 0 || children) && this.context.pinned; if (extendedView) { const isActive = this.isActive(); return (
{icon} {text}
    {subMenus.map(({ title, url }) => ( {title} ))} {React.Children.toArray(children).map((child: React.ReactElement) => { return React.cloneElement(child, { className: cssNames(child.props.className, { visible: this.isExpanded }), }); })}
); } return ( {icon} {text} ); } }