From bd8962df26eaeff5d1ea3119a6a7cef1a42508c0 Mon Sep 17 00:00:00 2001 From: goodmice Date: Thu, 13 Oct 2022 14:31:11 +0500 Subject: [PATCH] =?UTF-8?q?*=20=D0=9F=D0=B5=D1=80=D0=B5=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=B0=D0=BD=20LayoutPortal=20*=20=D0=9F=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=BD=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D1=84=D0=B8=D0=BB=D1=8C=20=D0=BF=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8F=20*=20=D0=9F?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=BD?= =?UTF-8?q?=D0=B0=20=D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC=D0=B0=20=D0=BE?= =?UTF-8?q?=D1=80=D0=B3=D0=B0=D0=BD=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B8=20?= =?UTF-8?q?=D1=81=D1=81=D1=8B=D0=BB=D0=BE=D0=BA=20=D0=BC=D0=B5=D0=BD=D1=8E?= =?UTF-8?q?=20*=20=D0=9D=D0=BE=D0=B2=D1=8B=D0=B9=20LayoutPortal=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=B2=D1=81=D0=B5=20=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B8=D1=86?= =?UTF-8?q?=D1=8B=20*=20=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D1=91=D0=BD=20?= =?UTF-8?q?=D1=80=D0=B5=D0=B4=D0=B8=D1=80=D0=B5=D0=BA=D1=82=20=D1=81=D0=BE?= =?UTF-8?q?=20=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B8=D1=86=D1=8B=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B8=20=D1=84=D0=B0=D0=B9?= =?UTF-8?q?=D0=BB=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Layout/AdminLayoutPortal.tsx | 28 ---- src/components/Layout/LayoutPortal.tsx | 31 ---- src/components/Layout/index.ts | 5 - src/components/LayoutPortal.tsx | 110 ++++++++++++++ src/components/PageHeader.tsx | 23 ++- src/components/Private/PrivateContent.tsx | 14 -- .../Private/PrivateDefaultRoute.tsx | 19 --- src/components/Private/PrivateMenu.tsx | 75 ---------- src/components/Private/PrivateMenuItem.tsx | 37 ----- src/components/Private/PrivateRoute.tsx | 30 ---- src/components/Private/PrivateRoutes.tsx | 67 --------- src/components/Private/index.ts | 13 -- src/components/PrivateWellMenu.tsx | 97 +++++++++++++ src/components/UserMenu.tsx | 136 ++++++++++++------ src/components/selectors/WellTreeSelector.tsx | 45 +++--- src/pages/AdminPanel/AdminNavigationMenu.jsx | 46 ++++++ src/pages/AdminPanel/index.jsx | 54 +++---- src/pages/Cluster/index.jsx | 6 +- src/pages/Deposit.jsx | 7 +- src/pages/FileDownload.jsx | 4 +- src/pages/NavigationMenu.jsx | 78 ++++++++++ src/pages/Well.jsx | 66 +++------ 22 files changed, 503 insertions(+), 488 deletions(-) delete mode 100755 src/components/Layout/AdminLayoutPortal.tsx delete mode 100755 src/components/Layout/LayoutPortal.tsx delete mode 100755 src/components/Layout/index.ts create mode 100644 src/components/LayoutPortal.tsx delete mode 100755 src/components/Private/PrivateContent.tsx delete mode 100755 src/components/Private/PrivateDefaultRoute.tsx delete mode 100644 src/components/Private/PrivateMenu.tsx delete mode 100755 src/components/Private/PrivateMenuItem.tsx delete mode 100755 src/components/Private/PrivateRoute.tsx delete mode 100644 src/components/Private/PrivateRoutes.tsx delete mode 100755 src/components/Private/index.ts create mode 100644 src/components/PrivateWellMenu.tsx create mode 100644 src/pages/AdminPanel/AdminNavigationMenu.jsx create mode 100644 src/pages/NavigationMenu.jsx diff --git a/src/components/Layout/AdminLayoutPortal.tsx b/src/components/Layout/AdminLayoutPortal.tsx deleted file mode 100755 index 1d087ba..0000000 --- a/src/components/Layout/AdminLayoutPortal.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { memo, ReactNode } from 'react' -import { Link, useLocation } from 'react-router-dom' -import { Button, Layout, LayoutProps } from 'antd' - -import PageHeader from '@components/PageHeader' - -export type AdminLayoutPortalProps = LayoutProps & { - title?: ReactNode -} - -export const AdminLayoutPortal = memo(({ title, ...props }) => { - const location = useLocation() - - return ( - - - - - - - - - ) -}) - -export default AdminLayoutPortal diff --git a/src/components/Layout/LayoutPortal.tsx b/src/components/Layout/LayoutPortal.tsx deleted file mode 100755 index e754811..0000000 --- a/src/components/Layout/LayoutPortal.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { Key, memo, ReactNode } from 'react' -import { Layout, LayoutProps } from 'antd' - -import PageHeader from '@components/PageHeader' -import { WellTreeSelector, WellTreeSelectorProps } from '@components/selectors/WellTreeSelector' -import { wrapPrivateComponent } from '@utils' - -export type LayoutPortalProps = LayoutProps & { - title?: ReactNode - noSheet?: boolean - selector?: WellTreeSelectorProps -} - -const _LayoutPortal = memo(({ title, noSheet, selector, ...props }) => ( - - - - - - {noSheet ? props.children : ( - - )} - - -)) - -export const LayoutPortal = wrapPrivateComponent(_LayoutPortal, { - requirements: ['Deposit.get'], -}) - -export default LayoutPortal diff --git a/src/components/Layout/index.ts b/src/components/Layout/index.ts deleted file mode 100755 index 044f1bc..0000000 --- a/src/components/Layout/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './AdminLayoutPortal' -export * from './LayoutPortal' - -export type { AdminLayoutPortalProps } from './AdminLayoutPortal' -export type { LayoutPortalProps } from './LayoutPortal' diff --git a/src/components/LayoutPortal.tsx b/src/components/LayoutPortal.tsx new file mode 100644 index 0000000..1bcb344 --- /dev/null +++ b/src/components/LayoutPortal.tsx @@ -0,0 +1,110 @@ +import { Button, Layout, LayoutProps, Menu, SiderProps } from 'antd' +import { HTMLProps, Key, memo, ReactNode, useEffect, useMemo, useState } from 'react' +import { ItemType } from 'antd/lib/menu/hooks/useItems' +import { Link } from 'react-router-dom' +import { + ApartmentOutlined, + CodeOutlined, + HomeOutlined, + MenuFoldOutlined, + MenuUnfoldOutlined, + UserOutlined, +} from '@ant-design/icons' + +import PageHeader from '@components/PageHeader' +import { UserMenu, UserMenuProps } from '@components/UserMenu' +import { WellTreeSelector, WellTreeSelectorProps } from '@components/selectors/WellTreeSelector' +import { isURLAvailable, wrapPrivateComponent } from '@utils' + +import '@styles/layout.less' + +const { Content, Sider } = Layout + +export type LayoutPortalProps = HTMLProps & { + title?: ReactNode + noSheet?: boolean + showSelector?: boolean + selectorProps?: WellTreeSelectorProps + sider?: boolean | JSX.Element + siderProps?: SiderProps & { userMenuProps?: UserMenuProps } + isAdmin?: boolean +} + +const makeItem = (title: string, key: Key, icon: JSX.Element, label?: ReactNode, onClick?: () => void) => ({ icon, key, title, label: label ?? title, onClick }) + +const _LayoutPortal = memo(({ isAdmin, title, noSheet, showSelector, selectorProps, sider, siderProps, ...props }) => { + const [menuCollapsed, setMenuCollapsed] = useState(true) + const [wellsTreeOpen, setWellsTreeOpen] = useState(false) + const [userMenuOpen, setUserMenuOpen] = useState(false) + const [currentWell, setCurrentWell] = useState('') + + useEffect(() => { + if (typeof showSelector === 'boolean') + setWellsTreeOpen(showSelector) + }, [showSelector]) + + const menuItems = useMemo(() => [ + !isAdmin && makeItem(currentWell, 'well', , null, () => setWellsTreeOpen((prev) => !prev)), + isAdmin && makeItem('Вернуться на сайт', 'go_back', , Домой), + !isAdmin && isURLAvailable('/admin') && makeItem('Панель администратора', 'admin_panel', , Панель администратора), + makeItem('Профиль', 'profile', , null, () => setUserMenuOpen((prev) => !prev)), + ].filter(Boolean) as ItemType[], [isAdmin, currentWell]) + + return ( + + {(sider || siderProps) && ( + +
+ +
+ {sider} +
+ + setUserMenuOpen(false)} + isAdmin={isAdmin} + {...siderProps?.userMenuProps} + /> +
+
+ )} + + + {isAdmin ? ( + + ) : ( + <> + setWellsTreeOpen(false)} + {...selectorProps} + onChange={(well) => setCurrentWell(well ?? 'Выберите месторождение')} + /> + + + )} + + +
+ + + + ) +}) + +export const LayoutPortal = wrapPrivateComponent(_LayoutPortal, { + requirements: ['Deposit.get'], +}) + +export default LayoutPortal diff --git a/src/components/PageHeader.tsx b/src/components/PageHeader.tsx index 3dc6c02..9c8ab99 100755 --- a/src/components/PageHeader.tsx +++ b/src/components/PageHeader.tsx @@ -4,27 +4,24 @@ import { Link } from 'react-router-dom' import { BasicProps } from 'antd/lib/layout/layout' import { headerHeight } from '@utils' -import { UserMenu } from './UserMenu' import Logo from '@images/Logo' +import '@styles/layout.less' + export type PageHeaderProps = BasicProps & { title?: string - isAdmin?: boolean children?: React.ReactNode } -export const PageHeader: React.FC = memo(({ title = 'Мониторинг', isAdmin, children, ...other }) => ( - - - - - -

{title}

- {children} - -
-
+export const PageHeader: React.FC = memo(({ title = 'Мониторинг', children, ...other }) => ( + + + + +

{title}

+ {children} +
)) export default PageHeader diff --git a/src/components/Private/PrivateContent.tsx b/src/components/Private/PrivateContent.tsx deleted file mode 100755 index 9b9e02b..0000000 --- a/src/components/Private/PrivateContent.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { memo, ReactElement } from 'react' - -import { isURLAvailable } from '@utils' - -export type PrivateContentProps = { - absolutePath: string - children?: ReactElement -} - -export const PrivateContent = memo(({ absolutePath, children = null }) => - isURLAvailable(absolutePath) ? children : null -) - -export default PrivateContent diff --git a/src/components/Private/PrivateDefaultRoute.tsx b/src/components/Private/PrivateDefaultRoute.tsx deleted file mode 100755 index e1cc07e..0000000 --- a/src/components/Private/PrivateDefaultRoute.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { memo } from 'react' -import { Navigate, Route, RouteProps } from 'react-router-dom' - -import { isURLAvailable } from '@utils' - -import { getDefaultRedirectPath } from './PrivateRoutes' - -export type PrivateDefaultRouteProps = RouteProps & { - urls: string[] - elseRedirect?: string -} - -export const PrivateDefaultRoute = memo(({ elseRedirect, urls, ...other }) => ( - isURLAvailable(url)) ?? elseRedirect ?? getDefaultRedirectPath()} /> - )} /> -)) - -export default PrivateDefaultRoute diff --git a/src/components/Private/PrivateMenu.tsx b/src/components/Private/PrivateMenu.tsx deleted file mode 100644 index 8913560..0000000 --- a/src/components/Private/PrivateMenu.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { join } from 'path' -import { Menu, MenuProps } from 'antd' -import { ItemType } from 'antd/lib/menu/hooks/useItems' -import { Link, LinkProps } from 'react-router-dom' -import { Children, isValidElement, memo, ReactNode, RefAttributes, useMemo } from 'react' - -import { useRootPath } from '@asb/context' -import { getTabname, hasPermission, PrivateComponent, PrivateProps } from '@utils' - -export type PrivateMenuProps = MenuProps & { root?: string } - -export type PrivateMenuLinkProps = Partial & Omit & RefAttributes & { - icon?: ReactNode - danger?: boolean - title?: ReactNode - content?: PrivateComponent - path?: string - visible?: boolean - permissions?: string[] -} - -export const PrivateMenuLink = memo(({ content, path = '', title, ...other }) => ( - {title ?? content?.title} -)) - -const PrivateMenuMain = memo(({ selectable, mode, selectedKeys, root, children, ...other }) => { - const rootContext = useRootPath() - const rootPath = useMemo(() => root ?? rootContext ?? '', [root, rootContext]) - - const tab = getTabname() - const keys = useMemo(() => selectedKeys ?? (tab ? [tab] : []), [selectedKeys, tab]) - - const items = useMemo(() => Children.map(children, (child) => { - if (!child || !isValidElement(child)) - return null - const content: PrivateProps | undefined = child.props.content - const visible: boolean | undefined = child.props.visible - - if (visible === false) return null - let key - if (content?.key) - key = content.key - else if (content?.route) - key = content.route - else if (child.key) { - key = child.key?.toString() - key = key.slice(key.lastIndexOf('$') + 1) - } else return null - - const permissions = child.props.permissions ?? content?.requirements - const path = child.props.path ?? join(rootPath, key) - - if (visible || hasPermission(permissions)) - return { - ...child.props, - key, - label: , - } - return null - })?.filter((v) => v) ?? [], [children, rootPath]) - - return ( - - ) -}) - -export const PrivateMenu = Object.assign(PrivateMenuMain, { Link: PrivateMenuLink }) - -export default PrivateMenu diff --git a/src/components/Private/PrivateMenuItem.tsx b/src/components/Private/PrivateMenuItem.tsx deleted file mode 100755 index e549625..0000000 --- a/src/components/Private/PrivateMenuItem.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { join } from 'path' -import { Menu, MenuItemProps } from 'antd' -import { memo, NamedExoticComponent } from 'react' -import { Link, useLocation } from 'react-router-dom' - -import { isURLAvailable } from '@utils' - -export type PrivateMenuItemProps = MenuItemProps & { - root: string - path: string -} - -export type PrivateMenuItemLinkProps = MenuItemProps & { - root?: string - path: string - title: string -} - -export const PrivateMenuItemLink = memo(({ root = '', path, title, ...other }) => { - const location = useLocation() - return ( - - {title} - - ) -}) - -export const PrivateMenuItem: NamedExoticComponent & { - Link: NamedExoticComponent -} = Object.assign(memo(({ root, path, ...other }) => -