From c63071f519356fc6634467b27971b8a8349207b9 Mon Sep 17 00:00:00 2001 From: Andrej Ocenas Date: Thu, 2 Jun 2022 13:50:10 +0200 Subject: [PATCH] Prometheus/Loki: Show raw query by default in the builder(#50007) --- .../LokiQueryBuilderContainer.test.tsx | 1 + .../components/LokiQueryBuilderContainer.tsx | 5 ++-- .../LokiQueryEditorSelector.test.tsx | 29 ++++++++++--------- .../components/LokiQueryEditorSelector.tsx | 8 +++-- .../datasource/loki/querybuilder/state.ts | 27 +++++++++++++++++ public/app/plugins/datasource/loki/types.ts | 2 -- .../components/PromQueryBuilderContainer.tsx | 5 ++-- .../PromQueryEditorSelector.test.tsx | 29 ++++++++++--------- .../components/PromQueryEditorSelector.tsx | 8 +++-- .../prometheus/querybuilder/state.ts | 27 +++++++++++++++++ .../plugins/datasource/prometheus/types.ts | 2 -- 11 files changed, 103 insertions(+), 40 deletions(-) diff --git a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderContainer.test.tsx b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderContainer.test.tsx index 170939451b6..24b391681d2 100644 --- a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderContainer.test.tsx +++ b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderContainer.test.tsx @@ -30,6 +30,7 @@ describe('LokiQueryBuilderContainer', () => { ), onChange: jest.fn(), onRunQuery: () => {}, + showRawQuery: true, }; render(); expect(screen.getByText('testjob')).toBeInTheDocument(); diff --git a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderContainer.tsx b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderContainer.tsx index 3e20f62bcf3..09a6fed59c2 100644 --- a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderContainer.tsx +++ b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderContainer.tsx @@ -15,6 +15,7 @@ export interface Props { datasource: LokiDatasource; onChange: (update: LokiQuery) => void; onRunQuery: () => void; + showRawQuery: boolean; } export interface State { @@ -26,7 +27,7 @@ export interface State { * This component is here just to contain the translation logic between string query and the visual query builder model. */ export function LokiQueryBuilderContainer(props: Props) { - const { query, onChange, onRunQuery, datasource } = props; + const { query, onChange, onRunQuery, datasource, showRawQuery } = props; const [state, dispatch] = useReducer(stateSlice.reducer, { expr: query.expr, // Use initial visual query only if query.expr is empty string @@ -62,7 +63,7 @@ export function LokiQueryBuilderContainer(props: Props) { onChange={onVisQueryChange} onRunQuery={onRunQuery} /> - {query.rawQuery && } + {showRawQuery && } ); } diff --git a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryEditorSelector.test.tsx b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryEditorSelector.test.tsx index 1b483c53dd1..d105157ef0e 100644 --- a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryEditorSelector.test.tsx +++ b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryEditorSelector.test.tsx @@ -10,6 +10,18 @@ import { LokiQuery, LokiQueryType } from '../../types'; import { LokiQueryEditorSelector } from './LokiQueryEditorSelector'; +jest.mock('app/core/store', () => { + return { + get() { + return undefined; + }, + set() {}, + getObject(key: string, defaultValue: any) { + return defaultValue; + }, + }; +}); + const defaultQuery = { refId: 'A', expr: '{label1="foo", label2="bar"}', @@ -86,23 +98,14 @@ describe('LokiQueryEditorSelector', () => { }); it('Can enable raw query', async () => { - const { onChange } = renderWithMode(QueryEditorMode.Builder); - expect(screen.queryByLabelText('selector')).not.toBeInTheDocument(); - + renderWithMode(QueryEditorMode.Builder); + expect(screen.queryByLabelText('selector')).toBeInTheDocument(); screen.getByLabelText('Raw query').click(); - - expect(onChange).toBeCalledWith({ - refId: 'A', - expr: defaultQuery.expr, - queryType: 'range', - editorMode: QueryEditorMode.Builder, - rawQuery: true, - }); + expect(screen.queryByLabelText('selector')).not.toBeInTheDocument(); }); - it('Should show raw query', async () => { + it('Should show raw query by default', async () => { renderWithProps({ - rawQuery: true, editorMode: QueryEditorMode.Builder, expr: '{job="grafana"}', }); diff --git a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryEditorSelector.tsx b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryEditorSelector.tsx index ef7aceaf560..e374302a2b6 100644 --- a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryEditorSelector.tsx +++ b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryEditorSelector.tsx @@ -11,7 +11,7 @@ import { LokiQueryEditorProps } from '../../components/types'; import { LokiQuery } from '../../types'; import { lokiQueryModeller } from '../LokiQueryModeller'; import { buildVisualQueryFromString } from '../parsing'; -import { changeEditorMode, getQueryWithDefaults } from '../state'; +import { changeEditorMode, getQueryWithDefaults, useRawQuery } from '../state'; import { LokiQueryBuilderContainer } from './LokiQueryBuilderContainer'; import { LokiQueryBuilderExplained } from './LokiQueryBuilderExplained'; @@ -24,6 +24,7 @@ export const LokiQueryEditorSelector = React.memo((props) const [dataIsStale, setDataIsStale] = useState(false); const query = getQueryWithDefaults(props.query); + const [rawQuery, setRawQuery] = useRawQuery(); // This should be filled in from the defaults by now. const editorMode = query.editorMode!; @@ -53,7 +54,7 @@ export const LokiQueryEditorSelector = React.memo((props) const onQueryPreviewChange = (event: SyntheticEvent) => { const isEnabled = event.currentTarget.checked; - onChange({ ...query, rawQuery: isEnabled }); + setRawQuery(isEnabled); }; return ( @@ -86,7 +87,7 @@ export const LokiQueryEditorSelector = React.memo((props) }} options={lokiQueryModeller.getQueryPatterns().map((x) => ({ label: x.name, value: x }))} /> - + )} @@ -110,6 +111,7 @@ export const LokiQueryEditorSelector = React.memo((props) query={query} onChange={onChangeInternal} onRunQuery={props.onRunQuery} + showRawQuery={rawQuery} /> )} {editorMode === QueryEditorMode.Explain && } diff --git a/public/app/plugins/datasource/loki/querybuilder/state.ts b/public/app/plugins/datasource/loki/querybuilder/state.ts index 741a0fbcd3e..94ab436ea20 100644 --- a/public/app/plugins/datasource/loki/querybuilder/state.ts +++ b/public/app/plugins/datasource/loki/querybuilder/state.ts @@ -1,3 +1,5 @@ +import { useCallback, useState } from 'react'; + import store from 'app/core/store'; import { QueryEditorMode } from '../../prometheus/querybuilder/shared/types'; @@ -53,3 +55,28 @@ export function getQueryWithDefaults(query: LokiQuery): LokiQuery { return result; } + +const queryEditorRawQueryLocalStorageKey = 'LokiQueryEditorRawQueryDefault'; + +function getRawQueryVisibility(): boolean { + const val = store.get(queryEditorRawQueryLocalStorageKey); + return val === undefined ? true : Boolean(parseInt(val, 10)); +} + +function setRawQueryVisibility(value: boolean) { + store.set(queryEditorRawQueryLocalStorageKey, value ? '1' : '0'); +} + +/** + * Use and store value of raw query switch in local storage. + * Needs to be a hook with local state to trigger rerenders. + */ +export function useRawQuery(): [boolean, (val: boolean) => void] { + const [rawQuery, setRawQuery] = useState(getRawQueryVisibility()); + const setter = useCallback((value: boolean) => { + setRawQueryVisibility(value); + setRawQuery(value); + }, []); + + return [rawQuery, setter]; +} diff --git a/public/app/plugins/datasource/loki/types.ts b/public/app/plugins/datasource/loki/types.ts index 345e2f23cbf..f84982d2e76 100644 --- a/public/app/plugins/datasource/loki/types.ts +++ b/public/app/plugins/datasource/loki/types.ts @@ -49,8 +49,6 @@ export interface LokiQuery extends DataQuery { /* @deprecated now use queryType */ instant?: boolean; editorMode?: QueryEditorMode; - /** Controls if the raw query text is shown */ - rawQuery?: boolean; } export interface LokiOptions extends DataSourceJsonData { diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryBuilderContainer.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryBuilderContainer.tsx index d7cc0ab0a32..cae0623fe73 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryBuilderContainer.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryBuilderContainer.tsx @@ -18,6 +18,7 @@ export interface Props { onChange: (update: PromQuery) => void; onRunQuery: () => void; data?: PanelData; + showRawQuery?: boolean; } export interface State { @@ -29,7 +30,7 @@ export interface State { * This component is here just to contain the translation logic between string query and the visual query builder model. */ export function PromQueryBuilderContainer(props: Props) { - const { query, onChange, onRunQuery, datasource, data } = props; + const { query, onChange, onRunQuery, datasource, data, showRawQuery } = props; const [state, dispatch] = useReducer(stateSlice.reducer, { expr: query.expr }); // Only rebuild visual query if expr changes from outside @@ -56,7 +57,7 @@ export function PromQueryBuilderContainer(props: Props) { onRunQuery={onRunQuery} data={data} /> - {query.rawQuery && } + {showRawQuery && } ); } diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryEditorSelector.test.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryEditorSelector.test.tsx index 3d3bd9821b9..d01bbd40f77 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryEditorSelector.test.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryEditorSelector.test.tsx @@ -20,6 +20,18 @@ jest.mock('../../components/monaco-query-field/MonacoQueryFieldWrapper', () => { }; }); +jest.mock('app/core/store', () => { + return { + get() { + return undefined; + }, + set() {}, + getObject(key: string, defaultValue: any) { + return defaultValue; + }, + }; +}); + jest.mock('@grafana/runtime', () => { return { ...jest.requireActual('@grafana/runtime'), @@ -87,23 +99,14 @@ describe('PromQueryEditorSelector', () => { }); it('Can enable raw query', async () => { - const { onChange } = renderWithMode(QueryEditorMode.Builder); - expect(screen.queryByLabelText('selector')).not.toBeInTheDocument(); - + renderWithMode(QueryEditorMode.Builder); + expect(screen.queryByLabelText('selector')).toBeInTheDocument(); screen.getByLabelText('Raw query').click(); - - expect(onChange).toBeCalledWith({ - refId: 'A', - expr: defaultQuery.expr, - range: true, - editorMode: QueryEditorMode.Builder, - rawQuery: true, - }); + expect(screen.queryByLabelText('selector')).not.toBeInTheDocument(); }); - it('Should show raw query', async () => { + it('Should show raw query by default', async () => { renderWithProps({ - rawQuery: true, editorMode: QueryEditorMode.Builder, expr: 'my_metric', }); diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryEditorSelector.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryEditorSelector.tsx index cbb5f0801bc..ca58fe5219e 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryEditorSelector.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryEditorSelector.tsx @@ -13,7 +13,7 @@ import { FeedbackLink } from '../shared/FeedbackLink'; import { QueryEditorModeToggle } from '../shared/QueryEditorModeToggle'; import { QueryHeaderSwitch } from '../shared/QueryHeaderSwitch'; import { QueryEditorMode } from '../shared/types'; -import { changeEditorMode, getQueryWithDefaults } from '../state'; +import { changeEditorMode, getQueryWithDefaults, useRawQuery } from '../state'; import { PromQueryBuilderContainer } from './PromQueryBuilderContainer'; import { PromQueryBuilderExplained } from './PromQueryBuilderExplained'; @@ -28,6 +28,7 @@ export const PromQueryEditorSelector = React.memo((props) => { const [dataIsStale, setDataIsStale] = useState(false); const query = getQueryWithDefaults(props.query, app); + const [rawQuery, setRawQuery] = useRawQuery(); // This should be filled in from the defaults by now. const editorMode = query.editorMode!; @@ -59,7 +60,7 @@ export const PromQueryEditorSelector = React.memo((props) => { const onQueryPreviewChange = (event: SyntheticEvent) => { const isEnabled = event.currentTarget.checked; - onChange({ ...query, rawQuery: isEnabled }); + setRawQuery(isEnabled); }; const onChangeInternal = (query: PromQuery) => { @@ -99,7 +100,7 @@ export const PromQueryEditorSelector = React.memo((props) => { }} options={promQueryModeller.getQueryPatterns().map((x) => ({ label: x.name, value: x }))} /> - + )} {editorMode === QueryEditorMode.Builder && ( @@ -127,6 +128,7 @@ export const PromQueryEditorSelector = React.memo((props) => { onChange={onChangeInternal} onRunQuery={props.onRunQuery} data={data} + showRawQuery={rawQuery} /> )} {editorMode === QueryEditorMode.Explain && } diff --git a/public/app/plugins/datasource/prometheus/querybuilder/state.ts b/public/app/plugins/datasource/prometheus/querybuilder/state.ts index 04a42555d40..a9c0b6e79d3 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/state.ts +++ b/public/app/plugins/datasource/prometheus/querybuilder/state.ts @@ -1,3 +1,5 @@ +import { useCallback, useState } from 'react'; + import { CoreApp } from '@grafana/data'; import store from 'app/core/store'; @@ -59,3 +61,28 @@ export function getQueryWithDefaults(query: PromQuery, app: CoreApp | undefined) return result; } + +const queryEditorRawQueryLocalStorageKey = 'PrometheusQueryEditorRawQueryDefault'; + +function getRawQueryVisibility(): boolean { + const val = store.get(queryEditorRawQueryLocalStorageKey); + return val === undefined ? true : Boolean(parseInt(val, 10)); +} + +function setRawQueryVisibility(value: boolean) { + store.set(queryEditorRawQueryLocalStorageKey, value ? '1' : '0'); +} + +/** + * Use and store value of raw query switch in local storage. + * Needs to be a hook with local state to trigger rerenders. + */ +export function useRawQuery(): [boolean, (val: boolean) => void] { + const [rawQuery, setRawQuery] = useState(getRawQueryVisibility()); + const setter = useCallback((value: boolean) => { + setRawQueryVisibility(value); + setRawQuery(value); + }, []); + + return [rawQuery, setter]; +} diff --git a/public/app/plugins/datasource/prometheus/types.ts b/public/app/plugins/datasource/prometheus/types.ts index e9f1776becd..7194bfcfb03 100644 --- a/public/app/plugins/datasource/prometheus/types.ts +++ b/public/app/plugins/datasource/prometheus/types.ts @@ -20,8 +20,6 @@ export interface PromQuery extends DataQuery { showingTable?: boolean; /** Code, Builder or Explain */ editorMode?: QueryEditorMode; - /** Controls if the raw query text is shown */ - rawQuery?: boolean; } export interface PromOptions extends DataSourceJsonData {