Добавлены оповещения сплывающими окнами. Изменены некоторые стили

This commit is contained in:
Alexey 2021-05-27 12:53:42 +05:00
parent fa45a27a4c
commit 6f12d57805
18 changed files with 263 additions and 212 deletions

View File

@ -32,7 +32,7 @@ export const ChartTimeOnlineFooter = (props) =>{
if(popContent)
spField = <Popover content={popContent}>
<div style={{display:"flex"}}>
<div className="menu_title">
<ControlOutlined className='display_label'/>
{spField}
</div>

View File

@ -20,8 +20,8 @@ export const ModeDisplay = (props)=>{
value = modeNames[index] ?? index
}
return(<>
return(<div className="display_header">
<span className="display_label">Режим:</span>
<span className="display_value">{value}</span>
</>)
</div>)
}

View File

@ -0,0 +1,24 @@
import { notification } from 'antd';
const typeDictionary = {
'error': 'Ошибка',
'warning': 'Предупрежение',
'info': 'Информация'
}
/**
* Вызов оповещений всплывающим окошком.
* @param body string или ReactNode
* @param type для параметра типа. Допустимые значение 'error', 'warning', 'info'
*/
export default function Notification(body, type='info'){
notification.info({
description: body,
message: typeDictionary[type],
type,
placement: "bottomRight",
duration: 10,
})
}

View File

