diff --git a/src/components/Layout/LayoutPortal.tsx b/src/components/Layout/LayoutPortal.tsx index ff915b0..e754811 100755 --- a/src/components/Layout/LayoutPortal.tsx +++ b/src/components/Layout/LayoutPortal.tsx @@ -1,20 +1,20 @@ -import { memo, ReactNode } from 'react' +import { Key, memo, ReactNode } from 'react' import { Layout, LayoutProps } from 'antd' import PageHeader from '@components/PageHeader' -import WellTreeSelector from '@components/selectors/WellTreeSelector' +import { WellTreeSelector, WellTreeSelectorProps } from '@components/selectors/WellTreeSelector' import { wrapPrivateComponent } from '@utils' export type LayoutPortalProps = LayoutProps & { title?: ReactNode noSheet?: boolean - showSelector?: boolean + selector?: WellTreeSelectorProps } -const _LayoutPortal = memo(({ title, noSheet, showSelector, ...props }) => ( +const _LayoutPortal = memo(({ title, noSheet, selector, ...props }) => ( - + {noSheet ? props.children : ( diff --git a/src/components/selectors/WellTreeSelector.tsx b/src/components/selectors/WellTreeSelector.tsx index addeaef..ee06e1d 100755 --- a/src/components/selectors/WellTreeSelector.tsx +++ b/src/components/selectors/WellTreeSelector.tsx @@ -1,6 +1,5 @@ -import { Button, Drawer, Skeleton, Tree, TreeProps, Typography } from 'antd' -import { DefaultValueType } from 'rc-tree-select/lib/interface' -import { useState, useEffect, ReactNode, useCallback, memo, Key } from 'react' +import { Button, Drawer, Skeleton, Tree, TreeDataNode, TreeProps, Typography } from 'antd' +import { useState, useEffect, useCallback, memo, Key } from 'react' import { useNavigate, useLocation } from 'react-router-dom' import { WellIcon, WellIconState } from '@components/icons' @@ -17,26 +16,18 @@ export const getWellState = (idState?: number): WellIconState => idState === 1 ? export const checkIsWellOnline = (lastTelemetryDate: unknown): boolean => isRawDate(lastTelemetryDate) && (Date.now() - +new Date(lastTelemetryDate) < 600_000) -export type TreeNodeData = { - title?: string | null - key?: string - value?: DefaultValueType - icon?: ReactNode - children?: TreeNodeData[] -} - const getKeyByUrl = (url?: string): [Key | null, string | null] => { const result = url?.match(/^\/([^\/]+)\/([^\/?]+)/) // pattern "/:type/:id" if (!result) return [null, null] return [result[0], result[1]] } -const getLabel = (wellsTree: TreeNodeData[], value?: string): string | undefined => { +const getLabel = (wellsTree: TreeDataNode[], value?: string): string | undefined => { const [url, type] = getKeyByUrl(value) if (!url) return - let deposit: TreeNodeData | undefined - let cluster: TreeNodeData | undefined - let well: TreeNodeData | undefined + let deposit: TreeDataNode | undefined + let cluster: TreeDataNode | undefined + let well: TreeDataNode | undefined switch (type) { case 'deposit': deposit = wellsTree.find((deposit) => deposit.key === url) @@ -46,7 +37,7 @@ const getLabel = (wellsTree: TreeNodeData[], value?: string): string | undefined case 'cluster': deposit = wellsTree.find((deposit) => ( - cluster = deposit.children?.find((cluster: TreeNodeData) => cluster.key === url) + cluster = deposit.children?.find((cluster: TreeDataNode) => cluster.key === url) )) if (deposit && cluster) return `${deposit.title} / ${cluster.title}` @@ -54,8 +45,8 @@ const getLabel = (wellsTree: TreeNodeData[], value?: string): string | undefined case 'well': deposit = wellsTree.find((deposit) => ( - cluster = deposit.children?.find((cluster: TreeNodeData) => ( - well = cluster.children?.find((well: TreeNodeData) => well.key === url) + cluster = deposit.children?.find((cluster: TreeDataNode) => ( + well = cluster.children?.find((well: TreeDataNode) => well.key === url) )) )) if (deposit && cluster && well) @@ -79,8 +70,26 @@ const sortWellsByActive = (a: WellDto, b: WellDto): number => { return (a.caption || '')?.localeCompare(b.caption || '') } -export const WellTreeSelector = memo(({ show, ...other }: TreeProps & { show?: boolean }) => { - const [wellsTree, setWellsTree] = useState([]) +export type WellTreeSelectorProps = TreeProps & { + show?: boolean + expand?: boolean | Key[] + current?: Key +} + +const getExpandKeys = (treeData: TreeDataNode[], depositKeys?: Key[] | boolean): Key[] => { + const out: Key[] = [] + treeData.forEach((deposit) => { + if (Array.isArray(depositKeys) && !depositKeys.includes(deposit.key)) return + if (deposit.key) out.push(deposit.key) + deposit.children?.forEach((cluster) => { + if (cluster.key) out.push(cluster.key) + }) + }) + return out +} + +export const WellTreeSelector = memo(({ show, expand, current, ...other }) => { + const [wellsTree, setWellsTree] = useState([]) const [showLoader, setShowLoader] = useState(false) const [visible, setVisible] = useState(false) const [expanded, setExpanded] = useState([]) @@ -91,26 +100,20 @@ export const WellTreeSelector = memo(({ show, ...other }: TreeProps { - setVisible((prev) => show ?? prev) - setExpanded((prev) => { - if (typeof show === 'undefined') return prev - if (!show) return [] - const out: Key[] = [] - wellsTree.forEach((deposit) => { - if (deposit.key) out.push(deposit.key) - deposit.children?.forEach((cluster) => { - if (cluster.key) out.push(cluster.key) - }) - }) - return out - }) - }, [wellsTree, show]) + if (current) setSelected([current]) + }, [current]) + + useEffect(() => setVisible((prev) => show ?? prev), [show]) + + useEffect(() => { + setExpanded((prev) => expand ? getExpandKeys(wellsTree, expand) : prev) + }, [wellsTree, expand]) useEffect(() => { invokeWebApiWrapperAsync( async () => { const deposits: Array = await DepositService.getDeposits() - const wellsTree: TreeNodeData[] = deposits.map(deposit =>({ + const wellsTree: TreeDataNode[] = deposits.map(deposit =>({ title: deposit.caption, key: `/deposit/${deposit.id}`, value: `/deposit/${deposit.id}`, diff --git a/src/pages/Deposit.jsx b/src/pages/Deposit.jsx index 98629b3..cb050d4 100755 --- a/src/pages/Deposit.jsx +++ b/src/pages/Deposit.jsx @@ -1,5 +1,5 @@ import { Map, Overlay } from 'pigeon-maps' -import { useState, useEffect, memo } from 'react' +import { useState, useEffect, memo, useMemo } from 'react' import { Link, useLocation } from 'react-router-dom' import { Popover, Badge } from 'antd' @@ -49,6 +49,16 @@ const Deposit = memo(() => { const location = useLocation() + const selectorProps = useMemo(() => { + const hasId = location.pathname.length > '/deposit/'.length + + return { + show: true, + expand: hasId ? [location.pathname] : true, + current: hasId ? location.pathname : undefined, + } + }, [location.pathname]) + useEffect(() => { invokeWebApiWrapperAsync( async () => { @@ -63,7 +73,7 @@ const Deposit = memo(() => { }, []) return ( - +