forked from ddrilling/asb_cloud_front
Удалён лиший экземпляр архива
This commit is contained in:
parent
76d7ac9949
commit
8107a4a3a5
@ -1,31 +0,0 @@
|
||||
import { memo, useMemo } from 'react'
|
||||
|
||||
import { Grid, GridItem } from '@components/Grid'
|
||||
import { Column } from '@components/charts/Column'
|
||||
|
||||
export const ArchiveColumn = memo(({ lineGroup, data, interval, style, headerHeight, yStart }) => {
|
||||
const lgws = useMemo(() => lineGroup.filter(cfg => !cfg.isShape), [lineGroup])
|
||||
const pv = useMemo(() => lgws.filter(line => line.showLabels).map(line => ({
|
||||
color: line.color,
|
||||
label: line.label
|
||||
})), [lgws])
|
||||
|
||||
return (
|
||||
<div style={style}>
|
||||
<Grid style={{ height: headerHeight, margin: 0 }}>
|
||||
{pv?.map((v, idx) => (
|
||||
<GridItem className={'display_chart_label'} key={idx} row={idx} col={1} style={{ color: v.color, padding: '0 8px' }}>{v.label}</GridItem>
|
||||
))}
|
||||
</Grid>
|
||||
<Column
|
||||
data={data}
|
||||
lineGroup={lgws}
|
||||
interval={interval}
|
||||
yDisplay={false}
|
||||
yStart={yStart}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
export default ArchiveColumn
|
@ -1,66 +0,0 @@
|
||||
import { memo, useMemo } from 'react'
|
||||
|
||||
import { Grid, GridItem } from '@components/Grid'
|
||||
|
||||
import { paramsGroups } from '@pages/TelemetryView'
|
||||
import { ArchiveColumn } from './ArchiveColumn'
|
||||
|
||||
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, 5)
|
||||
let x1 = findIdx(end, x0, 3)
|
||||
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
|
||||
}
|
||||
|
||||
export const ArchiveDisplay = memo(({data, startDate, interval, onWheel}) => {
|
||||
const endDate = useMemo(() => new Date(+startDate + interval), [startDate, interval])
|
||||
const chartData = useMemo(() => cutData(data, startDate, endDate), [data, startDate, endDate])
|
||||
|
||||
return (
|
||||
<Grid onWheel={onWheel}>
|
||||
{paramsGroups.map((group, index) => (
|
||||
<GridItem col={index + 1} row={'1'} className={'border_small'} key={`${group.label}${index}`} style={{ padding: 0 }}>
|
||||
<ArchiveColumn
|
||||
style={{ width: '15vw' }}
|
||||
data={chartData}
|
||||
lineGroup={group}
|
||||
interval={interval}
|
||||
headerHeight={'50px'}
|
||||
yStart={startDate}
|
||||
/>
|
||||
</GridItem>
|
||||
))}
|
||||
</Grid>
|
||||
)
|
||||
})
|
||||
|
||||
export default ArchiveDisplay
|
@ -1,185 +0,0 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { useState, useEffect, memo, useCallback } from 'react'
|
||||
|
||||
import { Flex } from '@components/Grid'
|
||||
import LoaderPortal from '@components/LoaderPortal'
|
||||
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||
import { DatePickerWrapper, makeDateSorter } from '@components/Table'
|
||||
import { PeriodPicker, defaultPeriod } from '@components/selectors/PeriodPicker'
|
||||
import { TelemetryDataSaubService } from '@api'
|
||||
|
||||
import { normalizeData } from '@pages/TelemetryView'
|
||||
import { ArchiveDisplay, cutData } from './ArchiveDisplay'
|
||||
|
||||
const DATA_COUNT = 2048 // Колличество точек на подгрузку графика
|
||||
const ADDITIVE_PAGES = 2 // Дополнительные данные для графиков
|
||||
const LOADING_TRIGGER = 0.5
|
||||
const WHEEL_SENSITIVITY = 1 / 530
|
||||
|
||||
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 range = (start, end) => {
|
||||
const result = []
|
||||
for (let i = start; i < end; i++)
|
||||
result.push(i)
|
||||
return result
|
||||
}
|
||||
|
||||
export const Archive = memo(({ idWell }) => {
|
||||
const [dataSaub, setDataSaub] = useState([])
|
||||
const [dateLimit, setDateLimit] = useState({ from: 0, to: new Date() })
|
||||
const [chartInterval, setChartInterval] = useState(parseInt(defaultPeriod) * 1000)
|
||||
const [startDate, setStartDate] = useState(new Date(Date.now() - chartInterval))
|
||||
const [showLoader, setShowLoader] = useState(false)
|
||||
const [loaded, setLoaded] = useState(null)
|
||||
|
||||
const onGraphWheel = useCallback((e) => {
|
||||
if (loaded && dateLimit.from && dateLimit.to) {
|
||||
setStartDate((prevStartDate) => {
|
||||
const offset = e.deltaY * chartInterval * WHEEL_SENSITIVITY
|
||||
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])
|
||||
|
||||
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])
|
||||
|
||||
const isDateTimeDisabled = useCallback((date) => ({
|
||||
disabledHours: () => range(0, 24).filter(h => {
|
||||
if (!date) return false
|
||||
const dt = +new Date(date).setHours(h)
|
||||
return dt < dateLimit.from || dt > +dateLimit.to - chartInterval
|
||||
}),
|
||||
disabledMinutes: () => range(0, 60).filter(m => {
|
||||
if (!date) return false
|
||||
const dt = +new Date(date).setMinutes(m)
|
||||
return dt < dateLimit.from || dt > +dateLimit.to - chartInterval
|
||||
}),
|
||||
disabledSeconds: () => range(0, 60).filter(s => {
|
||||
if (!date) return false
|
||||
const dt = +new Date(date).setSeconds(s)
|
||||
return dt < dateLimit.from || dt > +dateLimit.to - chartInterval
|
||||
})
|
||||
}), [dateLimit])
|
||||
|
||||
useEffect(() => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
let dates = await TelemetryDataSaubService.getDataDatesRange(idWell)
|
||||
dates = {
|
||||
from: new Date(dates?.from ?? 0),
|
||||
to: new Date(dates?.to ?? 0)
|
||||
}
|
||||
setDateLimit(dates)
|
||||
setStartDate(new Date(Math.max(dates.from, +dates.to - chartInterval)))
|
||||
},
|
||||
setShowLoader,
|
||||
`Не удалось загрузить диапозон телеметрии для скважины "${idWell}"`,
|
||||
'Загрузка диапозона телеметрии'
|
||||
), [])
|
||||
|
||||
useEffect(() => {
|
||||
setStartDate((startDate) => new Date(Math.min(Date.now() - chartInterval, startDate)))
|
||||
setDataSaub([])
|
||||
}, [chartInterval])
|
||||
|
||||
useEffect(() => {
|
||||
if (showLoader) return
|
||||
const { loadingStartDate, loadingInterval, newLoaded } = getLoadingInterval(loaded, startDate, chartInterval)
|
||||
if (loadingInterval <= 0) return
|
||||
invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
const data = await TelemetryDataSaubService.getData(idWell, 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,
|
||||
`Не удалось загрузить данные по скважине "${idWell}" c ${startDate.toISOString()} по ${new Date(+startDate + chartInterval).toISOString()}`,
|
||||
'Загрузка телеметрий в диапозоне'
|
||||
)
|
||||
}, [idWell, chartInterval, loaded, startDate])
|
||||
|
||||
return (
|
||||
<>
|
||||
<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 onChange={(val) => setChartInterval(val * 1000)} />
|
||||
</div>
|
||||
</Flex>
|
||||
<LoaderPortal show={showLoader}>
|
||||
<ArchiveDisplay
|
||||
data={dataSaub}
|
||||
startDate={startDate}
|
||||
interval={chartInterval}
|
||||
onWheel={onGraphWheel}
|
||||
/>
|
||||
</LoaderPortal>
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
export default Archive
|
Loading…
Reference in New Issue
Block a user