Skip to content

Commit 47a01ad

Browse files
committed
app/vmui: add back action for hits chart time range (#1535)
1 parent 55c4446 commit 47a01ad

5 files changed

Lines changed: 113 additions & 5 deletions

File tree

‎app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsChart.tsx‎

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FC, useMemo, useState } from "preact/compat";
1+
import { FC, useEffect, useMemo, useRef, useState } from "preact/compat";
22
import "./style.scss";
33
import "uplot/dist/uPlot.min.css";
44
import { AlignedData } from "uplot";
@@ -11,6 +11,7 @@ import { calculateTotalHits } from "../../../utils/logs";
1111
import BarHitsStats from "./BarHitsStats/BarHitsStats";
1212
import { HitsChartAlert } from "../../../pages/QueryPage/HitsPanel/hooks/useHitsChartAlert";
1313
import Alert from "../../Main/Alert/Alert";
14+
import { timeParamsToDateRange } from "../../../utils/time";
1415

1516
interface Props {
1617
logHits: LogHits[];
@@ -45,6 +46,58 @@ const BarHitsChart: FC<Props> = ({
4546
const isHitsMode = graphOptions.queryMode === GRAPH_QUERY_MODE.hits;
4647
const totalHits = useMemo(() => calculateTotalHits(logHits), [logHits]);
4748

49+
const currentPeriodRef = useRef(period);
50+
const chartPeriodChangeRef = useRef(false);
51+
const periodChangeTimeoutRef = useRef<ReturnType<typeof setTimeout>>();
52+
const periodBeforeInteractionRef = useRef<TimeParams>();
53+
const [prevPeriod, setPrevPeriod] = useState<TimeParams>();
54+
55+
const handleChangePeriod = (nextPeriod: TimePeriod) => {
56+
chartPeriodChangeRef.current = true;
57+
58+
if (periodChangeTimeoutRef.current === undefined) {
59+
periodBeforeInteractionRef.current = currentPeriodRef.current;
60+
}
61+
62+
clearTimeout(periodChangeTimeoutRef.current);
63+
64+
periodChangeTimeoutRef.current = setTimeout(() => {
65+
setPrevPeriod(periodBeforeInteractionRef.current);
66+
periodBeforeInteractionRef.current = undefined;
67+
periodChangeTimeoutRef.current = undefined;
68+
chartPeriodChangeRef.current = false;
69+
}, 500);
70+
71+
setPeriod(nextPeriod);
72+
};
73+
74+
75+
const resetPeriodInteraction = () => {
76+
clearTimeout(periodChangeTimeoutRef.current);
77+
periodChangeTimeoutRef.current = undefined;
78+
periodBeforeInteractionRef.current = undefined;
79+
setPrevPeriod(undefined);
80+
};
81+
82+
const handleRevertPeriod = () => {
83+
if (!prevPeriod) return;
84+
85+
setPeriod(timeParamsToDateRange(prevPeriod));
86+
resetPeriodInteraction();
87+
};
88+
89+
useEffect(() => {
90+
currentPeriodRef.current = period;
91+
92+
if (chartPeriodChangeRef.current) {
93+
return;
94+
}
95+
96+
resetPeriodInteraction();
97+
}, [period]);
98+
99+
useEffect(() => resetPeriodInteraction, []);
100+
48101
return (
49102
<div className="vm-bar-hits-chart__wrapper">
50103
<div className="vm-bar-hits-chart-header">
@@ -60,6 +113,8 @@ const BarHitsChart: FC<Props> = ({
60113
query={query}
61114
isHitsMode={isHitsMode}
62115
isOverview={isOverview}
116+
prevPeriod={prevPeriod}
117+
onRevertPeriod={handleRevertPeriod}
63118
onChange={setGraphOptions}
64119
/>
65120
</div>
@@ -76,7 +131,7 @@ const BarHitsChart: FC<Props> = ({
76131
totalHits={totalHits}
77132
data={_data}
78133
period={period}
79-
setPeriod={setPeriod}
134+
setPeriod={handleChangePeriod}
80135
graphOptions={graphOptions}
81136
/>
82137
)}

‎app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsOptions/BarHitsOptions.tsx‎

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ import "./style.scss";
55
import useStateSearchParams from "../../../../hooks/useStateSearchParams";
66
import { useSearchParams } from "react-router-dom";
77
import Button from "../../../Main/Button/Button";
8-
import { KeyboardIcon, MoreIcon, VisibilityIcon, VisibilityOffIcon } from "../../../Main/Icons";
8+
import {
9+
ArrowBackIcon,
10+
KeyboardIcon,
11+
MoreIcon,
12+
VisibilityIcon,
13+
VisibilityOffIcon
14+
} from "../../../Main/Icons";
915
import Tooltip from "../../../Main/Tooltip/Tooltip";
1016
import ShortcutKeys from "../../../Main/ShortcutKeys/ShortcutKeys";
1117
import { useCallback } from "react";
@@ -18,18 +24,27 @@ import { WITHOUT_GROUPING } from "../../../../constants/logs";
1824
import { useHitsChartConfig } from "../../../../pages/QueryPage/HitsPanel/hooks/useHitsChartConfig";
1925
import { useExtraFilters } from "../../../ExtraFilters/hooks/useExtraFilters";
2026
import { useFetchFieldNames } from "../../../../pages/OverviewPage/hooks/useFetchFieldNames";
21-
import { getDurationFromMilliseconds } from "../../../../utils/time";
27+
import {
28+
getDurationFromMilliseconds,
29+
nanosToIsoString,
30+
vmDate
31+
} from "../../../../utils/time";
2232
import { generateIntervalsMs } from "../../../../utils/intervals";
2333
import { useTimePeriod } from "../../../../pages/QueryPage/hooks/useTimePeriod";
34+
import { TimeParams } from "../../../../types";
35+
import { DATE_TIME_FORMAT } from "../../../../constants/date";
36+
import { useTimeState } from "../../../../state/time/TimeStateContext";
2437

2538
interface Props {
2639
query?: string;
2740
isHitsMode?: boolean;
2841
isOverview?: boolean;
42+
prevPeriod?: TimeParams;
43+
onRevertPeriod: () => void
2944
onChange: (options: GraphOptions) => void;
3045
}
3146

32-
const BarHitsOptions: FC<Props> = ({ query, isHitsMode, isOverview, onChange }) => {
47+
const BarHitsOptions: FC<Props> = ({ query, isHitsMode, isOverview, prevPeriod, onRevertPeriod, onChange }) => {
3348
const { isMobile } = useDeviceDetect();
3449
const {
3550
value: openList,
@@ -40,6 +55,7 @@ const BarHitsOptions: FC<Props> = ({ query, isHitsMode, isOverview, onChange })
4055
const [searchParams, setSearchParams] = useSearchParams();
4156

4257
const { topHits, groupFieldHits, step } = useHitsChartConfig();
58+
const { timezone } = useTimeState();
4359

4460
const { extraParams } = useExtraFilters();
4561
const { period: { start, end } } = useTimePeriod();
@@ -55,6 +71,14 @@ const BarHitsOptions: FC<Props> = ({ query, isHitsMode, isOverview, onChange })
5571
const [cumulative, setCumulative] = useStateSearchParams(false, "cumulative");
5672
const [hideChart, setHideChart] = useStateSearchParams(false, "hide_chart");
5773

74+
const prevPeriodFormatted = useMemo(() => {
75+
if (!prevPeriod) return;
76+
77+
const startIso = nanosToIsoString(prevPeriod.start);
78+
const endIso = nanosToIsoString(prevPeriod.end);
79+
return `${vmDate(startIso).tz().format(DATE_TIME_FORMAT)} - ${vmDate(endIso).tz().format(DATE_TIME_FORMAT)}`;
80+
}, [prevPeriod, timezone]);
81+
5882
const options: GraphOptions = useMemo(() => ({
5983
graphStyle: GRAPH_STYLES.BAR,
6084
queryMode,
@@ -168,6 +192,18 @@ const BarHitsOptions: FC<Props> = ({ query, isHitsMode, isOverview, onChange })
168192
/>
169193
</div>
170194
)}
195+
196+
{prevPeriod && (
197+
<div
198+
className="vm-bar-hits-options-item"
199+
onClick={onRevertPeriod}
200+
>
201+
<button className="vm-select-limits-button vm-bar-hits-options-item_timerange">
202+
<ArrowBackIcon/>
203+
Back to {prevPeriodFormatted}
204+
</button>
205+
</div>
206+
)}
171207
</div>
172208

173209
<div className="vm-bar-hits-options-item vm-bar-hits-options-item_switch">

‎app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsOptions/style.scss‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@
2929
&_switch {
3030
padding-right: $padding-global;
3131
}
32+
33+
&_timerange {
34+
gap: calc($padding-small / 4);
35+
padding-inline: calc($padding-small / 2) $padding-small;
36+
grid-template-columns: 16px 1fr;
37+
min-height: 24px;
38+
}
3239
}
3340

3441
&_mobile {

‎app/vmui/packages/vmui/src/components/Main/Icons/index.tsx‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,15 @@ export const ArrowDropDownIcon = () => (
114114
</svg>
115115
);
116116

117+
export const ArrowBackIcon = () => (
118+
<svg
119+
viewBox="0 0 24 24"
120+
fill="currentColor"
121+
>
122+
<path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20z"></path>
123+
</svg>
124+
);
125+
117126
export const ClockIcon = () => (
118127
<svg
119128
viewBox="0 0 24 24"

‎docs/victorialogs/CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ according to the following docs:
3333
* FEATURE: [LogsQL](https://docs.victoriametrics.com/victorialogs/logsql/): add [`json_array_concat` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#json_array_concat-pipe) for joining JSON array items stored in the given [log field](https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model) into a string with the given delimiter. See [#712](https://github.com/VictoriaMetrics/VictoriaLogs/issues/712).
3434
* FEATURE: [data ingestion](https://docs.victoriametrics.com/victorialogs/data-ingestion/): adjust [`_stream` field](https://docs.victoriametrics.com/victorialogs/keyconcepts/#stream-fields) value according to the actual log fields. This simplifies importing of previously modified VictoriaLogs-exported data. See [#1122](https://github.com/VictoriaMetrics/VictoriaLogs/issues/1122).
3535
* FEATURE: [vlagent](https://docs.victoriametrics.com/victorialogs/vlagent/): add `-remoteWrite.basicAuth.usernameFile` command-line flag for dynamically reloading basic auth username for the corresponding `-remoteWrite.url` from the given file.
36+
* FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): add a `Back` action to the Hits chart for restoring the previous time range after zooming or panning the chart. See [#1535](https://github.com/VictoriaMetrics/VictoriaLogs/issues/1535).
3637

3738
* BUGFIX: [syslog data ingestion](https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/): avoid stamping [RFC3164](https://datatracker.ietf.org/doc/html/rfc3164) messages received right after the new year with the previous year (which could drop them under a short `-retentionPeriod`), and compute the year in `-syslog.timezone` instead of the server local timezone. See [#1556](https://github.com/VictoriaMetrics/VictoriaLogs/pull/1556).
3839
* BUGFIX: [LogsQL](https://docs.victoriametrics.com/victorialogs/logsql/): fix [`field_names` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#field_names-pipe) not respecting [`hidden_fields_filters`](https://docs.victoriametrics.com/victorialogs/querying/#hidden-fields). Fields listed in `hidden_fields_filters` still appeared in `field_names` output, leaking their existence to the caller. See [#1574](https://github.com/VictoriaMetrics/VictoriaLogs/pull/1574/).

0 commit comments

Comments
 (0)