mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2025-01-10 15:14:09 +00:00
vmui: step (#3521)
* feat: add step rounding * fix: change step in URL parameters * refactor: change comment for roundStep
This commit is contained in:
parent
c2fc996e01
commit
b3398a125f
4 changed files with 49 additions and 14 deletions
|
@ -1,6 +1,6 @@
|
|||
import React, { FC } from "preact/compat";
|
||||
import React, { FC, useEffect } from "preact/compat";
|
||||
import StepConfigurator from "../StepConfigurator/StepConfigurator";
|
||||
import { useGraphDispatch } from "../../../state/graph/GraphStateContext";
|
||||
import { useGraphDispatch, useGraphState } from "../../../state/graph/GraphStateContext";
|
||||
import { getAppModeParams } from "../../../utils/app-mode";
|
||||
import TenantsConfiguration from "../TenantsConfiguration/TenantsConfiguration";
|
||||
import { useCustomPanelDispatch, useCustomPanelState } from "../../../state/customPanel/CustomPanelStateContext";
|
||||
|
@ -8,10 +8,13 @@ import { useTimeState } from "../../../state/time/TimeStateContext";
|
|||
import { useQueryDispatch, useQueryState } from "../../../state/query/QueryStateContext";
|
||||
import "./style.scss";
|
||||
import Switch from "../../Main/Switch/Switch";
|
||||
import usePrevious from "../../../hooks/usePrevious";
|
||||
|
||||
const AdditionalSettings: FC = () => {
|
||||
|
||||
const { customStep } = useGraphState();
|
||||
const graphDispatch = useGraphDispatch();
|
||||
|
||||
const { inputTenantID } = getAppModeParams();
|
||||
|
||||
const { autocomplete } = useQueryState();
|
||||
|
@ -20,7 +23,8 @@ const AdditionalSettings: FC = () => {
|
|||
const { nocache, isTracingEnabled } = useCustomPanelState();
|
||||
const customPanelDispatch = useCustomPanelDispatch();
|
||||
|
||||
const { period: { step } } = useTimeState();
|
||||
const { period: { step }, duration } = useTimeState();
|
||||
const prevDuration = usePrevious(duration);
|
||||
|
||||
const onChangeCache = () => {
|
||||
customPanelDispatch({ type: "TOGGLE_NO_CACHE" });
|
||||
|
@ -38,6 +42,15 @@ const AdditionalSettings: FC = () => {
|
|||
graphDispatch({ type: "SET_CUSTOM_STEP", payload: value });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!customStep && step) onChangeStep(step);
|
||||
}, [step]);
|
||||
|
||||
useEffect(() => {
|
||||
if (duration === prevDuration || !prevDuration) return;
|
||||
if (step) onChangeStep(step);
|
||||
}, [duration, prevDuration]);
|
||||
|
||||
return <div className="vm-additional-settings">
|
||||
<Switch
|
||||
label={"Autocomplete"}
|
||||
|
@ -58,6 +71,7 @@ const AdditionalSettings: FC = () => {
|
|||
<StepConfigurator
|
||||
defaultStep={step}
|
||||
setStep={onChangeStep}
|
||||
value={customStep}
|
||||
/>
|
||||
</div>
|
||||
{!!inputTenantID && (
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React, { FC, useCallback, useState } from "preact/compat";
|
||||
import { useEffect } from "react";
|
||||
import React, { FC, useCallback, useEffect, useState } from "preact/compat";
|
||||
import debounce from "lodash.debounce";
|
||||
import { RestartIcon } from "../../Main/Icons";
|
||||
import TextField from "../../Main/TextField/TextField";
|
||||
|
@ -8,16 +7,17 @@ import Tooltip from "../../Main/Tooltip/Tooltip";
|
|||
|
||||
interface StepConfiguratorProps {
|
||||
defaultStep?: number,
|
||||
value?: number,
|
||||
setStep: (step: number) => void,
|
||||
}
|
||||
|
||||
const StepConfigurator: FC<StepConfiguratorProps> = ({ defaultStep, setStep }) => {
|
||||
const StepConfigurator: FC<StepConfiguratorProps> = ({ value, defaultStep, setStep }) => {
|
||||
|
||||
const [customStep, setCustomStep] = useState(defaultStep);
|
||||
const [customStep, setCustomStep] = useState(value || defaultStep);
|
||||
const [error, setError] = useState("");
|
||||
|
||||
const handleApply = (step: number) => setStep(step || 1);
|
||||
const debouncedHandleApply = useCallback(debounce(handleApply, 700), []);
|
||||
const debouncedHandleApply = useCallback(debounce(handleApply, 500), []);
|
||||
|
||||
const onChangeStep = (val: string) => {
|
||||
const value = +val;
|
||||
|
@ -40,12 +40,12 @@ const StepConfigurator: FC<StepConfiguratorProps> = ({ defaultStep, setStep }) =
|
|||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (defaultStep) handleSetStep(defaultStep);
|
||||
}, [defaultStep]);
|
||||
if (value) handleSetStep(value);
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<TextField
|
||||
label="Step value"
|
||||
label="Step value of seconds"
|
||||
type="number"
|
||||
value={customStep}
|
||||
error={error}
|
||||
|
|
|
@ -6,12 +6,14 @@ import { useQueryState } from "../../../state/query/QueryStateContext";
|
|||
import { displayTypeTabs } from "../DisplayTypeSwitch";
|
||||
import { setQueryStringWithoutPageReload } from "../../../utils/query-string";
|
||||
import { compactObject } from "../../../utils/object";
|
||||
import { useGraphState } from "../../../state/graph/GraphStateContext";
|
||||
|
||||
export const useSetQueryParams = () => {
|
||||
const { tenantId } = useAppState();
|
||||
const { displayType } = useCustomPanelState();
|
||||
const { query } = useQueryState();
|
||||
const { duration, relativeTime, period: { date, step } } = useTimeState();
|
||||
const { customStep } = useGraphState();
|
||||
|
||||
const setSearchParamsFromState = () => {
|
||||
const params: Record<string, unknown> = {};
|
||||
|
@ -20,15 +22,16 @@ export const useSetQueryParams = () => {
|
|||
params[`${group}.expr`] = q;
|
||||
params[`${group}.range_input`] = duration;
|
||||
params[`${group}.end_input`] = date;
|
||||
params[`${group}.step_input`] = step;
|
||||
params[`${group}.tab`] = displayTypeTabs.find(t => t.value === displayType)?.prometheusCode || 0;
|
||||
params[`${group}.relative_time`] = relativeTime;
|
||||
params[`${group}.tenantID`] = tenantId;
|
||||
|
||||
if ((step !== customStep) && customStep) params[`${group}.step_input`] = customStep;
|
||||
});
|
||||
|
||||
setQueryStringWithoutPageReload(compactObject(params));
|
||||
};
|
||||
|
||||
useEffect(setSearchParamsFromState, [tenantId, displayType, query, duration, relativeTime, date, step]);
|
||||
useEffect(setSearchParamsFromState, [tenantId, displayType, query, duration, relativeTime, date, step, customStep]);
|
||||
useEffect(setSearchParamsFromState, []);
|
||||
};
|
||||
|
|
|
@ -26,6 +26,23 @@ const shortDurations = supportedDurations.map(d => d.short);
|
|||
|
||||
export const roundToMilliseconds = (num: number): number => Math.round(num*1000)/1000;
|
||||
|
||||
const roundStep = (step: number) => {
|
||||
const integerStep = Math.round(step);
|
||||
if (step >= 100) {
|
||||
return integerStep - (integerStep%10); // integer multiple of 10
|
||||
}
|
||||
if (step < 100 && step >= 10) {
|
||||
return integerStep - (integerStep%5); // integer multiple of 5
|
||||
}
|
||||
if (step < 10 && step >= 1) {
|
||||
return integerStep; // integer
|
||||
}
|
||||
if (step < 1 && step > 0.01) {
|
||||
return Math.round(step * 40) / 40; // float to thousandths multiple of 5
|
||||
}
|
||||
return roundToMilliseconds(step);
|
||||
};
|
||||
|
||||
export const isSupportedDuration = (str: string): Partial<Record<UnitTypeShort, string>> | undefined => {
|
||||
|
||||
const digits = str.match(/\d+/g);
|
||||
|
@ -57,7 +74,8 @@ export const getTimeperiodForDuration = (dur: string, date?: Date): TimeParams =
|
|||
}, {});
|
||||
|
||||
const delta = dayjs.duration(durObject).asSeconds();
|
||||
const step = roundToMilliseconds(delta / MAX_ITEMS_PER_CHART) || 0.001;
|
||||
const rawStep = delta / MAX_ITEMS_PER_CHART;
|
||||
const step = roundStep(rawStep) || 0.001;
|
||||
|
||||
return {
|
||||
start: n - delta,
|
||||
|
|
Loading…
Reference in a new issue