Removed modifiedQueries from state

This commit is contained in:
Hugo Häggmark 2019-02-04 11:07:32 +01:00
parent d9578bc485
commit 6b98b05976
5 changed files with 26 additions and 59 deletions

View File

@ -14,7 +14,7 @@ interface QueryEditorProps {
datasource: any; datasource: any;
error?: string | JSX.Element; error?: string | JSX.Element;
onExecuteQuery?: () => void; onExecuteQuery?: () => void;
onQueryChange?: (value: DataQuery, override?: boolean) => void; onQueryChange?: (value: DataQuery) => void;
initialQuery: DataQuery; initialQuery: DataQuery;
exploreEvents: Emitter; exploreEvents: Emitter;
range: RawTimeRange; range: RawTimeRange;
@ -40,20 +40,17 @@ export default class QueryEditor extends PureComponent<QueryEditorProps, any> {
datasource, datasource,
target, target,
refresh: () => { refresh: () => {
this.props.onQueryChange(target, false); this.props.onQueryChange(target);
this.props.onExecuteQuery(); this.props.onExecuteQuery();
}, },
events: exploreEvents, events: exploreEvents,
panel: { panel: { datasource, targets: [target] },
datasource,
targets: [target],
},
dashboard: {}, dashboard: {},
}, },
}; };
this.component = loader.load(this.element, scopeProps, template); this.component = loader.load(this.element, scopeProps, template);
this.props.onQueryChange(target, false); this.props.onQueryChange(target);
} }
componentWillUnmount() { componentWillUnmount() {

View File

@ -21,10 +21,11 @@ export default class QueryRows extends PureComponent<QueryRowsProps> {
const { className = '', exploreEvents, exploreId, initialQueries } = this.props; const { className = '', exploreEvents, exploreId, initialQueries } = this.props;
return ( return (
<div className={className}> <div className={className}>
{initialQueries.map((query, index) => ( {initialQueries.map((query, index) => {
// TODO instead of relying on initialQueries, move to react key list in redux // using query.key will introduce infinite loop because QueryEditor#53
<QueryRow key={query.key} exploreEvents={exploreEvents} exploreId={exploreId} index={index} /> const key = query.datasource ? `${query.datasource}-${index}` : query.key;
))} return <QueryRow key={key} exploreEvents={exploreEvents} exploreId={exploreId} index={index} />;
})}
</div> </div>
); );
} }

View File

@ -84,9 +84,9 @@ export function changeDatasource(exploreId: ExploreId, datasource: string): Thun
return async (dispatch, getState) => { return async (dispatch, getState) => {
const newDataSourceInstance = await getDatasourceSrv().get(datasource); const newDataSourceInstance = await getDatasourceSrv().get(datasource);
const currentDataSourceInstance = getState().explore[exploreId].datasourceInstance; const currentDataSourceInstance = getState().explore[exploreId].datasourceInstance;
const modifiedQueries = getState().explore[exploreId].modifiedQueries; const queries = getState().explore[exploreId].initialQueries;
await dispatch(importQueries(exploreId, modifiedQueries, currentDataSourceInstance, newDataSourceInstance)); await dispatch(importQueries(exploreId, queries, currentDataSourceInstance, newDataSourceInstance));
dispatch(updateDatasourceInstanceAction({ exploreId, datasourceInstance: newDataSourceInstance })); dispatch(updateDatasourceInstanceAction({ exploreId, datasourceInstance: newDataSourceInstance }));
dispatch(loadDatasource(exploreId, newDataSourceInstance)); dispatch(loadDatasource(exploreId, newDataSourceInstance));
@ -254,7 +254,7 @@ export function importQueries(
} }
const nextQueries = importedQueries.map((q, i) => ({ const nextQueries = importedQueries.map((q, i) => ({
...importedQueries[i], ...q,
...generateEmptyQuery(i), ...generateEmptyQuery(i),
})); }));
@ -474,7 +474,7 @@ export function runQueries(exploreId: ExploreId) {
return (dispatch, getState) => { return (dispatch, getState) => {
const { const {
datasourceInstance, datasourceInstance,
modifiedQueries, initialQueries,
showingLogs, showingLogs,
showingGraph, showingGraph,
showingTable, showingTable,
@ -483,7 +483,7 @@ export function runQueries(exploreId: ExploreId) {
supportsTable, supportsTable,
} = getState().explore[exploreId]; } = getState().explore[exploreId];
if (!hasNonEmptyQuery(modifiedQueries)) { if (!hasNonEmptyQuery(initialQueries)) {
dispatch(runQueriesEmptyAction({ exploreId })); dispatch(runQueriesEmptyAction({ exploreId }));
dispatch(stateSave()); // Remember to saves to state and update location dispatch(stateSave()); // Remember to saves to state and update location
return; return;
@ -547,7 +547,7 @@ function runQueriesForType(
const { const {
datasourceInstance, datasourceInstance,
eventBridge, eventBridge,
modifiedQueries: queries, initialQueries: queries,
queryIntervals, queryIntervals,
range, range,
scanning, scanning,
@ -632,7 +632,7 @@ export function splitOpen(): ThunkResult<void> {
const itemState = { const itemState = {
...leftState, ...leftState,
queryTransactions: [], queryTransactions: [],
initialQueries: leftState.modifiedQueries.slice(), initialQueries: leftState.initialQueries.slice(),
}; };
dispatch(splitOpenAction({ itemState })); dispatch(splitOpenAction({ itemState }));
dispatch(stateSave()); dispatch(stateSave());
@ -649,14 +649,14 @@ export function stateSave() {
const urlStates: { [index: string]: string } = {}; const urlStates: { [index: string]: string } = {};
const leftUrlState: ExploreUrlState = { const leftUrlState: ExploreUrlState = {
datasource: left.datasourceInstance.name, datasource: left.datasourceInstance.name,
queries: left.modifiedQueries.map(clearQueryKeys), queries: left.initialQueries.map(clearQueryKeys),
range: left.range, range: left.range,
}; };
urlStates.left = serializeStateToUrlParam(leftUrlState, true); urlStates.left = serializeStateToUrlParam(leftUrlState, true);
if (split) { if (split) {
const rightUrlState: ExploreUrlState = { const rightUrlState: ExploreUrlState = {
datasource: right.datasourceInstance.name, datasource: right.datasourceInstance.name,
queries: right.modifiedQueries.map(clearQueryKeys), queries: right.initialQueries.map(clearQueryKeys),
range: right.range, range: right.range,
}; };
urlStates.right = serializeStateToUrlParam(rightUrlState, true); urlStates.right = serializeStateToUrlParam(rightUrlState, true);

View File

@ -61,7 +61,6 @@ export const makeExploreItemState = (): ExploreItemState => ({
history: [], history: [],
initialQueries: [], initialQueries: [],
initialized: false, initialized: false,
modifiedQueries: [],
queryTransactions: [], queryTransactions: [],
queryIntervals: { interval: '15s', intervalMs: DEFAULT_GRAPH_INTERVAL }, queryIntervals: { interval: '15s', intervalMs: DEFAULT_GRAPH_INTERVAL },
range: DEFAULT_RANGE, range: DEFAULT_RANGE,
@ -91,16 +90,9 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
.addMapper({ .addMapper({
filter: addQueryRowAction, filter: addQueryRowAction,
mapper: (state, action): ExploreItemState => { mapper: (state, action): ExploreItemState => {
const { initialQueries, modifiedQueries, queryTransactions } = state; const { initialQueries, queryTransactions } = state;
const { index, query } = action.payload; const { index, query } = action.payload;
// Add new query row after given index, keep modifications of existing rows
const nextModifiedQueries = [
...modifiedQueries.slice(0, index + 1),
{ ...query },
...initialQueries.slice(index + 1),
];
// Add to initialQueries, which will cause a new row to be rendered // Add to initialQueries, which will cause a new row to be rendered
const nextQueries = [...initialQueries.slice(0, index + 1), { ...query }, ...initialQueries.slice(index + 1)]; const nextQueries = [...initialQueries.slice(0, index + 1), { ...query }, ...initialQueries.slice(index + 1)];
@ -116,7 +108,6 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
...state, ...state,
initialQueries: nextQueries, initialQueries: nextQueries,
logsHighlighterExpressions: undefined, logsHighlighterExpressions: undefined,
modifiedQueries: nextModifiedQueries,
queryTransactions: nextQueryTransactions, queryTransactions: nextQueryTransactions,
}; };
}, },
@ -125,20 +116,12 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
filter: changeQueryAction, filter: changeQueryAction,
mapper: (state, action): ExploreItemState => { mapper: (state, action): ExploreItemState => {
const { initialQueries, queryTransactions } = state; const { initialQueries, queryTransactions } = state;
let { modifiedQueries } = state; const { query, index } = action.payload;
const { query, index, override } = action.payload;
// Fast path: only change modifiedQueries to not trigger an update
modifiedQueries[index] = query;
if (!override) {
return { ...state, modifiedQueries };
}
// Override path: queries are completely reset // Override path: queries are completely reset
const nextQuery: DataQuery = { ...query, ...generateEmptyQuery(index) }; const nextQuery: DataQuery = { ...query, ...generateEmptyQuery(index) };
const nextQueries = [...initialQueries]; const nextQueries = [...initialQueries];
nextQueries[index] = nextQuery; nextQueries[index] = nextQuery;
modifiedQueries = [...nextQueries];
// Discard ongoing transaction related to row query // Discard ongoing transaction related to row query
const nextQueryTransactions = queryTransactions.filter(qt => qt.rowIndex !== index); const nextQueryTransactions = queryTransactions.filter(qt => qt.rowIndex !== index);
@ -146,7 +129,6 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
return { return {
...state, ...state,
initialQueries: nextQueries, initialQueries: nextQueries,
modifiedQueries: nextQueries.slice(),
queryTransactions: nextQueryTransactions, queryTransactions: nextQueryTransactions,
}; };
}, },
@ -177,7 +159,6 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
return { return {
...state, ...state,
initialQueries: queries.slice(), initialQueries: queries.slice(),
modifiedQueries: queries.slice(),
queryTransactions: [], queryTransactions: [],
showingStartPage: Boolean(state.StartPage), showingStartPage: Boolean(state.StartPage),
}; };
@ -202,7 +183,6 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
range, range,
initialQueries: queries, initialQueries: queries,
initialized: true, initialized: true,
modifiedQueries: queries.slice(),
}; };
}, },
}) })
@ -268,14 +248,14 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
.addMapper({ .addMapper({
filter: modifyQueriesAction, filter: modifyQueriesAction,
mapper: (state, action): ExploreItemState => { mapper: (state, action): ExploreItemState => {
const { initialQueries, modifiedQueries, queryTransactions } = state; const { initialQueries, queryTransactions } = state;
const { modification, index, modifier } = action.payload; const { modification, index, modifier } = action.payload;
let nextQueries: DataQuery[]; let nextQueries: DataQuery[];
let nextQueryTransactions; let nextQueryTransactions;
if (index === undefined) { if (index === undefined) {
// Modify all queries // Modify all queries
nextQueries = initialQueries.map((query, i) => ({ nextQueries = initialQueries.map((query, i) => ({
...modifier(modifiedQueries[i], modification), ...modifier({ ...query }, modification),
...generateEmptyQuery(i), ...generateEmptyQuery(i),
})); }));
// Discard all ongoing transactions // Discard all ongoing transactions
@ -285,7 +265,7 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
nextQueries = initialQueries.map((query, i) => { nextQueries = initialQueries.map((query, i) => {
// Synchronize all queries with local query cache to ensure consistency // Synchronize all queries with local query cache to ensure consistency
// TODO still needed? // TODO still needed?
return i === index ? { ...modifier(modifiedQueries[i], modification), ...generateEmptyQuery(i) } : query; return i === index ? { ...modifier({ ...query }, modification), ...generateEmptyQuery(i) } : query;
}); });
nextQueryTransactions = queryTransactions nextQueryTransactions = queryTransactions
// Consume the hint corresponding to the action // Consume the hint corresponding to the action
@ -301,7 +281,6 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
return { return {
...state, ...state,
initialQueries: nextQueries, initialQueries: nextQueries,
modifiedQueries: nextQueries.slice(),
queryTransactions: nextQueryTransactions, queryTransactions: nextQueryTransactions,
}; };
}, },
@ -347,11 +326,8 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
filter: removeQueryRowAction, filter: removeQueryRowAction,
mapper: (state, action): ExploreItemState => { mapper: (state, action): ExploreItemState => {
const { datasourceInstance, initialQueries, queryIntervals, queryTransactions } = state; const { datasourceInstance, initialQueries, queryIntervals, queryTransactions } = state;
let { modifiedQueries } = state;
const { index } = action.payload; const { index } = action.payload;
modifiedQueries = [...modifiedQueries.slice(0, index), ...modifiedQueries.slice(index + 1)];
if (initialQueries.length <= 1) { if (initialQueries.length <= 1) {
return state; return state;
} }
@ -371,7 +347,6 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
...results, ...results,
initialQueries: nextQueries, initialQueries: nextQueries,
logsHighlighterExpressions: undefined, logsHighlighterExpressions: undefined,
modifiedQueries: nextQueries.slice(),
queryTransactions: nextQueryTransactions, queryTransactions: nextQueryTransactions,
}; };
}, },
@ -412,7 +387,7 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
filter: setQueriesAction, filter: setQueriesAction,
mapper: (state, action): ExploreItemState => { mapper: (state, action): ExploreItemState => {
const { queries } = action.payload; const { queries } = action.payload;
return { ...state, initialQueries: queries.slice(), modifiedQueries: queries.slice() }; return { ...state, initialQueries: queries.slice() };
}, },
}) })
.addMapper({ .addMapper({
@ -461,7 +436,7 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
.addMapper({ .addMapper({
filter: queriesImportedAction, filter: queriesImportedAction,
mapper: (state, action): ExploreItemState => { mapper: (state, action): ExploreItemState => {
return { ...state, initialQueries: action.payload.queries, modifiedQueries: action.payload.queries.slice() }; return { ...state, initialQueries: action.payload.queries };
}, },
}) })
.create(); .create();

View File

@ -145,7 +145,7 @@ export interface ExploreItemState {
history: HistoryItem[]; history: HistoryItem[];
/** /**
* Initial queries for this Explore, e.g., set via URL. Each query will be * Initial queries for this Explore, e.g., set via URL. Each query will be
* converted to a query row. Query edits should be tracked in `modifiedQueries` though. * converted to a query row.
*/ */
initialQueries: DataQuery[]; initialQueries: DataQuery[];
/** /**
@ -162,12 +162,6 @@ export interface ExploreItemState {
* Log query result to be displayed in the logs result viewer. * Log query result to be displayed in the logs result viewer.
*/ */
logsResult?: LogsModel; logsResult?: LogsModel;
/**
* Copy of `initialQueries` that tracks user edits.
* Don't connect this property to a react component as it is updated on every query change.
* Used when running queries. Needs to be reset to `initialQueries` when those are reset as well.
*/
modifiedQueries: DataQuery[];
/** /**
* Query intervals for graph queries to determine how many datapoints to return. * Query intervals for graph queries to determine how many datapoints to return.
* Needs to be updated when `datasourceInstance` or `containerWidth` is changed. * Needs to be updated when `datasourceInstance` or `containerWidth` is changed.