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 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 { getAppModeEnable } from "../../utils/app-mode";
|
||||
import classNames from "classnames";
|
||||
|
@ -12,14 +13,33 @@ import useDeviceDetect from "../../hooks/useDeviceDetect";
|
|||
const Layout: FC = () => {
|
||||
const appModeEnable = getAppModeEnable();
|
||||
const { isMobile } = useDeviceDetect();
|
||||
const { pathname } = useLocation();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
|
||||
useFetchDashboards();
|
||||
|
||||
const { pathname } = useLocation();
|
||||
useEffect(() => {
|
||||
const setDocumentTitle = () => {
|
||||
const defaultTitle = "vmui";
|
||||
const routeTitle = routerOptions[pathname]?.title;
|
||||
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">
|
||||
<Header/>
|
||||
|
|
|
@ -19,9 +19,15 @@ export interface QueryConfiguratorProps {
|
|||
error?: ErrorTypes | string;
|
||||
queryOptions: string[]
|
||||
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 { query, queryHistory, autocomplete } = useQueryState();
|
||||
|
@ -45,21 +51,22 @@ const QueryConfigurator: FC<QueryConfiguratorProps> = ({ error, queryOptions, on
|
|||
});
|
||||
};
|
||||
|
||||
const onRunQuery = () => {
|
||||
const handleRunQuery = () => {
|
||||
updateHistory();
|
||||
queryDispatch({ type: "SET_QUERY", payload: stateQuery });
|
||||
timeDispatch({ type: "RUN_QUERY" });
|
||||
onRunQuery();
|
||||
};
|
||||
|
||||
const onAddQuery = () => {
|
||||
const handleAddQuery = () => {
|
||||
setStateQuery(prev => [...prev, ""]);
|
||||
};
|
||||
|
||||
const onRemoveQuery = (index: number) => {
|
||||
const handleRemoveQuery = (index: number) => {
|
||||
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 ctrlMetaKey = ctrlKey || metaKey;
|
||||
|
||||
|
@ -95,17 +102,17 @@ const QueryConfigurator: FC<QueryConfiguratorProps> = ({ error, queryOptions, on
|
|||
};
|
||||
|
||||
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));
|
||||
};
|
||||
|
||||
const createHandlerHideQuery = (i: number) => (e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||
onToggleHideQuery(e, i);
|
||||
handleToggleHideQuery(e, i);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (prevStateQuery && (stateQuery.length < prevStateQuery.length)) {
|
||||
onRunQuery();
|
||||
handleRunQuery();
|
||||
}
|
||||
}, [stateQuery]);
|
||||
|
||||
|
@ -137,7 +144,7 @@ const QueryConfigurator: FC<QueryConfiguratorProps> = ({ error, queryOptions, on
|
|||
error={error}
|
||||
onArrowUp={createHandlerArrow(-1, i)}
|
||||
onArrowDown={createHandlerArrow(1, i)}
|
||||
onEnter={onRunQuery}
|
||||
onEnter={handleRunQuery}
|
||||
onChange={createHandlerChangeQuery(i)}
|
||||
label={`Query ${i + 1}`}
|
||||
disabled={hideQuery.includes(i)}
|
||||
|
@ -173,7 +180,7 @@ const QueryConfigurator: FC<QueryConfiguratorProps> = ({ error, queryOptions, on
|
|||
{stateQuery.length < MAX_QUERY_FIELDS && (
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={onAddQuery}
|
||||
onClick={handleAddQuery}
|
||||
startIcon={<PlusIcon/>}
|
||||
>
|
||||
Add Query
|
||||
|
@ -181,7 +188,7 @@ const QueryConfigurator: FC<QueryConfiguratorProps> = ({ error, queryOptions, on
|
|||
)}
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={onRunQuery}
|
||||
onClick={handleRunQuery}
|
||||
startIcon={<PlayIcon/>}
|
||||
>
|
||||
{isMobile ? "Execute" : "Execute Query"}
|
||||
|
|
|
@ -35,6 +35,7 @@ const CustomPanel: FC = () => {
|
|||
const [tracesState, setTracesState] = useState<Trace[]>([]);
|
||||
const [hideQuery, setHideQuery] = useState<number[]>([]);
|
||||
const [showAllSeries, setShowAllSeries] = useState(false);
|
||||
const [hideError, setHideError] = useState(!query[0]);
|
||||
|
||||
const { customStep, yaxis } = useGraphState();
|
||||
const graphDispatch = useGraphDispatch();
|
||||
|
@ -72,6 +73,10 @@ const CustomPanel: FC = () => {
|
|||
setHideQuery(queries);
|
||||
};
|
||||
|
||||
const handleRunQuery = () => {
|
||||
setHideError(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (traces) {
|
||||
setTracesState([...tracesState, ...traces]);
|
||||
|
@ -94,9 +99,10 @@ const CustomPanel: FC = () => {
|
|||
})}
|
||||
>
|
||||
<QueryConfigurator
|
||||
error={error}
|
||||
error={!hideError ? error : ""}
|
||||
queryOptions={queryOptions}
|
||||
onHideQuery={handleHideQuery}
|
||||
onRunQuery={handleRunQuery}
|
||||
/>
|
||||
{isTracingEnabled && (
|
||||
<div className="vm-custom-panel__trace">
|
||||
|
@ -107,7 +113,7 @@ const CustomPanel: FC = () => {
|
|||
</div>
|
||||
)}
|
||||
{isLoading && <Spinner />}
|
||||
{error && <Alert variant="error">{error}</Alert>}
|
||||
{!hideError && error && <Alert variant="error">{error}</Alert>}
|
||||
{warning && <Alert variant="warning">
|
||||
<div
|
||||
className={classNames({
|
||||
|
@ -121,7 +127,7 @@ const CustomPanel: FC = () => {
|
|||
variant="outlined"
|
||||
onClick={handleShowAll}
|
||||
>
|
||||
Show all
|
||||
Show all
|
||||
</Button>
|
||||
</div>
|
||||
</Alert>}
|
||||
|
|
Loading…
Reference in a new issue