From 073743c29cea12a89ffd6ff7da4f20d5d534bdc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A4=D1=80=D0=BE=D0=BB=D0=BE=D0=B2?= Date: Tue, 13 Apr 2021 18:03:17 +0500 Subject: [PATCH] =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D0=B0=D0=BB=20=D0=B3=D1=80=D0=B0=D1=84=D0=B8=D0=BA=D0=B8=20js?= =?UTF-8?q?=20=D0=BD=D0=B0=20ts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/charts/ChartTime.jsx | 127 ---------------------- src/components/charts/ChartTime.tsx | 78 +++++++++++++ src/components/charts/__ChartTime.__tsx | 4 + src/components/charts/__ChartTimeBase_jsx | 113 +++++++++++++++++++ src/pages/Well.jsx | 6 +- 5 files changed, 198 insertions(+), 130 deletions(-) delete mode 100644 src/components/charts/ChartTime.jsx create mode 100644 src/components/charts/ChartTime.tsx create mode 100644 src/components/charts/__ChartTimeBase_jsx diff --git a/src/components/charts/ChartTime.jsx b/src/components/charts/ChartTime.jsx deleted file mode 100644 index a48e8ef..0000000 --- a/src/components/charts/ChartTime.jsx +++ /dev/null @@ -1,127 +0,0 @@ -import React, { useEffect, useRef, useState} from 'react'; -import { Chart, TimeScale, LinearScale, Legend, LineController, PointElement, LineElement} from 'chart.js' -import 'chartjs-adapter-date-fns'; - -Chart.register( TimeScale, LinearScale, LineController, LineElement, PointElement, Legend ); - -const options = { - maintainAspectRatio: false, - //responsive:false, - aspectRatio:0.4, - animation: false, - scales: { - y:{ - type: 'time', - reverse:true, - time: { - unit: 'second', - stepSize: 20, - displayFormats: { - millisecond: 'HH:mm:ss.SSS', - second: 'HH:mm:ss', - minute: 'HH:mm:ss', - hour: 'dd HH:mm:ss', - day: 'MM.dd HH:mm', - week: 'yy.MM.dd HH:mm', - month: 'yyyy.MM.dd', - quarter: 'yyyy.MM.dd', - year: 'yyyy.MM', - }, - }, - position:{ x: 20 }, - grid:{ - drawTicks: false, - }, - ticks: { - z: 1, - textStrokeColor : "#ffff", - textStrokeWidth : 1, - color:"#000" - } - }, - - x:{ - type:'linear', - position:'top' - } - }, - elements:{ - point:{ - radius:0, - hoverRadius:5, - }, - }, -} - -const GetRandomColor = () => "#" + Math.floor(Math.random()*16777215).toString(16) - -function GetOrCreateDatasetByLineConfig (chart, lineConfig) { - let dataset = chart?.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 ?? [], - } - chart.data.datasets.push(dataset); - } - return dataset -} - -export const ChartTime = (props) => { - const chartRef = useRef(null) - const [chart, setChart] = useState(null) - - useEffect(()=>{ - if(chartRef.current && (!chart)){ - let thisOptions = {} - Object.assign(thisOptions, options, props.options) - let newChart = new Chart(chartRef.current, { - type: 'line', - options: thisOptions, - }) - setChart(newChart) - return () => chart?.destroy() - } - }, [chart, props.options]) - - useEffect(()=>{ - if((!chart) - || (!props?.config?.lines) - || (!props?.data) - || (props.config.lines.length === 0) - || (props.data.length === 0)) - return - - props.config.lines.forEach(lineCfg => { - let dataset = GetOrCreateDatasetByLineConfig(chart, lineCfg) - let points = props.data.map(dataItem => {return{ - x: dataItem[lineCfg.xAcessorName], - y: new Date(dataItem[lineCfg.yAcessorName])} - }) - dataset.data = [ ...dataset.data, ...points, ].slice(-1024) - }); - - let now = new Date() - let max = new Date() - max.setSeconds(now.getSeconds() - props.config.interval) - - let yAxes = chart.options.scales.y - yAxes.ticks.display = props.config.yDisplay ?? true - yAxes.min = max.getTime() - yAxes.max = now.getTime() - - chart.update() - }, [ chart, props.data, props.config]) - return() -} - diff --git a/src/components/charts/ChartTime.tsx b/src/components/charts/ChartTime.tsx new file mode 100644 index 0000000..4f6727a --- /dev/null +++ b/src/components/charts/ChartTime.tsx @@ -0,0 +1,78 @@ +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 + xAcessorName: string + yAcessorName: string + color?:string + borderColor?: string + backgroundColor?: string + borderWidth?: number + dash?:number[] + labels?: any[] +} + +export type ChartTimeProps = { + yDisplay: Boolean, + lines: LineConfig[], + data: any[], + interval: number, +} + +export const ChartTime: React.FC = (props) => { + + const [dataParams, setDataParams] = useState({data: {datasets:[]}, yStart: new Date(), }) + + useEffect(()=>{ + if( (!props?.lines) + || (!props?.data) + || (props.lines.length === 0) + || (props.data.length === 0)) + return + + props.lines.forEach(lineCfg => { + let dataset = GetOrCreateDatasetByLineConfig(dataParams.data, lineCfg) + let points = props.data.map(dataItem => {return{ + x: dataItem[lineCfg.xAcessorName], + y: new Date(dataItem[lineCfg.yAcessorName])} + }) + dataset.data = [ ...dataset.data, ...points, ].slice(-1024) + }); + + dataParams.yStart = new Date() + dataParams.yStart.setSeconds(dataParams.yStart.getSeconds() - props.interval) + dataParams.yInterval = props.interval + + setDataParams(dataParams) + + }, [ props.data, props.lines, props.interval]) + + return() +} + diff --git a/src/components/charts/__ChartTime.__tsx b/src/components/charts/__ChartTime.__tsx index de88cfc..4555508 100644 --- a/src/components/charts/__ChartTime.__tsx +++ b/src/components/charts/__ChartTime.__tsx @@ -32,6 +32,7 @@ const options: ChartOptions = { } }, } + type ChartTimeData = ChartData = (props) => { const chartRef = useRef(null) props.config.forEach(lineCfg => { diff --git a/src/components/charts/__ChartTimeBase_jsx b/src/components/charts/__ChartTimeBase_jsx new file mode 100644 index 0000000..f33ea95 --- /dev/null +++ b/src/components/charts/__ChartTimeBase_jsx @@ -0,0 +1,113 @@ +import { useEffect, useRef, useState} from 'react'; +import { + Chart, + TimeScale, + LinearScale, + Legend, + LineController, + PointElement, + LineElement, + ChartData, + ChartTypeRegistry, + ChartOptions} from 'chart.js' +import 'chartjs-adapter-date-fns'; + +Chart.register( TimeScale, LinearScale, LineController, LineElement, PointElement, Legend ); + +const defaultOptions = { + maintainAspectRatio: false, + aspectRatio:0.4, + animation: false, + scales: { + y:{ + type: 'time', + reverse:true, + time: { + unit: 'second', + stepSize: 20, + displayFormats: { + millisecond: 'HH:mm:ss.SSS', + second: 'HH:mm:ss', + minute: 'HH:mm:ss', + hour: 'dd HH:mm:ss', + day: 'MM.dd HH:mm', + week: 'yy.MM.dd HH:mm', + month: 'yyyy.MM.dd', + quarter: 'yyyy.MM.dd', + year: 'yyyy.MM', + }, + }, + position:{ x: 20 }, + grid:{ + drawTicks: false, + }, + ticks: { + z: 1, + textStrokeColor : "#ffff", + textStrokeWidth : 1, + color:"#000" + } + }, + + x:{ + type:'linear', + position:'top' + } + }, + elements:{ + point:{ + radius:0, + hoverRadius:5, + }, + }, + plugins:{ + legend:{ + display: false, + } + } +} + + +export const ChartTimeBase = (props) => { + const chartRef = useRef(null) + + const [chart, setChart] = useState(null) + + useEffect(()=>{ + if(chartRef.current && (!chart)){ + let thisOptions = {} + Object.assign(thisOptions, defaultOptions, props.options) + + let newChart = new Chart(chartRef.current, { + type: 'line', + options: thisOptions, + data: props.data + }) + setChart(newChart) + return () => chart?.destroy() + } + }, [chart, props.options, props.data]) + + useEffect(()=>{ + if(!chart) + return + + chart.data = props.data + + if(props.yStart){ + let interval = props.yInterval ?? 600 + let start = props.yStart + let end = props.yStart + end.setSeconds(end.getSeconds() + interval) + + if(chart.options.scales?.y){ + chart.options.scales.y.min = end.getSeconds() + chart.options.scales.y.max = start.getSeconds() + } + } + + chart.update() + },[chart, props.data]) + + return() +} \ No newline at end of file diff --git a/src/pages/Well.jsx b/src/pages/Well.jsx index b257c45..f30ae07 100644 --- a/src/pages/Well.jsx +++ b/src/pages/Well.jsx @@ -52,10 +52,11 @@ const lineParameters = [ } ] +const interval = 600 + export default function Well(props){ let { id } = useParams(); const [saubData, setSaubData] = useState([]) - const [interval, setInterval] = useState(600) const handleReceiveDataSaub = (data)=>{ if(data) @@ -71,11 +72,10 @@ export default function Well(props){ }, [id]); - let colSpan = 24/lineParameters.length let cols = lineParameters.map(line => - + ) return(