2022-11-11 00:06:11 +05:00
|
|
|
|
import { Drawer, Tree, TreeDataNode, TreeProps } from 'antd'
|
|
|
|
|
import { useState, useEffect, useCallback, memo, Key, useMemo } from 'react'
|
2022-06-09 17:51:41 +05:00
|
|
|
|
import { useNavigate, useLocation } from 'react-router-dom'
|
2022-02-25 16:57:08 +05:00
|
|
|
|
|
2022-12-05 20:39:14 +05:00
|
|
|
|
import { useDepositList } from '@asb/context'
|
2022-03-23 14:28:08 +05:00
|
|
|
|
import { WellIcon, WellIconState } from '@components/icons'
|
2022-11-11 00:06:11 +05:00
|
|
|
|
import { DepositDto, WellDto } from '@api'
|
2022-08-01 17:34:44 +05:00
|
|
|
|
import { isRawDate } from '@utils'
|
2021-12-27 15:58:31 +05:00
|
|
|
|
|
2022-01-24 17:32:45 +05:00
|
|
|
|
import { ReactComponent as DepositIcon } from '@images/DepositIcon.svg'
|
|
|
|
|
import { ReactComponent as ClusterIcon } from '@images/ClusterIcon.svg'
|
2021-12-27 15:31:37 +05:00
|
|
|
|
|
2022-12-08 12:13:58 +05:00
|
|
|
|
import '@styles/components/well_tree_select.css'
|
2021-11-19 11:46:11 +05:00
|
|
|
|
|
2022-12-05 21:07:17 +05:00
|
|
|
|
/**
|
|
|
|
|
* Для поиска в URL текущего раздела по шаблону `/{type}/{id}`
|
|
|
|
|
*
|
|
|
|
|
* Если найдено совпадение может вернуть 1 или 2 группы соответственно
|
|
|
|
|
*/
|
|
|
|
|
const URL_REGEX = /^\/([^\/?#]+)(?:\/([^\/?#]+))?/
|
|
|
|
|
|
2021-11-19 11:46:11 +05:00
|
|
|
|
export const getWellState = (idState?: number): WellIconState => idState === 1 ? 'active' : 'unknown'
|
2021-12-27 15:58:31 +05:00
|
|
|
|
export const checkIsWellOnline = (lastTelemetryDate: unknown): boolean =>
|
|
|
|
|
isRawDate(lastTelemetryDate) && (Date.now() - +new Date(lastTelemetryDate) < 600_000)
|
2021-11-19 11:46:11 +05:00
|
|
|
|
|
2022-12-06 00:51:41 +05:00
|
|
|
|
const getKeyByUrl = (url?: string): [Key | null, string | null, number | null] => {
|
2022-12-05 21:07:17 +05:00
|
|
|
|
const result = url?.match(URL_REGEX) // pattern "/:type/:id"
|
2022-12-06 00:51:41 +05:00
|
|
|
|
if (!result) return [null, null, null]
|
|
|
|
|
return [result[0], result[1], result[2] && result[2] !== 'null' ? Number(result[2]) : null]
|
2022-08-01 17:34:44 +05:00
|
|
|
|
}
|
|
|
|
|
|
2022-10-03 21:35:26 +05:00
|
|
|
|
const getLabel = (wellsTree: TreeDataNode[], value?: string): string | undefined => {
|
2022-12-06 00:51:41 +05:00
|
|
|
|
const [url, type, key] = getKeyByUrl(value)
|
2022-08-01 17:34:44 +05:00
|
|
|
|
if (!url) return
|
2022-10-03 21:35:26 +05:00
|
|
|
|
let deposit: TreeDataNode | undefined
|
|
|
|
|
let cluster: TreeDataNode | undefined
|
|
|
|
|
let well: TreeDataNode | undefined
|
2021-12-23 12:42:52 +05:00
|
|
|
|
switch (type) {
|
2022-06-09 17:51:41 +05:00
|
|
|
|
case 'deposit':
|
2022-12-06 00:51:41 +05:00
|
|
|
|
if (key === null) return 'Месторождение не выбрано'
|
2022-06-09 17:51:41 +05:00
|
|
|
|
deposit = wellsTree.find((deposit) => deposit.key === url)
|
|
|
|
|
if (deposit)
|
|
|
|
|
return `${deposit.title}`
|
|
|
|
|
return 'Ошибка! Месторождение не найдено!'
|
|
|
|
|
|
2021-12-23 12:42:52 +05:00
|
|
|
|
case 'cluster':
|
2022-12-06 00:51:41 +05:00
|
|
|
|
if (key === null) return 'Куст не выбран'
|
2021-12-23 12:42:52 +05:00
|
|
|
|
deposit = wellsTree.find((deposit) => (
|
2022-10-03 21:35:26 +05:00
|
|
|
|
cluster = deposit.children?.find((cluster: TreeDataNode) => cluster.key === url)
|
2021-12-23 12:42:52 +05:00
|
|
|
|
))
|
|
|
|
|
if (deposit && cluster)
|
|
|
|
|
return `${deposit.title} / ${cluster.title}`
|
2022-06-09 17:51:41 +05:00
|
|
|
|
return 'Ошибка! Куст не найден!'
|
|
|
|
|
|
2021-12-23 12:42:52 +05:00
|
|
|
|
case 'well':
|
2022-12-06 00:51:41 +05:00
|
|
|
|
if (key === null) return 'Скважина не выбрана'
|
2021-12-23 12:42:52 +05:00
|
|
|
|
deposit = wellsTree.find((deposit) => (
|
2022-10-03 21:35:26 +05:00
|
|
|
|
cluster = deposit.children?.find((cluster: TreeDataNode) => (
|
|
|
|
|
well = cluster.children?.find((well: TreeDataNode) => well.key === url)
|
2021-12-23 12:42:52 +05:00
|
|
|
|
))
|
|
|
|
|
))
|
|
|
|
|
if (deposit && cluster && well)
|
|
|
|
|
return `${deposit.title} / ${cluster.title} / ${well.title}`
|
2022-06-09 17:51:41 +05:00
|
|
|
|
return 'Ошибка! Скважина не найдена!'
|
|
|
|
|
|
2021-12-23 12:42:52 +05:00
|
|
|
|
default: break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-01 17:34:44 +05:00
|
|
|
|
const getWellSortScore = (well: WellDto) => {
|
|
|
|
|
let out = [1, 2, 0][well.idState ?? 2]
|
|
|
|
|
const timeout = Date.now() - +new Date(well.lastTelemetryDate || 0)
|
|
|
|
|
if (timeout < 600_000) out += 600_000 - timeout
|
|
|
|
|
return out
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const sortWellsByActive = (a: WellDto, b: WellDto): number => {
|
|
|
|
|
const score = getWellSortScore(b) - getWellSortScore(a)
|
|
|
|
|
if (score !== 0) return score
|
|
|
|
|
return (a.caption || '')?.localeCompare(b.caption || '')
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-03 21:35:26 +05:00
|
|
|
|
export type WellTreeSelectorProps = TreeProps<TreeDataNode> & {
|
|
|
|
|
show?: boolean
|
|
|
|
|
expand?: boolean | Key[]
|
|
|
|
|
current?: Key
|
2022-10-13 14:31:11 +05:00
|
|
|
|
onClose?: () => void
|
|
|
|
|
onChange?: (value: string | undefined) => void
|
|
|
|
|
open?: boolean
|
2022-10-03 21:35:26 +05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-11 00:06:11 +05:00
|
|
|
|
const makeWellsTreeData = (deposits: DepositDto[]): TreeDataNode[] => deposits.map(deposit =>({
|
|
|
|
|
title: deposit.caption,
|
|
|
|
|
key: `/deposit/${deposit.id}`,
|
|
|
|
|
value: `/deposit/${deposit.id}`,
|
|
|
|
|
icon: <DepositIcon width={24} height={24}/>,
|
|
|
|
|
children: deposit.clusters?.map(cluster => {
|
|
|
|
|
const wells = cluster.wells ? cluster.wells.slice() : []
|
|
|
|
|
wells.sort(sortWellsByActive)
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
title: cluster.caption,
|
|
|
|
|
key: `/cluster/${cluster.id}`,
|
|
|
|
|
value: `/cluster/${cluster.id}`,
|
|
|
|
|
icon: <ClusterIcon width={24} height={24}/>,
|
|
|
|
|
children: wells.map(well => ({
|
|
|
|
|
title: well.caption,
|
|
|
|
|
key: `/well/${well.id}`,
|
|
|
|
|
value: `/well/${well.id}`,
|
|
|
|
|
icon: <WellIcon
|
|
|
|
|
width={24}
|
|
|
|
|
height={24}
|
|
|
|
|
state={getWellState(well.idState)}
|
|
|
|
|
online={checkIsWellOnline(well.lastTelemetryDate)}
|
|
|
|
|
/>
|
|
|
|
|
})),
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
}))
|
|
|
|
|
|
2022-10-13 14:31:11 +05:00
|
|
|
|
export const WellTreeSelector = memo<WellTreeSelectorProps>(({ expand, current, onChange, onClose, open, ...other }) => {
|
2022-08-01 17:34:44 +05:00
|
|
|
|
const [expanded, setExpanded] = useState<Key[]>([])
|
|
|
|
|
const [selected, setSelected] = useState<Key[]>([])
|
|
|
|
|
|
2022-06-09 17:51:41 +05:00
|
|
|
|
const navigate = useNavigate()
|
2022-02-25 16:57:08 +05:00
|
|
|
|
const location = useLocation()
|
2022-12-05 20:39:14 +05:00
|
|
|
|
const deposits = useDepositList()
|
2021-11-19 11:46:11 +05:00
|
|
|
|
|
2022-11-11 00:06:11 +05:00
|
|
|
|
const wellsTree = useMemo(() => makeWellsTreeData(deposits), [deposits])
|
2021-11-19 11:46:11 +05:00
|
|
|
|
|
2022-10-13 14:31:11 +05:00
|
|
|
|
const onValueChange = useCallback((value?: string): void => {
|
2022-08-01 17:34:44 +05:00
|
|
|
|
const key = getKeyByUrl(value)[0]
|
|
|
|
|
setSelected(key ? [key] : [])
|
2022-10-13 14:31:11 +05:00
|
|
|
|
onChange?.(getLabel(wellsTree, value))
|
2022-08-01 17:34:44 +05:00
|
|
|
|
}, [wellsTree])
|
2021-12-23 12:42:52 +05:00
|
|
|
|
|
2022-08-01 17:34:44 +05:00
|
|
|
|
const onSelect = useCallback((value: Key[]): void => {
|
2022-12-05 21:07:17 +05:00
|
|
|
|
const newRoot = URL_REGEX.exec(String(value))
|
|
|
|
|
const oldRoot = URL_REGEX.exec(location.pathname)
|
2022-10-06 15:14:44 +05:00
|
|
|
|
if (!newRoot || !oldRoot) return
|
|
|
|
|
|
|
|
|
|
let newPath = newRoot[0]
|
2022-10-06 15:21:25 +05:00
|
|
|
|
if (oldRoot[1] === newRoot[1]) {
|
|
|
|
|
/// Если типы страницы одинаковые (deposit, cluster, well), добавляем остаток старого пути
|
2022-10-06 15:14:44 +05:00
|
|
|
|
const url = location.pathname.substring(oldRoot[0].length)
|
|
|
|
|
newPath = newPath + url
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
navigate(newPath, { state: { from: location.pathname }})
|
2022-06-09 17:51:41 +05:00
|
|
|
|
}, [navigate, location])
|
2021-11-19 11:46:11 +05:00
|
|
|
|
|
2022-11-11 00:06:11 +05:00
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (current) setSelected([current])
|
|
|
|
|
}, [current])
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
setExpanded((prev) => expand ? getExpandKeys(wellsTree, expand) : prev)
|
|
|
|
|
}, [wellsTree, expand])
|
|
|
|
|
|
|
|
|
|
useEffect(() => onValueChange(location.pathname), [onValueChange, location.pathname])
|
2022-08-01 17:34:44 +05:00
|
|
|
|
|
2021-11-19 11:46:11 +05:00
|
|
|
|
return (
|
2022-10-13 14:31:11 +05:00
|
|
|
|
<Drawer open={open} mask={false} onClose={onClose} title={'Список скважин'}>
|
2022-11-11 00:06:11 +05:00
|
|
|
|
<Tree
|
|
|
|
|
{...other}
|
|
|
|
|
showIcon
|
|
|
|
|
selectedKeys={selected}
|
|
|
|
|
treeData={wellsTree}
|
|
|
|
|
onSelect={onSelect}
|
|
|
|
|
onExpand={setExpanded}
|
|
|
|
|
expandedKeys={expanded}
|
|
|
|
|
/>
|
2022-10-13 14:31:11 +05:00
|
|
|
|
</Drawer>
|
2021-11-19 11:46:11 +05:00
|
|
|
|
)
|
2022-02-25 16:57:08 +05:00
|
|
|
|
})
|
2021-11-19 11:46:11 +05:00
|
|
|
|
|
|
|
|
|
export default WellTreeSelector
|