diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e1de3ea..cbef8e27 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## tip * FEATURE: add datasource settings for limiting the number of metrics during discovery. The proper limits should protect users from slowing down the browser when datasource returns big amounts of discovered metrics in response. See [this issue](https://github.com/VictoriaMetrics/grafana-datasource/issues/82). +* FEATURE: add a `prettify query` icon, which when clicked, formats the query. See [this issue](https://github.com/VictoriaMetrics/grafana-datasource/issues/86). +* FEATURE: change the style of the buttons `WITH templates` and `Run in vmui` to icons. * BUGFIX: correctly handle custom query parameters in annotation queries. See [this issue](https://github.com/VictoriaMetrics/grafana-datasource/issues/95) * BUGFIX: fix the duplication of labels in the legend when using expressions. See [this issue](https://github.com/VictoriaMetrics/grafana-datasource/issues/93) diff --git a/src/components/PrettifyQuery.tsx b/src/components/PrettifyQuery.tsx new file mode 100755 index 00000000..4b7f5322 --- /dev/null +++ b/src/components/PrettifyQuery.tsx @@ -0,0 +1,53 @@ +import React, { FC, useState, memo } from 'react'; + +import { IconButton } from "@grafana/ui"; + +import { PrometheusDatasource } from '../datasource'; +import { PromQuery } from "../types"; + +interface Props { + datasource: PrometheusDatasource; + query: PromQuery; + onChange: (update: PromQuery) => void; +} + +enum ResponseStatus { + Success = 'success', + Error = 'error' +} + +const PrettifyQuery: FC = ({ + datasource, + query, + onChange +}) => { + const [loading, setLoading] = useState(false) + + const handleClickPrettify = async () => { + setLoading(true) + try { + const response = await datasource.prettifyRequest(query.expr) + const { data, status } = response + if (data?.status === ResponseStatus.Success) { + onChange({ ...query, expr: data.query }); + } else { + console.error(`Error requesting /prettify-query, status: ${status}`) + } + } catch (e) { + console.error(e) + } + setLoading(false) + } + + return ( + + ); +}; + +export default memo(PrettifyQuery); diff --git a/src/components/VmuiLink.tsx b/src/components/VmuiLink.tsx index c57d9486..c8c10615 100755 --- a/src/components/VmuiLink.tsx +++ b/src/components/VmuiLink.tsx @@ -18,7 +18,7 @@ import React, { FC, useEffect, useState, memo } from 'react'; import { PanelData, ScopedVars, textUtil, rangeUtil } from '@grafana/data'; import { getBackendSrv } from "@grafana/runtime"; -import { Button } from "@grafana/ui"; +import { IconButton } from "@grafana/ui"; import { PrometheusDatasource } from '../datasource'; import { PromQuery } from '../types'; @@ -55,11 +55,11 @@ export const relativeTimeOptionsVMUI = [ })) const VmuiLink: FC = ({ - panelData, - query, - datasource, - dashboardUID, - }) => { + panelData, + query, + datasource, + dashboardUID, +}) => { const [href, setHref] = useState(''); useEffect(() => { @@ -132,14 +132,13 @@ const VmuiLink: FC = ({ }, [dashboardUID, datasource, panelData, query]); return ( - - + + ); }; diff --git a/src/components/WithTemplateConfig/index.tsx b/src/components/WithTemplateConfig/index.tsx index e1ded718..56c9878a 100644 --- a/src/components/WithTemplateConfig/index.tsx +++ b/src/components/WithTemplateConfig/index.tsx @@ -1,6 +1,6 @@ import React, { FC, useCallback, useEffect, useState } from 'react' -import { Badge, Button, Modal, useStyles2 } from "@grafana/ui"; +import { Badge, Button, IconButton, Modal, useStyles2 } from "@grafana/ui"; import { PrometheusDatasource } from "../../datasource"; @@ -82,14 +82,12 @@ const WithTemplateConfig: FC = ({ template, setTemplate, dashboardUID, da return ( <> - + /> (query: string) { + // If URL includes endpoint that supports POST and GET method, try to use configured method. This might fail as POST is supported only in v2.10+. + try { + return await lastValueFrom( + this._request(`/api/datasources/proxy/${this.id}/prettify-query`, {}, { + method: 'GET', + hideFromInspector: true, + showErrorAlert: false, + params: { + query + } + }) + ); + } catch (err) { + throw err; + } + } + interpolateQueryExpr(value: string | string[] = [], variable: any) { // if no multi or include all do not regexEscape if (!variable.multi && !variable.includeAll) { diff --git a/src/querybuilder/components/PromQueryEditorSelector.tsx b/src/querybuilder/components/PromQueryEditorSelector.tsx index 5d296b62..a51d2df4 100755 --- a/src/querybuilder/components/PromQueryEditorSelector.tsx +++ b/src/querybuilder/components/PromQueryEditorSelector.tsx @@ -20,8 +20,9 @@ import React, { SyntheticEvent, useCallback, useEffect, useState } from 'react'; import { CoreApp, LoadingState } from '@grafana/data'; import { reportInteraction } from '@grafana/runtime'; -import { Button, ConfirmModal, Tooltip } from '@grafana/ui'; +import { ConfirmModal, IconButton } from '@grafana/ui'; +import PrettifyQuery from "../../components/PrettifyQuery"; import { EditorHeader, EditorRows, FlexItem, InlineSelect, Space } from '../../components/QueryEditor'; import VmuiLink from "../../components/VmuiLink"; import WithTemplateConfig from "../../components/WithTemplateConfig"; @@ -52,7 +53,6 @@ export const PromQueryEditorSelector = React.memo((props) => { const { onChange, onRunQuery, data, app, datasource } = props; const [parseModalOpen, setParseModalOpen] = useState(false); - const [dataIsStale, setDataIsStale] = useState(false); const [trace, setTrace] = useState(false); const [rawQuery, setRawQuery] = useState(false) const { flag: explain, setFlag: setExplain } = useFlag(promQueryEditorExplainKey); @@ -86,12 +86,7 @@ export const PromQueryEditorSelector = React.memo((props) => { [onChange, query, app] ); - useEffect(() => { - setDataIsStale(false); - }, [data]); - const onChangeInternal = (query: PromQuery) => { - setDataIsStale(true); onChange(query); }; @@ -156,17 +151,14 @@ export const PromQueryEditorSelector = React.memo((props) => { dashboardUID={dashboardUID} datasource={datasource} /> + {app !== CoreApp.Explore && ( - -