feat: add base styles and base routes
This commit is contained in:
parent
51227bfd7b
commit
583d2005a7
3
client/public/icons/sider/more.svg
Normal file
3
client/public/icons/sider/more.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="4" height="16" viewBox="0 0 4 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 4C3.1 4 4 3.1 4 2C4 0.9 3.1 0 2 0C0.9 0 0 0.9 0 2C0 3.1 0.9 4 2 4ZM2 6C0.9 6 0 6.9 0 8C0 9.1 0.9 10 2 10C3.1 10 4 9.1 4 8C4 6.9 3.1 6 2 6ZM2 12C0.9 12 0 12.9 0 14C0 15.1 0.9 16 2 16C3.1 16 4 15.1 4 14C4 12.9 3.1 12 2 12Z" fill="#606060"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 392 B |
@ -6,7 +6,6 @@ import ProtectedRoute from './pages/ProtectedRoute';
|
|||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<div>
|
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/login" element={<div>login</div>} />
|
<Route path="/login" element={<div>login</div>} />
|
||||||
<Route element={<ProtectedRoute />}>
|
<Route element={<ProtectedRoute />}>
|
||||||
@ -14,7 +13,6 @@ function App() {
|
|||||||
</Route>
|
</Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
56
client/src/components/Header.tsx
Normal file
56
client/src/components/Header.tsx
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import Title from 'antd/es/typography/Title';
|
||||||
|
|
||||||
|
interface HeaderProps {
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Header({ title }: HeaderProps) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: '72px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Title style={{ marginLeft: '16px' }} level={3}>
|
||||||
|
{title}
|
||||||
|
</Title>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: '24px',
|
||||||
|
marginRight: '26px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src="./icons/sider/more.svg"
|
||||||
|
alt="more"
|
||||||
|
style={{ height: '16px', width: '16px' }}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
borderRadius: '50%',
|
||||||
|
border: '2px solid #8BC34A',
|
||||||
|
height: '32px',
|
||||||
|
width: '32px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src="https://cdn-icons-png.flaticon.com/512/219/219986.png"
|
||||||
|
alt="user"
|
||||||
|
style={{
|
||||||
|
height: '25.771240234375px',
|
||||||
|
width: '25.771240234375px',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -1,61 +1,96 @@
|
|||||||
import { Menu, MenuProps } from 'antd';
|
import { Divider, Menu } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
type MenuItem = Required<MenuProps>['items'][number];
|
|
||||||
|
|
||||||
function getItem(
|
|
||||||
label: React.ReactNode,
|
|
||||||
key: React.Key,
|
|
||||||
icon?: React.ReactNode,
|
|
||||||
children?: MenuItem[]
|
|
||||||
): MenuItem {
|
|
||||||
return {
|
|
||||||
key,
|
|
||||||
icon,
|
|
||||||
children,
|
|
||||||
label,
|
|
||||||
} as MenuItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
const sidebarItems: MenuItem[] = [
|
|
||||||
getItem('VORKOUT', '0', <img src="./icons/sider/menu.svg" alt="toggle" />),
|
|
||||||
getItem(
|
|
||||||
'Схемы процессов',
|
|
||||||
'1',
|
|
||||||
<img src="./icons/sider/process-diagram.svg" alt="process diagram" />
|
|
||||||
),
|
|
||||||
getItem(
|
|
||||||
'Запущенные процессы',
|
|
||||||
'2',
|
|
||||||
<img src="./icons/sider/running-processes.svg" alt="running processes" />
|
|
||||||
),
|
|
||||||
getItem(
|
|
||||||
'Настройки',
|
|
||||||
'sub1',
|
|
||||||
<img src="./icons/sider/settings.svg" alt="settings" />,
|
|
||||||
[
|
|
||||||
getItem('Учетные записи', '3'),
|
|
||||||
getItem('Справичник событий', '4'),
|
|
||||||
getItem('Конфигурация', '5'),
|
|
||||||
]
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
interface SiderMenuProps {
|
interface SiderMenuProps {
|
||||||
|
collapsed: boolean;
|
||||||
selectedKey: string;
|
selectedKey: string;
|
||||||
hangleMenuClick: (e: any) => void;
|
hangleMenuClick: (e: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SiderMenu({
|
export default function SiderMenu({
|
||||||
|
collapsed,
|
||||||
selectedKey,
|
selectedKey,
|
||||||
hangleMenuClick,
|
hangleMenuClick,
|
||||||
}: SiderMenuProps) {
|
}: SiderMenuProps) {
|
||||||
|
const menuItems = (
|
||||||
|
<React.Fragment>
|
||||||
|
<Menu.Item
|
||||||
|
key="0"
|
||||||
|
icon={
|
||||||
|
<img
|
||||||
|
src={
|
||||||
|
!collapsed
|
||||||
|
? './icons/sider/menu_open.svg'
|
||||||
|
: './icons/sider/menu.svg'
|
||||||
|
}
|
||||||
|
alt="toggle"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
style={{ fontSize: '20px' }}
|
||||||
|
>
|
||||||
|
VORKOUT
|
||||||
|
</Menu.Item>
|
||||||
|
|
||||||
|
<Menu.Item
|
||||||
|
key="/process-diagram"
|
||||||
|
icon={
|
||||||
|
<img src="./icons/sider/process-diagram.svg" alt="process diagram" />
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Схемы процессов
|
||||||
|
</Menu.Item>
|
||||||
|
|
||||||
|
<Menu.Item
|
||||||
|
key="/running-processes"
|
||||||
|
icon={
|
||||||
|
<img
|
||||||
|
src="./icons/sider/running-processes.svg"
|
||||||
|
alt="running processes"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Запущенные процессы
|
||||||
|
</Menu.Item>
|
||||||
|
|
||||||
|
{!collapsed && <Divider style={{ marginBottom: 0 }} />}
|
||||||
|
|
||||||
|
<Menu.SubMenu
|
||||||
|
key="sub1"
|
||||||
|
icon={<img src="./icons/sider/settings.svg" alt="settings" />}
|
||||||
|
title="Настройки"
|
||||||
|
expandIcon={false}
|
||||||
|
>
|
||||||
|
<Menu.Item
|
||||||
|
key="/accounts"
|
||||||
|
style={{ fontSize: '12px', paddingLeft: '52px' }}
|
||||||
|
>
|
||||||
|
Учетные записи
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item
|
||||||
|
key="/events-list"
|
||||||
|
style={{ fontSize: '12px', paddingLeft: '52px' }}
|
||||||
|
>
|
||||||
|
Справочник событий
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item
|
||||||
|
key="/configuration"
|
||||||
|
style={{ fontSize: '12px', paddingLeft: '52px' }}
|
||||||
|
>
|
||||||
|
Конфигурация
|
||||||
|
</Menu.Item>
|
||||||
|
</Menu.SubMenu>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Menu
|
<Menu
|
||||||
theme="light"
|
theme="light"
|
||||||
selectedKeys={[selectedKey]}
|
selectedKeys={[selectedKey]}
|
||||||
mode="inline"
|
mode="inline"
|
||||||
items={sidebarItems}
|
|
||||||
onClick={hangleMenuClick}
|
onClick={hangleMenuClick}
|
||||||
/>
|
defaultOpenKeys={['sub1']}
|
||||||
|
>
|
||||||
|
{menuItems}
|
||||||
|
</Menu>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
14
client/src/config/customTheme.ts
Normal file
14
client/src/config/customTheme.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
export const theme = {
|
||||||
|
token: {
|
||||||
|
fontFamily: 'Roboto, sans-serif',
|
||||||
|
colorPrimary: '#548d10',
|
||||||
|
Menu: {
|
||||||
|
itemColor: 'f2f2f2',
|
||||||
|
itemBg: '#f2f2f2',
|
||||||
|
subMenuItemBg: '#f2f2f2',
|
||||||
|
},
|
||||||
|
Layout: {
|
||||||
|
bodyBg: '#f2f2f2',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
@ -11,3 +11,17 @@ code {
|
|||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||||
monospace;
|
monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-menu-inline .ant-menu-submenu-selected {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-menu-inline .ant-menu-submenu-selected > .ant-menu-submenu-title {
|
||||||
|
color: #548d10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-menu-inline .ant-menu-item-selected {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
color: #548d10;
|
||||||
|
}
|
||||||
|
@ -3,12 +3,17 @@ import ReactDOM from 'react-dom/client';
|
|||||||
import './index.css';
|
import './index.css';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import { BrowserRouter } from 'react-router-dom';
|
import { BrowserRouter } from 'react-router-dom';
|
||||||
|
import { ConfigProvider } from 'antd';
|
||||||
|
import { theme } from './config/customTheme';
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(
|
const root = ReactDOM.createRoot(
|
||||||
document.getElementById('root') as HTMLElement
|
document.getElementById('root') as HTMLElement
|
||||||
);
|
);
|
||||||
|
|
||||||
root.render(
|
root.render(
|
||||||
|
<ConfigProvider theme={theme}>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<App />
|
<App />
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
|
</ConfigProvider>
|
||||||
);
|
);
|
||||||
|
9
client/src/pages/AccountsPage.tsx
Normal file
9
client/src/pages/AccountsPage.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import Header from '../components/Header';
|
||||||
|
|
||||||
|
export default function AccountsPage() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Header title="Учетные записи" />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
9
client/src/pages/ConfigurationPage.tsx
Normal file
9
client/src/pages/ConfigurationPage.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import Header from '../components/Header';
|
||||||
|
|
||||||
|
export default function ConfigurationPage() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Header title="Конфигурация" />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
9
client/src/pages/EventsListPage.tsx
Normal file
9
client/src/pages/EventsListPage.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import Header from '../components/Header';
|
||||||
|
|
||||||
|
export default function EventsListPage() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Header title="Справочник событий" />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -1,19 +1,40 @@
|
|||||||
import React, { useState } from 'react';
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
import { Layout } from 'antd';
|
import { Layout } from 'antd';
|
||||||
import Sider from 'antd/es/layout/Sider';
|
import Sider from 'antd/es/layout/Sider';
|
||||||
import SiderMenu from '../components/SiderMenu';
|
import SiderMenu from '../components/SiderMenu';
|
||||||
|
import { Route, Routes, useLocation, useNavigate } from 'react-router-dom';
|
||||||
|
import ProcessDiagramPage from './ProcessDiagramPage';
|
||||||
|
import RunningProcessesPage from './RunningProcessesPage';
|
||||||
|
import AccountsPage from './AccountsPage';
|
||||||
|
import EventsListPage from './EventsListPage';
|
||||||
|
import ConfigurationPage from './ConfigurationPage';
|
||||||
|
|
||||||
export default function MainLayout() {
|
export default function MainLayout() {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
const [collapsed, setCollapsed] = useState(false);
|
const [collapsed, setCollapsed] = useState(false);
|
||||||
const [selectedKey, setSelectedKey] = useState('1');
|
const [selectedKey, setSelectedKey] = useState('1');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (location.pathname === '/') {
|
||||||
|
navigate('/process-diagram');
|
||||||
|
}
|
||||||
|
}, [location.pathname]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSelectedKey(location.pathname);
|
||||||
|
});
|
||||||
|
|
||||||
function hangleMenuClick(e: any) {
|
function hangleMenuClick(e: any) {
|
||||||
if (e.key === '0') {
|
const key = e.key;
|
||||||
setCollapsed((prev) => !prev);
|
if (key === '0') {
|
||||||
|
setCollapsed(!collapsed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setSelectedKey(e.key);
|
setSelectedKey(key);
|
||||||
|
navigate(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -26,14 +47,23 @@ export default function MainLayout() {
|
|||||||
width={'15%'}
|
width={'15%'}
|
||||||
collapsedWidth={'3.8%'}
|
collapsedWidth={'3.8%'}
|
||||||
trigger={null}
|
trigger={null}
|
||||||
|
style={{ backgroundColor: '#f2f2f2' }}
|
||||||
>
|
>
|
||||||
<SiderMenu
|
<SiderMenu
|
||||||
|
collapsed={collapsed}
|
||||||
selectedKey={selectedKey}
|
selectedKey={selectedKey}
|
||||||
hangleMenuClick={hangleMenuClick}
|
hangleMenuClick={hangleMenuClick}
|
||||||
/>
|
/>
|
||||||
</Sider>
|
</Sider>
|
||||||
<Layout>
|
<Layout>
|
||||||
<div>Main layout</div>
|
<Routes>
|
||||||
|
<Route path="/process-diagram" element={<ProcessDiagramPage />} />
|
||||||
|
<Route path="/running-processes" element={<RunningProcessesPage />} />
|
||||||
|
<Route path="/accounts" element={<AccountsPage />} />
|
||||||
|
<Route path="/events-list" element={<EventsListPage />} />
|
||||||
|
<Route path="/configuration" element={<ConfigurationPage />} />
|
||||||
|
<Route path="*" element={<div>404 Not Found</div>} />
|
||||||
|
</Routes>
|
||||||
</Layout>
|
</Layout>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
|
9
client/src/pages/ProcessDiagramPage.tsx
Normal file
9
client/src/pages/ProcessDiagramPage.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import Header from '../components/Header';
|
||||||
|
|
||||||
|
export default function ProcessDiagramPage() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Header title="Схемы процессов" />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
9
client/src/pages/RunningProcessesPage.tsx
Normal file
9
client/src/pages/RunningProcessesPage.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import Header from '../components/Header';
|
||||||
|
|
||||||
|
export default function RunningProcessesPage() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Header title="Запущенные процессы" />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user