Добавил возможность выбора множества тегов для отображения.

This commit is contained in:
Первов Артем
2026-06-22 21:49:52 +03:00
parent 6ab9cd1c75
commit 9fc66624dc
10 changed files with 229 additions and 109 deletions

View File

@@ -1,8 +1,7 @@
import { useMemo, useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useParams } from 'react-router-dom';
import { getCurrent } from '../../entities/current/api';
import { getHistory } from '../../entities/history/api';
import { toIsoFromInput } from '../../utils/format';
import { getHistoryGranularity } from '../../utils/historyGranularity';
import { createCurrentTagLabels, filterCurrentItems } from '../current/model';
@@ -13,6 +12,7 @@ import { EdgePageLayout } from './components/EdgePageLayout';
export function EdgeHistoryPage() {
const { edgeId = '' } = useParams();
const queryClient = useQueryClient();
const [search, setSearch] = useState('');
const [range, setRange] = useState(() => createRange(24));
const [selectedTags, setSelectedTags] = useState<string[]>([]);
@@ -30,23 +30,8 @@ export function EdgeHistoryPage() {
const from = toIsoFromInput(range.from) as string;
const to = toIsoFromInput(range.to) as string;
const historyGranularity = useMemo(() => getHistoryGranularity(from, to), [from, to]);
const selectedTag = selectedTags[0];
const history = useQuery({
queryKey: ['history', edgeId, selectedTag, from, to, historyGranularity.granulate],
queryFn: () =>
getHistory({
edge: edgeId,
tag: selectedTag as string,
from,
to,
granulate: historyGranularity.granulate,
}),
enabled: Boolean(edgeId && selectedTag),
refetchInterval: false,
});
const toggleTag = (tag: string) => {
setSelectedTags((prev) => (prev.includes(tag) ? [] : [tag]));
setSelectedTags((prev) => (prev.includes(tag) ? prev.filter((selected) => selected !== tag) : [...prev, tag]));
};
const selectFirstTags = () => {
@@ -54,7 +39,7 @@ export function EdgeHistoryPage() {
};
const selectVisibleTags = () => {
setSelectedTags(visibleItems[0] ? [visibleItems[0].tag] : []);
setSelectedTags((prev) => Array.from(new Set([...prev, ...visibleItems.map((item) => item.tag)])));
};
const clearVisibleTags = () => {
@@ -69,15 +54,14 @@ export function EdgeHistoryPage() {
view="archive"
onRefresh={() => {
void current.refetch();
void history.refetch();
void queryClient.invalidateQueries({ queryKey: ['history', edgeId] });
}}
>
<ArchiveView
edgeId={edgeId}
items={visibleItems}
search={search}
selectedTags={selectedTags}
history={history.data}
historyLoading={history.isPending && selectedTags.length > 0}
historyGranulate={historyGranularity.granulate}
historyAxis={historyGranularity}
range={range}

View File

@@ -1,20 +1,18 @@
import { useState } from 'react';
import type { RefObject } from 'react';
import { useRef } from 'react';
import { CalendarDays, CalendarClock, ChevronDown, Clock3, DatabaseZap, Search } from 'lucide-react';
import { CalendarDays, CalendarClock, Check, ChevronDown, Clock3, DatabaseZap, Search } from 'lucide-react';
import type { CurrentItem } from '../../../entities/current/types';
import type { HistoryResponse } from '../../../entities/history/types';
import { HistoryChart } from '../../../features/history-chart/HistoryChart';
import { RANGE_PRESETS, createRange, type DateRangeState } from '../../../features/history/dateRange';
import { toIsoFromInput } from '../../../utils/format';
import type { HistoryGranularity } from '../../../utils/historyGranularity';
type ArchiveViewProps = {
edgeId: string;
getTagLabel: (tag: string) => string;
history?: HistoryResponse;
historyAxis: HistoryGranularity;
historyGranulate?: string;
historyLoading: boolean;
items: CurrentItem[];
range: DateRangeState;
search: string;
@@ -78,11 +76,10 @@ function DateRangeField({ icon, inputRef, type, value, onChange }: DateRangeFiel
}
export function ArchiveView({
edgeId,
getTagLabel,
history,
historyAxis,
historyGranulate,
historyLoading,
items,
range,
search,
@@ -103,6 +100,8 @@ export function ArchiveView({
const fromTimeRef = useRef<HTMLInputElement>(null);
const toDateRef = useRef<HTMLInputElement>(null);
const toTimeRef = useRef<HTMLInputElement>(null);
const fromIso = toIsoFromInput(range.from) as string;
const toIso = toIsoFromInput(range.to) as string;
const updateRangePart = (rangePart: RangePart, inputPart: RangeInputPart, value: string) => {
onRangeChange({
...range,
@@ -185,12 +184,16 @@ export function ArchiveView({
className={`tag-select-item ${selected ? 'tag-select-item--selected' : ''}`}
title={item.tag}
onClick={() => onToggleTag(item.tag)}
aria-pressed={selected}
>
<span className="tag-select-item__name">
<span>{label}</span>
{label !== item.tag ? <small>{item.tag}</small> : null}
</span>
<strong>{item.value.toLocaleString('ru-RU', { maximumFractionDigits: item.precision ?? 3 })}</strong>
<span className="tag-select-item__side">
<strong>{item.value.toLocaleString('ru-RU', { maximumFractionDigits: item.precision ?? 3 })}</strong>
{selected ? <Check size={15} /> : null}
</span>
</button>
);
})}
@@ -247,13 +250,13 @@ export function ArchiveView({
{selectedTags.length ? (
<HistoryChart
key={`${range.from}:${range.to}:${selectedTags.join(',')}`}
data={history}
loading={historyLoading}
from={toIsoFromInput(range.from)}
to={toIsoFromInput(range.to)}
edge={edgeId}
from={fromIso}
to={toIso}
granulate={historyAxis.granulate}
tickIntervalMs={historyAxis.tickIntervalMs}
labelFormat={historyAxis.labelFormat}
tag={selectedTags[0]}
tags={selectedTags}
tagLabels={tagLabels}
/>
) : (