mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
vmui: show query error (#3890)
* add links support with old query params * show error after execute query
This commit is contained in:
parent
f9723aca44
commit
c383c9b864
3 changed files with 51 additions and 18 deletions
|
@ -1,6 +1,7 @@
|
||||||
import Header from "./Header/Header";
|
import Header from "./Header/Header";
|
||||||
import React, { FC, useEffect } from "preact/compat";
|
import React, { FC, useEffect } from "preact/compat";
|
||||||
import { Outlet, useLocation } from "react-router-dom";
|
import { Outlet, useLocation, useSearchParams } from "react-router-dom";
|
||||||
|
import qs from "qs";
|
||||||
import "./style.scss";
|
import "./style.scss";
|
||||||
import { getAppModeEnable } from "../../utils/app-mode";
|
import { getAppModeEnable } from "../../utils/app-mode";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
@ -12,14 +13,33 @@ import useDeviceDetect from "../../hooks/useDeviceDetect";
|
||||||
const Layout: FC = () => {
|
const Layout: FC = () => {
|
||||||
const appModeEnable = getAppModeEnable();
|
const appModeEnable = getAppModeEnable();
|
||||||
const { isMobile } = useDeviceDetect();
|
const { isMobile } = useDeviceDetect();
|
||||||
|
const { pathname } = useLocation();
|
||||||
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
|
|
||||||
useFetchDashboards();
|
useFetchDashboards();
|
||||||
|
|
||||||
const { pathname } = useLocation();
|
const setDocumentTitle = () => {
|
||||||
useEffect(() => {
|
|
||||||
const defaultTitle = "vmui";
|
const defaultTitle = "vmui";
|
||||||
const routeTitle = routerOptions[pathname]?.title;
|
const routeTitle = routerOptions[pathname]?.title;
|
||||||
document.title = routeTitle ? `${routeTitle} - ${defaultTitle}` : defaultTitle;
|
document.title = routeTitle ? `${routeTitle} - ${defaultTitle}` : defaultTitle;
|
||||||
}, [pathname]);
|
};
|
||||||
|
|
||||||
|
// for support old links with search params
|
||||||
|
const redirectSearchToHashParams = () => {
|
||||||
|
const { search } = window.location;
|
||||||
|
if (search) {
|
||||||
|
const query = qs.parse(search, { ignoreQueryPrefix: true });
|
||||||
|
Object.entries(query).forEach(([key, value]) => {
|
||||||
|
searchParams.set(key, value as string);
|
||||||
|
setSearchParams(searchParams);
|
||||||
|
});
|
||||||
|
window.location.search = "";
|
||||||
|
}
|
||||||
|
window.location.replace(window.location.href.replace(/\/\?#\//, "/#/"));
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(setDocumentTitle, [pathname]);
|
||||||
|
useEffect(redirectSearchToHashParams, []);
|
||||||
|
|
||||||
return <section className="vm-container">
|
return <section className="vm-container">
|
||||||
<Header/>
|
<Header/>
|
||||||
|
|
|
@ -19,9 +19,15 @@ export interface QueryConfiguratorProps {
|
||||||
error?: ErrorTypes | string;
|
error?: ErrorTypes | string;
|
||||||
queryOptions: string[]
|
queryOptions: string[]
|
||||||
onHideQuery: (queries: number[]) => void
|
onHideQuery: (queries: number[]) => void
|
||||||
|
onRunQuery: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const QueryConfigurator: FC<QueryConfiguratorProps> = ({ error, queryOptions, onHideQuery }) => {
|
const QueryConfigurator: FC<QueryConfiguratorProps> = ({
|
||||||
|
error,
|
||||||
|
queryOptions,
|
||||||
|
onHideQuery,
|
||||||
|
onRunQuery
|
||||||
|
}) => {
|
||||||
const { isMobile } = useDeviceDetect();
|
const { isMobile } = useDeviceDetect();
|
||||||
|
|
||||||
const { query, queryHistory, autocomplete } = useQueryState();
|
const { query, queryHistory, autocomplete } = useQueryState();
|
||||||
|
@ -45,21 +51,22 @@ const QueryConfigurator: FC<QueryConfiguratorProps> = ({ error, queryOptions, on
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRunQuery = () => {
|
const handleRunQuery = () => {
|
||||||
updateHistory();
|
updateHistory();
|
||||||
queryDispatch({ type: "SET_QUERY", payload: stateQuery });
|
queryDispatch({ type: "SET_QUERY", payload: stateQuery });
|
||||||
timeDispatch({ type: "RUN_QUERY" });
|
timeDispatch({ type: "RUN_QUERY" });
|
||||||
|
onRunQuery();
|
||||||
};
|
};
|
||||||
|
|
||||||
const onAddQuery = () => {
|
const handleAddQuery = () => {
|
||||||
setStateQuery(prev => [...prev, ""]);
|
setStateQuery(prev => [...prev, ""]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRemoveQuery = (index: number) => {
|
const handleRemoveQuery = (index: number) => {
|
||||||
setStateQuery(prev => prev.filter((q, i) => i !== index));
|
setStateQuery(prev => prev.filter((q, i) => i !== index));
|
||||||
};
|
};
|
||||||
|
|
||||||
const onToggleHideQuery = (e: ReactMouseEvent<HTMLButtonElement, MouseEvent>, index: number) => {
|
const handleToggleHideQuery = (e: ReactMouseEvent<HTMLButtonElement, MouseEvent>, index: number) => {
|
||||||
const { ctrlKey, metaKey } = e;
|
const { ctrlKey, metaKey } = e;
|
||||||
const ctrlMetaKey = ctrlKey || metaKey;
|
const ctrlMetaKey = ctrlKey || metaKey;
|
||||||
|
|
||||||
|
@ -95,17 +102,17 @@ const QueryConfigurator: FC<QueryConfiguratorProps> = ({ error, queryOptions, on
|
||||||
};
|
};
|
||||||
|
|
||||||
const createHandlerRemoveQuery = (i: number) => () => {
|
const createHandlerRemoveQuery = (i: number) => () => {
|
||||||
onRemoveQuery(i);
|
handleRemoveQuery(i);
|
||||||
setHideQuery(prev => prev.includes(i) ? prev.filter(n => n !== i) : prev.map(n => n > i ? n - 1: n));
|
setHideQuery(prev => prev.includes(i) ? prev.filter(n => n !== i) : prev.map(n => n > i ? n - 1: n));
|
||||||
};
|
};
|
||||||
|
|
||||||
const createHandlerHideQuery = (i: number) => (e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => {
|
const createHandlerHideQuery = (i: number) => (e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||||
onToggleHideQuery(e, i);
|
handleToggleHideQuery(e, i);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (prevStateQuery && (stateQuery.length < prevStateQuery.length)) {
|
if (prevStateQuery && (stateQuery.length < prevStateQuery.length)) {
|
||||||
onRunQuery();
|
handleRunQuery();
|
||||||
}
|
}
|
||||||
}, [stateQuery]);
|
}, [stateQuery]);
|
||||||
|
|
||||||
|
@ -137,7 +144,7 @@ const QueryConfigurator: FC<QueryConfiguratorProps> = ({ error, queryOptions, on
|
||||||
error={error}
|
error={error}
|
||||||
onArrowUp={createHandlerArrow(-1, i)}
|
onArrowUp={createHandlerArrow(-1, i)}
|
||||||
onArrowDown={createHandlerArrow(1, i)}
|
onArrowDown={createHandlerArrow(1, i)}
|
||||||
onEnter={onRunQuery}
|
onEnter={handleRunQuery}
|
||||||
onChange={createHandlerChangeQuery(i)}
|
onChange={createHandlerChangeQuery(i)}
|
||||||
label={`Query ${i + 1}`}
|
label={`Query ${i + 1}`}
|
||||||
disabled={hideQuery.includes(i)}
|
disabled={hideQuery.includes(i)}
|
||||||
|
@ -173,7 +180,7 @@ const QueryConfigurator: FC<QueryConfiguratorProps> = ({ error, queryOptions, on
|
||||||
{stateQuery.length < MAX_QUERY_FIELDS && (
|
{stateQuery.length < MAX_QUERY_FIELDS && (
|
||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onClick={onAddQuery}
|
onClick={handleAddQuery}
|
||||||
startIcon={<PlusIcon/>}
|
startIcon={<PlusIcon/>}
|
||||||
>
|
>
|
||||||
Add Query
|
Add Query
|
||||||
|
@ -181,7 +188,7 @@ const QueryConfigurator: FC<QueryConfiguratorProps> = ({ error, queryOptions, on
|
||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
onClick={onRunQuery}
|
onClick={handleRunQuery}
|
||||||
startIcon={<PlayIcon/>}
|
startIcon={<PlayIcon/>}
|
||||||
>
|
>
|
||||||
{isMobile ? "Execute" : "Execute Query"}
|
{isMobile ? "Execute" : "Execute Query"}
|
||||||
|
|
|
@ -35,6 +35,7 @@ const CustomPanel: FC = () => {
|
||||||
const [tracesState, setTracesState] = useState<Trace[]>([]);
|
const [tracesState, setTracesState] = useState<Trace[]>([]);
|
||||||
const [hideQuery, setHideQuery] = useState<number[]>([]);
|
const [hideQuery, setHideQuery] = useState<number[]>([]);
|
||||||
const [showAllSeries, setShowAllSeries] = useState(false);
|
const [showAllSeries, setShowAllSeries] = useState(false);
|
||||||
|
const [hideError, setHideError] = useState(!query[0]);
|
||||||
|
|
||||||
const { customStep, yaxis } = useGraphState();
|
const { customStep, yaxis } = useGraphState();
|
||||||
const graphDispatch = useGraphDispatch();
|
const graphDispatch = useGraphDispatch();
|
||||||
|
@ -72,6 +73,10 @@ const CustomPanel: FC = () => {
|
||||||
setHideQuery(queries);
|
setHideQuery(queries);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleRunQuery = () => {
|
||||||
|
setHideError(false);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (traces) {
|
if (traces) {
|
||||||
setTracesState([...tracesState, ...traces]);
|
setTracesState([...tracesState, ...traces]);
|
||||||
|
@ -94,9 +99,10 @@ const CustomPanel: FC = () => {
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<QueryConfigurator
|
<QueryConfigurator
|
||||||
error={error}
|
error={!hideError ? error : ""}
|
||||||
queryOptions={queryOptions}
|
queryOptions={queryOptions}
|
||||||
onHideQuery={handleHideQuery}
|
onHideQuery={handleHideQuery}
|
||||||
|
onRunQuery={handleRunQuery}
|
||||||
/>
|
/>
|
||||||
{isTracingEnabled && (
|
{isTracingEnabled && (
|
||||||
<div className="vm-custom-panel__trace">
|
<div className="vm-custom-panel__trace">
|
||||||
|
@ -107,7 +113,7 @@ const CustomPanel: FC = () => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{isLoading && <Spinner />}
|
{isLoading && <Spinner />}
|
||||||
{error && <Alert variant="error">{error}</Alert>}
|
{!hideError && error && <Alert variant="error">{error}</Alert>}
|
||||||
{warning && <Alert variant="warning">
|
{warning && <Alert variant="warning">
|
||||||
<div
|
<div
|
||||||
className={classNames({
|
className={classNames({
|
||||||
|
@ -121,7 +127,7 @@ const CustomPanel: FC = () => {
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onClick={handleShowAll}
|
onClick={handleShowAll}
|
||||||
>
|
>
|
||||||
Show all
|
Show all
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Alert>}
|
</Alert>}
|
||||||
|
|
Loading…
Reference in a new issue