vmui: show query error (#3890)

* add links support with old query params
* show error after execute query
This commit is contained in:
Yury Molodov 2023-03-03 16:07:47 +01:00 committed by Aliaksandr Valialkin
parent f9723aca44
commit c383c9b864
No known key found for this signature in database
GPG key ID: A72BEC6CD3D0DED1
3 changed files with 51 additions and 18 deletions

View file

@ -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/>

View file

@ -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"}

View file

@ -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>}