forked from ddrilling/asb_cloud_front
133 lines
5.3 KiB
TypeScript
Executable File
133 lines
5.3 KiB
TypeScript
Executable File
import { TreeSelect } from 'antd'
|
||
import { DefaultValueType } from 'rc-tree-select/lib/interface'
|
||
import { useState, useEffect, ReactNode, useCallback, memo } from 'react'
|
||
import { useHistory, useLocation, useRouteMatch } from 'react-router-dom'
|
||
|
||
import { RawValueType } from 'rc-tree-select/lib/TreeSelect'
|
||
import { LabelInValueType } from 'rc-select/lib/Select'
|
||
|
||
import { isRawDate } from '@utils'
|
||
import LoaderPortal from '@components/LoaderPortal'
|
||
import { WellIcon, WellIconState } from '@components/icons'
|
||
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||
import { DepositService, DepositDto } from '@api'
|
||
|
||
import { ReactComponent as DepositIcon } from '@images/DepositIcon.svg'
|
||
import { ReactComponent as ClusterIcon } from '@images/ClusterIcon.svg'
|
||
|
||
import '@styles/wellTreeSelect.css'
|
||
|
||
export const getWellState = (idState?: number): WellIconState => idState === 1 ? 'active' : 'unknown'
|
||
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 getLabel = (wellsTree: TreeNodeData[], value?: string): string | undefined => {
|
||
if (!value) return value
|
||
const type = value.replaceAll('/', ' ').trim().split(' ')[0]
|
||
let deposit: TreeNodeData | undefined
|
||
let cluster: TreeNodeData | undefined
|
||
let well: TreeNodeData | undefined
|
||
switch (type) {
|
||
case 'cluster':
|
||
deposit = wellsTree.find((deposit) => (
|
||
cluster = deposit.children?.find((cluster: TreeNodeData) => cluster.key === value)
|
||
))
|
||
if (deposit && cluster)
|
||
return `${deposit.title} / ${cluster.title}`
|
||
break
|
||
case 'well':
|
||
deposit = wellsTree.find((deposit) => (
|
||
cluster = deposit.children?.find((cluster: TreeNodeData) => (
|
||
well = cluster.children?.find((well: TreeNodeData) => well.key === value)
|
||
))
|
||
))
|
||
if (deposit && cluster && well)
|
||
return `${deposit.title} / ${cluster.title} / ${well.title}`
|
||
break
|
||
default: break
|
||
}
|
||
return 'Ошибка! Скважина не найдена!'
|
||
}
|
||
|
||
export const WellTreeSelector = memo(({ ...other }) => {
|
||
const [wellsTree, setWellsTree] = useState<TreeNodeData[]>([])
|
||
const [showLoader, setShowLoader] = useState<boolean>(false)
|
||
const [value, setValue] = useState<string>()
|
||
const history = useHistory()
|
||
const location = useLocation()
|
||
const routeMatch = useRouteMatch('/:route/:id')
|
||
|
||
useEffect(() => {
|
||
invokeWebApiWrapperAsync(
|
||
async () => {
|
||
const deposits: Array<DepositDto> = await DepositService.getDeposits()
|
||
const wellsTree: TreeNodeData[] = 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 => ({
|
||
title: cluster.caption,
|
||
key: `/cluster/${cluster.id}`,
|
||
value: `/cluster/${cluster.id}`,
|
||
icon: <ClusterIcon width={24} height={24}/>,
|
||
children: cluster.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)}
|
||
/>
|
||
})),
|
||
})),
|
||
}))
|
||
setWellsTree(wellsTree)
|
||
},
|
||
setShowLoader,
|
||
`Не удалось загрузить список скважин`,
|
||
'Получить список скважин'
|
||
)
|
||
}, [])
|
||
|
||
useEffect(() => setValue(getLabel(wellsTree, routeMatch?.url)), [wellsTree, routeMatch])
|
||
|
||
const onChange = useCallback((value?: string): void => setValue(getLabel(wellsTree, value)), [wellsTree])
|
||
|
||
const onSelect = useCallback((value: RawValueType | LabelInValueType): void => {
|
||
if (['number', 'string'].includes(typeof value))
|
||
history.push({ pathname: String(value), state: { from: location.pathname }})
|
||
}, [history, location])
|
||
|
||
return (
|
||
<LoaderPortal show={showLoader}>
|
||
<TreeSelect
|
||
treeIcon
|
||
className={'header-tree-select'}
|
||
bordered={false}
|
||
dropdownMatchSelectWidth={false}
|
||
placeholder={'Выберите месторождение'}
|
||
treeData={wellsTree}
|
||
treeDefaultExpandAll
|
||
onSelect={onSelect}
|
||
onChange={onChange}
|
||
value={value}
|
||
style={{ width: '350px' }}
|
||
{...other}
|
||
/>
|
||
</LoaderPortal>
|
||
)
|
||
})
|
||
|
||
export default WellTreeSelector
|