forked from ddrilling/asb_cloud_front
Страница архива удалена
This commit is contained in:
parent
e39ce8d410
commit
d56810700f
@ -4,7 +4,6 @@ import {
|
|||||||
BarChartOutlined,
|
BarChartOutlined,
|
||||||
BuildOutlined,
|
BuildOutlined,
|
||||||
ControlOutlined,
|
ControlOutlined,
|
||||||
DatabaseOutlined,
|
|
||||||
DeploymentUnitOutlined,
|
DeploymentUnitOutlined,
|
||||||
ExperimentOutlined,
|
ExperimentOutlined,
|
||||||
FilePdfOutlined,
|
FilePdfOutlined,
|
||||||
@ -20,7 +19,6 @@ export const menuItems = [
|
|||||||
makeItem('Телеметрия', 'telemetry', [], <FundViewOutlined />, [
|
makeItem('Телеметрия', 'telemetry', [], <FundViewOutlined />, [
|
||||||
makeItem('Мониторинг', 'telemetry', [], <FundViewOutlined />),
|
makeItem('Мониторинг', 'telemetry', [], <FundViewOutlined />),
|
||||||
makeItem('Сообщения', 'messages', [], <AlertOutlined />),
|
makeItem('Сообщения', 'messages', [], <AlertOutlined />),
|
||||||
makeItem('Архив', 'archive', [], <DatabaseOutlined />),
|
|
||||||
makeItem('ННБ', 'dashboard_nnb', [], <FolderOutlined />),
|
makeItem('ННБ', 'dashboard_nnb', [], <FolderOutlined />),
|
||||||
makeItem('Операции', 'operations', [], <FolderOutlined />),
|
makeItem('Операции', 'operations', [], <FolderOutlined />),
|
||||||
makeItem('Наработка', 'operation_time', [], <FolderOutlined />),
|
makeItem('Наработка', 'operation_time', [], <FolderOutlined />),
|
||||||
|
@ -1,270 +0,0 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
|
||||||
import { useState, useEffect, memo, useCallback, useMemo } from 'react'
|
|
||||||
import { useSearchParams } from 'react-router-dom'
|
|
||||||
import { Select } from 'antd'
|
|
||||||
|
|
||||||
import { useWell } from '@asb/context'
|
|
||||||
import { Flex } from '@components/Grid'
|
|
||||||
import { D3MonitoringCharts } from '@components/d3/monitoring'
|
|
||||||
import { CopyUrlButton } from '@components/CopyUrl'
|
|
||||||
import LoaderPortal from '@components/LoaderPortal'
|
|
||||||
import { invokeWebApiWrapperAsync } from '@components/factory'
|
|
||||||
import { DatePickerWrapper, makeDateSorter } from '@components/Table'
|
|
||||||
import { PeriodPicker, defaultPeriod } from '@components/selectors/PeriodPicker'
|
|
||||||
import { formatDate, range, withPermissions } from '@utils'
|
|
||||||
import { TelemetryDataSaubService } from '@api'
|
|
||||||
|
|
||||||
import { normalizeData } from '../TelemetryView'
|
|
||||||
import { cursorRender } from '../TelemetryView/cursorRender'
|
|
||||||
import { makeChartGroups, yAxis } from '../TelemetryView/dataset'
|
|
||||||
|
|
||||||
const DATA_COUNT = 2048 // Колличество точек на подгрузку графика
|
|
||||||
const ADDITIVE_PAGES = 2 // Дополнительные данные для графиков
|
|
||||||
const LOADING_TRIGGER = 0.5
|
|
||||||
|
|
||||||
const scrollOptions = [
|
|
||||||
{ label: '10%', value: 0.1 },
|
|
||||||
{ label: '15%', value: 0.15 },
|
|
||||||
{ label: '25%', value: 0.25 },
|
|
||||||
]
|
|
||||||
|
|
||||||
const getLoadingInterval = (loaded, startDate, interval) => {
|
|
||||||
// Если данные загружены и дата не заходит за тригер дозагрузка не требуется
|
|
||||||
if (
|
|
||||||
loaded &&
|
|
||||||
+startDate - interval * LOADING_TRIGGER > loaded.start &&
|
|
||||||
+startDate + interval * (LOADING_TRIGGER + 1) < loaded.end
|
|
||||||
)
|
|
||||||
return { loadingStartDate: startDate, newLoaded: loaded, loadingInterval: 0 }
|
|
||||||
|
|
||||||
let loadingStartDate = +startDate - interval * ADDITIVE_PAGES
|
|
||||||
let loadingEndDate = +startDate + interval * (ADDITIVE_PAGES + 1)
|
|
||||||
|
|
||||||
const newLoaded = {
|
|
||||||
start: loadingStartDate,
|
|
||||||
end: loadingEndDate
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loaded) {
|
|
||||||
if (loadingStartDate >= loaded.start)
|
|
||||||
loadingStartDate = loaded.end
|
|
||||||
if (loadingEndDate <= loaded.end)
|
|
||||||
loadingEndDate = loaded.start
|
|
||||||
newLoaded.start = Math.min(loaded.start, loadingStartDate)
|
|
||||||
newLoaded.end = Math.max(loaded.end, loadingEndDate)
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadingInterval = Math.trunc((loadingEndDate - loadingStartDate) / 1000)
|
|
||||||
|
|
||||||
return {
|
|
||||||
loadingStartDate: new Date(loadingStartDate),
|
|
||||||
newLoaded: {
|
|
||||||
start: new Date(newLoaded.start),
|
|
||||||
end: new Date(newLoaded.end)
|
|
||||||
},
|
|
||||||
loadingInterval
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const interpolationSearch = (data, begin, end, accessor) => {
|
|
||||||
const fy = (i) => new Date(data[i]?.[accessor] ?? 0)
|
|
||||||
const fx = (y, b, e) => Math.round(b + (y - fy(b)) * (e - b) / (fy(e) - fy(b)))
|
|
||||||
const findIdx = (val, startIdx, c) => {
|
|
||||||
let x = startIdx
|
|
||||||
let endIdx = data.length - 1
|
|
||||||
if(val < fy(startIdx))
|
|
||||||
return startIdx
|
|
||||||
if(val > fy(endIdx))
|
|
||||||
return endIdx
|
|
||||||
for(let i = 0; i < c; i++){
|
|
||||||
x = fx(val, startIdx, endIdx)
|
|
||||||
if(fy(x) < val)
|
|
||||||
startIdx = x
|
|
||||||
else
|
|
||||||
endIdx = x
|
|
||||||
if ((startIdx === endIdx)||(fy(startIdx) === fy(endIdx)))
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
let x0 = findIdx(begin, 0, 100)
|
|
||||||
let x1 = findIdx(end, x0, 100)
|
|
||||||
return { start: x0, end: x1, count: x1 - x0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const cutData = (data, beginDate, endDate) => {
|
|
||||||
if (data?.length > 0) {
|
|
||||||
let { start, end } = interpolationSearch(data, beginDate, endDate, 'date')
|
|
||||||
if (start > 0) start--
|
|
||||||
if (end + 1 < end.length) end++
|
|
||||||
return data.slice(start, end)
|
|
||||||
}
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
const chartGroups = makeChartGroups([])
|
|
||||||
|
|
||||||
const Archive = memo(() => {
|
|
||||||
const [dataSaub, setDataSaub] = useState([])
|
|
||||||
const [dateLimit, setDateLimit] = useState({ from: 0, to: new Date() })
|
|
||||||
const [showLoader, setShowLoader] = useState(false)
|
|
||||||
const [loaded, setLoaded] = useState(null)
|
|
||||||
|
|
||||||
const [well] = useWell()
|
|
||||||
const [search, setSearchParams] = useSearchParams()
|
|
||||||
|
|
||||||
const getInitialRange = useCallback(() => parseInt(search.get('range') ?? defaultPeriod) * 1000, [search])
|
|
||||||
|
|
||||||
const [scrollPercent, setScrollPercent] = useState(0.15)
|
|
||||||
const [chartInterval, setChartInterval] = useState(getInitialRange)
|
|
||||||
const getInitialDate = useCallback(() => new Date(search.get('start') ?? (Date.now() - chartInterval)), [search, chartInterval])
|
|
||||||
const [startDate, setStartDate] = useState(getInitialDate)
|
|
||||||
|
|
||||||
const onGraphWheel = useCallback((e) => {
|
|
||||||
if (loaded && dateLimit.from && dateLimit.to) {
|
|
||||||
setStartDate((prevStartDate) => {
|
|
||||||
const offset = e.deltaY / 100 * chartInterval * scrollPercent
|
|
||||||
const nextStartDate = +prevStartDate + offset
|
|
||||||
const firstPossibleDate = Math.max(loaded.start, dateLimit.from)
|
|
||||||
const lastPossibleDate = Math.min(dateLimit.to, (loaded.end ?? Date.now())) - chartInterval
|
|
||||||
return new Date(Math.max(firstPossibleDate, Math.min(nextStartDate, lastPossibleDate)))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, [loaded, dateLimit, chartInterval, scrollPercent])
|
|
||||||
|
|
||||||
const isDateDisabled = useCallback((date) => {
|
|
||||||
if (!date) return false
|
|
||||||
const dt = new Date(date).setHours(0, 0, 0, 0)
|
|
||||||
return dt < dateLimit.from || dt > +dateLimit.to - chartInterval
|
|
||||||
}, [dateLimit, chartInterval])
|
|
||||||
|
|
||||||
const isDateTimeDisabled = useCallback((date) => ({
|
|
||||||
disabledHours: () => range(24).filter(h => {
|
|
||||||
if (!date) return false
|
|
||||||
const dt = +new Date(date).setHours(h)
|
|
||||||
return dt < dateLimit.from || dt > +dateLimit.to - chartInterval
|
|
||||||
}),
|
|
||||||
disabledMinutes: () => range(60).filter(m => {
|
|
||||||
if (!date) return false
|
|
||||||
const dt = +new Date(date).setMinutes(m)
|
|
||||||
return dt < dateLimit.from || dt > +dateLimit.to - chartInterval
|
|
||||||
}),
|
|
||||||
disabledSeconds: () => range(60).filter(s => {
|
|
||||||
if (!date) return false
|
|
||||||
const dt = +new Date(date).setSeconds(s)
|
|
||||||
return dt < dateLimit.from || dt > +dateLimit.to - chartInterval
|
|
||||||
})
|
|
||||||
}), [dateLimit, chartInterval])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const params = {}
|
|
||||||
if (startDate)
|
|
||||||
params.start = startDate.toISOString()
|
|
||||||
if (chartInterval)
|
|
||||||
params.range = chartInterval / 1000
|
|
||||||
setSearchParams(params)
|
|
||||||
}, [startDate, chartInterval])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
invokeWebApiWrapperAsync(
|
|
||||||
async () => {
|
|
||||||
let dates = await TelemetryDataSaubService.getDataDatesRange(well.id)
|
|
||||||
dates = {
|
|
||||||
from: new Date(dates?.from ?? 0),
|
|
||||||
to: new Date(dates?.to ?? 0)
|
|
||||||
}
|
|
||||||
setDateLimit(dates)
|
|
||||||
},
|
|
||||||
setShowLoader,
|
|
||||||
`Не удалось загрузить диапозон телеметрии`,
|
|
||||||
{ actionName: 'Загрузка диапозона телеметрии', well }
|
|
||||||
)
|
|
||||||
}, [well])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setStartDate((prev) => new Date(Math.max(dateLimit.from, Math.min(+prev, +dateLimit.to - chartInterval))))
|
|
||||||
}, [chartInterval, dateLimit])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (showLoader) return
|
|
||||||
const { loadingStartDate, loadingInterval, newLoaded } = getLoadingInterval(loaded, startDate, chartInterval)
|
|
||||||
if (loadingInterval <= 0) return
|
|
||||||
invokeWebApiWrapperAsync(
|
|
||||||
async () => {
|
|
||||||
const data = await TelemetryDataSaubService.getData(well.id, loadingStartDate.toISOString(), loadingInterval, DATA_COUNT)
|
|
||||||
|
|
||||||
const loadedStartDate = new Date(Math.max(+newLoaded.start, +startDate - chartInterval * ADDITIVE_PAGES))
|
|
||||||
const loadedEndDate = new Date(Math.min(+newLoaded.end, +startDate + chartInterval * (ADDITIVE_PAGES + 1)))
|
|
||||||
setLoaded({ start: loadedStartDate, end: loadedEndDate })
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
data.forEach(elm => elm.date = new Date(elm.date))
|
|
||||||
setDataSaub((prevDataSaub) => {
|
|
||||||
const newData = [...prevDataSaub, ...normalizeData(data)]
|
|
||||||
newData.sort(makeDateSorter('date'))
|
|
||||||
return cutData(newData, loadedStartDate, loadedEndDate)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
setShowLoader,
|
|
||||||
`Не удалось загрузить данные c ${formatDate(startDate)} по ${formatDate(+startDate + chartInterval)}`,
|
|
||||||
{ actionName: 'Загрузка телеметрий в диапозоне', well }
|
|
||||||
)
|
|
||||||
}, [well, chartInterval, loaded, startDate])
|
|
||||||
|
|
||||||
const onRangeChange = useCallback((value) => {
|
|
||||||
setChartInterval(value * 1000)
|
|
||||||
setDataSaub([])
|
|
||||||
setLoaded(null)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const domain = useMemo(() => ({ min: startDate, max: new Date(+startDate + chartInterval)}), [startDate, chartInterval])
|
|
||||||
const chartData = useMemo(() => cutData(dataSaub, domain.min, domain.max), [dataSaub, domain])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<LoaderPortal show={showLoader} style={{ flexGrow: 1 }}>
|
|
||||||
<Flex style={{margin: '8px 8px 0'}}>
|
|
||||||
<div>
|
|
||||||
Начальная дата:
|
|
||||||
<DatePickerWrapper
|
|
||||||
value={startDate}
|
|
||||||
disabledDate={isDateDisabled}
|
|
||||||
disabledTime={isDateTimeDisabled}
|
|
||||||
onChange={(startDate) => setStartDate(new Date(startDate))}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div style={{ marginLeft: '1rem' }}>
|
|
||||||
Период:
|
|
||||||
<PeriodPicker value={chartInterval / 1000} onChange={onRangeChange} />
|
|
||||||
</div>
|
|
||||||
<div style={{ marginLeft: '1rem' }}>
|
|
||||||
Прокрутка:
|
|
||||||
<Select options={scrollOptions} value={scrollPercent} onChange={setScrollPercent} />
|
|
||||||
</div>
|
|
||||||
<CopyUrlButton style={{ marginLeft: '1rem' }} />
|
|
||||||
</Flex>
|
|
||||||
<D3MonitoringCharts
|
|
||||||
datasetGroups={chartGroups}
|
|
||||||
data={chartData}
|
|
||||||
yDomain={domain}
|
|
||||||
yAxis={yAxis}
|
|
||||||
yTicks={{
|
|
||||||
visible: true,
|
|
||||||
format: (d) => formatDate(d)
|
|
||||||
}}
|
|
||||||
plugins={{
|
|
||||||
menu: { enabled: false },
|
|
||||||
cursor: {
|
|
||||||
render: cursorRender,
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
style={{ flexGrow: 1 }}
|
|
||||||
height={'76vh'}
|
|
||||||
onWheel={onGraphWheel}
|
|
||||||
/>
|
|
||||||
</LoaderPortal>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export default withPermissions(Archive, ['TelemetryDataSaub.get'])
|
|
@ -28,7 +28,6 @@ const WellSectionsStat = lazy(() => import('./WellOperations/WellSectionsStat'))
|
|||||||
const WellOperationsEditorFact = lazy(() => import('./WellOperations/OperationEditor/Fact'))
|
const WellOperationsEditorFact = lazy(() => import('./WellOperations/OperationEditor/Fact'))
|
||||||
const WellOperationsEditorPlan = lazy(() => import('./WellOperations/OperationEditor/Plan'))
|
const WellOperationsEditorPlan = lazy(() => import('./WellOperations/OperationEditor/Plan'))
|
||||||
|
|
||||||
const Archive = lazy(() => import('./Telemetry/Archive'))
|
|
||||||
const Messages = lazy(() => import('./Telemetry/Messages'))
|
const Messages = lazy(() => import('./Telemetry/Messages'))
|
||||||
const Operations = lazy(() => import('./Telemetry/Operations'))
|
const Operations = lazy(() => import('./Telemetry/Operations'))
|
||||||
const DashboardNNB = lazy(() => import('./Telemetry/DashboardNNB'))
|
const DashboardNNB = lazy(() => import('./Telemetry/DashboardNNB'))
|
||||||
@ -99,7 +98,6 @@ const Well = memo(() => {
|
|||||||
|
|
||||||
<Route path={'telemetry'} element={<TelemetryView />} />
|
<Route path={'telemetry'} element={<TelemetryView />} />
|
||||||
<Route path={'messages'} element={<Messages />} />
|
<Route path={'messages'} element={<Messages />} />
|
||||||
<Route path={'archive'} element={<Archive />} />
|
|
||||||
<Route path={'dashboard_nnb/*'} element={<DashboardNNB />} />
|
<Route path={'dashboard_nnb/*'} element={<DashboardNNB />} />
|
||||||
<Route path={'operations'} element={<Operations />} />
|
<Route path={'operations'} element={<Operations />} />
|
||||||
<Route path={'operation_time'} element={<OperationTime />} />
|
<Route path={'operation_time'} element={<OperationTime />} />
|
||||||
|
Loading…
Reference in New Issue
Block a user