* Добавлено редактирование привязки

* Исправлено сохранение
This commit is contained in:
goodmice 2022-08-11 17:14:36 +05:00
parent a8613e6b75
commit 934eab2f3c
6 changed files with 137 additions and 75 deletions

View File

@ -1,5 +1,5 @@
import { Button, Form, FormItemProps, Input, InputNumber, Select, Tooltip } from 'antd' import { Button, Form, FormItemProps, Input, InputNumber, Select, Tooltip } from 'antd'
import { CSSProperties, memo, useCallback, useEffect, useMemo, useState } from 'react' import { memo, useCallback, useEffect, useMemo } from 'react'
import { ColorPicker, Color } from '../ColorPicker' import { ColorPicker, Color } from '../ColorPicker'
import { ExtendedChartDataset } from './D3MonitoringCharts' import { ExtendedChartDataset } from './D3MonitoringCharts'
@ -18,11 +18,13 @@ const lineTypes = [
] ]
export type D3MonitoringChartEditorProps<DataType> = { export type D3MonitoringChartEditorProps<DataType> = {
group: ExtendedChartDataset<DataType>[]
chart: ExtendedChartDataset<DataType> chart: ExtendedChartDataset<DataType>
onChange: (value: ExtendedChartDataset<DataType>) => boolean onChange: (value: ExtendedChartDataset<DataType>) => boolean
} }
const _D3MonitoringChartEditor = <DataType,>({ const _D3MonitoringChartEditor = <DataType,>({
group,
chart: value, chart: value,
onChange, onChange,
}: D3MonitoringChartEditorProps<DataType>) => { }: D3MonitoringChartEditorProps<DataType>) => {
@ -30,6 +32,7 @@ const _D3MonitoringChartEditor = <DataType,>({
const onSave = useCallback((props: Partial<ExtendedChartDataset<DataType>>) => { const onSave = useCallback((props: Partial<ExtendedChartDataset<DataType>>) => {
const values = form.getFieldsValue() const values = form.getFieldsValue()
if (!values['label']) return
const newValue = { const newValue = {
...value, ...value,
...values, ...values,
@ -51,16 +54,34 @@ const _D3MonitoringChartEditor = <DataType,>({
useEffect(() => { useEffect(() => {
if (value.type) if (value.type)
form.setFieldsValue(value) form.setFieldsValue({
linkedTo: null,
label: null,
shortLabel: null,
...value,
})
else else
form.resetFields() form.resetFields()
}, [value, form]) }, [value, form])
const options = useMemo(() => group.filter((chart) => chart.key !== value.key).map((chart) => ({
value: chart.key,
label: chart.label,
})), [group, value])
return ( return (
<Form form={form}> <Form form={form}>
<Tooltip title={'Возможность изменения типов линий будет добавлена в будущих обновлениях'}> <Tooltip title={'Возможность изменения типов линий будет добавлена в будущих обновлениях'}>
<Item label={'Тип'}><Select disabled value={value.type ?? 'Неизвестный'} options={lineTypes} /></Item> <Item label={'Тип'} name={'type'}><Select disabled options={lineTypes} defaultValue={'Неизвестный'} /></Item>
</Tooltip> </Tooltip>
<Item label={'Привязан к'} name={'linkedTo'}>
<Select
allowClear
options={options}
defaultValue={'Привязанный график отсутствует в группе'}
onChange={(value) => onSave({ linkedTo: value })}
/>
</Item>
<Item label={'Название'}> <Item label={'Название'}>
<Input.Group compact> <Input.Group compact>
<Item name={'label'} rules={[{ required: true }]}><Input placeholder={'Полное'} onChange={(e) => onSave({ label: e.target.value })} /></Item> <Item name={'label'} rules={[{ required: true }]}><Input placeholder={'Полное'} onChange={(e) => onSave({ label: e.target.value })} /></Item>
@ -69,10 +90,10 @@ const _D3MonitoringChartEditor = <DataType,>({
</Item> </Item>
<Item label={'Диапазон'}> <Item label={'Диапазон'}>
<Input.Group compact> <Input.Group compact>
<InputNumber value={value.xDomain?.min} onChange={(min) => onDomainChange({ min })} placeholder={'Мин'} /> <InputNumber disabled={!!value.linkedTo} value={value.xDomain?.min} onChange={(min) => onDomainChange({ min })} placeholder={'Мин'} />
<InputNumber value={value.xDomain?.max} onChange={(max) => onDomainChange({ max })} placeholder={'Макс'} /> <InputNumber disabled={!!value.linkedTo} value={value.xDomain?.max} onChange={(max) => onDomainChange({ max })} placeholder={'Макс'} />
<Button <Button
disabled={!Number.isFinite(value.xDomain?.min) && !Number.isFinite(value.xDomain?.max)} disabled={!!value.linkedTo || (!Number.isFinite(value.xDomain?.min) && !Number.isFinite(value.xDomain?.max))}
onClick={() => onDomainChange({ min: undefined, max: undefined })} onClick={() => onDomainChange({ min: undefined, max: undefined })}
>Авто</Button> >Авто</Button>
</Input.Group> </Input.Group>

View File

@ -5,7 +5,9 @@ import { Empty } from 'antd'
import * as d3 from 'd3' import * as d3 from 'd3'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { isDev, usePartialProps } from '@utils' import { isDev, usePartialProps } from '@utils'
import { UserSettingsService } from '@api'
import { import {
ChartAxis, ChartAxis,
@ -23,22 +25,25 @@ import {
D3HorizontalCursorSettings D3HorizontalCursorSettings
} from './plugins' } from './plugins'
import D3MouseZone from './D3MouseZone' import D3MouseZone from './D3MouseZone'
import D3MonitoringGroupsEditor from './D3MonitoringGroupsEditor'
import { getByAccessor, getChartClass, getGroupClass, getTicks } from './functions' import { getByAccessor, getChartClass, getGroupClass, getTicks } from './functions'
import { renderArea, renderLine, renderNeedle, renderPoint, renderRectArea } from './renders' import { renderArea, renderLine, renderNeedle, renderPoint, renderRectArea } from './renders'
import D3MonitoringGroupsEditor from './D3MonitoringGroupsEditor'
import { UserSettingsService } from '@asb/services/api'
import { invokeWebApiWrapperAsync } from '../factory'
const roundTo = (v: number, to: number = 50) => { const roundTo = (v: number, to: number = 50) => {
if (to == 0) return v if (v === 0) return v
if (v < 0) return Math.round(v / to) * to return (v > 0 ? Math.ceil : Math.round)(v / to) * to
return Math.ceil(v / to) * to
} }
const calculateDomain = (mm: MinMax, round: number = 100): Required<MinMax> => { const calculateDomain = (mm: MinMax): Required<MinMax> => {
let round = Math.abs((mm.max ?? 0) - (mm.min ?? 0))
if (round < 10) round = 10
else if (round < 100) round = roundTo(round, 10)
else if (round < 1000) round = roundTo(round, 100)
else if (round < 10000) round = roundTo(round, 1000)
else round = 0
let min = roundTo(mm.min ?? 0, round) let min = roundTo(mm.min ?? 0, round)
let max = roundTo(mm.max ?? round, round) let max = roundTo(mm.max ?? round, round)
if (min - max < round) { if (round && Math.abs(min - max) < round) {
const mid = (min + max) / 2 const mid = (min + max) / 2
min = mid - round min = mid - round
max = mid + round max = mid + round
@ -86,7 +91,7 @@ const getDefaultYTicks = <DataType,>(): Required<ChartTick<DataType>> => ({
/** /**
* @template DataType тип данных отображаемых записей * @template DataType тип данных отображаемых записей
*/ */
export type D3MonitoringChartsProps<DataType extends Record<string, any>> = React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> & { export type D3MonitoringChartsProps<DataType extends Record<string, any>> = Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, 'ref'> & {
/** Двумерный массив датасетов (группа-график) */ /** Двумерный массив датасетов (группа-график) */
datasetGroups: ExtendedChartDataset<DataType>[][] datasetGroups: ExtendedChartDataset<DataType>[][]
/** Ширина графика числом пикселей или CSS-значением (px/%/em/rem) */ /** Ширина графика числом пикселей или CSS-значением (px/%/em/rem) */
@ -126,6 +131,9 @@ export type D3MonitoringChartsProps<DataType extends Record<string, any>> = Reac
spaceBetweenGroups?: number spaceBetweenGroups?: number
/** Название графика для сохранения в базе */ /** Название графика для сохранения в базе */
chartName?: string chartName?: string
methods?: (value: {
setSettingsVisible: (visible: boolean) => void
}) => void
} }
export type ChartSizes = ChartOffset & { export type ChartSizes = ChartOffset & {
@ -171,6 +179,7 @@ const _D3MonitoringCharts = <DataType extends Record<string, unknown>>({
spaceBetweenGroups = 30, spaceBetweenGroups = 30,
dash, dash,
chartName, chartName,
methods,
className = '', className = '',
...other ...other
@ -181,32 +190,8 @@ const _D3MonitoringCharts = <DataType extends Record<string, unknown>>({
const [yAxisRef, setYAxisRef] = useState<SVGGElement | null>(null) const [yAxisRef, setYAxisRef] = useState<SVGGElement | null>(null)
const [chartAreaRef, setChartAreaRef] = useState<SVGGElement | null>(null) const [chartAreaRef, setChartAreaRef] = useState<SVGGElement | null>(null)
const [axesAreaRef, setAxesAreaRef] = useState<SVGGElement | null>(null) const [axesAreaRef, setAxesAreaRef] = useState<SVGGElement | null>(null)
const [settingsVisible, setSettingsVisible] = useState<boolean>(true) const [settingsVisible, setSettingsVisible] = useState<boolean>(false)
useEffect(() => {
invokeWebApiWrapperAsync(
async () => {
let sets = chartName ? await UserSettingsService.get(chartName) : null
if (typeof sets === 'string')
sets = JSON.parse(sets)
if (Array.isArray(sets)) {
setDatasets(sets)
} else if (Array.isArray(datasetGroups)) {
setDatasets(datasetGroups)
if (chartName) {
invokeWebApiWrapperAsync(
async () => await UserSettingsService.insert(chartName, datasetGroups),
undefined,
'Не удалось сохранить настройки графиков'
)
}
}
},
undefined,
'Не удалось загрузить настройки графиков'
)
}, [datasetGroups, chartName])
const offset = usePartialProps(_offset, defaultOffsets) const offset = usePartialProps(_offset, defaultOffsets)
const yTicks = usePartialProps<Required<ChartTick<DataType>>>(_yTicks, getDefaultYTicks) const yTicks = usePartialProps<Required<ChartTick<DataType>>>(_yTicks, getDefaultYTicks)
const yAxisConfig = usePartialProps<ChartAxis<DataType>>(_yAxisConfig, getDefaultYAxisConfig) const yAxisConfig = usePartialProps<ChartAxis<DataType>>(_yAxisConfig, getDefaultYAxisConfig)
@ -258,7 +243,7 @@ const _D3MonitoringCharts = <DataType extends Record<string, unknown>>({
domain = mm as Required<MinMax> domain = mm as Required<MinMax>
} else if (data) { } else if (data) {
const [min, max] = d3.extent(data, chart.x) const [min, max] = d3.extent(data, chart.x)
domain = calculateDomain({ min, max, ...mm }, 100) domain = calculateDomain({ min, max, ...mm })
} }
return [chart.key, { return [chart.key, {
scale: d3.scaleLinear().domain([domain.min, domain.max]), scale: d3.scaleLinear().domain([domain.min, domain.max]),
@ -268,7 +253,7 @@ const _D3MonitoringCharts = <DataType extends Record<string, unknown>>({
out.forEach(([key], i) => { out.forEach(([key], i) => {
const chart = group.charts.find((chart) => chart.key === key) const chart = group.charts.find((chart) => chart.key === key)
const bind = chart?.bindDomainFrom const bind = chart?.linkedTo
if (!bind) return if (!bind) return
const bindDomain = out.find(([key]) => key === bind) const bindDomain = out.find(([key]) => key === bind)
if (bindDomain) if (bindDomain)
@ -284,7 +269,7 @@ const _D3MonitoringCharts = <DataType extends Record<string, unknown>>({
key: i, key: i,
charts: [], charts: [],
} }
), [chartArea, axesArea]) ), [chartArea])
const onGroupsChange = useCallback((sets: ExtendedChartDataset<DataType>[][]) => { const onGroupsChange = useCallback((sets: ExtendedChartDataset<DataType>[][]) => {
if (chartName) { if (chartName) {
@ -300,6 +285,44 @@ const _D3MonitoringCharts = <DataType extends Record<string, unknown>>({
setSettingsVisible(false) setSettingsVisible(false)
}, [chartName]) }, [chartName])
const onGroupsReset = useCallback(() => {
setSettingsVisible(false)
setDatasets(datasetGroups)
if (chartName) {
invokeWebApiWrapperAsync(
async () => await UserSettingsService.delete(chartName),
undefined,
'Не удалось удалить настройки графиков'
)
}
}, [datasetGroups, chartName])
useEffect(() => methods?.({ setSettingsVisible }), [methods])
useEffect(() => {
invokeWebApiWrapperAsync(
async () => {
let sets = chartName ? await UserSettingsService.get(chartName) : null
if (typeof sets === 'string')
sets = JSON.parse(sets)
if (Array.isArray(sets)) {
setDatasets(sets)
} else if (Array.isArray(datasetGroups)) {
setDatasets(datasetGroups)
if (chartName) {
invokeWebApiWrapperAsync(
async () => await UserSettingsService.insert(chartName, datasetGroups),
undefined,
'Не удалось сохранить настройки графиков'
)
}
}
},
undefined,
'Не удалось загрузить настройки графиков'
)
}, [datasetGroups, chartName])
useEffect(() => { useEffect(() => {
if (isDev()) { if (isDev()) {
datasets.forEach((sets, i) => { datasets.forEach((sets, i) => {
@ -374,7 +397,7 @@ const _D3MonitoringCharts = <DataType extends Record<string, unknown>>({
}, [yAxisConfig, chartArea, datasets, animDurationMs, createAxesGroup]) }, [yAxisConfig, chartArea, datasets, animDurationMs, createAxesGroup])
useEffect(() => { useEffect(() => {
const axesGroups = d3.select(axesAreaRef) const axesGroups = axesArea()
.selectAll('.charts-group') .selectAll('.charts-group')
.data(groups) .data(groups)
@ -383,7 +406,7 @@ const _D3MonitoringCharts = <DataType extends Record<string, unknown>>({
.append('g') .append('g')
.attr('class', 'charts-group') .attr('class', 'charts-group')
const actualAxesGroups = d3.select(axesAreaRef) const actualAxesGroups = axesArea()
.selectAll<SVGGElement | null, ChartGroup<DataType>>('.charts-group') .selectAll<SVGGElement | null, ChartGroup<DataType>>('.charts-group')
.attr('class', (g) => `charts-group ${getGroupClass(g.key)}`) .attr('class', (g) => `charts-group ${getGroupClass(g.key)}`)
.attr('transform', (g) => `translate(${sizes.groupLeft(g.key)}, 0)`) .attr('transform', (g) => `translate(${sizes.groupLeft(g.key)}, 0)`)
@ -436,7 +459,7 @@ const _D3MonitoringCharts = <DataType extends Record<string, unknown>>({
.attr('stroke', j === chartsData.length - 1 ? 'gray' : 'currentColor') .attr('stroke', j === chartsData.length - 1 ? 'gray' : 'currentColor')
}) })
}) })
}, [groups, sizes, spaceBetweenGroups, chartDomains]) }, [groups, sizes, spaceBetweenGroups, chartDomains, axesArea])
useEffect(() => { // Рисуем ось Y useEffect(() => { // Рисуем ось Y
if (!yAxis) return if (!yAxis) return
@ -566,11 +589,11 @@ const _D3MonitoringCharts = <DataType extends Record<string, unknown>>({
</div> </div>
)} )}
<D3MonitoringGroupsEditor <D3MonitoringGroupsEditor
name={chartName}
groups={datasets} groups={datasets}
visible={settingsVisible} visible={settingsVisible}
onChange={onGroupsChange} onChange={onGroupsChange}
onCancel={() => setSettingsVisible(false)} onCancel={() => setSettingsVisible(false)}
onReset={onGroupsReset}
/> />
</div> </div>
</LoaderPortal> </LoaderPortal>

View File

@ -1,5 +1,7 @@
import { CSSProperties, Key, memo, useCallback, useEffect, useMemo, useState } from 'react' import { CSSProperties, Key, memo, useCallback, useEffect, useMemo, useState } from 'react'
import { Divider, Empty, Modal, Tooltip, Tree } from 'antd' import { Button, Divider, Empty, Modal, Popconfirm, Tooltip, Tree } from 'antd'
import { UndoOutlined } from '@ant-design/icons'
import { EventDataNode } from 'antd/lib/tree'
import { getChartIcon } from '@utils' import { getChartIcon } from '@utils'
@ -12,7 +14,7 @@ export type D3MonitoringGroupsEditorProps<DataType> = {
groups: ExtendedChartDataset<DataType>[][] groups: ExtendedChartDataset<DataType>[][]
onChange: (value: ExtendedChartDataset<DataType>[][]) => void onChange: (value: ExtendedChartDataset<DataType>[][]) => void
onCancel: () => void onCancel: () => void
name?: string onReset: () => void
} }
const getChartLabel = <DataType,>(chart: ExtendedChartDataset<DataType>) => ( const getChartLabel = <DataType,>(chart: ExtendedChartDataset<DataType>) => (
@ -29,7 +31,7 @@ const divStyle: CSSProperties = {
flexGrow: 1, flexGrow: 1,
} }
const getNodePos = (node: any): { group: number, chart?: number } => { const getNodePos = (node: EventDataNode): { group: number, chart?: number } => {
const out = node.pos.split('-').map(Number) const out = node.pos.split('-').map(Number)
return { group: out[1], chart: out[2] } return { group: out[1], chart: out[2] }
} }
@ -39,6 +41,7 @@ const _D3MonitoringGroupsEditor = <DataType,>({
groups: oldGroups, groups: oldGroups,
onChange, onChange,
onCancel, onCancel,
onReset,
}: D3MonitoringGroupsEditorProps<DataType>) => { }: D3MonitoringGroupsEditorProps<DataType>) => {
const [groups, setGroups] = useState<ExtendedChartDataset<DataType>[][]>([]) const [groups, setGroups] = useState<ExtendedChartDataset<DataType>[][]>([])
const [expand, setExpand] = useState<Key[]>([]) const [expand, setExpand] = useState<Key[]>([])
@ -48,30 +51,37 @@ const _D3MonitoringGroupsEditor = <DataType,>({
const onModalOk = useCallback(() => onChange(groups), [groups]) const onModalOk = useCallback(() => onChange(groups), [groups])
const onDrop = useCallback((info: any) => { const onDrop = useCallback((info: {
node: EventDataNode
dragNode: EventDataNode
dropPosition: number
}) => {
const { dragNode, dropPosition, node } = info const { dragNode, dropPosition, node } = info
const targetNodes = getNodePos(node) const targetNodes = getNodePos(node)
const dragNodes = getNodePos(dragNode) const dragNodes = getNodePos(dragNode)
const groupPos = dragNodes.group const groupPos = dragNodes.group
if (!Number.isFinite(groupPos)) return if (!Number.isFinite(groupPos + dropPosition)) return
setGroups((prev) => { setGroups((prev) => {
if (typeof dragNodes.chart === 'undefined') { const chartPos = dragNodes.chart
if (typeof chartPos === 'undefined') {
const groups = [ ...prev ] const groups = [ ...prev ]
const movedGroups = groups.splice(dragNodes.group, 1) const movedGroups = groups.splice(groupPos, 1)
groups.splice(Math.max(dropPosition - 1, 0), 0, ...movedGroups) groups.splice(Math.max(dropPosition - 1, 0), 0, ...movedGroups)
return groups return groups
} else if (Number.isFinite(dragNodes.chart)) { } else if (Number.isFinite(chartPos)) {
if (groupPos !== targetNodes.group) { const targetGroup = targetNodes.group
const dragKey = prev[dragNodes.group][dragNodes.chart].key const dragKey = prev[groupPos][chartPos].key
if (prev[targetNodes.group].find((chart) => chart.key === dragKey)) { if (groupPos !== targetGroup) {
if (prev[targetGroup].find((chart) => chart.key === dragKey)) {
notify('График с данным ключом уже существует в этой группе. Перемещение невозможно', 'warning') notify('График с данным ключом уже существует в этой группе. Перемещение невозможно', 'warning')
return prev return prev
} }
} }
const groups = [ ...prev ] const groups = [ ...prev ]
const charts = groups[groupPos].splice(dragNodes.chart, 1) const charts = groups[groupPos].filter((chart) => chart.key === dragKey || chart.linkedTo === dragKey)
groups[targetNodes.group].splice(Math.max(dropPosition - 1, 0), 0, ...charts) groups[groupPos] = groups[groupPos].filter((chart) => chart.key !== dragKey && chart.linkedTo !== dragKey)
groups[targetGroup].splice(Math.max(dropPosition - 1, 0), 0, ...charts)
return groups return groups
} }
return prev return prev
@ -98,11 +108,8 @@ const _D3MonitoringGroupsEditor = <DataType,>({
return { group, chart } return { group, chart }
}, [selected]) }, [selected])
const selectedChart = useMemo(() => { const selectedGroup = useMemo(() => selectedIdx ? groups[selectedIdx.group] : null, [groups, selectedIdx])
if (!selectedIdx) return null const selectedChart = useMemo(() => selectedIdx ? groups[selectedIdx.group][selectedIdx.chart] : null, [groups, selectedIdx])
return groups[selectedIdx.group][selectedIdx.chart]
}, [groups, selectedIdx])
const onChartChange = useCallback((chart: ExtendedChartDataset<DataType>) => { const onChartChange = useCallback((chart: ExtendedChartDataset<DataType>) => {
if (!selectedIdx) return false if (!selectedIdx) return false
@ -119,10 +126,17 @@ const _D3MonitoringGroupsEditor = <DataType,>({
centered centered
width={800} width={800}
visible={visible} visible={visible}
onOk={onModalOk}
onCancel={onCancel}
okText={'Сохранить изменения'}
title={'Настройка групп графиков'} title={'Настройка групп графиков'}
onCancel={onCancel}
footer={(
<>
<Popconfirm title={'Вы уверены что хотите сбросить настройки графиков?'} onConfirm={onReset}>
<Button icon={<UndoOutlined />}>Сброс</Button>
</Popconfirm>
<Button onClick={onCancel}>Отмена</Button>
<Button type={'primary'} onClick={onModalOk}>Сохранить изменения</Button>
</>
)}
> >
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'stretch', height: 250 }}> <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'stretch', height: 250 }}>
<div style={{ width: '35%' }}> <div style={{ width: '35%' }}>
@ -140,8 +154,8 @@ const _D3MonitoringGroupsEditor = <DataType,>({
</div> </div>
<Divider type={'vertical'} style={{ height: '100%', padding: '0 5px' }} /> <Divider type={'vertical'} style={{ height: '100%', padding: '0 5px' }} />
<div style={divStyle}> <div style={divStyle}>
{selectedChart ? ( {selectedGroup && selectedChart ? (
<D3MonitoringChartEditor<DataType> chart={selectedChart} onChange={onChartChange} /> <D3MonitoringChartEditor<DataType> group={selectedGroup} chart={selectedChart} onChange={onChartChange} />
) : ( ) : (
<Empty description={'Выберите график для редактирования'} /> <Empty description={'Выберите график для редактирования'} />
)} )}

View File

@ -62,7 +62,7 @@ export type BaseChartDataset<DataType> = {
/** Параметры штриховки графика */ /** Параметры штриховки графика */
dash?: string | number | [string | number, string | number] dash?: string | number | [string | number, string | number]
/** Привязка домена к домену другого графика */ /** Привязка домена к домену другого графика */
bindDomainFrom?: string | number linkedTo?: string | number
} }
export type LineChartDataset = { export type LineChartDataset = {

View File

@ -14,7 +14,7 @@ import { PeriodPicker, defaultPeriod } from '@components/selectors/PeriodPicker'
import { formatDate, range, wrapPrivateComponent } from '@utils' import { formatDate, range, wrapPrivateComponent } from '@utils'
import { TelemetryDataSaubService } from '@api' import { TelemetryDataSaubService } from '@api'
import { makeChartGroups, normalizeData } from '../TelemetryView' import { makeChartGroups, normalizeData, yAxis } from '../TelemetryView'
import cursorRender from '../TelemetryView/cursorRender' import cursorRender from '../TelemetryView/cursorRender'
const DATA_COUNT = 2048 // Колличество точек на подгрузку графика const DATA_COUNT = 2048 // Колличество точек на подгрузку графика
@ -247,6 +247,7 @@ const Archive = memo(() => {
datasetGroups={chartGroups} datasetGroups={chartGroups}
data={chartData} data={chartData}
yDomain={domain} yDomain={domain}
yAxis={yAxis}
yTicks={{ yTicks={{
visible: true, visible: true,
format: (d) => formatDate(d) format: (d) => formatDate(d)

View File

@ -1,6 +1,6 @@
import { useState, useEffect, useCallback, memo, useMemo } from 'react' import { useState, useEffect, useCallback, memo, useMemo } from 'react'
import { BehaviorSubject, buffer, throttleTime } from 'rxjs' import { BehaviorSubject, buffer, throttleTime } from 'rxjs'
import { Select } from 'antd' import { Button, Select } from 'antd'
import { useIdWell } from '@asb/context' import { useIdWell } from '@asb/context'
import { makeDateSorter } from '@components/Table' import { makeDateSorter } from '@components/Table'
@ -36,7 +36,7 @@ import '@styles/message.css'
const { Option } = Select const { Option } = Select
const yAxis = { export const yAxis = {
type: 'time', type: 'time',
accessor: (d) => new Date(d.date), accessor: (d) => new Date(d.date),
format: (d) => formatDate(d, undefined, 'YYYY-MM-DD HH:mm:ss'), format: (d) => formatDate(d, undefined, 'YYYY-MM-DD HH:mm:ss'),
@ -71,7 +71,7 @@ export const makeChartGroups = (flowChart) => {
maxXAccessor: 'depthEnd', maxXAccessor: 'depthEnd',
minYAccessor: accessor + 'Min', minYAccessor: accessor + 'Min',
maxYAccessor: accessor + 'Max', maxYAccessor: accessor + 'Max',
bindDomainFrom: accessor, linkedTo: accessor,
}) })
return [ return [
@ -148,6 +148,7 @@ const TelemetryView = memo(() => {
const [flowChartData, setFlowChartData] = useState([]) const [flowChartData, setFlowChartData] = useState([])
const [rop, setRop] = useState(null) const [rop, setRop] = useState(null)
const [domain, setDomain] = useState({}) const [domain, setDomain] = useState({})
const [chartMethods, setChartMethods] = useState()
const idWell = useIdWell() const idWell = useIdWell()
@ -271,6 +272,7 @@ const TelemetryView = memo(() => {
Интервал:&nbsp; Интервал:&nbsp;
<PeriodPicker onChange={setChartInterval} /> <PeriodPicker onChange={setChartInterval} />
</div> </div>
<Button onClick={() => chartMethods?.setSettingsVisible(true)}>Настроить графики</Button>
<div style={{ marginLeft: '1rem' }}> <div style={{ marginLeft: '1rem' }}>
Статус:&nbsp; Статус:&nbsp;
<Select value={wellData.idState ?? 0} onChange={onStatusChanged} disabled={!hasPermission('Well.edit')}> <Select value={wellData.idState ?? 0} onChange={onStatusChanged} disabled={!hasPermission('Well.edit')}>
@ -293,6 +295,7 @@ const TelemetryView = memo(() => {
</GridItem> </GridItem>
<GridItem col={2} row={2} colSpan={8} rowSpan={2}> <GridItem col={2} row={2} colSpan={8} rowSpan={2}>
<D3MonitoringCharts <D3MonitoringCharts
methods={setChartMethods}
chartName={'monitoring'} chartName={'monitoring'}
datasetGroups={chartGroups} datasetGroups={chartGroups}
data={filteredData} data={filteredData}