asb_cloud_front/src/pages/TelemetryView.jsx
2021-07-27 12:08:11 +05:00

306 lines
9.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {useState, useEffect} from 'react'
import {useParams} from 'react-router-dom'
import {Row, Col, Select, Table} from 'antd'
import {ChartTimeOnline} from '../components/charts/ChartTimeOnline'
import LoaderPortal from '../components/LoaderPortal'
import {ChartTimeOnlineFooter} from '../components/ChartTimeOnlineFooter'
import {CustomColumn} from '../components/CustomColumn'
import {UserOfWells} from '../components/UserOfWells'
import {ModeDisplay} from '../components/ModeDisplay'
import {Display} from '../components/Display'
import moment from 'moment'
import {Subscribe} from '../services/signalr'
import {DataService, MessageService} from '../services/api'
import '../styles/message.css'
import notify from "../components/notify"
const {Option} = Select
const dash = [7, 3]
const blockHeightGroup = {
label: "Высота блока",
yDisplay: false,
linePv: { label: "blockPosition", units: 'м', xAccessorName: "blockPosition", yAccessorName: "date", color: '#333' },
lineOther: { label: "wellDepth", units: 'м', xAccessorName: "wellDepth", yAccessorName: "date", color: '#333', showLine: false, xConstValue:30 },
}
const blockSpeedGroup = {
label: "Скорость блока",
yDisplay: false,
linePv: {label: "blockSpeed", units: 'м/ч', xAccessorName: "blockSpeed", yAccessorName: "date", color: '#0a0'},
lineSp: {label: "blockSpeedSp", units: 'м/ч', xAccessorName: "blockSpeedSp", yAccessorName: "date", color: '#0a0'},
}
const pressureGroup = {
label: "Давление",
yDisplay: false,
linePv: {label: "pressure", units: 'атм', xAccessorName: "pressure", yAccessorName: "date", color: '#c00'},
lineSp: {label: "pressureSp", units: 'атм', xAccessorName: "pressureSp", yAccessorName: "date", color: '#c00'},
lineIdle: {label: "pressureIdle", units: 'атм', xAccessorName: "pressureIdle", yAccessorName: "date", color: '#c00'},
linesOther: [
{
label: "мекс. перепад",
units: 'атм',
xAccessorName: "pressureDeltaLimitMax",
yAccessorName: "date",
color: '#c00'
},
],
}
const axialLoadGroup = {
label: "Осевая нагрузка",
yDisplay: false,
linePv: {label: "axialLoad", units: 'т', xAccessorName: "axialLoad", yAccessorName: "date", color: '#00a'},
lineSp: {label: "axialLoadSp", units: 'т', xAccessorName: "axialLoadSp", yAccessorName: "date", color: '#00a', dash},
linesOther: [
{label: "axialLoadLimitMax", units: 'т', xAccessorName: "axialLoadLimitMax", yAccessorName: "date", color: '#00a'},
],
}
const hookWeightGroup = {
label: "Вес на крюке",
yDisplay: false,
linePv: {label: "hookWeight", units: 'т', xAccessorName: "hookWeight", yAccessorName: "date", color: '#0aa'},
lineIdle: {
label: "hookWeightIdle",
units: 'т',
xAccessorName: "hookWeightIdle",
yAccessorName: "date",
color: '#0aa',
dash
},
linesOther: [
{
label: "hookWeightLimitMin",
units: 'т',
xAccessorName: "hookWeightLimitMin",
yAccessorName: "date",
color: '#0aa'
},
{
label: "hookWeightLimitMax",
units: 'т',
xAccessorName: "hookWeightLimitMax",
yAccessorName: "date",
color: '#0aa'
},
],
}
const rotorTorqueGroup = {
label: "Момент на роторе",
yDisplay: false,
linePv: {label: "rotorTorque", units: 'кН·м', xAccessorName: "rotorTorque", yAccessorName: "date", color: '#a0a'},
lineSp: {label: "rotorTorqueSp", units: 'кН·м', xAccessorName: "rotorTorqueSp", yAccessorName: "date", color: '#a0a'},
lineIdle: {
label: "rotorTorqueIdle",
units: 'кН·м',
xAccessorName: "rotorTorqueIdle",
yAccessorName: "date",
color: '#a0a'
},
linesOther: [
{
label: "rotorTorqueLimitMax",
units: 'кН·м',
xAccessorName: "rotorTorqueLimitMax",
yAccessorName: "date",
color: '#a0a'
},
],
}
const paramsGroups = [blockHeightGroup, blockSpeedGroup, pressureGroup, axialLoadGroup, hookWeightGroup, rotorTorqueGroup]
export const Column = ({lineGroup, data, interval, showBorder}) => {
let lines = [lineGroup.linePv]
if (lineGroup.lineSp)
lines.push(lineGroup.lineSp)
if (lineGroup.lineOther)
lines.push(lineGroup.lineOther)
if (lineGroup.lineAvg)
lines.push(lineGroup.lineAvg)
if (lineGroup.lineMax)
lines.push(lineGroup.lineMax)
let dataLast = null
let pv = null
if (data?.length > 0) {
dataLast = data[data.length - 1];
if (lineGroup.linePv)
pv = dataLast[lineGroup.linePv?.xAccessorName]
}
return (
<>
<div style={{boxShadow: showBorder ? "inset 0px 0px 0px 3px black" : ""}}>
<Display
label={lineGroup.label}
value={pv}
suffix={lineGroup.linePv?.units} isArrowVisible={false}/>
</div>
<ChartTimeOnline
data={data}
yDisplay={lineGroup.yDisplay}
lines={lines}
interval={interval}/>
<ChartTimeOnlineFooter
data={dataLast}
{...lineGroup} />
</>)
}
// Словарь категорий для строк таблицы
const categoryDictionary = {
1: {title: 'Важное'},
2: {title: 'Предупреждение'},
3: {title: 'Информация'},
}
// Конфигурация таблицы
const columns = [
{
title: 'Дата',
dataIndex: 'date',
render: (item) => moment(item).format('DD MMM YYYY, HH:MM:ss'),
sorter: (a, b) => new Date(b.date) - new Date(a.date),
sortDirections: ['descend', 'ascend'],
},
{
title: 'Категория',
dataIndex: 'categoryId',
render: (_, item) => categoryDictionary[item.categoryId].title,
style: (_, item) => categoryDictionary[item.categoryId].style,
sorter: (a, b) => a.categoryId - b.categoryId,
sortDirections: ['descend', 'ascend'],
},
{
title: 'Сообщение',
dataIndex: 'message',
onFilter: (value, record) => record.name.indexOf(value) === 0,
},
{
title: 'Пользователь',
dataIndex: 'user',
},
];
const timePeriodCollection = [
{value: '60', label: '1 минута'},
{value: '300', label: '5 минут'},
{value: '600', label: '10 минут'},
{value: '1800', label: '30 минут'},
{value: '3600', label: '1 час'},
{value: '21600', label: '6 часов'},
{value: '43200', label: '12 часов'},
{value: '86400', label: '24 часа'}
]
const defaultChartInterval = '600'
export default function TelemetryView(props) {
let {id} = useParams()
const [saubData, setSaubData] = useState([])
const [chartInterval, setChartInterval] = useState(defaultChartInterval)
const [messages, setMessages] = useState([])
const [loader, setLoader] = useState(false)
const options = timePeriodCollection.map((line) => <Option key={line.value}>{line.label}</Option>)
const handleReceiveDataSaub = (data) => {
if (data) {
setSaubData(data)
}
}
const handleReceiveMessages = (messages) => {
if (messages) {
setMessages(messages.items.splice(0, 4))
}
}
useEffect(() => {
setLoader(true)
let promiseData = DataService.getData(id)
.then(handleReceiveDataSaub)
.catch((ex) => {
notify(`Не удалось загрузить данные по скважине "${id}"`, 'error')
console.log(ex)
})
let promiseMessages = MessageService.getMessage(id)
.then(handleReceiveMessages)
.catch((ex) => {
notify(`Не удалось загрузить сообщения по скважине "${id}"`, 'error')
console.log(ex)
})
Promise.all([promiseData, promiseMessages]).then(()=>setLoader(false))
let unSubscribeDataSaubHub = Subscribe('hubs/telemetry', 'ReceiveDataSaub', `well_${id}`, handleReceiveDataSaub)
let unSubscribeMessagesHub = Subscribe('hubs/telemetry','ReceiveMessages', `well_${id}`, handleReceiveMessages)
return () => {
unSubscribeDataSaubHub()
unSubscribeMessagesHub()
}
}, [id]);
useEffect(() => {
setLoader(true)
DataService.getData(id, null, chartInterval)
.then(handleReceiveDataSaub)
.catch(error => console.error(error))
.finally(()=>setLoader(false))
}, [id, chartInterval]);
const colSpan = 24 / (paramsGroups.length)
return (<LoaderPortal show={loader}>
<Row style={{marginBottom: '1rem'}}>
<Col>
<ModeDisplay data={saubData}/>
</Col>
<span style={{flexGrow: 0.1}}>&nbsp;</span>
<Col>
Интервал:&nbsp;
<Select defaultValue={defaultChartInterval} onChange={setChartInterval}>
{options}
</Select>
</Col>
<span style={{flexGrow: 1}}>&nbsp;</span>
<Col>
<UserOfWells data={saubData}/>
</Col>
</Row>
<Row>
<Col span={3}>
<CustomColumn data={saubData}/>
</Col>
<Col span={24 - 3}>
<Row>
{paramsGroups.map((group, index) =>
<Col span={colSpan} className='border_small' key={group.label}>
<Column data={saubData} lineGroup={group} interval={chartInterval} showBorder = {saubData[saubData.length - 1]?.drillingBy === index}/>
</Col>)}
</Row>
</Col>
</Row>
<Table
showHeader={false}
columns={columns}
dataSource={messages}
rowClassName={(record) => `event_message_${record.categoryId} event_message`}
className={'message_table'}
size={'small'}
pagination={false}
rowKey={(record) => record.id}
/>
</LoaderPortal>)
}