import "./sidebar.scss"; import * as 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 { configStore } from "../../config.store"; 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.routes"; 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 { TabRoute } from "./main-layout"; 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"; 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) 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 { isClusterAdmin, allowedResources } = configStore; const query = namespaceStore.getContextParams(); return (
Lens
Compact view : Extended view} 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()}
) } } 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 { 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} ) } }