Merge pull request #15119 from grafana/explore/queries-import-changes

Fix queries being imported incorrectly on datasource change
This commit is contained in:
Torkel Ödegaard 2019-01-30 16:11:36 +01:00 committed by GitHub
commit bd688449f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 75 additions and 37 deletions

View File

@ -43,6 +43,7 @@ export enum ActionTypes {
ToggleTable = 'explore/TOGGLE_TABLE',
UpdateDatasourceInstance = 'explore/UPDATE_DATASOURCE_INSTANCE',
ResetExplore = 'explore/RESET_EXPLORE',
QueriesImported = 'explore/QueriesImported',
}
export interface AddQueryRowAction {
@ -142,7 +143,6 @@ export interface LoadDatasourceSuccessAction {
StartPage?: any;
datasourceInstance: any;
history: HistoryItem[];
initialQueries: DataQuery[];
logsHighlighterExpressions?: any[];
showingStartPage: boolean;
supportsGraph: boolean;
@ -283,6 +283,14 @@ export interface ResetExploreAction {
payload: {};
}
export interface QueriesImported {
type: ActionTypes.QueriesImported;
payload: {
exploreId: ExploreId;
queries: DataQuery[];
};
}
export type Action =
| AddQueryRowAction
| ChangeQueryAction
@ -312,4 +320,5 @@ export type Action =
| ToggleLogsAction
| ToggleTableAction
| UpdateDatasourceInstanceAction
| ResetExploreAction;
| ResetExploreAction
| QueriesImported;

View File

@ -53,6 +53,7 @@ import {
QueryTransactionStartAction,
ScanStopAction,
UpdateDatasourceInstanceAction,
QueriesImported,
} from './actionTypes';
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, ThunkableAction>;
@ -69,10 +70,15 @@ export function addQueryRow(exploreId: ExploreId, index: number): AddQueryRowAct
* Loads a new datasource identified by the given name.
*/
export function changeDatasource(exploreId: ExploreId, datasource: string): ThunkResult<void> {
return async dispatch => {
const instance = await getDatasourceSrv().get(datasource);
dispatch(updateDatasourceInstance(exploreId, instance));
dispatch(loadDatasource(exploreId, instance));
return async (dispatch, getState) => {
const newDataSourceInstance = await getDatasourceSrv().get(datasource);
const currentDataSourceInstance = getState().explore[exploreId].datasourceInstance;
const modifiedQueries = getState().explore[exploreId].modifiedQueries;
await dispatch(importQueries(exploreId, modifiedQueries, currentDataSourceInstance, newDataSourceInstance));
dispatch(updateDatasourceInstance(exploreId, newDataSourceInstance));
dispatch(loadDatasource(exploreId, newDataSourceInstance));
};
}
@ -174,6 +180,7 @@ export function initializeExplore(
if (exploreDatasources.length >= 1) {
let instance;
if (datasourceName) {
try {
instance = await getDatasourceSrv().get(datasourceName);
@ -185,6 +192,7 @@ export function initializeExplore(
if (!instance) {
instance = await getDatasourceSrv().get();
}
dispatch(updateDatasourceInstance(exploreId, instance));
dispatch(loadDatasource(exploreId, instance));
} else {
@ -224,7 +232,10 @@ export const loadDatasourceMissing = (exploreId: ExploreId): LoadDatasourceMissi
/**
* Start the async process of loading a datasource to display a loading indicator
*/
export const loadDatasourcePending = (exploreId: ExploreId, requestedDatasourceName: string): LoadDatasourcePendingAction => ({
export const loadDatasourcePending = (
exploreId: ExploreId,
requestedDatasourceName: string
): LoadDatasourcePendingAction => ({
type: ActionTypes.LoadDatasourcePending,
payload: {
exploreId,
@ -232,6 +243,16 @@ export const loadDatasourcePending = (exploreId: ExploreId, requestedDatasourceN
},
});
export const queriesImported = (exploreId: ExploreId, queries: DataQuery[]): QueriesImported => {
return {
type: ActionTypes.QueriesImported,
payload: {
exploreId,
queries,
},
};
};
/**
* Datasource loading was successfully completed. The instance is stored in the state as well in case we need to
* run datasource-specific code. Existing queries are imported to the new datasource if an importer exists,
@ -240,7 +261,6 @@ export const loadDatasourcePending = (exploreId: ExploreId, requestedDatasourceN
export const loadDatasourceSuccess = (
exploreId: ExploreId,
instance: any,
queries: DataQuery[]
): LoadDatasourceSuccessAction => {
// Capabilities
const supportsGraph = instance.meta.metrics;
@ -261,7 +281,6 @@ export const loadDatasourceSuccess = (
StartPage,
datasourceInstance: instance,
history,
initialQueries: queries,
showingStartPage: Boolean(StartPage),
supportsGraph,
supportsLogs,
@ -286,6 +305,35 @@ export function updateDatasourceInstance(
};
}
export function importQueries(
exploreId: ExploreId,
queries: DataQuery[],
sourceDataSource: DataSourceApi,
targetDataSource: DataSourceApi
) {
return async dispatch => {
let importedQueries = queries;
// Check if queries can be imported from previously selected datasource
if (sourceDataSource.meta.id === targetDataSource.meta.id) {
// Keep same queries if same type of datasource
importedQueries = [...queries];
} else if (targetDataSource.importQueries) {
// Datasource-specific importers
importedQueries = await targetDataSource.importQueries(queries, sourceDataSource.meta);
} else {
// Default is blank queries
importedQueries = ensureQueries();
}
const nextQueries = importedQueries.map((q, i) => ({
...importedQueries[i],
...generateEmptyQuery(i),
}));
dispatch(queriesImported(exploreId, nextQueries));
};
}
/**
* Main action to asynchronously load a datasource. Dispatches lots of smaller actions for feedback.
*/
@ -318,35 +366,12 @@ export function loadDatasource(exploreId: ExploreId, instance: DataSourceApi): T
instance.init();
}
// Check if queries can be imported from previously selected datasource
const queries = getState().explore[exploreId].modifiedQueries;
let importedQueries = queries;
const origin = getState().explore[exploreId].datasourceInstance;
if (origin) {
if (origin.meta.id === instance.meta.id) {
// Keep same queries if same type of datasource
importedQueries = [...queries];
} else if (instance.importQueries) {
// Datasource-specific importers
importedQueries = await instance.importQueries(queries, origin.meta);
} else {
// Default is blank queries
importedQueries = ensureQueries();
}
}
if (datasourceName !== getState().explore[exploreId].requestedDatasourceName) {
// User already changed datasource again, discard results
return;
}
// Reset edit state with new queries
const nextQueries = importedQueries.map((q, i) => ({
...importedQueries[i],
...generateEmptyQuery(i),
}));
dispatch(loadDatasourceSuccess(exploreId, instance, nextQueries));
dispatch(loadDatasourceSuccess(exploreId, instance));
dispatch(runQueries(exploreId));
};
}

View File

@ -203,7 +203,6 @@ export const itemReducer = (state, action: Action): ExploreItemState => {
StartPage,
datasourceInstance,
history,
initialQueries,
showingStartPage,
supportsGraph,
supportsLogs,
@ -217,7 +216,6 @@ export const itemReducer = (state, action: Action): ExploreItemState => {
StartPage,
datasourceInstance,
history,
initialQueries,
showingStartPage,
supportsGraph,
supportsLogs,
@ -226,7 +224,6 @@ export const itemReducer = (state, action: Action): ExploreItemState => {
datasourceMissing: false,
datasourceError: null,
logsHighlighterExpressions: undefined,
modifiedQueries: initialQueries.slice(),
queryTransactions: [],
};
}
@ -295,7 +292,6 @@ export const itemReducer = (state, action: Action): ExploreItemState => {
// Append new transaction
const nextQueryTransactions: QueryTransaction[] = [...remainingTransactions, transaction];
return {
...state,
queryTransactions: nextQueryTransactions,
@ -417,6 +413,14 @@ export const itemReducer = (state, action: Action): ExploreItemState => {
return { ...state, ...results, queryTransactions: nextQueryTransactions, showingTable };
}
case ActionTypes.QueriesImported: {
return {
...state,
initialQueries: action.payload.queries,
modifiedQueries: action.payload.queries.slice(),
};
}
}
return state;