Улучшен вывод значений на экран на ННБ, Мониторинге и Архиве

This commit is contained in:
goodmice 2022-07-19 10:20:06 +05:00
parent 600c752675
commit c3b48d210c
5 changed files with 61 additions and 28 deletions

View File

@ -2,6 +2,8 @@ import { Button } from 'antd'
import { memo, ReactNode, useMemo } from 'react'
import { CloseOutlined, SettingOutlined } from '@ant-design/icons'
import { makeDisplayValue } from '@utils'
import '@styles/widgets/base.less'
export type WidgetSettings<T = any> = {
@ -19,13 +21,7 @@ export type WidgetSettings<T = any> = {
const emptyNumber = '----'
const defaultFormatter = (v: any) => {
if (typeof v === 'undefined' || v === null || String(v) === 'NaN') return emptyNumber
if (Number.isNaN(+v)) return v
const f = parseFloat(v)
if (Number.isFinite(v)) return f.toFixed(2)
return `${f < 0 ? '-' : ''}\u221E`
}
const defaultFormatter = makeDisplayValue({ def: emptyNumber, fixed: 2 })
export const defaultSettings: WidgetSettings = {
unit: '----',

View File

@ -1,39 +1,34 @@
import { BarChartOutlined, LineChartOutlined, DotChartOutlined, AreaChartOutlined, BorderOuterOutlined } from '@ant-design/icons'
import { Grid, GridItem } from '@components/Grid'
import { Fragment } from 'react'
import { Grid, GridItem } from '@components/Grid'
import { getChartIcon, makeDisplayValue } from '@utils'
const defaultFormater = makeDisplayValue({ def: '---', fixed: 2 })
const defaultValueRender = (v, unit) => (
<>{defaultFormater(v)} {unit ?? ''}</>
)
export const cursorRender = (group, data) => {
const d = data.length > 0 ? data[0] : {}
if (group.charts.length <= 0) return <></>
const firstChart = group.charts[0]
const y = firstChart.y(d)
const yValue = firstChart.yAxis.format?.(y) ?? `${(+y).toFixed(2)} ${firstChart.yAxis.unit ?? ''}`
const yFormat = (chart) => {
const yValue = firstChart.yAxis.format?.(y) ?? defaultValueRender(y, chart.yAxis.unit)
const xFormat = (chart) => {
const v = chart.x(d)
return chart.xAxis.format?.(v) ?? `${(+v)?.toFixed(2)} ${chart.xAxis.unit ?? ''}`
return chart.xAxis.format?.(v) ?? defaultValueRender(v, chart.xAxis.unit)
}
return (
<Grid>
<GridItem row={1} col={1} colSpan={4}>{yValue}</GridItem>
{group.charts.map((chart, i) => {
let Icon
switch (chart.type) {
case 'needle': Icon = BarChartOutlined; break
case 'line': Icon = LineChartOutlined; break
case 'point': Icon = DotChartOutlined; break
case 'area': Icon = AreaChartOutlined; break
case 'rect_area': Icon = BorderOuterOutlined; break
}
const d = data[0]
return (
<Fragment key={chart.key}>
<GridItem row={i+2} col={1} style={{ padding: '4px 0' }}><Icon style={{ color: chart.color }} /></GridItem>
<GridItem row={i+2} col={1} style={{ padding: '4px 0' }}>{getChartIcon(chart)}</GridItem>
<GridItem row={i+2} col={2}>{chart.shortLabel || chart.label}</GridItem>
<GridItem row={i+2} col={3} style={{ paddingRight: 0 }}>{yFormat(chart)}</GridItem>
<GridItem row={i+2} col={3} style={{ paddingRight: 0 }}>{xFormat(chart)}</GridItem>
</Fragment>
)
})}

View File

@ -38,7 +38,7 @@ const { Option } = Select
const yAxis = {
type: 'time',
accessor: (d) => new Date(d.date),
format: (d) => formatDate(d),
format: (d) => formatDate(d, undefined, 'YYYY-MM-DD HH:mm:ss'),
}
const dash = [7, 3]
@ -251,7 +251,7 @@ const TelemetryView = memo(() => {
yDomain={domain}
yTicks={{
visible: true,
format: (d) => formatDate(d)
format: (d) => formatDate(d, 'YYYY-MM-DD')
}}
plugins={{
menu: { enabled: false },

View File

@ -1,3 +1,8 @@
import { BarChartOutlined, LineChartOutlined, DotChartOutlined, AreaChartOutlined, BorderOuterOutlined, } from '@ant-design/icons'
import { AntdIconProps } from '@ant-design/icons/lib/components/AntdIcon'
import { ChartDataset } from '@components/d3'
export const makePointsOptimizator = <DataType extends Record<string, unknown>>(isEquals: (a: DataType, b: DataType) => boolean) => (points: DataType[]) => {
if (!Array.isArray(points) || points.length < 3) return points
@ -17,3 +22,16 @@ export const getDistance = (x1: number, y1: number, x2: number, y2: number, type
return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2))
}
export const getChartIcon = <DataType,>(chart: ChartDataset<DataType>, options: Omit<AntdIconProps, 'ref'>) => {
let Icon
switch (chart.type) {
case 'needle': Icon = BarChartOutlined; break
case 'line': Icon = LineChartOutlined; break
case 'point': Icon = DotChartOutlined; break
case 'area': Icon = AreaChartOutlined; break
case 'rect_area': Icon = BorderOuterOutlined; break
}
return <Icon { ...options } style={{ color: chart.color, ...options?.style }} />
}

View File

@ -1,3 +1,5 @@
import { ReactNode } from 'react'
export const getPrecision = (number: number, def: string = '-', fixed: number = 2): string => Number.isFinite(number) ? number.toFixed(fixed) : def
/**
@ -7,7 +9,7 @@ export const getPrecision = (number: number, def: string = '-', fixed: number =
* @param max Максимальное значение
* @returns Функция, ограничивающая значение в диапазоне [`min`; `max`]
*/
export const limitValue = <T>(min: T, max: T) => (value: T) => {
export const limitValue = <T,>(min: T, max: T) => (value: T) => {
if (value > max) return max
if (value < min) return min
return value
@ -22,3 +24,25 @@ export const limitValue = <T>(min: T, max: T) => (value: T) => {
* @returns Массив чисел в диапазоне от `start` до `end`
*/
export const range = (end: number, start: number = 0) => Array.from({ length: end - start }, (_, i) => start + i)
export type DisplayValueOptions = {
def?: ReactNode
inf?: ReactNode | ((v: number) => ReactNode)
fixed?: number
}
export const makeDisplayValue = ({
def = '----',
inf = (v) => `${v < 0 ? '-' : ''}\u221E`,
fixed = 2
}: DisplayValueOptions) => (v: unknown): ReactNode => {
if (typeof v === 'undefined' || v === null || String(v) === 'NaN') return def
let f = Number(v)
if (typeof v === 'string') {
if (Number.isNaN(+v)) return v
f = parseFloat(v)
}
if (Number.isFinite(f)) return f.toFixed(fixed)
return typeof inf === 'function' ? inf(f) : inf
}