vmui: improve the context for autocomplete #5736 #5737 #5739 (#5804)

Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com>
This commit is contained in:
Yury Molodov 2024-02-14 01:22:51 +01:00 committed by Aliaksandr Valialkin
parent 5f2905d120
commit b08a23c4a5
No known key found for this signature in database
GPG key ID: 52C003EE2BCDB9EB
7 changed files with 45 additions and 39 deletions

View file

@ -4,9 +4,8 @@ import { useFetchQueryOptions } from "../../../hooks/useFetchQueryOptions";
import { getTextWidth } from "../../../utils/uplot";
import { escapeRegexp } from "../../../utils/regexp";
import useGetMetricsQL from "../../../hooks/useGetMetricsQL";
import { RefreshIcon } from "../../Main/Icons";
import { QueryContextType } from "../../../types";
import { AUTOCOMPLETE_LIMITS, AUTOCOMPLETE_MIN_SYMBOLS } from "../../../constants/queryAutocomplete";
import { AUTOCOMPLETE_LIMITS } from "../../../constants/queryAutocomplete";
interface QueryEditorAutocompleteProps {
value: string;
@ -26,22 +25,27 @@ const QueryEditorAutocomplete: FC<QueryEditorAutocompleteProps> = ({
const [leftOffset, setLeftOffset] = useState(0);
const metricsqlFunctions = useGetMetricsQL();
const exprLastPart = useMemo(() => {
const parts = value.split("}");
return parts[parts.length - 1];
}, [value]);
const metric = useMemo(() => {
const regexp = /\b[^{}(),\s]+(?={|$)/g;
const match = value.match(regexp);
const match = exprLastPart.match(regexp);
return match ? match[0] : "";
}, [value]);
}, [exprLastPart]);
const label = useMemo(() => {
const regexp = /[a-z_:-][\w\-.:/]*\b(?=\s*(=|!=|=~|!~))/g;
const match = value.match(regexp);
const match = exprLastPart.match(regexp);
return match ? match[match.length - 1] : "";
}, [value]);
}, [exprLastPart]);
const context = useMemo(() => {
if (!value) return QueryContextType.empty;
if (!value || value.endsWith("}")) return QueryContextType.empty;
const labelRegexp = /\{[^}]*?(\w+)$/gm;
const labelRegexp = /\{[^}]*?(\w+)*$/gm;
const labelValueRegexp = new RegExp(`(${escapeRegexp(metric)})?{?.+${escapeRegexp(label)}(=|!=|=~|!~)"?([^"]*)$`, "g");
switch (true) {
@ -88,6 +92,13 @@ const QueryEditorAutocomplete: FC<QueryEditorAutocompleteProps> = ({
const beforeValueByContext = value.substring(0, startIndexOfValueByContext);
const afterValueByContext = value.substring(endIndexOfValueByContext);
// Add quotes around the value if the context is labelValue
if (context === QueryContextType.labelValue) {
const quote = "\"";
const needsQuote = /(?:=|!=|=~|!~)$/.test(beforeValueByContext);
insert = `${needsQuote ? quote : ""}${insert}`;
}
// Assemble the new value with the inserted text
const newVal = `${beforeValueByContext}${insert}${afterValueByContext}`;
onSelect(newVal);
@ -109,11 +120,12 @@ const QueryEditorAutocomplete: FC<QueryEditorAutocompleteProps> = ({
return (
<>
<Autocomplete
loading={loading}
disabledFullScreen
value={valueByContext}
options={options?.length < AUTOCOMPLETE_LIMITS.queryLimit ? options : []}
options={options}
anchor={anchorEl}
minLength={AUTOCOMPLETE_MIN_SYMBOLS[context]}
minLength={0}
offset={{ top: 0, left: leftOffset }}
onSelect={handleSelect}
onFoundOptions={onFoundOptions}
@ -122,7 +134,6 @@ const QueryEditorAutocomplete: FC<QueryEditorAutocompleteProps> = ({
message: "Please, specify the query more precisely."
}}
/>
{loading && <div className="vm-query-editor-autocomplete"><RefreshIcon/></div>}
</>
);
};

View file

@ -2,20 +2,4 @@
.vm-query-editor {
position: relative;
&-autocomplete {
position: absolute;
display: flex;
align-items: center;
justify-items: center;
top: 0;
bottom: 0;
right: $padding-global;
width: 12px;
height: 100%;
color: $color-text-secondary;
z-index: 2;
animation: half-circle-spinner-animation 1s infinite linear, vm-fade 0.5s ease-in;
pointer-events: none;
}
}

View file

@ -2,7 +2,7 @@ import React, { FC, Ref, useCallback, useEffect, useMemo, useRef, useState, JSX
import classNames from "classnames";
import Popper from "../Popper/Popper";
import "./style.scss";
import { DoneIcon } from "../Icons";
import { DoneIcon, RefreshIcon } from "../Icons";
import useDeviceDetect from "../../../hooks/useDeviceDetect";
import useBoolean from "../../../hooks/useBoolean";
import useEventListener from "../../../hooks/useEventListener";
@ -27,6 +27,7 @@ interface AutocompleteProps {
disabledFullScreen?: boolean
offset?: {top: number, left: number}
maxDisplayResults?: {limit: number, message?: string}
loading?: boolean;
onSelect: (val: string) => void
onOpenAutocomplete?: (val: boolean) => void
onFoundOptions?: (val: AutocompleteOptions[]) => void
@ -51,6 +52,7 @@ const Autocomplete: FC<AutocompleteProps> = ({
disabledFullScreen,
offset,
maxDisplayResults,
loading,
onSelect,
onOpenAutocomplete,
onFoundOptions,
@ -190,6 +192,7 @@ const Autocomplete: FC<AutocompleteProps> = ({
})}
ref={wrapperEl}
>
{loading && <div className="vm-autocomplete__loader"><RefreshIcon/><span>Loading...</span></div>}
{displayNoOptionsText && <div className="vm-autocomplete__no-options">{noOptionsText}</div>}
{!hideFoundedOptions && foundOptions.map((option, i) =>
<div

View file

@ -16,6 +16,22 @@
color: $color-text-disabled;
}
&__loader {
display: grid;
grid-template-columns: 14px auto;
align-items: center;
justify-content: center;
gap: $padding-small;
padding: $padding-global;
color: $color-text-secondary;
z-index: 2;
pointer-events: none;
svg {
animation: half-circle-spinner-animation 1s infinite linear, vm-fade 0.5s ease-in;
}
}
&-info,
&-message {
padding: $padding-global;

View file

@ -1,14 +1,5 @@
import { QueryContextType } from "../types";
export const AUTOCOMPLETE_LIMITS = {
displayResults: 50,
queryLimit: 1000,
cacheLimit: 1000,
};
export const AUTOCOMPLETE_MIN_SYMBOLS = {
[QueryContextType.metricsql]: 2,
[QueryContextType.empty]: 2,
[QueryContextType.label]: 0,
[QueryContextType.labelValue]: 0,
};

View file

@ -47,7 +47,7 @@ export const useFetchQueryOptions = ({ valueByContext, metric, label, context }:
const [loading, setLoading] = useState(false);
const [value, setValue] = useState(valueByContext);
const debouncedSetValue = debounce(setValue, 800);
const debouncedSetValue = debounce(setValue, 500);
useEffect(() => {
debouncedSetValue(valueByContext);
return debouncedSetValue.cancel;
@ -80,7 +80,7 @@ export const useFetchQueryOptions = ({ valueByContext, metric, label, context }:
};
const fetchData = async ({ value, urlSuffix, setter, type, params }: FetchDataArgs) => {
if (!value) return;
if (!value && type === TypeData.metric) return;
abortControllerRef.current.abort();
abortControllerRef.current = new AbortController();
const { signal } = abortControllerRef.current;

View file

@ -58,6 +58,7 @@ The sandbox cluster installation is running under the constant load generated by
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): fix handling invalid timezone. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5732).
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): fix the bug where the select does not open. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5728).
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): clear entered text in select after selecting a value. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5727).
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): improve the operation of the context for autocomplete. See [this](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5736), [this](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5737) and [this](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5739) issues.
* BUGFIX: [dashboards](https://grafana.com/orgs/victoriametrics): update `Storage full ETA` panels for Single-node and Cluster dashboards to prevent them from showing negative or blank results caused by increase of deduplicated samples. Deduplicated samples were part of the expression to provide a better estimate for disk usage, but due to sporadic nature of [deduplication](https://docs.victoriametrics.com/#deduplication) in VictoriaMetrics it rather produced skewed results. See [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/5747).
## [v1.97.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.97.1)