@ -18,7 +18,7 @@ export default function Well() {
<Menu
mode="horizontal"
selectable={false}
style={{height: '100%', borderRight: 0}}
className="well_menu"
>
<Menu.Item key="1" icon={<FundViewOutlined/>}>
<Link to='telemetry'>Мониторинг</Link>

View File

@ -44,7 +44,6 @@ 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')
// setWells( newWells )
setWellsTree(wellsTree)
}
catch (e) {

View File

@ -1,3 +1,7 @@
export default function Analysis(props) {
return(<h2>Анализ</h2>)
return (
<div className="menu_title">
<h2>Анализ</h2>
</div>
)
}

View File

@ -72,6 +72,7 @@ const SelectDataCharts = () => {
{label: "Расход. Аварийный макс.", xAccessorName: "flowDeltaLimitMax", color: '#a0a'},
]
const children = linesCollection.map((line) => (<Option key={line.xAccessorName}>{line.label}</Option>))
function handleChange(value) {
console.log(`selected ${value}`);
}
@ -146,23 +147,20 @@ export default function Archive(props) {
const colSpan = 24 / (paramsGroups.length)
return (<>
<div style={{ display: 'flex' }}>
return (<div className="content-sheet">
<div className="menu_title">
<h2>Архив</h2>
<span style={{flexGrow: 10}}></span>
<UserOfWells data={saubData}/>
</div>
<hr/>
<div className="content-sheet">
<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>
@ -171,8 +169,8 @@ export default function Archive(props) {
<Option value='21600'>6 час</Option>
<Option value='86400'>1 день</Option>
</Select>
</Col>
</Row>
<SelectDataCharts/>
<PeriodOfTime/>
<Row>
<Col span={24 - 2}>
<Row>
@ -183,5 +181,6 @@ export default function Archive(props) {
</Row>
</Col>
</Row>
</>)
</div>
</div>)
}

View File

@ -1,3 +1,7 @@
export default function Files(props) {
return (<h2>Файлы</h2>)
return (
<div className="menu_title">
<h2>Файлы</h2>
</div>
)
}

View File

@ -1,6 +1,5 @@
import { useState } from 'react';
import { Layout, Button } from 'antd'
import { UserOutlined, MenuOutlined } from '@ant-design/icons'
import { UserOutlined } from '@ant-design/icons'
import logo from '../images/logo_32.png'
import { Link } from "react-router-dom"
import WellTreeSelector from '../components/WellTreeSelector'
@ -8,7 +7,6 @@ import WellTreeSelector from '../components/WellTreeSelector'
const { Header } = Layout
export default function PageHeader(props){
const [sidebarVisible, setSidebarVisible] = useState(true)
const login = localStorage['login']
let handleLogout = () => {
@ -19,7 +17,6 @@ export default function PageHeader(props){
return(
<Layout>
<Header className="header">
<Button icon={<MenuOutlined />} onClick={()=>setSidebarVisible(!sidebarVisible)}/>
<img src={logo} alt="АСБ" className="logo"/>
<WellTreeSelector />
<h1 className="title">Мониторинг</h1>

View File

@ -1,8 +1,9 @@
import { Layout, } from 'antd'
import {Layout} from 'antd'
import Wells from './Wells'
import PageHeader from './Header'
import Well from "../components/Well";
import {Redirect, Route, Switch} from "react-router-dom";
import Notification from "../components/Notification";
const {Content} = Layout
@ -12,9 +13,7 @@ export default function Main(){
<Content>
<PageHeader/>
<Layout>
<Content className="site-layout-background sheet"
style={{ marginTop: '0',
paddingTop: '0'}}>
<Content className="site-layout-background sheet well_menu">
<Switch>
<Route path="/well/:id/">
<Well/>
@ -29,5 +28,5 @@ export default function Main(){
</Content>
</Layout>
</Content>
);
)
}

View File

@ -6,6 +6,7 @@ import { Subscribe } from '../services/signalr'
import Loader from '../components/Loader'
import moment from 'moment';
import '../styles/message.css'
import Notification from '../components/Notification'
// Словарь категорий для строк таблицы
@ -48,7 +49,7 @@ const columns = [
];
// Данные для таблицы
export default function Messages(props) {
export default function Messages() {
let {id} = useParams()
const [messages, setMessages] = useState([])
const [loader] = useState(false)
@ -62,7 +63,11 @@ export default function Messages(props) {
useEffect(() => {
MessageService.getMessage(id)
.then(handleReceiveMessages)
.catch(error => console.error(error))
.catch ((ex) => {
Notification(`Не удалось загрузить сообщения по скважине "${id}"`, 'error')
console.log(ex)
})
let unSubscribeMessagesHub = Subscribe('ReceiveMessages', `well_${id}`, handleReceiveMessages)
return () => {
unSubscribeMessagesHub()
@ -76,9 +81,9 @@ export default function Messages(props) {
<Table
columns={columns}
dataSource={messages}
rowClassName={(record) => `event_message_${record.categoryId}`}
rowClassName={(record) => `event_message_${record.categoryId} event_message`}
size={'small'}
pagination={{ pageSize: 10 }}
pagination={{pageSize: 28}}
rowKey={(record) => record.id}
/>
{loader && <Loader/>}

View File

@ -1,4 +1,4 @@
import React from "react"; // , { useState }
import React from "react";
import {
DatePicker,
Radio,
@ -37,8 +37,6 @@ const PeriodOfTime = () => {
function disabledDate(current) {
return current && current < moment().subtract(3, 'days'); // Наверно, не надо)
}
// const [startDate, setStartDate] = useState(new Date());
return (
<ConfigProvider locale={locale}
@ -97,12 +95,9 @@ export default function Report(props) {
<p>*Предполагаемое колличество страниц</p>
<hr />
<div>
<Button type="primary" style={{
display: 'flex',
alignItems: 'center',
padding: '20px',
borderRadius: '5px'
}}>Получить рапорт</Button>
<Button type="primary" className="submit_button">
Получить рапорт
</Button>
</div>
</>

View File

@ -1,20 +1,19 @@
import { useState, useEffect } from 'react';
import { Row, Col, Select, } from 'antd'
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 Loader from '../components/Loader'
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 notify from '../components/Notification'
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'
import { DataService, MessageService } from '../services/api'
import '../styles/message.css'
import Notification from "../components/Notification";
const { Option } = Select
@ -165,13 +164,20 @@ export default function TelemetryView(props) {
}
useEffect(() => {
try {
DataService.getData(id)
.then(handleReceiveDataSaub)
.catch(error => console.error(error))
} catch (ex) {
Notification(`Не удалось загрузить данные по скважине ${id}`, 'error')
}
try {
MessageService.getMessage(id)
.then(handleReceiveMessages)
.catch(error => console.error(error))
} catch (ex) {
Notification(`Не удалось загрузить сообщения по скважине ${id}`, 'error')
console.log(ex)
}
let unSubscribeDataSaubHub = Subscribe('ReceiveDataSaub', `well_${id}`, handleReceiveDataSaub)
let unSubscribeMessagesHub = Subscribe('ReceiveMessages', `well_${id}`, handleReceiveMessages)
@ -184,11 +190,11 @@ export default function TelemetryView(props) {
const colSpan = 24 / (paramsGroups.length)
return (<div>
{/* <div>Well id: {id}; points count: {saubData.length}</div> */}
<Row style={{ marginBottom: '1rem' }}>
<Col>
<ModeDisplay data={saubData} />
</Col>
<span style={{ flexGrow: 0.1 }}>&nbsp;</span>
<Col>
Интервал:&nbsp;
<Select defaultValue="600" onChange={setChartInterval}>
@ -199,7 +205,7 @@ export default function TelemetryView(props) {
<Option value='86400'>1 день</Option>
</Select>
</Col>
<span style={{ flexGrow: 1 }}></span>
<span style={{ flexGrow: 1 }}>&nbsp;</span>
<Col>
<UserOfWells data={saubData}/>
</Col>
@ -221,7 +227,8 @@ export default function TelemetryView(props) {
showHeader={false}
columns={columns}
dataSource={messages}
rowClassName={(record) => `event_message_${record.categoryId}`}
rowClassName={(record) => `event_message_${record.categoryId} event_message`}
className={'message_table'}
size={'small'}
pagination={false}
rowKey={(record) => record.id}

View File

@ -5,7 +5,7 @@ import { HubConnectionBuilder, HubConnectionState } from '@microsoft/signalr';
const ConnectionOptions = {
accessTokenFactory: () => localStorage['token'],
//transport:1,
transport:1,
}
const Connection = new HubConnectionBuilder()
@ -15,16 +15,6 @@ const Connection = new HubConnectionBuilder()
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()
@ -35,32 +25,6 @@ const GetConnectionAsync = async () => {
return Connection
}
// 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;

View File

@ -11,6 +11,11 @@
#root, .app{min-height:100%;}
html {
display: flex;
height: 100%;
}
.login_page{
position: absolute;
height:100%;
@ -28,7 +33,7 @@
.header {
display: flex;
align-items: center;
padding: 4px 24px;
//padding: 4px 24px;
}
.header .logo {
@ -36,14 +41,15 @@
border-radius: 32px;
padding: 8px 24px;
margin: 8px 10px;
box-shadow: #fff 2px;
box-shadow: 0 0 2px #fff;
}
.header .title{
flex-grow: 1;
color: #fff;
text-align: center;
justify-content: baseline;
text-align: start;
justify-content: start;
margin-left: 100px;
}
.header button{
@ -53,9 +59,8 @@
}
.sheet{
padding: 24px;
margin: 8px;
min-height: 280;
padding: 5px 24px;
min-height: 280px;
}
.site-layout-background {
@ -71,14 +76,26 @@
flex-wrap: wrap;
flex: auto;
}
.display_header {
font-size: 16px;
flex-grow: 1;
display: flex;
}
.display_label{
font-size: 16px;
color: rgb(70, 70, 70);
text-align: left;
justify-content: baseline;
justify-content: center;
margin: 1px 1rem 1px 1rem;
flex: auto;
align-items: baseline;
text-overflow: ellipsis;
overflow-x: hidden;
overflow-y: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
height: 30px;
}
.display_value{
@ -95,7 +112,29 @@
.display_small_value{
color: rgb(50, 50, 50);
text-align: right;
justify-content: baseline;
justify-content: center;
margin: 1px 1rem 1px 1rem;
flex: auto;
}
.menu_title {
display: flex;
}
.submit_button {
display: flex;
align-items: center;
padding: 20px;
border-radius: 5px;
}
.well_menu {
margin-top: 0;
padding-top: 0;
height: 100%;
border-right: 0;
}
tr.table_row_size {
height: 10px;
}

View File

@ -0,0 +1,3 @@
.content-sheet {
display: inline-flex;
}

View File

@ -1,3 +1,7 @@
::-webkit-scrollbar {
width: 0;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',

View File

@ -1,5 +1,15 @@
.event_message {
/*.ant-table.ant-table-small .ant-table-tbody > tr > td {*/
/* padding: 0;*/
/*}*/
/*.ant-table-tbody > tr > td {*/
/* border-bottom: 0.5px;*/
/*}*/
.event_message > td {
font-size: 14px;
padding: 1px !important;
border-bottom: 1px !important;
}
.event_message_off {
@ -22,11 +32,9 @@
background: gold;
}
.event_message_3,
.event_message_3:hover {
.event_message_3 {
color: #c0c0c0;
background: #505060;
height: 1px;
}
td.ant-table-column-sort {