forked from ddrilling/asb_cloud_front
Добавлено меню навигации для раздела месторождения
This commit is contained in:
parent
ebe3a50fbe
commit
4dd57aff98
@ -3,6 +3,8 @@ import { createContext, useContext, useEffect } from 'react'
|
|||||||
import { LayoutPortalProps } from '@components/LayoutPortal'
|
import { LayoutPortalProps } from '@components/LayoutPortal'
|
||||||
import { DepositDto, UserTokenDto, WellDto } from '@api'
|
import { DepositDto, UserTokenDto, WellDto } from '@api'
|
||||||
|
|
||||||
|
/** Контекст текущего месторождения */
|
||||||
|
export const DepositContext = createContext<DepositDto | null>(null)
|
||||||
/** Контекст текущей скважины */
|
/** Контекст текущей скважины */
|
||||||
export const WellContext = createContext<[WellDto, (well: WellDto) => void]>([{}, () => {}])
|
export const WellContext = createContext<[WellDto, (well: WellDto) => void]>([{}, () => {}])
|
||||||
/** Контекст текущего корневого пути */
|
/** Контекст текущего корневого пути */
|
||||||
@ -19,10 +21,17 @@ export const DepositListContext = createContext<DepositDto[]>([])
|
|||||||
/**
|
/**
|
||||||
* Получить текущую скважину
|
* Получить текущую скважину
|
||||||
*
|
*
|
||||||
* @returns Текущая скважина, либо `null`
|
* @returns Текущая скважина, либо пустой объект
|
||||||
*/
|
*/
|
||||||
export const useWell = () => useContext(WellContext)
|
export const useWell = () => useContext(WellContext)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить текущее месторождение
|
||||||
|
*
|
||||||
|
* @returns Текущее месторождение, либо `null`
|
||||||
|
*/
|
||||||
|
export const useDeposit = () => useContext(DepositContext)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Получить текущий корневой путь
|
* Получить текущий корневой путь
|
||||||
*
|
*
|
||||||
|
@ -1,106 +0,0 @@
|
|||||||
import { useEffect, memo, useMemo, useCallback } from 'react'
|
|
||||||
import { Link, useLocation } from 'react-router-dom'
|
|
||||||
import { Map, Overlay } from 'pigeon-maps'
|
|
||||||
import { Popover, Badge } from 'antd'
|
|
||||||
|
|
||||||
import { useDepositList, useLayoutProps } from '@asb/context'
|
|
||||||
import { PointerIcon } from '@components/icons'
|
|
||||||
import { FastRunMenu } from '@components/FastRunMenu'
|
|
||||||
import { limitValue, withPermissions } from '@utils'
|
|
||||||
|
|
||||||
import '@styles/index.css'
|
|
||||||
|
|
||||||
const zoomLimit = limitValue(5, 15)
|
|
||||||
|
|
||||||
const calcViewParams = (clusters) => {
|
|
||||||
if ((clusters?.length ?? 0) <= 0)
|
|
||||||
return { center: [60.81226, 70.0562], zoom: 5 }
|
|
||||||
|
|
||||||
const center = clusters.reduce((sum, cluster) => {
|
|
||||||
sum[0] += cluster.latitude
|
|
||||||
sum[1] += cluster.longitude
|
|
||||||
return sum
|
|
||||||
}, [0, 0]).map((elm) => elm / clusters.length)
|
|
||||||
|
|
||||||
const maxDeg = clusters.reduce((max, cluster) => {
|
|
||||||
const dLatitude = Math.abs(center[0] - cluster.latitude)
|
|
||||||
const dLongitude = Math.abs(center[1] - cluster.longitude)
|
|
||||||
return Math.max(Math.max(dLatitude, dLongitude), max)
|
|
||||||
}, 0)
|
|
||||||
|
|
||||||
// zoom max = 20 (too close)
|
|
||||||
// zoom min = 1 (mega far)
|
|
||||||
// 4 - full Russia (161.6 deg)
|
|
||||||
// 13.5 - Khanty-Mansiysk
|
|
||||||
const zoom = zoomLimit(5 + 5 / (maxDeg + 0.5))
|
|
||||||
|
|
||||||
return { center, zoom }
|
|
||||||
}
|
|
||||||
|
|
||||||
const Deposit = memo(() => {
|
|
||||||
const deposits = useDepositList()
|
|
||||||
const setLayoutProps = useLayoutProps()
|
|
||||||
const location = useLocation()
|
|
||||||
|
|
||||||
const makeDepositLinks = useCallback((clusters) => (
|
|
||||||
<div>
|
|
||||||
{clusters.map(cluster => (
|
|
||||||
<Link
|
|
||||||
key={cluster.id}
|
|
||||||
to={{
|
|
||||||
pathname: `/cluster/${cluster.id}`,
|
|
||||||
state: { from: location.pathname }
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div>{cluster.caption}</div>
|
|
||||||
</Link>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
), [location.pathname])
|
|
||||||
|
|
||||||
const viewParams = useMemo(() => calcViewParams(deposits), [deposits])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const hasId = location.pathname.length > '/deposit/'.length
|
|
||||||
|
|
||||||
const selectorProps = {
|
|
||||||
expand: hasId ? [location.pathname] : true,
|
|
||||||
current: hasId ? location.pathname : undefined,
|
|
||||||
}
|
|
||||||
|
|
||||||
setLayoutProps({
|
|
||||||
sheet: false,
|
|
||||||
showSelector: true,
|
|
||||||
selectorProps,
|
|
||||||
title: 'Месторождение',
|
|
||||||
})
|
|
||||||
}, [setLayoutProps, location.pathname])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<FastRunMenu />
|
|
||||||
<div className={'deposit-page'}>
|
|
||||||
<Map {...viewParams}>
|
|
||||||
{deposits.map(deposit => {
|
|
||||||
const anchor = [deposit.latitude, deposit.longitude]
|
|
||||||
const links = makeDepositLinks(deposit.clusters)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Overlay width={32} anchor={anchor} key={anchor.join(' ')}>
|
|
||||||
<Popover content={links} trigger={['click']} title={deposit.caption}>
|
|
||||||
<div className={'pointer'}>
|
|
||||||
<Badge count={deposit.clusters.length}>
|
|
||||||
<PointerIcon state={'active'} width={48} height={59} />
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
</Popover>
|
|
||||||
</Overlay>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</Map>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export default withPermissions(Deposit, ['Cluster.get'])
|
|
23
src/pages/Deposit/DepositNavigationMenu.jsx
Normal file
23
src/pages/Deposit/DepositNavigationMenu.jsx
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { memo } from 'react'
|
||||||
|
import {
|
||||||
|
HeatMapOutlined,
|
||||||
|
} from '@ant-design/icons'
|
||||||
|
|
||||||
|
import { makeItem, PrivateMenu } from '@components/PrivateMenu'
|
||||||
|
|
||||||
|
export const menuItems = [
|
||||||
|
makeItem('Карта', 'map', [], <HeatMapOutlined />),
|
||||||
|
]
|
||||||
|
|
||||||
|
export const DepositNavigationMenu = memo((props) => (
|
||||||
|
<PrivateMenu
|
||||||
|
{...props}
|
||||||
|
items={menuItems}
|
||||||
|
rootPath={'/deposit/{idDeposit}'}
|
||||||
|
mode={'inline'}
|
||||||
|
theme={'dark'}
|
||||||
|
style={{ backgroundColor: 'transparent' }}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
|
||||||
|
export default DepositNavigationMenu
|
85
src/pages/Deposit/Map.jsx
Normal file
85
src/pages/Deposit/Map.jsx
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import { memo, useMemo, useCallback } from 'react'
|
||||||
|
import { Link, useLocation } from 'react-router-dom'
|
||||||
|
import { Map as PigeonMap, Overlay } from 'pigeon-maps'
|
||||||
|
import { Popover, Badge } from 'antd'
|
||||||
|
|
||||||
|
import { useDepositList } from '@asb/context'
|
||||||
|
import { PointerIcon } from '@components/icons'
|
||||||
|
import { limitValue, withPermissions } from '@utils'
|
||||||
|
|
||||||
|
import '@styles/index.css'
|
||||||
|
|
||||||
|
const zoomLimit = limitValue(5, 15)
|
||||||
|
|
||||||
|
const calcViewParams = (clusters) => {
|
||||||
|
if ((clusters?.length ?? 0) <= 0)
|
||||||
|
return { center: [60.81226, 70.0562], zoom: 5 }
|
||||||
|
|
||||||
|
const center = clusters.reduce((sum, cluster) => {
|
||||||
|
sum[0] += cluster.latitude
|
||||||
|
sum[1] += cluster.longitude
|
||||||
|
return sum
|
||||||
|
}, [0, 0]).map((elm) => elm / clusters.length)
|
||||||
|
|
||||||
|
const maxDeg = clusters.reduce((max, cluster) => {
|
||||||
|
const dLatitude = Math.abs(center[0] - cluster.latitude)
|
||||||
|
const dLongitude = Math.abs(center[1] - cluster.longitude)
|
||||||
|
return Math.max(Math.max(dLatitude, dLongitude), max)
|
||||||
|
}, 0)
|
||||||
|
|
||||||
|
// zoom max = 20 (too close)
|
||||||
|
// zoom min = 1 (mega far)
|
||||||
|
// 4 - full Russia (161.6 deg)
|
||||||
|
// 13.5 - Khanty-Mansiysk
|
||||||
|
const zoom = zoomLimit(5 + 5 / (maxDeg + 0.5))
|
||||||
|
|
||||||
|
return { center, zoom }
|
||||||
|
}
|
||||||
|
|
||||||
|
const Map = memo(() => {
|
||||||
|
const deposits = useDepositList()
|
||||||
|
const location = useLocation()
|
||||||
|
|
||||||
|
const makeDepositLinks = useCallback((clusters) => (
|
||||||
|
<div>
|
||||||
|
{clusters.map(cluster => (
|
||||||
|
<Link
|
||||||
|
key={cluster.id}
|
||||||
|
to={{
|
||||||
|
pathname: `/cluster/${cluster.id}`,
|
||||||
|
state: { from: location.pathname }
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>{cluster.caption}</div>
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
), [location.pathname])
|
||||||
|
|
||||||
|
const viewParams = useMemo(() => calcViewParams(deposits), [deposits])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={'deposit-page'}>
|
||||||
|
<PigeonMap {...viewParams}>
|
||||||
|
{deposits.map(deposit => {
|
||||||
|
const anchor = [deposit.latitude, deposit.longitude]
|
||||||
|
const links = makeDepositLinks(deposit.clusters)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Overlay width={32} anchor={anchor} key={anchor.join(' ')}>
|
||||||
|
<Popover content={links} trigger={['click']} title={deposit.caption}>
|
||||||
|
<div className={'pointer'}>
|
||||||
|
<Badge count={deposit.clusters.length}>
|
||||||
|
<PointerIcon state={'active'} width={48} height={59} />
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
</Popover>
|
||||||
|
</Overlay>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</PigeonMap>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default withPermissions(Map, ['Cluster.get'])
|
64
src/pages/Deposit/index.jsx
Normal file
64
src/pages/Deposit/index.jsx
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import { Navigate, Route, Routes, useLocation, useParams } from 'react-router-dom'
|
||||||
|
import { lazy, memo, useEffect, useMemo } from 'react'
|
||||||
|
|
||||||
|
import { DepositContext, RootPathContext, useDepositList, useLayoutProps, useRootPath } from '@asb/context'
|
||||||
|
import FastRunMenu from '@components/FastRunMenu'
|
||||||
|
import { NoAccessComponent, withPermissions } from '@utils'
|
||||||
|
|
||||||
|
const Map = lazy(() => import('./Map'))
|
||||||
|
const DepositNavigationMenu = lazy(() => import('./DepositNavigationMenu'))
|
||||||
|
|
||||||
|
const Deposit = memo(() => {
|
||||||
|
const { '*': param } = useParams()
|
||||||
|
const location = useLocation()
|
||||||
|
|
||||||
|
const setLayoutProps = useLayoutProps()
|
||||||
|
const deposits = useDepositList()
|
||||||
|
|
||||||
|
const idDeposit = useMemo(() => {
|
||||||
|
const result = /^([^\/#?]+)/.exec(param)
|
||||||
|
return result && result[1] !== 'null' ? Number(result[1]) : null
|
||||||
|
}, [param])
|
||||||
|
|
||||||
|
const deposit = useMemo(() => deposits.find((deposit) => deposit.id === idDeposit) || null, [deposits, idDeposit])
|
||||||
|
|
||||||
|
const root = useRootPath()
|
||||||
|
const rootPath = useMemo(() => `${root}/deposit`, [root])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const hasId = location.pathname.length > '/deposit/'.length
|
||||||
|
|
||||||
|
const selectorProps = {
|
||||||
|
expand: hasId ? [location.pathname] : true,
|
||||||
|
current: hasId ? location.pathname : undefined,
|
||||||
|
}
|
||||||
|
|
||||||
|
setLayoutProps({
|
||||||
|
sheet: false,
|
||||||
|
sider: <DepositNavigationMenu disabled={idDeposit === null} variables={{ idDeposit: idDeposit }} />,
|
||||||
|
showSelector: true,
|
||||||
|
selectorProps,
|
||||||
|
title: 'Месторождение',
|
||||||
|
})
|
||||||
|
}, [setLayoutProps, location.pathname, deposit])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RootPathContext.Provider value={rootPath}>
|
||||||
|
<DepositContext.Provider value={deposit}>
|
||||||
|
<FastRunMenu />
|
||||||
|
<Routes>
|
||||||
|
<Route index element={<Navigate to={'null/'} />} />
|
||||||
|
|
||||||
|
<Route path={':idDeposit'}>
|
||||||
|
<Route index element={<Navigate to={'map'} replace />} />
|
||||||
|
<Route path={'*'} element={<NoAccessComponent />} />
|
||||||
|
|
||||||
|
<Route path={'map'} element={<Map />} />
|
||||||
|
</Route>
|
||||||
|
</Routes>
|
||||||
|
</DepositContext.Provider>
|
||||||
|
</RootPathContext.Provider>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default withPermissions(Deposit, [])
|
Loading…
Reference in New Issue
Block a user