From cf55d6889429df959b48d6f54ccb4bad5b690cbe Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Thu, 14 Mar 2019 17:20:33 +0100 Subject: [PATCH 1/7] using refId from panel model --- public/app/core/utils/explore.ts | 13 +++++------- public/app/core/utils/query.ts | 12 +++++++++++ .../features/dashboard/state/PanelModel.ts | 15 +++----------- public/app/features/explore/state/actions.ts | 20 ++++++++++--------- public/app/features/explore/state/reducers.ts | 8 +++++--- 5 files changed, 36 insertions(+), 32 deletions(-) create mode 100644 public/app/core/utils/query.ts diff --git a/public/app/core/utils/explore.ts b/public/app/core/utils/explore.ts index 31e5a392050..33adbfb5a73 100644 --- a/public/app/core/utils/explore.ts +++ b/public/app/core/utils/explore.ts @@ -23,6 +23,7 @@ import { ResultGetter, } from 'app/types/explore'; import { LogsDedupStrategy } from 'app/core/logs_model'; +import { getNextQueryLetter } from './query'; export const DEFAULT_RANGE = { from: 'now-6h', @@ -225,12 +226,8 @@ export function generateKey(index = 0): string { return `Q-${Date.now()}-${Math.random()}-${index}`; } -export function generateRefId(index = 0): string { - return `${index + 1}`; -} - -export function generateEmptyQuery(index = 0): { refId: string; key: string } { - return { refId: generateRefId(index), key: generateKey(index) }; +export function generateEmptyQuery(queries: DataQuery[], index = 0): { refId: string; key: string } { + return { refId: getNextQueryLetter(queries), key: generateKey(index) }; } /** @@ -238,9 +235,9 @@ export function generateEmptyQuery(index = 0): { refId: string; key: string } { */ export function ensureQueries(queries?: DataQuery[]): DataQuery[] { if (queries && typeof queries === 'object' && queries.length > 0) { - return queries.map((query, i) => ({ ...query, ...generateEmptyQuery(i) })); + return queries.map((query, i) => ({ ...query, ...generateEmptyQuery(queries, i) })); } - return [{ ...generateEmptyQuery() }]; + return [{ ...generateEmptyQuery(queries) }]; } /** diff --git a/public/app/core/utils/query.ts b/public/app/core/utils/query.ts new file mode 100644 index 00000000000..3a3fd64fbc8 --- /dev/null +++ b/public/app/core/utils/query.ts @@ -0,0 +1,12 @@ +import _ from 'lodash'; +import { DataQuery } from '@grafana/ui/'; + +export const getNextQueryLetter = (queries: DataQuery[]): string => { + const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + + return _.find(letters, refId => { + return _.every(queries, other => { + return other.refId !== refId; + }); + }); +}; diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index 128bd8d0785..db9a9c04e14 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -5,6 +5,7 @@ import _ from 'lodash'; import { Emitter } from 'app/core/utils/emitter'; import { DataQuery, TimeSeries, Threshold, ScopedVars, PanelTypeChangedHook } from '@grafana/ui'; import { TableData } from '@grafana/ui/src'; +import { getNextQueryLetter } from '../../../core/utils/query'; export interface GridPos { x: number; @@ -128,7 +129,7 @@ export class PanelModel { if (this.targets) { for (const query of this.targets) { if (!query.refId) { - query.refId = this.getNextQueryLetter(); + query.refId = getNextQueryLetter(this.targets); } } } @@ -266,20 +267,10 @@ export class PanelModel { addQuery(query?: Partial) { query = query || { refId: 'A' }; - query.refId = this.getNextQueryLetter(); + query.refId = getNextQueryLetter(this.targets); this.targets.push(query as DataQuery); } - getNextQueryLetter(): string { - const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - - return _.find(letters, refId => { - return _.every(this.targets, other => { - return other.refId !== refId; - }); - }); - } - changeQuery(query: DataQuery, index: number) { // ensure refId is maintained query.refId = this.targets[index].refId; diff --git a/public/app/features/explore/state/actions.ts b/public/app/features/explore/state/actions.ts index e0b84320fa7..fda8fe5eef4 100644 --- a/public/app/features/explore/state/actions.ts +++ b/public/app/features/explore/state/actions.ts @@ -60,7 +60,6 @@ import { splitCloseAction, splitOpenAction, addQueryRowAction, - AddQueryRowPayload, toggleGraphAction, toggleLogsAction, toggleTableAction, @@ -87,9 +86,12 @@ const updateExploreUIState = (exploreId, uiStateFragment: Partial { - const query = generateEmptyQuery(index + 1); - return addQueryRowAction({ exploreId, index, query }); +export function addQueryRow(exploreId: ExploreId, index: number): ThunkResult { + return (dispatch, getState) => { + const query = generateEmptyQuery(getState().explore[exploreId].queries, index); + + dispatch(addQueryRowAction({ exploreId, index, query })); + }; } /** @@ -126,10 +128,10 @@ export function changeQuery( index: number, override: boolean ): ThunkResult { - return dispatch => { + return (dispatch, getState) => { // Null query means reset if (query === null) { - query = { ...generateEmptyQuery(index) }; + query = { ...generateEmptyQuery(getState().explore[exploreId].queries) }; } dispatch(changeQueryAction({ exploreId, query, index, override })); @@ -287,7 +289,7 @@ export function importQueries( const nextQueries = importedQueries.map((q, i) => ({ ...q, - ...generateEmptyQuery(i), + ...generateEmptyQuery(queries), })); dispatch(queriesImportedAction({ exploreId, queries: nextQueries })); @@ -629,9 +631,9 @@ export function scanStart(exploreId: ExploreId, scanner: RangeScanner): ThunkRes * Use this action for clicks on query examples. Triggers a query run. */ export function setQueries(exploreId: ExploreId, rawQueries: DataQuery[]): ThunkResult { - return dispatch => { + return (dispatch, getState) => { // Inject react keys into query objects - const queries = rawQueries.map(q => ({ ...q, ...generateEmptyQuery() })); + const queries = rawQueries.map(q => ({ ...q, ...generateEmptyQuery(getState().explore[exploreId].queries) })); dispatch(setQueriesAction({ exploreId, queries })); dispatch(runQueries(exploreId)); }; diff --git a/public/app/features/explore/state/reducers.ts b/public/app/features/explore/state/reducers.ts index a8815842c89..32bfe09a96b 100644 --- a/public/app/features/explore/state/reducers.ts +++ b/public/app/features/explore/state/reducers.ts @@ -127,7 +127,7 @@ export const itemReducer = reducerFactory({} as ExploreItemSta const { query, index } = action.payload; // Override path: queries are completely reset - const nextQuery: DataQuery = { ...query, ...generateEmptyQuery(index) }; + const nextQuery: DataQuery = { ...query, ...generateEmptyQuery(state.queries) }; const nextQueries = [...queries]; nextQueries[index] = nextQuery; @@ -267,7 +267,7 @@ export const itemReducer = reducerFactory({} as ExploreItemSta // Modify all queries nextQueries = queries.map((query, i) => ({ ...modifier({ ...query }, modification), - ...generateEmptyQuery(i), + ...generateEmptyQuery(state.queries), })); // Discard all ongoing transactions nextQueryTransactions = []; @@ -276,7 +276,9 @@ export const itemReducer = reducerFactory({} as ExploreItemSta nextQueries = queries.map((query, i) => { // Synchronize all queries with local query cache to ensure consistency // TODO still needed? - return i === index ? { ...modifier({ ...query }, modification), ...generateEmptyQuery(i) } : query; + return i === index + ? { ...modifier({ ...query }, modification), ...generateEmptyQuery(state.queries) } + : query; }); nextQueryTransactions = queryTransactions // Consume the hint corresponding to the action From 52dcb9bf002f4670e452d88f1d53255407dd1aab Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Thu, 14 Mar 2019 17:39:56 +0100 Subject: [PATCH 2/7] renaming function --- public/app/core/utils/explore.ts | 4 ++-- public/app/core/utils/query.ts | 2 +- public/app/features/dashboard/state/PanelModel.ts | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/public/app/core/utils/explore.ts b/public/app/core/utils/explore.ts index 33adbfb5a73..06456fef0ba 100644 --- a/public/app/core/utils/explore.ts +++ b/public/app/core/utils/explore.ts @@ -23,7 +23,7 @@ import { ResultGetter, } from 'app/types/explore'; import { LogsDedupStrategy } from 'app/core/logs_model'; -import { getNextQueryLetter } from './query'; +import { getNextRefIdLetter } from './query'; export const DEFAULT_RANGE = { from: 'now-6h', @@ -227,7 +227,7 @@ export function generateKey(index = 0): string { } export function generateEmptyQuery(queries: DataQuery[], index = 0): { refId: string; key: string } { - return { refId: getNextQueryLetter(queries), key: generateKey(index) }; + return { refId: getNextRefIdLetter(queries), key: generateKey(index) }; } /** diff --git a/public/app/core/utils/query.ts b/public/app/core/utils/query.ts index 3a3fd64fbc8..304dcf1846f 100644 --- a/public/app/core/utils/query.ts +++ b/public/app/core/utils/query.ts @@ -1,7 +1,7 @@ import _ from 'lodash'; import { DataQuery } from '@grafana/ui/'; -export const getNextQueryLetter = (queries: DataQuery[]): string => { +export const getNextRefIdLetter = (queries: DataQuery[]): string => { const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; return _.find(letters, refId => { diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index db9a9c04e14..5aca2bad462 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -5,7 +5,7 @@ import _ from 'lodash'; import { Emitter } from 'app/core/utils/emitter'; import { DataQuery, TimeSeries, Threshold, ScopedVars, PanelTypeChangedHook } from '@grafana/ui'; import { TableData } from '@grafana/ui/src'; -import { getNextQueryLetter } from '../../../core/utils/query'; +import { getNextRefIdLetter } from '../../../core/utils/query'; export interface GridPos { x: number; @@ -129,7 +129,7 @@ export class PanelModel { if (this.targets) { for (const query of this.targets) { if (!query.refId) { - query.refId = getNextQueryLetter(this.targets); + query.refId = getNextRefIdLetter(this.targets); } } } @@ -267,7 +267,7 @@ export class PanelModel { addQuery(query?: Partial) { query = query || { refId: 'A' }; - query.refId = getNextQueryLetter(this.targets); + query.refId = getNextRefIdLetter(this.targets); this.targets.push(query as DataQuery); } From 6ca1ae309a4cfbfa7f85c691d63c72f0a8277772 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Fri, 15 Mar 2019 08:52:25 +0100 Subject: [PATCH 3/7] set correct return type --- public/app/core/utils/explore.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/core/utils/explore.ts b/public/app/core/utils/explore.ts index 06456fef0ba..45e26e79ebf 100644 --- a/public/app/core/utils/explore.ts +++ b/public/app/core/utils/explore.ts @@ -226,7 +226,7 @@ export function generateKey(index = 0): string { return `Q-${Date.now()}-${Math.random()}-${index}`; } -export function generateEmptyQuery(queries: DataQuery[], index = 0): { refId: string; key: string } { +export function generateEmptyQuery(queries: DataQuery[], index = 0): DataQuery { return { refId: getNextRefIdLetter(queries), key: generateKey(index) }; } From 515fb5903ee772a1f43823d53c13c2ba2dea3e74 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 18 Mar 2019 10:44:00 +0100 Subject: [PATCH 4/7] sorting imports --- public/app/features/dashboard/state/PanelModel.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index 5aca2bad462..f49ed2c0785 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -1,11 +1,13 @@ // Libraries import _ from 'lodash'; -// Types +// Utils import { Emitter } from 'app/core/utils/emitter'; +import { getNextRefIdLetter } from 'app/core/utils/query'; + +// Types import { DataQuery, TimeSeries, Threshold, ScopedVars, PanelTypeChangedHook } from '@grafana/ui'; import { TableData } from '@grafana/ui/src'; -import { getNextRefIdLetter } from '../../../core/utils/query'; export interface GridPos { x: number; From 39728c885b8c9567ad5887895cb21bd88c877ab8 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 18 Mar 2019 11:17:58 +0100 Subject: [PATCH 5/7] rename to char --- public/app/core/utils/explore.ts | 4 ++-- public/app/core/utils/query.ts | 2 +- public/app/features/dashboard/state/PanelModel.ts | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/public/app/core/utils/explore.ts b/public/app/core/utils/explore.ts index 45e26e79ebf..2e79610c3c6 100644 --- a/public/app/core/utils/explore.ts +++ b/public/app/core/utils/explore.ts @@ -23,7 +23,7 @@ import { ResultGetter, } from 'app/types/explore'; import { LogsDedupStrategy } from 'app/core/logs_model'; -import { getNextRefIdLetter } from './query'; +import { getNextRefIdChar } from './query'; export const DEFAULT_RANGE = { from: 'now-6h', @@ -227,7 +227,7 @@ export function generateKey(index = 0): string { } export function generateEmptyQuery(queries: DataQuery[], index = 0): DataQuery { - return { refId: getNextRefIdLetter(queries), key: generateKey(index) }; + return { refId: getNextRefIdChar(queries), key: generateKey(index) }; } /** diff --git a/public/app/core/utils/query.ts b/public/app/core/utils/query.ts index 304dcf1846f..933a73138a8 100644 --- a/public/app/core/utils/query.ts +++ b/public/app/core/utils/query.ts @@ -1,7 +1,7 @@ import _ from 'lodash'; import { DataQuery } from '@grafana/ui/'; -export const getNextRefIdLetter = (queries: DataQuery[]): string => { +export const getNextRefIdChar = (queries: DataQuery[]): string => { const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; return _.find(letters, refId => { diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index f49ed2c0785..8ffce0f1e3b 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -3,7 +3,7 @@ import _ from 'lodash'; // Utils import { Emitter } from 'app/core/utils/emitter'; -import { getNextRefIdLetter } from 'app/core/utils/query'; +import { getNextRefIdChar } from 'app/core/utils/query'; // Types import { DataQuery, TimeSeries, Threshold, ScopedVars, PanelTypeChangedHook } from '@grafana/ui'; @@ -131,7 +131,7 @@ export class PanelModel { if (this.targets) { for (const query of this.targets) { if (!query.refId) { - query.refId = getNextRefIdLetter(this.targets); + query.refId = getNextRefIdChar(this.targets); } } } @@ -269,7 +269,7 @@ export class PanelModel { addQuery(query?: Partial) { query = query || { refId: 'A' }; - query.refId = getNextRefIdLetter(this.targets); + query.refId = getNextRefIdChar(this.targets); this.targets.push(query as DataQuery); } From cb9bda810fae9bb49ee25d2059dddbec53766ad7 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 18 Mar 2019 11:21:40 +0100 Subject: [PATCH 6/7] test --- public/app/core/utils/query.test.ts | 30 +++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 public/app/core/utils/query.test.ts diff --git a/public/app/core/utils/query.test.ts b/public/app/core/utils/query.test.ts new file mode 100644 index 00000000000..a69162751a4 --- /dev/null +++ b/public/app/core/utils/query.test.ts @@ -0,0 +1,30 @@ +import { DataQuery } from '@grafana/ui'; +import { getNextRefIdChar } from './query'; + +const dataQueries: DataQuery[] = [ + { + refId: 'A', + }, + { + refId: 'B', + }, + { + refId: 'C', + }, + { + refId: 'D', + }, + { + refId: 'E', + }, +]; + +describe('Get next refId char', () => { + it('should return next char', () => { + expect(getNextRefIdChar(dataQueries)).toEqual('F'); + }); + + it('should get first char', () => { + expect(getNextRefIdChar([])).toEqual('A'); + }); +}); From be7a5dab69cefe7e2e6dac258fc31cbeb1ee99d8 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 18 Mar 2019 11:23:40 +0100 Subject: [PATCH 7/7] reorder imports --- public/app/core/utils/explore.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/core/utils/explore.ts b/public/app/core/utils/explore.ts index 2e79610c3c6..fdc63b931f7 100644 --- a/public/app/core/utils/explore.ts +++ b/public/app/core/utils/explore.ts @@ -9,6 +9,7 @@ import store from 'app/core/store'; import { parse as parseDate } from 'app/core/utils/datemath'; import { colors } from '@grafana/ui'; import TableModel, { mergeTablesIntoModel } from 'app/core/table_model'; +import { getNextRefIdChar } from './query'; // Types import { RawTimeRange, IntervalValues, DataQuery, DataSourceApi } from '@grafana/ui'; @@ -23,7 +24,6 @@ import { ResultGetter, } from 'app/types/explore'; import { LogsDedupStrategy } from 'app/core/logs_model'; -import { getNextRefIdChar } from './query'; export const DEFAULT_RANGE = { from: 'now-6h',