Выделены методы генерации датасетов для графика мониторинга

This commit is contained in:
Александр Сироткин 2022-10-31 05:12:33 +05:00
parent 685191484a
commit 17ccecb2dd
3 changed files with 259 additions and 270 deletions

View File

@ -14,8 +14,9 @@ import { PeriodPicker, defaultPeriod } from '@components/selectors/PeriodPicker'
import { formatDate, range, withPermissions } from '@utils' import { formatDate, range, withPermissions } from '@utils'
import { TelemetryDataSaubService } from '@api' import { TelemetryDataSaubService } from '@api'
import { makeChartGroups, normalizeData, yAxis } from '../TelemetryView' import { normalizeData } from '../TelemetryView'
import cursorRender from '../TelemetryView/cursorRender' import cursorRender from '../TelemetryView/cursorRender'
import { makeChartGroups, yAxis } from '../TelemetryView/dataset'
const DATA_COUNT = 2048 // Колличество точек на подгрузку графика const DATA_COUNT = 2048 // Колличество точек на подгрузку графика
const ADDITIVE_PAGES = 2 // Дополнительные данные для графиков const ADDITIVE_PAGES = 2 // Дополнительные данные для графиков
@ -108,10 +109,10 @@ const Archive = memo(() => {
const [dateLimit, setDateLimit] = useState({ from: 0, to: new Date() }) const [dateLimit, setDateLimit] = useState({ from: 0, to: new Date() })
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const [loaded, setLoaded] = useState(null) const [loaded, setLoaded] = useState(null)
const [well] = useWell() const [well] = useWell()
const [search, setSearchParams] = useSearchParams() const [search, setSearchParams] = useSearchParams()
const getInitialRange = useCallback(() => parseInt(search.get('range') ?? defaultPeriod) * 1000, [search]) const getInitialRange = useCallback(() => parseInt(search.get('range') ?? defaultPeriod) * 1000, [search])
const [scrollPercent, setScrollPercent] = useState(0.15) const [scrollPercent, setScrollPercent] = useState(0.15)
@ -181,7 +182,7 @@ const Archive = memo(() => {
}, [well]) }, [well])
useEffect(() => { useEffect(() => {
setStartDate((prev) => new Date(Math.max(dateLimit.from, Math.min(+prev, +dateLimit.to - chartInterval)))) setStartDate((prev) => new Date(Math.max(dateLimit.from, Math.min(+prev, +dateLimit.to - chartInterval))))
}, [chartInterval, dateLimit]) }, [chartInterval, dateLimit])
useEffect(() => { useEffect(() => {
@ -191,11 +192,11 @@ const Archive = memo(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const data = await TelemetryDataSaubService.getData(well.id, loadingStartDate.toISOString(), loadingInterval, DATA_COUNT) 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 loadedStartDate = new Date(Math.max(+newLoaded.start, +startDate - chartInterval * ADDITIVE_PAGES))
const loadedEndDate = new Date(Math.min(+newLoaded.end, +startDate + chartInterval * (ADDITIVE_PAGES + 1))) const loadedEndDate = new Date(Math.min(+newLoaded.end, +startDate + chartInterval * (ADDITIVE_PAGES + 1)))
setLoaded({ start: loadedStartDate, end: loadedEndDate }) setLoaded({ start: loadedStartDate, end: loadedEndDate })
if (data) { if (data) {
data.forEach(elm => elm.date = new Date(elm.date)) data.forEach(elm => elm.date = new Date(elm.date))
setDataSaub((prevDataSaub) => { setDataSaub((prevDataSaub) => {
@ -204,7 +205,7 @@ const Archive = memo(() => {
return cutData(newData, loadedStartDate, loadedEndDate) return cutData(newData, loadedStartDate, loadedEndDate)
}) })
} }
}, },
setShowLoader, setShowLoader,
`Не удалось загрузить данные c ${formatDate(startDate)} по ${formatDate(+startDate + chartInterval)}`, `Не удалось загрузить данные c ${formatDate(startDate)} по ${formatDate(+startDate + chartInterval)}`,

View File

@ -0,0 +1,77 @@
import { formatDate } from "@utils"
export const yAxis = {
type: 'time',
accessor: (d) => new Date(d.date),
format: (d) => formatDate(d, undefined, 'DD.MM.YYYY HH:mm:ss'),
}
const dash = [7, 3]
const makeDataset = (label, shortLabel, color, key, unit, other) => ({
key,
label,
shortLabel,
color,
xAxis: {
type: 'linear',
accessor: key,
unit,
},
type: 'line',
...other,
})
export const makeChartGroups = (flowChart) => {
const makeAreaOptions = (accessor) => ({
type: 'rect_area',
data: flowChart,
hideLabel: true,
yAxis: {
type: 'linear',
accessor: 'depth',
},
minXAccessor: 'depthStart',
maxXAccessor: 'depthEnd',
minYAccessor: accessor + 'Min',
maxYAccessor: accessor + 'Max',
linkedTo: accessor,
})
return [
[
makeDataset('Высота блока', 'Высота ТБ','#303030', 'blockPosition', 'м'),
makeDataset('Глубина скважины', 'Глубина скв','#7789A1', 'wellDepth', 'м', { dash }),
makeDataset('Расход', 'Расход','#007070', 'flow', 'л/с'),
makeDataset('Положение долота', 'Долото','#B39D59', 'bitPosition', 'м'),
makeDataset('Расход', 'Расход','#007070', 'flowMM', 'л/с', makeAreaOptions('flow')),
], [
makeDataset('Скорость блока', 'Скорость ТБ','#59B359', 'blockSpeed', 'м/ч'),
makeDataset('Скорость заданная', 'Скор зад-я','#95B359', 'blockSpeedSp', 'м/ч', { dash }),
], [
makeDataset('Давление', 'Давл','#FF0000', 'pressure', 'атм'),
makeDataset('Давление заданное', 'Давл зад-е','#CC0000', 'pressureSp', 'атм'),
makeDataset('Давление ХХ', 'Давл ХХ','#CC4429', 'pressureIdle', 'атм', { dash }),
makeDataset('Перепад давления МАКС', 'ΔР макс','#B34A36', 'pressureDeltaLimitMax', 'атм', { dash }),
makeDataset('Давление', 'Давл','#FF0000', 'pressureMM', 'атм', makeAreaOptions('pressure')),
], [
makeDataset('Осевая нагрузка', 'Нагр','#0000CC', 'axialLoad', 'т'),
makeDataset('Осевая нагрузка заданная', 'Нагр зад-я','#3D6DCC', 'axialLoadSp', 'т', { dash }),
makeDataset('Осевая нагрузка МАКС', 'Нагр макс','#3D3DCC', 'axialLoadLimitMax', 'т', { dash }),
makeDataset('Осевая нагрузка', 'Нагр','#0000CC', 'axialLoadMM', 'т', makeAreaOptions('axialLoad')),
], [
makeDataset('Вес на крюке', 'Вес на крюке','#00B3B3', 'hookWeight', 'т'),
makeDataset('Вес инструмента ХХ', 'Вес инст ХХ','#29CCB1', 'hookWeightIdle', 'т', { dash }),
makeDataset('Вес инструмента МИН', 'Вес инст мин','#47A1B3', 'hookWeightLimitMin', 'т', { dash }),
makeDataset('Вес инструмента МАКС', 'Вес инст мах','#2D7280', 'hookWeightLimitMax', 'т', { dash }),
makeDataset('Обороты ротора', 'Об ротора','#11B32F', 'rotorSpeed', 'об/мин'),
makeDataset('Обороты ротора', 'Об ротора','#11B32F', 'rotorSpeedMM', 'об/мин', makeAreaOptions('rotorSpeed')),
], [
makeDataset('Момент на роторе', 'Момент','#990099', 'rotorTorque', 'кН·м'),
makeDataset('План. Момент на роторе', 'Момент зад-й','#9629CC', 'rotorTorqueSp', 'кН·м', { dash }),
makeDataset('Момент на роторе ХХ', 'Момент ХХ','#CC2996', 'rotorTorqueIdle', 'кН·м', { dash }),
makeDataset('Момент МАКС.', 'Момент макс','#FF00FF', 'rotorTorqueLimitMax', 'кН·м', { dash }),
makeDataset('Момент на роторе', 'Момент','#990099', 'rotorTorqueMM', 'кН·м', makeAreaOptions('rotorTorque')),
]
]
}

View File

@ -12,12 +12,13 @@ import { PeriodPicker, defaultPeriod } from '@components/selectors/PeriodPicker'
import { formatDate, hasPermission, withPermissions } from '@utils' import { formatDate, hasPermission, withPermissions } from '@utils'
import { Subscribe } from '@services/signalr' import { Subscribe } from '@services/signalr'
import { import {
DrillFlowChartService, DrillFlowChartService,
OperationStatService, OperationStatService,
TelemetryDataSaubService, TelemetryDataSaubService,
TelemetryDataSpinService TelemetryDataSpinService
} from '@api' } from '@api'
import { makeChartGroups, yAxis } from './dataset'
import ActiveMessagesOnline from './ActiveMessagesOnline' import ActiveMessagesOnline from './ActiveMessagesOnline'
import WirelineRunOut from './WirelineRunOut' import WirelineRunOut from './WirelineRunOut'
import { CustomColumn } from './CustomColumn' import { CustomColumn } from './CustomColumn'
@ -36,286 +37,196 @@ import '@styles/message.less'
const { Option } = Select const { Option } = Select
export const yAxis = { const getLast = (data) => Array.isArray(data) ? data.at(-1) : data
type: 'time',
accessor: (d) => new Date(d.date),
format: (d) => formatDate(d, undefined, 'DD.MM.YYYY HH:mm:ss'),
}
const dash = [7, 3]
const makeDataset = (label, shortLabel, color, key, unit, other) => ({
key,
label,
shortLabel,
color,
xAxis: {
type: 'linear',
accessor: key,
unit,
},
type: 'line',
...other,
})
export const makeChartGroups = (flowChart) => {
const makeAreaOptions = (accessor) => ({
type: 'rect_area',
data: flowChart,
hideLabel: true,
yAxis: {
type: 'linear',
accessor: 'depth',
},
minXAccessor: 'depthStart',
maxXAccessor: 'depthEnd',
minYAccessor: accessor + 'Min',
maxYAccessor: accessor + 'Max',
linkedTo: accessor,
})
return [
[
makeDataset('Высота блока', 'Высота ТБ','#303030', 'blockPosition', 'м'),
makeDataset('Глубина скважины', 'Глубина скв','#7789A1', 'wellDepth', 'м', { dash }),
makeDataset('Расход', 'Расход','#007070', 'flow', 'л/с'),
makeDataset('Положение долота', 'Долото','#B39D59', 'bitPosition', 'м'),
makeDataset('Расход', 'Расход','#007070', 'flowMM', 'л/с', makeAreaOptions('flow')),
], [
makeDataset('Скорость блока', 'Скорость ТБ','#59B359', 'blockSpeed', 'м/ч'),
makeDataset('Скорость заданная', 'Скор зад-я','#95B359', 'blockSpeedSp', 'м/ч', { dash }),
], [
makeDataset('Давление', 'Давл','#FF0000', 'pressure', 'атм'),
makeDataset('Давление заданное', 'Давл зад-е','#CC0000', 'pressureSp', 'атм'),
makeDataset('Давление ХХ', 'Давл ХХ','#CC4429', 'pressureIdle', 'атм', { dash }),
makeDataset('Перепад давления МАКС', 'ΔР макс','#B34A36', 'pressureDeltaLimitMax', 'атм', { dash }),
makeDataset('Давление', 'Давл','#FF0000', 'pressureMM', 'атм', makeAreaOptions('pressure')),
], [
makeDataset('Осевая нагрузка', 'Нагр','#0000CC', 'axialLoad', 'т'),
makeDataset('Осевая нагрузка заданная', 'Нагр зад-я','#3D6DCC', 'axialLoadSp', 'т', { dash }),
makeDataset('Осевая нагрузка МАКС', 'Нагр макс','#3D3DCC', 'axialLoadLimitMax', 'т', { dash }),
makeDataset('Осевая нагрузка', 'Нагр','#0000CC', 'axialLoadMM', 'т', makeAreaOptions('axialLoad')),
], [
makeDataset('Вес на крюке', 'Вес на крюке','#00B3B3', 'hookWeight', 'т'),
makeDataset('Вес инструмента ХХ', 'Вес инст ХХ','#29CCB1', 'hookWeightIdle', 'т', { dash }),
makeDataset('Вес инструмента МИН', 'Вес инст мин','#47A1B3', 'hookWeightLimitMin', 'т', { dash }),
makeDataset('Вес инструмента МАКС', 'Вес инст мах','#2D7280', 'hookWeightLimitMax', 'т', { dash }),
makeDataset('Обороты ротора', 'Об ротора','#11B32F', 'rotorSpeed', 'об/мин'),
makeDataset('Обороты ротора', 'Об ротора','#11B32F', 'rotorSpeedMM', 'об/мин', makeAreaOptions('rotorSpeed')),
], [
makeDataset('Момент на роторе', 'Момент','#990099', 'rotorTorque', 'кН·м'),
makeDataset('План. Момент на роторе', 'Момент зад-й','#9629CC', 'rotorTorqueSp', 'кН·м', { dash }),
makeDataset('Момент на роторе ХХ', 'Момент ХХ','#CC2996', 'rotorTorqueIdle', 'кН·м', { dash }),
makeDataset('Момент МАКС.', 'Момент макс','#FF00FF', 'rotorTorqueLimitMax', 'кН·м', { dash }),
makeDataset('Момент на роторе', 'Момент','#990099', 'rotorTorqueMM', 'кН·м', makeAreaOptions('rotorTorque')),
]
]
}
const getLast = (data) =>
Array.isArray(data) ? data.at(-1) : data
const isMseEnabled = (dataSaub) => {
const lastData = getLast(dataSaub)
return (lastData?.mseState && 2) > 0
}
const isTorqueStabEnabled = (dataSpin) => {
const lastData = getLast(dataSpin)
return lastData?.state === 7
}
const isMseEnabled = (dataSaub) => (getLast(dataSaub)?.mseState && 2) > 0
const isTorqueStabEnabled = (dataSpin) => getLast(dataSpin)?.state === 7
const isSpinEnabled = (dataSpin) => { const isSpinEnabled = (dataSpin) => {
const lastData = getLast(dataSpin) const lastData = getLast(dataSpin)
return lastData?.state > 0 && lastData?.state !== 6 return lastData?.state > 0 && lastData?.state !== 6
} }
export const normalizeData = (data) => data?.map(item => ({ export const normalizeData = (data) => data?.map(item => ({
...item, ...item,
rotorSpeed: item.rotorSpeed < 1 ? 0 : item.rotorSpeed, rotorSpeed: item.rotorSpeed < 1 ? 0 : item.rotorSpeed,
rotorTorque: item.rotorTorque < 1 ? 0 : item.rotorTorque, rotorTorque: item.rotorTorque < 1 ? 0 : item.rotorTorque,
blockSpeed: Math.abs(item.blockSpeed) blockSpeed: Math.abs(item.blockSpeed)
})) ?? [] })) ?? []
const dateSorter = makeDateSorter('date') const dateSorter = makeDateSorter('date')
const makeSubjectSubsription = (subject$, handler) => {
const subscribtion = subject$.pipe(
buffer(subject$.pipe(throttleTime(700)))
).subscribe((data) => handler(data.flat().filter(Boolean)))
return () => subscribtion.unsubscribe()
}
const TelemetryView = memo(() => { const TelemetryView = memo(() => {
const [dataSaub, setDataSaub] = useState([]) const [dataSaub, setDataSaub] = useState([])
const [dataSpin, setDataSpin] = useState([]) const [dataSpin, setDataSpin] = useState([])
const [chartInterval, setChartInterval] = useState(defaultPeriod) const [chartInterval, setChartInterval] = useState(defaultPeriod)
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const [flowChartData, setFlowChartData] = useState([]) const [flowChartData, setFlowChartData] = useState([])
const [rop, setRop] = useState(null) const [rop, setRop] = useState(null)
const [domain, setDomain] = useState({}) const [domain, setDomain] = useState({})
const [chartMethods, setChartMethods] = useState() const [chartMethods, setChartMethods] = useState()
const [well, updateWell] = useWell() const [well, updateWell] = useWell()
const saubSubject$ = useMemo(() => new BehaviorSubject(), []) const saubSubject$ = useMemo(() => new BehaviorSubject(), [])
const spinSubject$ = useMemo(() => new BehaviorSubject(), []) const spinSubject$ = useMemo(() => new BehaviorSubject(), [])
const handleDataSaub = useCallback((data) => { const handleDataSaub = useCallback((data) => {
if (data) { if (!data) return
const dataSaub = normalizeData(data)
setDataSaub((prev) => {
const out = [...prev, ...dataSaub]
out.sort(dateSorter)
return out
})
}
}, [])
const handleDataSpin = useCallback((data) => data && setDataSpin((prev) => [...prev, ...data]), []) const dataSaub = normalizeData(data)
setDataSaub((prev) => {
const out = [...prev, ...dataSaub]
out.sort(dateSorter)
return out
})
}, [])
useEffect(() => { const handleDataSpin = useCallback((data) => data && setDataSpin((prev) => [...prev, ...data]), [])
const subscribtion = saubSubject$.pipe(
buffer(saubSubject$.pipe(throttleTime(700)))
).subscribe((data) => handleDataSaub(data.flat().filter(Boolean)))
return () => subscribtion.unsubscribe() const onStatusChanged = useCallback((value) => updateWell({ idState: value }), [well])
}, [saubSubject$])
useEffect(() => { const filteredData = useMemo(() => {
const subscribtion = spinSubject$.pipe( let i, j
buffer(spinSubject$.pipe(throttleTime(700))) for (i = 0; i < dataSaub.length; i++) {
).subscribe((data) => handleDataSpin(data.flat().filter(Boolean))) const date = +new Date(dataSaub[i]?.date)
if (date >= +domain.min) break
}
return () => subscribtion.unsubscribe() for (j = dataSaub.length - 1; j >= i; j--) {
}, [spinSubject$]) const date = +new Date(dataSaub[i]?.date)
if (date <= +domain.max) break
}
useEffect(() => { if (i >= j) return []
invokeWebApiWrapperAsync( return dataSaub.slice(i, j)
async () => { }, [dataSaub, domain])
const flowChart = await DrillFlowChartService.getByIdWell(well.id)
const dataSaub = await TelemetryDataSaubService.getData(well.id, null, chartInterval) const chartGroups = useMemo(() => makeChartGroups(flowChartData), [flowChartData])
const dataSpin = await TelemetryDataSpinService.getData(well.id, null, chartInterval)
setFlowChartData(flowChart ?? []) useEffect(() => makeSubjectSubsription(saubSubject$, handleDataSaub), [saubSubject$, handleDataSaub])
handleDataSaub(dataSaub) useEffect(() => makeSubjectSubsription(spinSubject$, handleDataSpin), [spinSubject$, handleDataSpin])
handleDataSpin(dataSpin)
}, useEffect(() => {
null, invokeWebApiWrapperAsync(
`Не удалось получить данные`, async () => {
{ actionName: 'Получение данных по скважине', well } const flowChart = await DrillFlowChartService.getByIdWell(well.id)
const dataSaub = await TelemetryDataSaubService.getData(well.id, null, chartInterval)
const dataSpin = await TelemetryDataSpinService.getData(well.id, null, chartInterval)
setFlowChartData(flowChart ?? [])
handleDataSaub(dataSaub)
handleDataSpin(dataSpin)
},
null,
`Не удалось получить данные`,
{ actionName: 'Получение данных по скважине', well }
)
}, [well, chartInterval, handleDataSpin, handleDataSaub])
useEffect(() => {
const unsubscribe = Subscribe(
'hubs/telemetry', `well_${well.id}`,
{ methodName: 'ReceiveDataSaub', handler: (data) => saubSubject$.next(data) },
{ methodName: 'ReceiveDataSpin', handler: (data) => spinSubject$.next(data) }
)
return () => unsubscribe()
}, [well.id, saubSubject$, spinSubject$])
useEffect(() => {
invokeWebApiWrapperAsync(
async () => {
const rop = await OperationStatService.getClusterRopStatByIdWell(well.id)
setRop(rop)
},
setShowLoader,
`Не удалось загрузить данные`,
{ actionName: 'Получение данных по скважине', well }
)
}, [well])
useEffect(() => {
if (dataSaub.length <= 0) return
const last = new Date(dataSaub.at(-1).date)
setDomain({
min: new Date(+last - chartInterval * 1000),
max: last
})
}, [dataSaub, chartInterval])
return (
<LoaderPortal show={showLoader}>
<Grid style={{ gridTemplateColumns: 'auto repeat(6, 1fr)' }}>
<GridItem col={'1'} row={'1'} colSpan={'8'} style={{ marginBottom: '0.5rem' }}>
<div className={'page-top'}>
<ModeDisplay data={dataSaub} />
<div>
Интервал:&nbsp;
<PeriodPicker onChange={setChartInterval} />
</div>
<Button onClick={() => chartMethods?.setSettingsVisible(true)}>Настроить графики</Button>
<div>
Статус:&nbsp;
<Select value={well.idState ?? 0} onChange={onStatusChanged} disabled={!hasPermission('Well.edit')}>
<Option value={0} disabled hidden>Неизвестно</Option>
<Option value={1}>В работе</Option>
<Option value={2}>Завершено</Option>
</Select>
</div>
<Setpoints />
<span style={{ flexGrow: 20 }}>&nbsp;</span>
<WirelineRunOut />
<div className={'icons'}>
<img src={isTorqueStabEnabled(dataSpin) ? MomentStabPicEnabled : MomentStabPicDisabled} alt={'TorqueMaster'} />
<img src={isSpinEnabled(dataSpin) ? SpinPicEnabled : SpinPicDisabled} alt={'SpinMaster'} />
<h2 style={{ marginBottom: 0, fontWeight: 'bold', color: isMseEnabled(dataSaub) ? 'green' : 'lightgrey' }}>MSE</h2>
</div>
<UserOfWell data={dataSaub} />
</div>
</GridItem>
<GridItem col={'1'} row={'2'} rowSpan={'3'} style={{ minWidth: '260px', width: '0.142fr' }}>
<CustomColumn data={dataSaub} />
</GridItem>
<GridItem col={2} row={2} colSpan={8} rowSpan={2}>
<D3MonitoringCharts
methods={setChartMethods}
chartName={'monitoring'}
datasetGroups={chartGroups}
data={filteredData}
yDomain={domain}
yAxis={yAxis}
yTicks={{
visible: true,
format: (d) => formatDate(d, 'YYYY-MM-DD')
}}
plugins={{
menu: { enabled: false },
cursor: {
render: cursorRender,
},
}}
height={'70vh'}
/>
</GridItem>
<GridItem col={'2'} row={'3'} colSpan={'7'}>
<ActiveMessagesOnline well={well} />
</GridItem>
</Grid>
</LoaderPortal>
) )
}, [well, chartInterval, handleDataSpin, handleDataSaub])
useEffect(() => {
const unsubscribe = Subscribe(
'hubs/telemetry', `well_${well.id}`,
{ methodName: 'ReceiveDataSaub', handler: (data) => saubSubject$.next(data) },
{ methodName: 'ReceiveDataSpin', handler: (data) => spinSubject$.next(data) }
)
return () => unsubscribe()
}, [well.id, saubSubject$, spinSubject$])
useEffect(() => {
invokeWebApiWrapperAsync(
async () => {
const rop = await OperationStatService.getClusterRopStatByIdWell(well.id)
setRop(rop)
},
setShowLoader,
`Не удалось загрузить данные`,
{ actionName: 'Получение данных по скважине', well }
)
}, [well])
const onStatusChanged = useCallback((value) => updateWell({ idState: value }), [well])
useEffect(() => {
if (dataSaub.length <= 0) return
const last = new Date(dataSaub.at(-1).date)
setDomain({
min: new Date(+last - chartInterval * 1000),
max: last
})
}, [dataSaub, chartInterval])
const filteredData = useMemo(() => {
let i, j
for (i = 0; i < dataSaub.length; i++) {
const date = +new Date(dataSaub[i]?.date)
if (date >= +domain.min) break
}
for (j = dataSaub.length - 1; j >= i; j--) {
const date = +new Date(dataSaub[i]?.date)
if (date <= +domain.max) break
}
if (i >= j) return []
return dataSaub.slice(i, j)
}, [dataSaub, domain])
const chartGroups = useMemo(() => makeChartGroups(flowChartData), [flowChartData])
return (
<LoaderPortal show={showLoader}>
<Grid style={{ gridTemplateColumns: 'auto repeat(6, 1fr)' }}>
<GridItem col={'1'} row={'1'} colSpan={'8'} style={{ marginBottom: '0.5rem' }}>
<div className={'page-top'}>
<ModeDisplay data={dataSaub} />
<div>
Интервал:&nbsp;
<PeriodPicker onChange={setChartInterval} />
</div>
<Button onClick={() => chartMethods?.setSettingsVisible(true)}>Настроить графики</Button>
<div>
Статус:&nbsp;
<Select value={well.idState ?? 0} onChange={onStatusChanged} disabled={!hasPermission('Well.edit')}>
<Option value={0} disabled hidden>Неизвестно</Option>
<Option value={1}>В работе</Option>
<Option value={2}>Завершено</Option>
</Select>
</div>
<Setpoints />
<span style={{ flexGrow: 20 }}>&nbsp;</span>
<WirelineRunOut />
<div className={'icons'}>
<img src={isTorqueStabEnabled(dataSpin) ? MomentStabPicEnabled : MomentStabPicDisabled} alt={'TorqueMaster'} />
<img src={isSpinEnabled(dataSpin) ? SpinPicEnabled : SpinPicDisabled} alt={'SpinMaster'} />
<h2 style={{ marginBottom: 0, fontWeight: 'bold', color: isMseEnabled(dataSaub) ? 'green' : 'lightgrey' }}>MSE</h2>
</div>
<UserOfWell data={dataSaub} />
</div>
</GridItem>
<GridItem col={'1'} row={'2'} rowSpan={'3'} style={{ minWidth: '260px', width: '0.142fr' }}>
<CustomColumn data={dataSaub} />
</GridItem>
<GridItem col={2} row={2} colSpan={8} rowSpan={2}>
<D3MonitoringCharts
methods={setChartMethods}
chartName={'monitoring'}
datasetGroups={chartGroups}
data={filteredData}
yDomain={domain}
yAxis={yAxis}
yTicks={{
visible: true,
format: (d) => formatDate(d, 'YYYY-MM-DD')
}}
plugins={{
menu: { enabled: false },
cursor: {
render: cursorRender,
},
}}
height={'70vh'}
/>
</GridItem>
<GridItem col={'2'} row={'3'} colSpan={'7'}>
<ActiveMessagesOnline well={well} />
</GridItem>
</Grid>
</LoaderPortal>
)
}) })
export default withPermissions(TelemetryView, [ export default withPermissions(TelemetryView, [
'DrillFlowChart.get', 'DrillFlowChart.get',
'OperationStat.get', 'OperationStat.get',
'TelemetryDataSaub.get', 'TelemetryDataSaub.get',
'TelemetryDataSpin.get', 'TelemetryDataSpin.get',
'Well.get', 'Well.get',
]) ])