mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-12 15:04:52 +09:00
Allow sidebar entries to be grouped together by specifiying a name under which they will be grouped. To avoid confusion groups are rendered at the bottom of the list.
113 lines
3.2 KiB
React
113 lines
3.2 KiB
React
import React, { useContext, useEffect, useState } from "react";
|
|
import { Switch, Route, useHistory } from "react-router-dom";
|
|
import { Dropdown, Layout, Menu } from "antd";
|
|
import UserOutlined from "@ant-design/icons/UserOutlined";
|
|
import webUiPackage from "../../package.json";
|
|
|
|
import { useAccount } from "../model/account";
|
|
import ErrorBoundary from "./ErrorBoundary";
|
|
import ErrorPage from "./ErrorPage";
|
|
import ControlContext from "./ControlContext";
|
|
import { pages } from "../pages";
|
|
|
|
const { Header, Sider } = Layout;
|
|
|
|
|
|
export default function SiteLayout(props) {
|
|
let history = useHistory();
|
|
let [currentSidebarPath, setCurrentSidebarPath] = useState(null);
|
|
let account = useAccount();
|
|
let plugins = useContext(ControlContext).plugins;
|
|
|
|
function SetSidebar(setSidebarProps) {
|
|
useEffect(() => {
|
|
setCurrentSidebarPath(setSidebarProps.path);
|
|
});
|
|
return null;
|
|
}
|
|
|
|
let accountMenu = <Menu>
|
|
<Menu.Item key="1" onClick={() => { history.push(`/users/${account.name}/view`); }}>{account.name}</Menu.Item>
|
|
<Menu.Divider/>
|
|
<Menu.Item key="2" danger onClick={() => { account.logOut(); }}>Log out</Menu.Item>
|
|
</Menu>;
|
|
|
|
let combinedPages = [...pages];
|
|
for (let plugin of plugins.values()) {
|
|
combinedPages.push(...plugin.pages);
|
|
}
|
|
|
|
let menuItems = [];
|
|
let menuGroups = new Map();
|
|
for (let { sidebarName, sidebarGroup, permission, path } of combinedPages) {
|
|
if (!sidebarName || permission && !account.hasPermission(permission)) {
|
|
continue;
|
|
}
|
|
if (sidebarGroup) {
|
|
let group = menuGroups.get(sidebarGroup);
|
|
if (!group) {
|
|
group = [];
|
|
menuGroups.set(sidebarGroup, group);
|
|
}
|
|
group.push(<Menu.Item key={path}>{sidebarName}</Menu.Item>);
|
|
} else {
|
|
menuItems.push(<Menu.Item key={path}>{sidebarName}</Menu.Item>);
|
|
}
|
|
}
|
|
for (let [name, group] of menuGroups) {
|
|
menuItems.push(<Menu.ItemGroup key={name} title={name}>{group}</Menu.ItemGroup>);
|
|
}
|
|
|
|
return <Layout style={{ minHeight: "100vh" }}>
|
|
<Header className="header">
|
|
<div className="site-logo" />
|
|
<span className="site-name">Clusterio</span>
|
|
<span className="site-version">{ webUiPackage.version }</span>
|
|
<Menu theme="dark" mode="horizontal" defaultSelectedKeys={["1"]}>
|
|
<Menu.Item key="1">Dashboard</Menu.Item>
|
|
</Menu>
|
|
<Dropdown
|
|
className="account-dropdown-header"
|
|
placement="bottomRight"
|
|
trigger="click"
|
|
overlay={accountMenu}
|
|
>
|
|
<UserOutlined/>
|
|
</Dropdown>
|
|
</Header>
|
|
<Layout className="site-layout">
|
|
<Sider
|
|
collapsible
|
|
collapsedWidth={0}
|
|
breakpoint="md"
|
|
zeroWidthTriggerStyle={{ top: 6, zIndex: -1 }}
|
|
width={250}
|
|
className="site-layout-sider"
|
|
>
|
|
<Menu
|
|
mode="inline"
|
|
defaultOpenKeys={[...menuGroups.keys()]}
|
|
selectedKeys={[currentSidebarPath]}
|
|
style={{ height: "100%", borderRight: 0 }}
|
|
onClick={({ key }) => history.push(key)}
|
|
>
|
|
{menuItems}
|
|
</Menu>
|
|
</Sider>
|
|
<Layout className="site-layout-content-container">
|
|
<Switch>
|
|
{combinedPages.map(({path, sidebarPath, content}) => <Route exact path={path} key={path}>
|
|
<SetSidebar path={sidebarPath ? sidebarPath : path} />
|
|
<ErrorBoundary Component={ErrorPage}>
|
|
{content}
|
|
</ErrorBoundary>
|
|
</Route>)}
|
|
<Route>
|
|
<SetSidebar path={null} />
|
|
</Route>
|
|
</Switch>
|
|
</Layout>
|
|
</Layout>
|
|
</Layout>;
|
|
}
|