Исправление работы dataLabels (+мемоизация и косметика)

This commit is contained in:
Александр Сироткин 2022-03-01 19:32:29 +05:00
parent fee4ee938b
commit 8431e40a39
7 changed files with 51 additions and 50 deletions

View File

@ -10,7 +10,6 @@ const { RangePicker } = DatePicker
export type DateRangeWrapperProps = RangePickerSharedProps<Moment> & { export type DateRangeWrapperProps = RangePickerSharedProps<Moment> & {
value: RangeValue<Moment>, value: RangeValue<Moment>,
onChange: (date: RangeValue<Moment>) => any
isUTC?: boolean isUTC?: boolean
} }
@ -19,13 +18,15 @@ const normalizeDates = (value: RangeValue<Moment>, isUTC?: boolean): RangeValue<
value[1] ? (isUTC ? moment.utc(value[1]).local() : moment(value[1])) : null, value[1] ? (isUTC ? moment.utc(value[1]).local() : moment(value[1])) : null,
] ]
export const DateRangeWrapper = memo<DateRangeWrapperProps>(({ value, onChange, isUTC, ...other }) => ( export const DateRangeWrapper = memo<DateRangeWrapperProps>(({ value, isUTC, ...other }) => (
<RangePicker <RangePicker
showTime showTime
allowClear={false} allowClear={false}
format={defaultFormat} format={defaultFormat}
defaultValue={[moment().subtract(60000), moment()]} defaultValue={[
onChange={(date) => onChange(date)} moment().subtract(1, 'days').startOf('day'),
moment().startOf('day'),
]}
value={normalizeDates(value)} value={normalizeDates(value)}
{...other} {...other}
/> />

View File

@ -1,4 +1,4 @@
import { useEffect, useRef, useState } from 'react' import { memo, useEffect, useRef, useState } from 'react'
import { import {
Chart, Chart,
TimeScale, TimeScale,
@ -178,7 +178,7 @@ export const timeParamsByInterval = (intervalSec: number): TimeParams => {
return { unit, stepSize } return { unit, stepSize }
} }
export const ChartTimeBase: React.FC<ChartTimeBaseProps> = ({options, dataParams}) => { export const ChartTimeBase = memo<ChartTimeBaseProps>(({ options, dataParams }) => {
const chartRef = useRef<HTMLCanvasElement>(null) const chartRef = useRef<HTMLCanvasElement>(null)
const [chart, setChart] = useState<any>() const [chart, setChart] = useState<any>()
@ -217,4 +217,4 @@ export const ChartTimeBase: React.FC<ChartTimeBaseProps> = ({options, dataParams
}, [chart, dataParams]) }, [chart, dataParams])
return(<canvas ref={chartRef} />) return(<canvas ref={chartRef} />)
} })

View File

@ -1,6 +1,7 @@
import { ChartOptions, Scriptable, ScriptableContext } from 'chart.js' import { ChartOptions, Scriptable, ScriptableContext } from 'chart.js'
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import { makeDateSorter } from '../Table'
import { makeDateSorter } from '@components/Table'
import { import {
ChartTimeBase, ChartTimeBase,
ChartTimeData, ChartTimeData,
@ -21,7 +22,8 @@ export type ColumnLineConfig = {
dash?: Array<number> dash?: Array<number>
borderColor?: string borderColor?: string
backgroundColor?: string backgroundColor?: string
borderWidth?: Scriptable<number, ScriptableContext<'radar'>> borderWidth?: Scriptable<number, ScriptableContext<'line'>>
showDatalabels?: boolean
fill?: string fill?: string
} }
export type ColumnPostParsing = (data: ChartTimeDataParams) => void export type ColumnPostParsing = (data: ChartTimeDataParams) => void
@ -44,7 +46,7 @@ const chartPluginsOptions: ChartOptions = {
backgroundColor: 'transparent', backgroundColor: 'transparent',
borderRadius: 4, borderRadius: 4,
color: '#000B', color: '#000B',
display: context => (context.dataset.label === 'wellDepth') && 'auto', display: context => !!context.dataset.label?.endsWith(' ') && 'auto',
formatter: value => `${value.y.toLocaleTimeString()} ${value.label.toPrecision(4)}`, formatter: value => `${value.y.toLocaleTimeString()} ${value.label.toPrecision(4)}`,
padding: 6, padding: 6,
align: 'left', align: 'left',
@ -67,14 +69,14 @@ export const GetOrCreateDatasetByLineConfig = (data: ChartTimeData, lineConfig:
?? GetRandomColor() ?? GetRandomColor()
dataset = { dataset = {
label: lineConfig.label, label: lineConfig.label?.trimEnd() + (lineConfig.showDatalabels ? ' ' : ''),
data: [], data: [],
backgroundColor: lineConfig.backgroundColor ?? color, backgroundColor: lineConfig.backgroundColor ?? color,
borderColor: lineConfig.borderColor ?? color, borderColor: lineConfig.borderColor ?? color,
borderWidth: lineConfig.borderWidth ?? 1, borderWidth: lineConfig.borderWidth ?? 1,
borderDash: lineConfig.dash ?? [], borderDash: lineConfig.dash ?? [],
showLine: lineConfig.showLine ?? !lineConfig.isShape, showLine: lineConfig.showLine ?? !lineConfig.isShape,
fill: lineConfig.fill ?? (lineConfig.isShape ? 'shape' : 'none') fill: lineConfig.fill ?? (lineConfig.isShape ? 'shape' : 'none'),
} }
data.datasets.push(dataset) data.datasets.push(dataset)

View File

@ -1,5 +1,5 @@
import { Table } from 'antd' import { Table } from 'antd'
import { useState, useEffect } from 'react' import { useState, useEffect, useCallback, memo } from 'react'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
@ -10,14 +10,14 @@ import { columns } from '@pages/Messages'
import '@styles/message.css' import '@styles/message.css'
export const ActiveMessagesOnline = ({ idWell }) => { export const ActiveMessagesOnline = memo(({ idWell }) => {
const [messages, setMessages] = useState([]) const [messages, setMessages] = useState([])
const [loader, setLoader] = useState(false) const [loader, setLoader] = useState(false)
const handleReceiveMessages = (messages) => { const handleReceiveMessages = useCallback((messages) => {
if (messages) if (messages)
setMessages(messages.items.splice(0, 4)) setMessages(messages.items.splice(0, 4))
} }, [])
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
@ -30,7 +30,7 @@ export const ActiveMessagesOnline = ({ idWell }) => {
'Получение списка сообщений' 'Получение списка сообщений'
) )
return Subscribe('hubs/telemetry','ReceiveMessages', `well_${idWell}`, handleReceiveMessages) return Subscribe('hubs/telemetry','ReceiveMessages', `well_${idWell}`, handleReceiveMessages)
}, [idWell]) }, [idWell, handleReceiveMessages])
return ( return (
<LoaderPortal show={loader}> <LoaderPortal show={loader}>
@ -46,6 +46,6 @@ export const ActiveMessagesOnline = ({ idWell }) => {
/> />
</LoaderPortal> </LoaderPortal>
) )
} })
export default ActiveMessagesOnline export default ActiveMessagesOnline

View File

@ -1,9 +1,10 @@
import { memo } from 'react'
import { Popover } from 'antd' import { Popover } from 'antd'
import { ControlOutlined } from '@ant-design/icons' import { ControlOutlined } from '@ant-design/icons'
import { ValueDisplay } from '@components/Display' import { ValueDisplay } from '@components/Display'
export const ChartTimeOnlineFooter = ({ data, lineGroup }) => { export const ChartTimeOnlineFooter = memo(({ data, lineGroup }) => {
const getFooterData = (name) => { const getFooterData = (name) => {
const dataIdx = data && lineGroup?.find(line => line?.footer === name)?.xAccessorName const dataIdx = data && lineGroup?.find(line => line?.footer === name)?.xAccessorName
return (<ValueDisplay value={data?.[dataIdx]}/>) return (<ValueDisplay value={data?.[dataIdx]}/>)
@ -39,4 +40,6 @@ export const ChartTimeOnlineFooter = ({ data, lineGroup }) => {
</div> </div>
</div> </div>
) )
} })
export default ChartTimeOnlineFooter

View File

@ -1,4 +1,4 @@
import { useEffect, useState } from 'react' import { memo, useCallback, useEffect, useState } from 'react'
import { Grid, GridItem } from '@components/Grid' import { Grid, GridItem } from '@components/Grid'
import { makeDateSorter } from '@components/Table' import { makeDateSorter } from '@components/Table'
@ -9,7 +9,7 @@ import { ChartTimeOnlineFooter } from './ChartTimeOnlineFooter'
const GetLimitShape = (flowChartData, points, accessor) => { const GetLimitShape = (flowChartData, points, accessor) => {
const min = [], max = [] const min = [], max = []
for (let point of points) { for (const point of points) {
const program = flowChartData.find(v => v.depthStart < point.depth && point.depth < v.depthEnd) const program = flowChartData.find(v => v.depthStart < point.depth && point.depth < v.depthEnd)
if (!program) continue if (!program) continue
@ -29,7 +29,9 @@ const RemoveSimilar = (input, accessor) => {
return data return data
} }
export const MonitoringColumn = ({ lineGroup, data, flowChartData, interval, showBorder, style, headerHeight, pointCount = 2048, additionalLabels }) => { const addPointData = (point) => ({ depth: point.wellDepth })
export const MonitoringColumn = memo(({ lineGroup, data, flowChartData, interval, showBorder, style, headerHeight, pointCount = 2048, additionalLabels }) => {
const [dataStore, setDataStore] = useState([]) const [dataStore, setDataStore] = useState([])
const [lineGroupWithoutShapes, setLineGroupWithoutShapes] = useState([]) const [lineGroupWithoutShapes, setLineGroupWithoutShapes] = useState([])
const dataLast = data?.[data.length - 1] const dataLast = data?.[data.length - 1]
@ -41,9 +43,7 @@ export const MonitoringColumn = ({ lineGroup, data, flowChartData, interval, sho
value: dataLast?.[line.xAccessorName] value: dataLast?.[line.xAccessorName]
})) }))
const addPointData = (point) => ({ depth: point.wellDepth }) const postParsing = useCallback((data) => {
const postParsing = (data) => {
lineGroupWithoutShapes.forEach(lineCfg => { lineGroupWithoutShapes.forEach(lineCfg => {
const lineDataSet = GetOrCreateDatasetByLineConfig(data.data, lineCfg) const lineDataSet = GetOrCreateDatasetByLineConfig(data.data, lineCfg)
@ -54,7 +54,7 @@ export const MonitoringColumn = ({ lineGroup, data, flowChartData, interval, sho
}) })
} }
}) })
} }, [lineGroupWithoutShapes, flowChartData, lineGroup])
useEffect(() => { useEffect(() => {
setDataStore(prevData => { setDataStore(prevData => {
@ -119,6 +119,6 @@ export const MonitoringColumn = ({ lineGroup, data, flowChartData, interval, sho
<ChartTimeOnlineFooter data={dataLast} lineGroup={lineGroup} /> <ChartTimeOnlineFooter data={dataLast} lineGroup={lineGroup} />
</div> </div>
) )
} })
export default MonitoringColumn export default MonitoringColumn

View File

@ -1,5 +1,5 @@
import { Select } from 'antd' import { Select } from 'antd'
import { useState, useEffect } from 'react' import { useState, useEffect, useCallback } from 'react'
import { import {
DrillFlowChartService, DrillFlowChartService,
@ -49,7 +49,8 @@ const blockHeightGroup = [
yAccessorName: 'date', yAccessorName: 'date',
color: '#333', color: '#333',
showLine: false, showLine: false,
xConstValue: 30, showDatalabels: true,
xConstValue: 50,
dash dash
}, { }, {
label: 'Расход', label: 'Расход',
@ -310,19 +311,15 @@ export default function TelemetryView({ idWell }) {
const [flowChartData, setFlowChartData] = useState([]) const [flowChartData, setFlowChartData] = useState([])
const [rop, setRop] = useState(null) const [rop, setRop] = useState(null)
const handleDataSaub = (data) => { const handleDataSaub = useCallback((data) => {
if (data) { if (data) {
const dataSaub = normalizeData(data) const dataSaub = normalizeData(data)
dataSaub.sort(makeDateSorter('date')) dataSaub.sort(makeDateSorter('date'))
setDataSaub(dataSaub) setDataSaub(dataSaub)
} }
} }, [])
const handleDataSpin = (data) => { const handleDataSpin = useCallback((data) => data && setDataSpin(data), [])
if (data) {
setDataSpin(data)
}
}
useEffect(() => { useEffect(() => {
const unsubscribeSaub = Subscribe('hubs/telemetry', 'ReceiveDataSaub', `well_${idWell}`, handleDataSaub) const unsubscribeSaub = Subscribe('hubs/telemetry', 'ReceiveDataSaub', `well_${idWell}`, handleDataSaub)
@ -344,7 +341,7 @@ export default function TelemetryView({ idWell }) {
unsubscribeSaub() unsubscribeSaub()
unsubscribeSpin() unsubscribeSpin()
} }
}, [idWell, chartInterval]) }, [idWell, chartInterval, handleDataSpin, handleDataSaub])
useEffect(() => invokeWebApiWrapperAsync( useEffect(() => invokeWebApiWrapperAsync(
async () => { async () => {
@ -358,18 +355,16 @@ export default function TelemetryView({ idWell }) {
'Получение данных по скважине' 'Получение данных по скважине'
), [idWell]) ), [idWell])
const onStatusChanged = (value) => { const onStatusChanged = useCallback((value) => invokeWebApiWrapperAsync(
invokeWebApiWrapperAsync( async () => {
async () => { const well = { ...wellData, idState: value }
const well = { ...wellData, idState: value } await WellService.updateWell(idWell, well)
await WellService.updateWell(idWell, well) setWellData(well)
setWellData(well) },
}, setShowLoader,
setShowLoader, `Не удалось задать состояние скважины "${idWell}"`,
`Не удалось задать состояние скважины "${idWell}"`, 'Задание состояния скважины'
'Задание состояния скважины' ), [idWell, wellData])
)
}
const columnAdditionalLabels = { const columnAdditionalLabels = {
1: rop && [ 1: rop && [