Обновлены пакеты

This commit is contained in:
goodmice 2022-10-03 20:17:58 +05:00
parent 01f499b85d
commit b2feb95e82
No known key found for this signature in database
GPG Key ID: 63EA771203189CF1
15 changed files with 7404 additions and 5180 deletions

12463
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,7 @@ import {
D3TooltipSettings,
} from './plugins'
import type {
BaseDataType,
ChartAxis,
ChartDataset,
ChartDomain,
@ -50,13 +51,13 @@ export const getByAccessor = <DataType extends Record<any, any>, R>(accessor: ke
return (d) => d[accessor]
}
const createAxis = <DataType,>(config: ChartAxis<DataType>) => {
const createAxis = <DataType extends BaseDataType>(config: ChartAxis<DataType>) => {
if (config.type === 'time')
return d3.scaleTime()
return d3.scaleLinear()
}
export type D3ChartProps<DataType> = React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> & {
export type D3ChartProps<DataType extends BaseDataType> = React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> & {
/** Параметры общей горизонтальной оси */
xAxis: ChartAxis<DataType>
/** Параметры графиков */
@ -94,7 +95,7 @@ export type D3ChartProps<DataType> = React.DetailedHTMLProps<React.HTMLAttribute
}
}
const getDefaultXAxisConfig = <DataType,>(): ChartAxis<DataType> => ({
const getDefaultXAxisConfig = <DataType extends BaseDataType>(): ChartAxis<DataType> => ({
type: 'time',
accessor: (d: any) => new Date(d.date)
})

View File

@ -6,13 +6,14 @@ import { useD3MouseZone } from '@components/d3/D3MouseZone'
import { D3TooltipPosition } from '@components/d3/plugins/D3Tooltip'
import { getChartIcon, isDev, usePartialProps } from '@utils'
import { BaseDataType } from '../types'
import { ChartGroup, ChartSizes } from './D3MonitoringCharts'
import '@styles/d3.less'
type D3GroupRenderFunction<DataType> = (group: ChartGroup<DataType>, data: DataType[]) => ReactNode
type D3GroupRenderFunction<DataType extends BaseDataType> = (group: ChartGroup<DataType>, data: DataType[]) => ReactNode
export type D3HorizontalCursorSettings<DataType> = {
export type D3HorizontalCursorSettings<DataType extends BaseDataType> = {
width?: number
height?: number
render?: D3GroupRenderFunction<DataType>
@ -23,7 +24,7 @@ export type D3HorizontalCursorSettings<DataType> = {
lineStyle?: SVGProps<SVGLineElement>
}
export type D3HorizontalCursorProps<DataType> = D3HorizontalCursorSettings<DataType> & {
export type D3HorizontalCursorProps<DataType extends BaseDataType> = D3HorizontalCursorSettings<DataType> & {
groups: ChartGroup<DataType>[]
data: DataType[]
sizes: ChartSizes
@ -37,7 +38,7 @@ const defaultLineStyle: SVGProps<SVGLineElement> = {
const offsetY = 5
const makeDefaultRender = <DataType,>(): D3GroupRenderFunction<DataType> => (group, data) => (
const makeDefaultRender = <DataType extends BaseDataType>(): D3GroupRenderFunction<DataType> => (group, data) => (
<>
{data.length > 0 ? group.charts.map((chart) => {
const xFormat = (d: number | Date) => chart.xAxis.format?.(d) ?? `${(+d).toFixed(2)} ${chart.xAxis.unit ?? ''}`
@ -62,7 +63,7 @@ const makeDefaultRender = <DataType,>(): D3GroupRenderFunction<DataType> => (gro
</>
)
const _D3HorizontalCursor = <DataType,>({
const _D3HorizontalCursor = <DataType extends BaseDataType>({
spaceBetweenGroups = 30,
height = 200,
render = makeDefaultRender<DataType>(),

View File

@ -1,7 +1,7 @@
import { Button, Checkbox, Form, FormItemProps, Input, InputNumber, Select, Tooltip } from 'antd'
import { memo, useCallback, useEffect, useMemo } from 'react'
import { MinMax } from '@components/d3/types'
import { BaseDataType, MinMax } from '@components/d3/types'
import { ColorPicker, Color } from '@components/ColorPicker'
import { ExtendedChartDataset } from './D3MonitoringCharts'
@ -18,13 +18,13 @@ const lineTypes = [
{ value: 'needle', label: 'Иглы' },
]
export type D3MonitoringChartEditorProps<DataType> = {
export type D3MonitoringChartEditorProps<DataType extends BaseDataType> = {
group: ExtendedChartDataset<DataType>[]
chart: ExtendedChartDataset<DataType>
onChange: (value: ExtendedChartDataset<DataType>) => boolean
}
const _D3MonitoringChartEditor = <DataType,>({
const _D3MonitoringChartEditor = <DataType extends BaseDataType>({
group,
chart: value,
onChange,
@ -93,8 +93,8 @@ const _D3MonitoringChartEditor = <DataType,>({
</Item>
<Item label={'Диапазон'}>
<Input.Group compact>
<InputNumber disabled={!!value.linkedTo} value={value.xDomain?.min} onChange={(min) => onDomainChange({ min })} placeholder={'Мин'} />
<InputNumber disabled={!!value.linkedTo} value={value.xDomain?.max} onChange={(max) => onDomainChange({ max })} placeholder={'Макс'} />
<InputNumber disabled={!!value.linkedTo} value={value.xDomain?.min} onChange={(min) => onDomainChange({ min: min ?? undefined })} placeholder={'Мин'} />
<InputNumber disabled={!!value.linkedTo} value={value.xDomain?.max} onChange={(max) => onDomainChange({ max: max ?? undefined })} placeholder={'Макс'} />
<Button
disabled={!!value.linkedTo || (!Number.isFinite(value.xDomain?.min) && !Number.isFinite(value.xDomain?.max))}
onClick={() => onDomainChange({ min: undefined, max: undefined })}

View File

@ -8,6 +8,7 @@ import LoaderPortal from '@components/LoaderPortal'
import { isDev, usePartialProps, useUserSettings } from '@utils'
import {
BaseDataType,
ChartAxis,
ChartDataset,
ChartOffset,
@ -51,7 +52,7 @@ const calculateDomain = (mm: MinMax): Required<MinMax> => {
return { min, max }
}
export type ExtendedChartDataset<DataType> = ChartDataset<DataType> & {
export type ExtendedChartDataset<DataType extends BaseDataType> = ChartDataset<DataType> & {
/** Диапазон отображаемых значений по горизонтальной оси */
xDomain: MinMax
/** Скрыть отображение шкалы графика */
@ -60,9 +61,9 @@ export type ExtendedChartDataset<DataType> = ChartDataset<DataType> & {
showCurrentValue?: boolean
}
export type ExtendedChartRegistry<DataType> = ChartRegistry<DataType> & ExtendedChartDataset<DataType>
export type ExtendedChartRegistry<DataType extends BaseDataType> = ChartRegistry<DataType> & ExtendedChartDataset<DataType>
export type ChartGroup<DataType> = {
export type ChartGroup<DataType extends BaseDataType> = {
/** Получить D3 выборку, содержащую корневой G-элемент группы */
(): d3.Selection<SVGGElement, any, any, any>
/** Уникальный ключ группы (индекс) */
@ -86,12 +87,12 @@ const defaultRegulators: TelemetryRegulators = {
5: { color: '#007070', label: 'Расход' },
}
const getDefaultYAxisConfig = <DataType,>(): ChartAxis<DataType> => ({
const getDefaultYAxisConfig = <DataType extends BaseDataType>(): ChartAxis<DataType> => ({
type: 'time',
accessor: (d: any) => new Date(d.date)
})
const getDefaultYTicks = <DataType,>(): Required<ChartTick<DataType>> => ({
const getDefaultYTicks = <DataType extends BaseDataType>(): Required<ChartTick<DataType>> => ({
visible: false,
format: (d: d3.NumberValue, idx: number, data?: DataType) => String(d),
color: 'lightgray',
@ -101,7 +102,7 @@ const getDefaultYTicks = <DataType,>(): Required<ChartTick<DataType>> => ({
/**
* @template DataType тип данных отображаемых записей
*/
export type D3MonitoringChartsProps<DataType extends Record<string, any>> = Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, 'ref'> & {
export type D3MonitoringChartsProps<DataType extends BaseDataType> = Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, 'ref'> & {
/** Двумерный массив датасетов (группа-график) */
datasetGroups: ExtendedChartDataset<DataType>[][]
/** Ширина графика числом пикселей или CSS-значением (px/%/em/rem) */

View File

@ -1,9 +1,10 @@
import { memo } from 'react'
import { BaseDataType } from '@components/d3/types'
import { ChartGroup, ChartSizes } from '@components/d3/monitoring/D3MonitoringCharts'
import { makeDisplayValue } from '@utils'
export type D3MonitoringCurrentValuesProps<DataType> = {
export type D3MonitoringCurrentValuesProps<DataType extends BaseDataType> = {
groups: ChartGroup<DataType>[]
data: DataType[]
left: number
@ -12,7 +13,7 @@ export type D3MonitoringCurrentValuesProps<DataType> = {
const display = makeDisplayValue({ def: '---', fixed: 2 })
const _D3MonitoringCurrentValues = <DataType,>({ groups, data, left, sizes }: D3MonitoringCurrentValuesProps<DataType>) => (
const _D3MonitoringCurrentValues = <DataType extends BaseDataType>({ groups, data, left, sizes }: D3MonitoringCurrentValuesProps<DataType>) => (
<g transform={`translate(${left}, ${sizes.chartsTop})`} pointerEvents={'none'}>
{groups.map((group) => (
<g key={group.key} transform={`translate(${sizes.groupLeft(group.key)}, 0)`}>

View File

@ -1,17 +1,18 @@
import { CSSProperties, Key, memo, useCallback, useEffect, useMemo, useState } from 'react'
import { Button, Divider, Empty, Modal, Popconfirm, Tooltip, Tree } from 'antd'
import { Button, Divider, Empty, Modal, Popconfirm, Tooltip, Tree, TreeDataNode } from 'antd'
import { UndoOutlined } from '@ant-design/icons'
import { EventDataNode } from 'antd/lib/tree'
import { notify } from '@components/factory'
import { getChartIcon } from '@utils'
import { BaseDataType } from '../types'
import { ExtendedChartDataset } from './D3MonitoringCharts'
import { TelemetryRegulators } from './D3MonitoringLimitChart'
import D3MonitoringChartEditor from './D3MonitoringChartEditor'
import D3MonitoringLimitEditor from './D3MonitoringLimitEditor'
export type D3MonitoringGroupsEditorProps<DataType> = {
export type D3MonitoringGroupsEditorProps<DataType extends BaseDataType> = {
visible?: boolean
groups: ExtendedChartDataset<DataType>[][]
regulators: TelemetryRegulators
@ -20,7 +21,7 @@ export type D3MonitoringGroupsEditorProps<DataType> = {
onReset: () => void
}
const getChartLabel = <DataType,>(chart: ExtendedChartDataset<DataType>) => (
const getChartLabel = <DataType extends BaseDataType>(chart: ExtendedChartDataset<DataType>) => (
<Tooltip title={chart.label}>
{getChartIcon(chart)} {chart.label}
</Tooltip>
@ -34,14 +35,14 @@ const divStyle: CSSProperties = {
flexGrow: 1,
}
const getNodePos = (node: EventDataNode): { group: number, chart?: number } => {
const getNodePos = (node: EventDataNode<TreeDataNode>): { group: number, chart?: number } => {
const out = node.pos.split('-').map(Number)
return { group: out[1], chart: out[2] }
}
type EditingMode = null | 'limit' | 'chart'
const _D3MonitoringEditor = <DataType,>({
const _D3MonitoringEditor = <DataType extends BaseDataType>({
visible,
groups: oldGroups,
regulators: oldRegulators,
@ -61,8 +62,8 @@ const _D3MonitoringEditor = <DataType,>({
const onModalOk = useCallback(() => onChange(groups, regulators), [groups, regulators])
const onDrop = useCallback((info: {
node: EventDataNode
dragNode: EventDataNode
node: EventDataNode<TreeDataNode>
dragNode: EventDataNode<TreeDataNode>
dropPosition: number
}) => {
const { dragNode, dropPosition, node } = info
@ -152,12 +153,12 @@ const _D3MonitoringEditor = <DataType,>({
<Tree
draggable
selectable
onExpand={(keys) => setExpand(keys)}
onExpand={(keys: Key[]) => setExpand(keys)}
expandedKeys={expand}
selectedKeys={selected}
treeData={treeItems}
onDrop={onDrop}
onSelect={(value) => {
onSelect={(value: Key[]) => {
setSelected(value)
setMode('chart')
}}

View File

@ -2,7 +2,7 @@ import { useEffect, useMemo, useRef } from 'react'
import { Property } from 'csstype'
import * as d3 from 'd3'
import { ChartRegistry } from '@components/d3/types'
import { BaseDataType, ChartRegistry } from '@components/d3/types'
import { useD3MouseZone } from '@components/d3/D3MouseZone'
import { usePartialProps } from '@utils'
@ -32,12 +32,12 @@ export type D3LegendSettings = {
const defaultOffset = { x: 10, y: 10 }
export type D3LegendProps<DataType> = D3LegendSettings & {
export type D3LegendProps<DataType extends BaseDataType> = D3LegendSettings & {
/** Массив графиков */
charts: ChartRegistry<DataType>[]
}
const _D3Legend = <DataType,>({
const _D3Legend = <DataType extends BaseDataType>({
charts,
width,
height,

View File

@ -4,7 +4,7 @@ import * as d3 from 'd3'
import { isDev } from '@utils'
import { ChartRegistry } from '@components/d3/types'
import { BaseDataType, ChartRegistry } from '@components/d3/types'
import { D3MouseState, useD3MouseZone } from '@components/d3/D3MouseZone'
import { getTouchedElements, wrapPlugin } from './base'
@ -12,7 +12,7 @@ import '@styles/d3.less'
export type D3TooltipPosition = 'bottom' | 'top' | 'left' | 'right' | 'none'
export type D3RenderData<DataType> = {
export type D3RenderData<DataType extends BaseDataType> = {
/** Параметры графика */
chart: ChartRegistry<DataType>
/** Данные графика */
@ -21,9 +21,9 @@ export type D3RenderData<DataType> = {
selection?: d3.Selection<any, DataType, any, any>
}
export type D3RenderFunction<DataType> = (data: D3RenderData<DataType>[], mouseState: D3MouseState) => ReactNode
export type D3RenderFunction<DataType extends BaseDataType> = (data: D3RenderData<DataType>[], mouseState: D3MouseState) => ReactNode
export type D3TooltipSettings<DataType> = {
export type D3TooltipSettings<DataType extends BaseDataType> = {
/** Функция отрисоки тултипа */
render?: D3RenderFunction<DataType>
/** Ширина тултипа */
@ -39,7 +39,7 @@ export type D3TooltipSettings<DataType> = {
limit?: number
}
export const makeDefaultRender = <DataType,>(): D3RenderFunction<DataType> => (data, mouseState) => (
export const makeDefaultRender = <DataType extends BaseDataType>(): D3RenderFunction<DataType> => (data, mouseState) => (
<>
{data.length > 0 ? data.map(({ chart, data }) => {
let Icon
@ -74,11 +74,11 @@ export const makeDefaultRender = <DataType,>(): D3RenderFunction<DataType> => (d
</>
)
export type D3TooltipProps<DataType> = Partial<D3TooltipSettings<DataType>> & {
export type D3TooltipProps<DataType extends BaseDataType> = Partial<D3TooltipSettings<DataType>> & {
charts: ChartRegistry<DataType>[],
}
function _D3Tooltip<DataType extends Record<string, unknown>>({
function _D3Tooltip<DataType extends BaseDataType>({
width = 200,
height = 120,
render = makeDefaultRender<DataType>(),

View File

@ -3,7 +3,7 @@ import * as d3 from 'd3'
import { getDistance, TouchType } from '@utils'
import { ChartRegistry } from '../types'
import { BaseDataType, ChartRegistry } from '../types'
export type BasePluginSettings = {
enabled?: boolean
@ -16,7 +16,7 @@ export const wrapPlugin = <TProps,>(
const wrappedComponent = ({ enabled, ...props }: TProps & BasePluginSettings) => {
if (!(enabled ?? defaultEnabled)) return <></>
return <Component {...(props as TProps)} />
return <Component {...(props as (TProps & JSX.IntrinsicAttributes))} /> // IntrinsicAttributes добавлено как необходимое ограничение
}
return wrappedComponent
@ -89,7 +89,7 @@ const makeIsRectTouched = (x: number, y: number, limit: number, type: TouchType
}
}
export const getTouchedElements = <DataType,>(
export const getTouchedElements = <DataType extends BaseDataType>(
chart: ChartRegistry<DataType>,
x: number,
y: number,

View File

@ -1,8 +1,8 @@
import * as d3 from 'd3'
import { ChartRegistry } from '../types'
import { BaseDataType, ChartRegistry } from '../types'
export const appendTransition = <DataType, BaseType extends d3.BaseType, Datum, PElement extends d3.BaseType, PDatum>(
export const appendTransition = <DataType extends BaseDataType, BaseType extends d3.BaseType, Datum, PElement extends d3.BaseType, PDatum>(
elms: d3.Selection<BaseType, Datum, PElement, PDatum>,
chart: ChartRegistry<DataType>
): d3.Selection<BaseType, Datum, PElement, PDatum> => {

View File

@ -1,4 +1,4 @@
import { ChartRegistry, PointChartDataset } from '@components/d3/types'
import { BaseDataType, ChartRegistry, PointChartDataset } from '@components/d3/types'
import { appendTransition } from './base'
@ -12,7 +12,7 @@ const defaultConfig: Required<Omit<PointChartDataset, 'type'>> = {
fillOpacity: 1,
}
const getPointsRoot = <DataType,>(chart: ChartRegistry<DataType>, embeded?: boolean): d3.Selection<SVGGElement, any, any, any> => {
const getPointsRoot = <DataType extends BaseDataType>(chart: ChartRegistry<DataType>, embeded?: boolean): d3.Selection<SVGGElement, any, any, any> => {
const root = chart()
if (!embeded) return root
if (root.select('.points').empty())

View File

@ -1,9 +1,9 @@
import { getByAccessor } from '@components/d3/functions'
import { ChartRegistry } from '@components/d3/types'
import { BaseDataType, ChartRegistry } from '@components/d3/types'
import { appendTransition } from './base'
export const renderRectArea = <DataType extends Record<string, any>>(
export const renderRectArea = <DataType extends BaseDataType>(
xAxis: (value: d3.NumberValue) => number,
yAxis: (value: d3.NumberValue) => number,
chart: ChartRegistry<DataType>

View File

@ -3,9 +3,11 @@ import { Property } from 'csstype'
import { D3TooltipSettings } from './plugins'
export type AxisAccessor<DataType extends Record<string, any>> = keyof DataType | ((d: DataType) => any)
export type BaseDataType = Record<string, any>
export type ChartAxis<DataType> = {
export type AxisAccessor<DataType extends BaseDataType> = keyof DataType | ((d: DataType) => any)
export type ChartAxis<DataType extends BaseDataType> = {
/** Тип шкалы */
type: 'linear' | 'time',
/** Ключ записи или метод по которому будет извлекаться значение оси из массива данных */
@ -34,7 +36,7 @@ export type PointChartDataset = {
fillOpacity?: number
}
export type BaseChartDataset<DataType> = {
export type BaseChartDataset<DataType extends BaseDataType> = {
/** Уникальный ключ графика */
key: string | number
/** Параметры вертикальной оси */
@ -101,7 +103,7 @@ export type NeedleChartDataset = {
type: 'needle'
}
export type ChartDataset<DataType> = BaseChartDataset<DataType> & (
export type ChartDataset<DataType extends BaseDataType> = BaseChartDataset<DataType> & (
AreaChartDataset |
LineChartDataset |
NeedleChartDataset |
@ -154,7 +156,7 @@ export type ChartTicks<DataType> = {
y?: ChartTick<DataType>
}
export type ChartRegistry<DataType> = ChartDataset<DataType> & {
export type ChartRegistry<DataType extends BaseDataType> = ChartDataset<DataType> & {
/** Получить D3 выборку, содержащую корневой G-элемент графика */
(): d3.Selection<SVGGElement, DataType, any, any>
/** Получить значение по вертикальной оси из предоставленой записи */

View File

@ -1,9 +1,9 @@
import { BarChartOutlined, LineChartOutlined, DotChartOutlined, AreaChartOutlined, BorderOuterOutlined, } from '@ant-design/icons'
import { AntdIconProps } from '@ant-design/icons/lib/components/AntdIcon'
import { ChartDataset } from '@components/d3'
import { BaseDataType, ChartDataset } from '@components/d3'
export const makePointsOptimizator = <DataType extends Record<string, unknown>>(isEquals: (a: DataType, b: DataType) => boolean) => (points: DataType[]) => {
export const makePointsOptimizator = <DataType extends BaseDataType>(isEquals: (a: DataType, b: DataType) => boolean) => (points: DataType[]) => {
if (!Array.isArray(points) || points.length < 3) return points
const out: DataType[] = []
@ -23,7 +23,7 @@ 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'>) => {
export const getChartIcon = <DataType extends BaseDataType>(chart: ChartDataset<DataType>, options?: Omit<AntdIconProps, 'ref'>) => {
let Icon
switch (chart.type) {
case 'needle': Icon = BarChartOutlined; break