Добавлено отображение последних 3х сообщений, Имени пользователя, просмотр сообщений, перенесён выбор скважин в заголовок

This commit is contained in:
Alexey 2021-05-19 16:05:01 +05:00
parent d59e5a0fe4
commit 0c351640cd
19 changed files with 778 additions and 236 deletions

14
.vscode/launch.json vendored
View File

@ -5,19 +5,11 @@
"version": "0.2.0",
"configurations": [
{
"name": "Launch Edge",
"name": "Launch Chrome",
"request": "launch",
"type": "pwa-msedge",
"url": "http://localhost:3000",
"type": "pwa-chrome",
"url": "http://localhost:3000/",
"webRoot": "${workspaceFolder}"
},
{
"type": "pwa-chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}"
}
]
}

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"cSpell.words": [
"день"
]
}

View File

@ -18,7 +18,7 @@ export const CustomColumn = ({data}) => {
return (<>
{lines.map(line => <Display className='border_small display_flex_container'
kay={line.label}
key={line.label}
label={line.label}
value={line.value}
suffix={line.units}/>)}

View File

@ -0,0 +1,22 @@
import { Display } from './Display'
export const UserOfWells = ({ data }) => {
const dataLast = data[data.length - 1]
const lines = [
{ label: 'Пользователь', accessorName: 'user' },
]
if (dataLast)
lines.forEach(line => line.value = dataLast[line.accessorName] ?? '-')
else
lines.forEach(line => line.value = '-')
return (<>
{lines.map(line => <Display className='border_small display_flex_container user_card'
key={line.label}
label={line.label}
value={line.value}
suffix={line.units} />)}
</>)
}

View File

@ -1,7 +1,7 @@
import { useState, useEffect } from 'react'
import { WellService } from '../services/api'
import Loader from '../components/Loader'
import { TreeSelect } from 'antd' // TreeSelect
import { TreeSelect } from 'antd'
import { useHistory } from 'react-router-dom'
const groupBy = (table, ...keys) => {
@ -10,13 +10,13 @@ const groupBy = (table, ...keys) => {
let groups = table.reduce((rv, item) => {
let keyValue = item[key]
let group = rv.find(o => o.title === keyValue)
if(!group)
{
if (!group) {
group = {
title: keyValue,
value: keys.length === 1 ? item : `${key} ${keyValue} ${item['id']}`,
value: keys.length === 1 ? `${item['id']}` : `${key} ${keyValue} ${item['id']}`,
selectable: keys.length === 1,
children:[]}
children: []
}
rv.push(group)
}
if (keys.length > 1)
@ -34,8 +34,8 @@ const groupBy = (table, ...keys) => {
};
export default function WellTreeSelector(props) {
const [wells, setWells] = useState([])
const [wellsTree, setWellsTree] = useState([]) // wellsTree,
// const [wells, setWells] = useState([])
const [wellsTree, setWellsTree] = useState([])
const [loader, setLoader] = useState(false)
const history = useHistory()
@ -44,8 +44,7 @@ export default function WellTreeSelector(props){
try {
let newWells = (await WellService.getWells()).map(w => { return { key: w.id, ...w } })
let wellsTree = groupBy(newWells, 'deposit', 'cluster', 'caption')
console.log(wellsTree)
setWells( newWells )
// setWells( newWells )
setWellsTree(wellsTree)
}
catch (e) {
@ -56,19 +55,23 @@ export default function WellTreeSelector(props){
useEffect(() => { updateWellsList() }, [])
const onChange = (value) =>{
;
const onSelect = (value) => {
if (value)
history.push(`/well/${value}`);
console.log(value)
}
return (
<>
<TreeSelect /* не работает пока */
style={{ width: '25%',
alignItems: 'center' }}
<TreeSelect
style={{
width: '25%',
alignItems: 'center'
}}
placeholder="Выберите месторождение"
treeData={wellsTree}
treeDefaultExpandAll
onChange={onChange}
onSelect={onSelect}
/>
{loader && <Loader />}
</>

View File

@ -0,0 +1,82 @@
import { useEffect, useState} from 'react';
import {ChartTimeBase, ChartTimeData, ChartTimeDataParams} from './ChartTimeBase'
const GetRandomColor = () => "#" + Math.floor(Math.random()*16777215).toString(16)
function GetOrCreateDatasetByLineConfig(data: ChartTimeData, lineConfig: LineConfig) {
let dataset = data?.datasets.find(d => d.label === lineConfig.label)
if (!dataset) {
let color = lineConfig.borderColor
?? lineConfig.backgroundColor
?? lineConfig.color
?? GetRandomColor()
dataset = {
label: lineConfig.label,
data: [],
backgroundColor: lineConfig.backgroundColor ?? color,
borderColor: lineConfig.borderColor ?? color,
borderWidth: lineConfig.borderWidth ?? 1,
borderDash: lineConfig.dash ?? [],
}
data.datasets.push(dataset);
}
return dataset
}
export type LineConfig = {
type?: string
label: string
units?: string
xAccessorName: string
yAccessorName: string
color?: string
borderColor?: string
backgroundColor?: string
borderWidth?: number
dash?: number[]
labels?: any[]
}
export type ChartTimeProps = {
label?: string,
yDisplay: Boolean,
lines: LineConfig[],
data: any[],
interval: number,
}
export const ChartTimeArchive: React.FC<ChartTimeProps> = (props) => {
const [dataParams, setDataParams] = useState<ChartTimeDataParams>({ data: { datasets: [] }, yStart: new Date(), })
useEffect(() => {
if ((!props?.lines)
|| (!props?.data)
|| (props.lines.length === 0)
|| (props.data.length === 0))
return
setDataParams((preDataParams) => {
props.lines.forEach(lineCfg => {
let dataset = GetOrCreateDatasetByLineConfig(preDataParams.data, lineCfg)
let points = props.data.map(dataItem => {
return {
x: dataItem[lineCfg.xAccessorName],
y: new Date(dataItem[lineCfg.yAccessorName])
}
})
dataset.data = points;
});
preDataParams.yStart = new Date()
preDataParams.yStart.setSeconds(preDataParams.yStart.getSeconds() - props.interval)
preDataParams.yInterval = props.interval
preDataParams.displayLabels = props.yDisplay
return preDataParams
})
}, [props.data, props.lines, props.interval, props.yDisplay])
return (<ChartTimeBase dataParams={dataParams} />)
}

View File

@ -1,3 +0,0 @@
export default function Analise(props){
return(<h2>Анализ</h2>)
}

3
src/pages/Analysis.jsx Normal file
View File

@ -0,0 +1,3 @@
export default function Analysis(props){
return(<h2>Анализ</h2>)
}

View File

@ -1,5 +1,187 @@
import { useState, useEffect } from 'react'
import {
Button,
DatePicker,
ConfigProvider,
Select,
Row,
Col,
} from 'antd'
import { useParams } from 'react-router-dom'
import { Subscribe } from '../services/signalr'
import { DataService } from '../services/api'
import 'moment/locale/ru'
import locale from 'antd/lib/locale/ru_RU'
import { ChartTimeArchive } from '../components/charts/ChartTimeArchive'
import { Display } from '../components/Display'
import { ChartTimeOnlineFooter } from '../components/ChartTimeOnlineFooter'
import { UserOfWells } from '../components/UserOfWells'
const { RangePicker } = DatePicker;
const { Option } = Select;
// Выбор периода времени
const PeriodOfTime = () => {
// const [startDate, setStartDate] = useState(new Date());
return (
<ConfigProvider locale={locale}>
<RangePicker
showTime
style={{ margin: '5px 5px', }}
/>
</ConfigProvider>
)
}
// Выбор "перьев" для графиков - перенести в шапку графика
const SelectDataCharts = () => {
const linesCollection = [
{ label: "Глубина забоя", xAccessorName: "wellDepth", color: '#a0a' },
{ label: "Положение инструмента", xAccessorName: "bitDepth", color: '#a0a' },
{ label: "Высота талевого блока", xAccessorName: "blockPosition", color: '#a0a' },
{ label: "Талевый блок. Мин положение", xAccessorName: "blockPositionMin", color: '#a0a' },
{ label: "Талевый блок. Макс положение", xAccessorName: "blockPositionMax", color: '#a0a' },
{ label: "Скорость талевого блока", xAccessorName: "blockSpeed", color: '#a0a' },
{ label: "Скорости талевого блока. Задание", xAccessorName: "blockSpeedSp", color: '#a0a' },
{ label: "Талевый блок. Задание скорости для роторного бурения", xAccessorName: "blockSpeedSpRotor", color: '#a0a' },
{ label: "Талевый блок. Задание скорости для режима слайда", xAccessorName: "blockSpeedSpSlide", color: '#a0a' },
{ label: "Талевый блок. Задание скорости для проработки", xAccessorName: "blockSpeedSpDevelop", color: '#a0a' },
{ label: "Давление", xAccessorName: "pressure", color: '#a0a' },
{ label: "Давление. Холостой ход", xAccessorName: "pressureIdle", color: '#a0a' },
{ label: "Давление. Задание", xAccessorName: "pressureSp", color: '#a0a' },
{ label: "Давление. Задание для роторного бурения", xAccessorName: "pressureSpRotor", color: '#a0a' },
{ label: "Давление. Задание для режима слайда", xAccessorName: "pressureSpSlide", color: '#a0a' },
{ label: "Давление. Задание для проработки", xAccessorName: "pressureSpDevelop", color: '#a0a' },
{ label: "Давление дифф. Аварийное макс.", xAccessorName: "pressureDeltaLimitMax", color: '#a0a' },
{ label: "Осевая нагрузка", xAccessorName: "axialLoad", color: '#a0a' },
{ label: "Осевая нагрузка. Задание", xAccessorName: "axialLoadSp", color: '#a0a' },
{ label: "Осевая нагрузка. Аварийная макс.", xAccessorName: "axialLoadLimitMax", color: '#a0a' },
{ label: "Вес на крюке", xAccessorName: "hookWeight", color: '#a0a' },
{ label: "Вес на крюке. Холостой ход", xAccessorName: "hookWeightIdle", color: '#a0a' },
{ label: "Вес на крюке. Посадка", xAccessorName: "hookWeightLimitMin", color: '#a0a' },
{ label: "Вес на крюке. Затяжка", xAccessorName: "hookWeightLimitMax", color: '#a0a' },
{ label: "Момент на роторе", xAccessorName: "rotorTorque", color: '#a0a' },
{ label: "Момент на роторе. Холостой ход", xAccessorName: "rotorTorqueIdle", color: '#a0a' },
{ label: "Момент на роторе. Задание", xAccessorName: "rotorTorqueSp", color: '#a0a' },
{ label: "Момент на роторе. Аварийный макс.", xAccessorName: "rotorTorqueLimitMax", color: '#a0a' },
{ label: "Обороты ротора", xAccessorName: "rotorSpeed", color: '#a0a' },
{ label: "Расход", xAccessorName: "flow", color: '#a0a' },
{ label: "Расход. Холостой ход", xAccessorName: "flowIdle", color: '#a0a' },
{ label: "Расход. Аварийный макс.", xAccessorName: "flowDeltaLimitMax", color: '#a0a' },
]
const children = linesCollection.map((line) => (<Option key={line.xAccessorName}>{line.label}</Option>))
function handleChange(value) {
console.log(`selected ${value}`);
}
return (
<Select
mode="multiple"
allowClear
style={{ width: '50%' }}
placeholder="Выберите значения"
defaultValue={["wellDepth"]}
onChange={handleChange}
>
{children}
</Select>
)
}
const Column = ({ lineGroup, data, interval }) => {
let lines = [lineGroup.linePv]
if (lineGroup.lineSp)
lines.push(lineGroup.lineSp)
let dataLast = null
let pv = null
if (data?.length > 0) {
dataLast = data[data.length - 1];
if (lineGroup.linePv)
pv = dataLast[lineGroup.linePv?.xAccessorName]
}
return (
<>
<Display
label={lineGroup.label}
value={pv}
suffix={lineGroup.linePv?.units} />
<ChartTimeArchive
data={data}
yDisplay={lineGroup.yDisplay}
lines={lines}
interval={interval} />
<ChartTimeOnlineFooter
data={dataLast}
{...lineGroup} />
</>)
}
const paramsGroups = []
export default function Archive(props) {
return (<h2>Архив</h2>)
let { id } = useParams();
const [saubData, setSaubData] = useState([])
const [chartInterval, setChartInterval] = useState(600)
const handleReceiveDataSaub = (data) => {
if (data) {
setSaubData(data)
}
}
useEffect(() => {
DataService.getData(id)
.then(handleReceiveDataSaub)
.catch(error => console.error(error))
let unSubscribeMessages = Subscribe('ReceiveDataSaub', `well_${id}`, handleReceiveDataSaub)
return () => {
unSubscribeMessages()
}
}, [id]);
const colSpan = 24 / (paramsGroups.length)
return (<>
<div style={{ display: 'flex' }}>
<h2>Архив</h2>
<span style={{ flexGrow: 10 }}></span>
<UserOfWells data={saubData} />
</div>
<hr />
<Button type="primary" style={{
borderRadius: '5px',
font: 'bold',
textAlign: 'center',
margin: '5px 5px',
}}>Добавить график</Button>
<PeriodOfTime />
<SelectDataCharts />
<Row style={{ marginBottom: '1rem' }}>
<Col>
Интервал:&nbsp;
<Select defaultValue="600" onChange={setChartInterval}>
<Option value='600'>10 минут</Option>
<Option value='1800'>30 минут</Option>
<Option value='3600'>1 час</Option>
<Option value='21600'>6 час</Option>
<Option value='86400'>1 день</Option>
</Select>
</Col>
</Row>
<Row>
<Col span={24 - 2}>
<Row>
{paramsGroups.map(group =>
<Col span={colSpan} className='border_small' key={group.label}>
<Column data={saubData} lineGroup={group} interval={chartInterval} />
</Col>)}
</Row>
</Col>
</Row>
</>)
}

View File

@ -7,35 +7,6 @@ import WellTreeSelector from '../components/WellTreeSelector'
const { Header } = Layout
const groupBy = (table, ...keys) => {
let key = keys[0]
let groups = table.reduce((rv, item) => {
let keyValue = item[key]
let group = rv.find(o=>o.title === keyValue)
if(!group)
{
group = {
title: keyValue,
value: keys.length === 1 ? item : `${key} ${keyValue} ${item['id']}`,
selectable: keys.length === 1,
children:[]}
rv.push(group)
}
if(keys.length > 1)
group.children.push(item);
return rv;
}, []);
if(keys.length > 1){
for(let group of groups){
group.children = groupBy(group.children, ...keys.slice(1))
}
}
return groups
};
export default function PageHeader(props){
const [sidebarVisible, setSidebarVisible] = useState(true)
const login = localStorage['login']

View File

@ -8,10 +8,10 @@ import Files from './Files'
import Archive from './Archive'
import Messages from './Messages'
import Report from './Report'
import Analise from './Analise'
import Analysis from './Analysis'
import PageHeader from './Header'
const { Content, Sider } = Layout // Header
const { Content, Sider } = Layout
export default function Main(){
const [sidebarVisible] = useState(true) // setSidebarVisible
@ -47,7 +47,7 @@ export default function Main(){
<Link to="/report">Рапорт</Link>
</Menu.Item>
<Menu.Item key="5" icon= {<FolderOutlined />}>
<Link to="/analise">Анализ</Link>
<Link to="/analysis">Анализ</Link>
</Menu.Item>
<Menu.Item key="6" icon= {<FolderOutlined />}>
<Link to="/file">Файлы</Link>
@ -65,14 +65,14 @@ export default function Main(){
<Route path="/archive">
<Archive />
</Route>
<Route path="/messages">
<Route path="/well/:id/messages">
<Messages />
</Route>
<Route path="/report">
<Report />
</Route>
<Route path="/analise">
<Analise />
<Route path="/analysis">
<Analysis />
</Route>
<Route path="/well/:id">
<TelemetryView/>

View File

@ -1,3 +1,110 @@
export default function Messages(props){
return(<h2>Сообщения</h2>)
import { Table } from 'antd';
import { MessageService } from '../services/api'
import { useState, useEffect } from 'react'
import { useParams } from 'react-router-dom'
import { Subscribe } from '../services/signalr'
import Loader from '../components/Loader'
import moment from 'moment';
import '../styles/message.css'
// Словарь категорий для строк таблицы
const categoryDictionary = {
1: {title:'Авария'},
2: {title:'Предупреждение'},
3: {title:'Информация'},
}
// Конфигурация таблицы
const columns = [
{
title: 'Дата',
key: 'date',
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: 'Категория',
key: 'categoryId',
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: 'Сообщение',
key: 'message',
dataIndex: 'message',
onFilter: (value, record) => record.name.indexOf(value) === 0,
},
{
title: 'Пользователь',
key: 'user',
dataIndex: 'user',
},
];
// Данные для таблицы
export default function Messages(props) {
let { id } = useParams()
const [messages, setMessages] = useState([])
const [loader] = useState(false)
// const handleMessages = (messages) => {
// if (messages) {
// messages.map(m => { return { key: m.id, ...m } })
// }
// }
const handleReceiveMessages = (messages) => {
if (messages) {
setMessages(messages.items)
}
}
useEffect(() => {
MessageService.getMessage(id)
.then(handleReceiveMessages)
.catch(error => console.error(error))
let unSubscribeMessagesHub = Subscribe('ReceiveMessages', `well_${id}`, handleReceiveMessages)
return () => {
unSubscribeMessagesHub()
}
}, [id]);
// let updateMessagesTable = async () => {
// setLoader(true)
// try {
// let newMessages = await MessageService.getMessage(1, 0, 32, [], '2020-01-01T00:00:00', '2025-01-01T00:00:00')
// setMessages(newMessages.items)
// } catch (e) {
// console.error(`${e.message}`);
// }
// setLoader(false)
// }
// useEffect(() => {
// updateMessagesTable()
// }, [])
return (
<>
<h2>Сообщения</h2>
<hr />
<Table
columns={columns}
dataSource={messages}
rowClassName={(record) => `event_message_${record.categoryId}`}
size={'small'}
pagination={{ pageSize: 10 }}
rowKey={(record) => record.id}
/>
{loader && <Loader />}
</>
)
}
// TODO Стили для отсортированных страниц

View File

@ -1,4 +1,4 @@
import React, { useState } from "react";
import React from "react"; // , { useState }
import {
DatePicker,
Radio,
@ -6,18 +6,19 @@ import {
Button,
Select,
Checkbox,
Pagination
} from 'antd';
import 'moment/locale/ru';
import locale from 'antd/lib/locale/ru_RU';
import moment from "moment";
const { RangePicker } = DatePicker;
const { Option } = Select;
// Расширение файла для составленного рапорта
const ExeptionFileChecker = () => {
const ExceptionFileChecker = () => {
const [value, setValue] = React.useState(1);
const onChange = e => {
console.log('radio checked', e.target.value);
@ -33,12 +34,18 @@ const ExeptionFileChecker = () => {
// Выбор периода времени
const PeriodOfTime = () => {
const [startDate, setStartDate] = useState(new Date());
function disabledDate(current) {
return current && current < moment().subtract(3, 'days'); // Наверно, не надо)
}
// const [startDate, setStartDate] = useState(new Date());
return (
<ConfigProvider locale={locale}>
<ConfigProvider locale={locale}
disabledDate>
<RangePicker
showTime
disabledDate={disabledDate}
/>
</ConfigProvider>
)
@ -64,7 +71,9 @@ const GraphicStep = () => {
}
return (
<Select defaultValue="1 minute" style={{ width: 100 }} onChange={handleChange}>
<Select defaultValue="1 minute"
style={{ width: 100 }}
onChange={handleChange}>
<Option value="1 minute">1 минута</Option>
<Option value="1 day">1 день</Option>
<Option value="1 week">1 неделя</Option>
@ -81,14 +90,19 @@ export default function Report(props) {
<PeriodOfTime />
<h3>Шаг графиков</h3>
<GraphicStep />
{/* <h3>Содержимое отчёта</h3>
<ContentSelection /> */}
<h3>Содержимое отчёта</h3>
<ContentSelection />
<div></div>
<ExeptionFileChecker />
<ExceptionFileChecker />
<p>*Предполагаемое колличество страниц</p>
<hr />
<div>
<Button type="primary" style={{ display: 'flex', alignItems: 'center', padding: '20px', borderRadius: '5px' }}>Получить рапорт</Button>
<Button type="primary" style={{
display: 'flex',
alignItems: 'center',
padding: '20px',
borderRadius: '5px'
}}>Получить рапорт</Button>
</div>
</>

View File

@ -3,12 +3,18 @@ import { Row, Col, Select, } from 'antd'
import { ChartTimeOnline } from '../components/charts/ChartTimeOnline'
import { ChartTimeOnlineFooter } from '../components/ChartTimeOnlineFooter'
import { CustomColumn } from '../components/CustomColumn'
import { ModeDisplay } from '../components/ModeDisplay';
import { Display } from '../components/Display';
import { UserOfWells } from '../components/UserOfWells'
import { ModeDisplay } from '../components/ModeDisplay'
import { Display } from '../components/Display'
import moment from 'moment'
import { Table } from 'antd';
import { MessageService } from '../services/api'
import Loader from '../components/Loader'
import { useParams } from 'react-router-dom'
import { Subscribe } from '../services/signalr'
import { DataService } from '../services/api'
import '../styles/message_telemetry.css'
const { Option } = Select
@ -28,7 +34,7 @@ const blockSpeedGroup = {
}
const pressureGroup = {
label:"Давтение",
label: "Давление",
yDisplay: false,
linePv: { label: "pressure", units: 'атм', xAccessorName: "pressure", yAccessorName: "date", color: '#c00' },
lineSp: { label: "pressureSp", units: 'атм', xAccessorName: "pressureSp", yAccessorName: "date", color: '#c00' },
@ -103,10 +109,48 @@ export const Column = ({lineGroup, data, interval})=>{
</>)
}
// Словарь категорий для строк таблицы
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',
},
];
export default function TelemetryView(props) {
let { id } = useParams();
let { id } = useParams()
const [saubData, setSaubData] = useState([])
const [chartInterval, setchartInterval] = useState(600)
const [chartInterval, setChartInterval] = useState(600)
const [messages, setMessages] = useState([])
const [loader] = useState(false) // , setLoader
const handleReceiveDataSaub = (data) => {
if (data) {
@ -114,12 +158,27 @@ export default function TelemetryView(props){
}
}
const handleReceiveMessages = (messages) => {
if (messages) {
setMessages(messages.items.splice(0, 3))
}
}
useEffect(() => {
DataService.getData(id)
.then(handleReceiveDataSaub)
.catch(error => console.error(error))
return Subscribe('ReceiveDataSaub', `well_${id}`, handleReceiveDataSaub)
MessageService.getMessage(id)
.then(handleReceiveMessages)
.catch(error => console.error(error))
let unSubscribeDataSaubHub = Subscribe('ReceiveDataSaub', `well_${id}`, handleReceiveDataSaub)
let unSubscribeMessagesHub = Subscribe('ReceiveMessages', `well_${id}`, handleReceiveMessages)
return () => {
unSubscribeDataSaubHub()
unSubscribeMessagesHub()
}
}, [id]);
const colSpan = 24 / (paramsGroups.length)
@ -132,7 +191,7 @@ export default function TelemetryView(props){
</Col>
<Col>
Интервал:&nbsp;
<Select defaultValue="600" onChange={setchartInterval}>
<Select defaultValue="600" onChange={setChartInterval}>
<Option value='600'>10 минут</Option>
<Option value='1800'>30 минут</Option>
<Option value='3600'>1 час</Option>
@ -140,6 +199,10 @@ export default function TelemetryView(props){
<Option value='86400'>1 день</Option>
</Select>
</Col>
<span style={{ flexGrow: 1 }}></span>
<Col>
<UserOfWells data={saubData}/>
</Col>
</Row>
<Row>
<Col span={2} >
@ -154,5 +217,15 @@ export default function TelemetryView(props){
</Row>
</Col>
</Row>
<Table
showHeader={false}
columns={columns}
dataSource={messages}
rowClassName={(record) => `event_message_${record.categoryId}`}
size={'small'}
pagination={false}
rowKey={(record) => record.id}
/>
{loader && <Loader />}
</div>)
}

View File

@ -68,7 +68,7 @@ export default function Wells(props){
try{
let newWells = (await WellService.getWells()).map(w =>{return {key:w.id, ...w}})
let wellsTree = groupBy(newWells, 'deposit', 'cluster', 'caption')
console.log(wellsTree)
console.log(Wells.wellsTree)
setWells( newWells )
setWellsTree(wellsTree)
}
@ -80,10 +80,6 @@ export default function Wells(props){
useEffect(()=>{updateWellsList()}, [])
const onChange = (value) =>{
;
}
return(<>
<h2>Скважины</h2>
<Table
@ -94,13 +90,6 @@ export default function Wells(props){
onClick: event => {history.push(`well/${record.id}`)},
};
}}/>
{/* <TreeSelect
style={{ width: '100%' }}
placeholder="Please select"
treeData={wellsTree}
treeDefaultExpandAll
onChange={onChange}
/> */}
{loader&&<Loader/>}
</>)
}

View File

@ -9,20 +9,58 @@ const ConnectionOptions = {
}
const Connection = new HubConnectionBuilder()
.withUrl(`http://localhost:5000/hubs/telemetry`, ConnectionOptions)
.withUrl(`http://192.168.1.70:5000/hubs/telemetry`, ConnectionOptions)
.withAutomaticReconnect()
.build();
const GetConnectionAsync = async ()=>{
if(Connection.state !== HubConnectionState.Connected)
await Connection.start()
let connectionPromise: Promise<void>
// const GetConnectionAsync = async () => {
// try {
// await Connection.start();
// console.log(Connection.state);
// } catch (err) {
// console.log(err);
// }
// }
const GetConnectionAsync = async () => {
if (Connection.state === HubConnectionState.Disconnected)
connectionPromise = Connection.start()
if (Connection.state !== HubConnectionState.Connected)
await connectionPromise
if(Connection.state === HubConnectionState.Connected)
return Connection
else
throw new Error('Can`t connect to websocket')
}
// const GetConnectionAsync = async () => {
// if (Connection.state === HubConnectionState.Disconnected)
// connectionPromise = Connection.start()
// if (Connection.state !== HubConnectionState.Connected)
// await connectionPromise
// return Connection
// }
// const GetConnectionAsync = async ()=>{
// if(Connection.state === HubConnectionState.Disconnected)
// await Connection.start()
// if(Connection.state === HubConnectionState.Connecting)
// await Connection.onreconnected
// // if(Connection.state === HubConnectionState.Disconnecting)
// // await Connection.onclose
// // if(Connection.state === HubConnectionState.Connected)
// console.log(Connection.state)
// return Connection
// }
type handlerFunction = (...args: any[]) => void;
type cleanFunction = (...args: any[]) => void;
@ -38,11 +76,10 @@ const Subscribe = (
methodName: string,
groupName: string = '',
handler: handlerFunction ):cleanFunction=>{
GetConnectionAsync().then(async connection => {
if(groupName)
await connection.send('AddToGroup', groupName)
connection.on(methodName, handler)
await Connection.send('AddToGroup', groupName)
Connection.on(methodName, handler)
})
if(groupName)

View File

@ -88,7 +88,7 @@
text-align: right;
justify-content: flex-end;
align-items:baseline;
margin: 1px 1rem 1px 1rem;
margin: 1px 1rem;
flex: auto;
}

35
src/styles/message.css Normal file
View File

@ -0,0 +1,35 @@
.event_message {
font-size: 14px;
}
.event_message_off {
color: #505050;
background: #b5b5b5;
}
.event_message_disabled {
color: #656565;
background: #b5b5b5;
}
.event_message_1 {
color: white;
background: #ff3737;
}
.event_message_2 {
color: black;
background: gold;
}
.event_message_3,
.event_message_3:hover {
color: #c0c0c0;
background: #505060;
height: 1px;
}
td.ant-table-column-sort {
color: black;
background-color: rgb(221, 247, 221);
}

View File

@ -0,0 +1,30 @@
.event_message {
font-size: 14px;
}
.event_message_off {
color: #505050;
background: #b5b5b5;
}
.event_message_disabled {
color: #656565;
background: #b5b5b5;
}
.event_message_1 {
color: white;
background: #ff3737;
}
.event_message_2 {
color: black;
background: gold;
}
.event_message_3,
.event_message_3:hover {
color: #c0c0c0;
background: #505060;
height: 1px;
}