From da7f4aa5b2bbd8dcf92d819efcc989e089302b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Z=C3=ADpek?= Date: Thu, 25 Aug 2022 09:30:50 +0200 Subject: [PATCH] More graph options --- .../dashboard/components/BoxDialContent.tsx | 2 +- .../dashboard/components/BoxGraphContent.tsx | 46 ++++++++++----- .../BoxSettings/components/GraphSettings.tsx | 59 +++++++++++++++++-- client/src/utils/max.ts | 2 + client/src/utils/min.ts | 2 + client/src/utils/omit.ts | 7 +++ client/src/utils/parseDashboard.ts | 10 ++++ 7 files changed, 107 insertions(+), 21 deletions(-) create mode 100644 client/src/utils/max.ts create mode 100644 client/src/utils/min.ts create mode 100644 client/src/utils/omit.ts diff --git a/client/src/pages/dashboard/components/BoxDialContent.tsx b/client/src/pages/dashboard/components/BoxDialContent.tsx index 4393782..1be0c0b 100644 --- a/client/src/pages/dashboard/components/BoxDialContent.tsx +++ b/client/src/pages/dashboard/components/BoxDialContent.tsx @@ -53,7 +53,7 @@ export const BoxDialContent = ({ box, data, refreshRef }: Props) => { {value.data && ( <> {displayValue} - {` ${data.unit}`} + {data.unit && ` ${data.unit}`} )} diff --git a/client/src/pages/dashboard/components/BoxGraphContent.tsx b/client/src/pages/dashboard/components/BoxGraphContent.tsx index b856143..1fe8432 100644 --- a/client/src/pages/dashboard/components/BoxGraphContent.tsx +++ b/client/src/pages/dashboard/components/BoxGraphContent.tsx @@ -1,4 +1,6 @@ import { getSensorValues } from '@/api/sensorValues' +import { max } from '@/utils/max' +import { min } from '@/utils/min' import { DashboardGraphData } from '@/utils/parseDashboard' import { RefObject } from 'preact' import { useEffect, useRef } from 'preact/hooks' @@ -33,42 +35,58 @@ export const BoxGraphContent = ({ box, data, refreshRef }: Props) => { } useEffect(() => { - // TODO: These should be probably returned by server, could be outdated - const from = filter.customFrom - const to = filter.customTo - const minValue = parseFloat(data.min ?? '') - const maxValue = parseFloat(data.max ?? '') - const customRange = !isNaN(minValue) && !isNaN(maxValue) - if (bodyRef.current && values.data) { + // TODO: These should be probably returned by server, could be outdated + const from = filter.customFrom + const to = filter.customTo + const minValue = parseFloat(data.min ?? '') + const maxValue = parseFloat(data.max ?? '') + const customRange = !isNaN(minValue) || !isNaN(maxValue) + const graphType = data.graphType ?? 'line' + const fill = data.fill ?? undefined + const colorMode = data.colorMode + const staticColor = data.staticColor + + const x = values.data.map((v) => new Date(v.timestamp * 1000)) + const y = values.data.map((v) => v.value) + window.Plotly.newPlot( bodyRef.current, [ { - ...(data.graphType === 'line' && { + ...(graphType === 'line' && { type: 'scatter', mode: 'lines', + fill, }), - ...(data.graphType === 'points' && { + ...(graphType === 'points' && { type: 'scatter', mode: 'markers', + fill, }), - ...(data.graphType === 'lineAndPoints' && { + ...(graphType === 'lineAndPoints' && { type: 'scatter', mode: 'lines+markers', + fill, }), - ...(data.graphType === 'bar' && { type: 'bar' }), - x: values.data.map((v) => new Date(v.timestamp * 1000)), - y: values.data.map((v) => v.value), + ...(graphType === 'bar' && { type: 'bar' }), + x, + y, line: { width: 1, + ...(colorMode === 'static' && { color: staticColor }), }, }, ], { xaxis: { range: [from, to], type: 'date' }, yaxis: { - ...(customRange && { range: [minValue, maxValue] }), + ...(customRange && { + range: [ + isNaN(minValue) ? min(y) : minValue, + isNaN(maxValue) ? max(y) : maxValue, + ], + }), ...(data.unit && { ticksuffix: ` ${data.unit}` }), }, margin: { diff --git a/client/src/pages/dashboard/components/BoxSettings/components/GraphSettings.tsx b/client/src/pages/dashboard/components/BoxSettings/components/GraphSettings.tsx index 8ec26fe..6546465 100644 --- a/client/src/pages/dashboard/components/BoxSettings/components/GraphSettings.tsx +++ b/client/src/pages/dashboard/components/BoxSettings/components/GraphSettings.tsx @@ -1,3 +1,4 @@ +import { omit } from '@/utils/omit' import { DashboardGraphData } from '@/utils/parseDashboard' import { useEffect, useState } from 'preact/hooks' @@ -8,10 +9,7 @@ type Props = { export const GraphSettings = ({ value, onChange }: Props) => { const [formState, setFormState] = useState(() => ({ - min: value?.min, - max: value?.max, - graphType: value?.graphType, - unit: value?.unit, + ...(value && omit(value, ['type'])), })) const handleChange = (e: Event) => { @@ -43,18 +41,67 @@ export const GraphSettings = ({ value, onChange }: Props) => { +
+ + +
+
- +
- +
+
+ + +
+ + {formState.colorMode === 'static' && ( +
+ + +
+ )} ) } diff --git a/client/src/utils/max.ts b/client/src/utils/max.ts new file mode 100644 index 0000000..b4f8e7b --- /dev/null +++ b/client/src/utils/max.ts @@ -0,0 +1,2 @@ +export const max = (v: number[]) => + v.reduce((acc, item) => (item > acc ? item : acc), 0) diff --git a/client/src/utils/min.ts b/client/src/utils/min.ts new file mode 100644 index 0000000..29c5c42 --- /dev/null +++ b/client/src/utils/min.ts @@ -0,0 +1,2 @@ +export const min = (v: number[]) => + v.reduce((acc, item) => (item > acc ? item : acc), 0) diff --git a/client/src/utils/omit.ts b/client/src/utils/omit.ts new file mode 100644 index 0000000..38fee0a --- /dev/null +++ b/client/src/utils/omit.ts @@ -0,0 +1,7 @@ +export const omit = (v: T, keys: TOmitKeys[]) => { + const keysSet = new Set(keys as string[]) + + return Object.fromEntries( + Object.entries(v).filter(([key]) => !keysSet.has(key)) + ) as Omit +} diff --git a/client/src/utils/parseDashboard.ts b/client/src/utils/parseDashboard.ts index 2649e54..02b8f46 100644 --- a/client/src/utils/parseDashboard.ts +++ b/client/src/utils/parseDashboard.ts @@ -20,6 +20,16 @@ export type DashboardGraphData = { max?: string unit?: string graphType?: string + fill?: + | 'none' + | 'tozeroy' + | 'tozerox' + | 'tonexty' + | 'tonextx' + | 'toself' + | 'tonext' + colorMode?: 'static' + staticColor?: string } export type DashboardDialData = {