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 {