Fixes and proper box settings

This commit is contained in:
Jan Zípek 2022-08-24 09:31:10 +02:00
parent 8bff4d083e
commit ec690ebbcb
Signed by: kamen
GPG Key ID: A17882625B33AC31
5 changed files with 99 additions and 42 deletions

View File

@ -1,4 +1,5 @@
import { getSensorValues } from '@/api/sensorValues'
import { DashboardGraphData } from '@/utils/parseDashboard'
import { useEffect, useRef } from 'preact/hooks'
import { useQuery } from 'react-query'
import { useDashboardContext } from '../contexts/DashboardContext'
@ -6,9 +7,10 @@ import { BoxDefinition } from '../types'
type Props = {
box: BoxDefinition
data: DashboardGraphData
}
export const BoxGraphContent = ({ box }: Props) => {
export const BoxGraphContent = ({ box, data }: Props) => {
const { filter } = useDashboardContext()
const bodyRef = useRef<HTMLDivElement>(null)
@ -27,8 +29,8 @@ export const BoxGraphContent = ({ box }: Props) => {
// TODO: These should be probably returned by server, could be outdated
const from = filter.customFrom
const to = filter.customTo
const minValue = parseFloat(box.min ?? '')
const maxValue = parseFloat(box.max ?? '')
const minValue = parseFloat(data.min ?? '')
const maxValue = parseFloat(data.max ?? '')
const customRange = !isNaN(minValue) && !isNaN(maxValue)
if (bodyRef.current && values.data) {
@ -36,19 +38,19 @@ export const BoxGraphContent = ({ box }: Props) => {
bodyRef.current,
[
{
...(box.graphType === 'line' && {
...(data.graphType === 'line' && {
type: 'scatter',
mode: 'lines',
}),
...(box.graphType === 'points' && {
...(data.graphType === 'points' && {
type: 'scatter',
mode: 'markers',
}),
...(box.graphType === 'lineAndPoints' && {
...(data.graphType === 'lineAndPoints' && {
type: 'scatter',
mode: 'lines+markers',
}),
...(box.graphType === 'bar' && { type: 'bar' }),
...(data.graphType === 'bar' && { type: 'bar' }),
x: values.data.map((v) => new Date(v.timestamp * 1000)),
y: values.data.map((v) => v.value),
line: {
@ -60,7 +62,7 @@ export const BoxGraphContent = ({ box }: Props) => {
xaxis: { range: [from, to], type: 'date' },
yaxis: {
...(customRange && { range: [minValue, maxValue] }),
...(box.unit && { ticksuffix: ` ${box.unit}` }),
...(data.unit && { ticksuffix: ` ${data.unit}` }),
},
margin: {
l: 70,
@ -76,7 +78,7 @@ export const BoxGraphContent = ({ box }: Props) => {
}
)
}
}, [values.data, box])
}, [values.data, box, data])
return <div ref={bodyRef} />
}

View File

@ -1,7 +1,8 @@
import { getSensors } from '@/api/sensors'
import { useState } from 'preact/hooks'
import { useQuery } from 'react-query'
import { BoxDefinition } from '../types'
import { BoxDefinition } from '../../types'
import { GraphSettings } from './components/GraphSettings'
type Props = {
value: BoxDefinition
@ -15,12 +16,11 @@ export const BoxSettings = ({ value, onSave, onClose }: Props) => {
const [formState, setFormState] = useState(() => ({
sensor: value.sensor,
title: value.title,
min: value.min,
max: value.max,
graphType: value.graphType,
unit: value.unit,
type: value.data?.type ?? 'graph',
}))
const [data, setData] = useState(() => value.data)
const handleSave = async (e: Event) => {
e.preventDefault()
e.stopPropagation()
@ -29,7 +29,9 @@ export const BoxSettings = ({ value, onSave, onClose }: Props) => {
onSave({
...value,
...formState,
sensor: formState.sensor,
title: formState.title,
data: data,
})
}
@ -81,33 +83,17 @@ export const BoxSettings = ({ value, onSave, onClose }: Props) => {
<div className="input">
<label>Type</label>
<select
name="graphType"
value={formState.graphType || 'line'}
name="type"
value={formState.type}
onChange={handleChange}
>
<option value="line">Line</option>
<option value="points">Points</option>
<option value="lineAndPoints">Line + Points</option>
<option value="bar">Bar</option>
<option value="graph">Graph</option>
</select>
</div>
<div className="input">
<label>Unit</label>
<input
name="unit"
value={formState.unit}
onChange={handleChange}
/>
</div>
<div className="input">
<label>Min value</label>
<input name="min" value={formState.min} onChange={handleChange} />
</div>
<div className="input">
<label>Max value</label>
<input name="max" value={formState.max} onChange={handleChange} />
</div>
{formState.type === 'graph' && (
<GraphSettings value={data} onChange={setData} />
)}
<div className="actions">
<button className="cancel" onClick={onClose} type="button">

View File

@ -0,0 +1,60 @@
import { DashboardGraphData } from '@/utils/parseDashboard'
import { useEffect, useState } from 'preact/hooks'
type Props = {
value?: DashboardGraphData
onChange: (data: DashboardGraphData) => void
}
export const GraphSettings = ({ value, onChange }: Props) => {
const [formState, setFormState] = useState(() => ({
min: value?.min,
max: value?.max,
graphType: value?.graphType,
unit: value?.unit,
}))
const handleChange = (e: Event) => {
const target = e.target as HTMLSelectElement | HTMLInputElement
setFormState({
...formState,
[target.name]: target.value,
})
}
useEffect(() => {
onChange({ ...formState, type: 'graph' })
}, [formState])
return (
<>
<div className="input">
<label>Graph Type</label>
<select
name="graphType"
value={formState.graphType || 'line'}
onChange={handleChange}
>
<option value="line">Line</option>
<option value="points">Points</option>
<option value="lineAndPoints">Line + Points</option>
<option value="bar">Bar</option>
</select>
</div>
<div className="input">
<label>Unit</label>
<input name="unit" value={formState.unit} onChange={handleChange} />
</div>
<div className="input">
<label>Min value</label>
<input name="min" value={formState.min} onChange={handleChange} />
</div>
<div className="input">
<label>Max value</label>
<input name="max" value={formState.max} onChange={handleChange} />
</div>
</>
)
}

View File

@ -1,12 +1,11 @@
import { getElementPosition } from '@/utils/getElementPosition'
import { useWindowEvent } from '@/utils/hooks/useWindowEvent'
import { useRef, useState } from 'preact/hooks'
import { GRID_WIDTH } from '../constants'
import { ResizingMode, useResize } from '../hooks/useResize'
import { useDragging } from '../hooks/useDragging'
import { ResizingMode, useResize } from '../hooks/useResize'
import { BoxDefinition } from '../types'
import { BoxSettings } from './BoxSettings'
import { BoxGraphContent } from './BoxGraphContent'
import { BoxSettings } from './BoxSettings/BoxSettings'
type Props = {
box: BoxDefinition
@ -46,7 +45,10 @@ export const EditableBox = ({
e.preventDefault()
if (!dragging.active && boxRef.current) {
const pos = getElementPosition(boxRef.current)
const pos = {
top: boxRef.current.offsetTop,
left: boxRef.current.offsetLeft,
}
setDragging({
active: true,
@ -115,7 +117,9 @@ export const EditableBox = ({
</div>
</div>
<div className="body">
{box.sensor && <BoxGraphContent box={box} />}
{box.sensor && box.data?.type === 'graph' && (
<BoxGraphContent box={box} data={box.data} />
)}
</div>
<div

View File

@ -11,6 +11,11 @@ export type DashboardContentBox = {
h: number
sensor?: string
title?: string
data?: DashboardGraphData
}
export type DashboardGraphData = {
type: 'graph'
min?: string
max?: string
unit?: string