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 { DepositDto, UserTokenDto, WellDto } from '@api'
|
||||
|
||||
/** Контекст текущего месторождения */
|
||||
export const DepositContext = createContext<DepositDto | null>(null)
|
||||
/** Контекст текущей скважины */
|
||||
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)
|
||||
|
||||
/**
|
||||
* Получить текущее месторождение
|
||||
*
|
||||
* @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