Variables: Adds change tracking (#41143)

* Variables: Adds change tracking

* Chore: fix strict error

* Chore: removes updating value from isDirty check
pull/41174/head
Hugo Häggmark 4 years ago committed by GitHub
parent 778c860b3c
commit 418059bc23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      public/app/features/variables/state/selectors.ts
  2. 53
      public/app/features/variables/state/transactionReducer.test.ts
  3. 35
      public/app/features/variables/state/transactionReducer.ts

@ -49,3 +49,7 @@ export type GetVariables = typeof getVariables;
export const getNewVariabelIndex = (state: StoreState = getState()): number => { export const getNewVariabelIndex = (state: StoreState = getState()): number => {
return Object.values(state.templating.variables).length; return Object.values(state.templating.variables).length;
}; };
export function getVariablesIsDirty(state: StoreState = getState()): boolean {
return state.templating.transaction.isDirty;
}

@ -1,4 +1,5 @@
import { reducerTester } from '../../../../test/core/redux/reducerTester'; import { reducerTester } from '../../../../test/core/redux/reducerTester';
import { removeVariable, variableStateNotStarted } from './sharedReducer';
import { import {
initialTransactionState, initialTransactionState,
transactionReducer, transactionReducer,
@ -59,4 +60,56 @@ describe('transactionReducer', () => {
.thenStateShouldEqual({ ...initialTransactionState }); .thenStateShouldEqual({ ...initialTransactionState });
}); });
}); });
describe('extraReducers', () => {
describe('isDirty', () => {
describe('when called during fetch', () => {
it('then isDirty should not be changed', () => {
reducerTester<TransactionState>()
.givenReducer(transactionReducer, {
...initialTransactionState,
status: TransactionStatus.Fetching,
})
.whenActionIsDispatched(removeVariable({} as any))
.thenStateShouldEqual({ uid: null, status: TransactionStatus.Fetching, isDirty: false });
});
});
describe('when called after clean', () => {
it('then isDirty should not be changed', () => {
reducerTester<TransactionState>()
.givenReducer(transactionReducer, {
...initialTransactionState,
status: TransactionStatus.NotStarted,
})
.whenActionIsDispatched(removeVariable({} as any))
.thenStateShouldEqual({ uid: null, status: TransactionStatus.NotStarted, isDirty: false });
});
});
describe('when called after complete with action that affects isDirty', () => {
it('then isDirty should be changed', () => {
reducerTester<TransactionState>()
.givenReducer(transactionReducer, {
...initialTransactionState,
status: TransactionStatus.Completed,
})
.whenActionIsDispatched(removeVariable({} as any))
.thenStateShouldEqual({ uid: null, status: TransactionStatus.Completed, isDirty: true });
});
});
describe('when called after complete with action that does not affect isDirty', () => {
it('then isDirty should be changed', () => {
reducerTester<TransactionState>()
.givenReducer(transactionReducer, {
...initialTransactionState,
status: TransactionStatus.Completed,
})
.whenActionIsDispatched(variableStateNotStarted({} as any))
.thenStateShouldEqual({ uid: null, status: TransactionStatus.Completed, isDirty: false });
});
});
});
});
}); });

@ -1,4 +1,12 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { AnyAction, createSlice, PayloadAction } from '@reduxjs/toolkit';
import {
addVariable,
changeVariableOrder,
changeVariableProp,
changeVariableType,
duplicateVariable,
removeVariable,
} from './sharedReducer';
export enum TransactionStatus { export enum TransactionStatus {
NotStarted = 'Not started', NotStarted = 'Not started',
@ -9,9 +17,14 @@ export enum TransactionStatus {
export interface TransactionState { export interface TransactionState {
uid: string | undefined | null; uid: string | undefined | null;
status: TransactionStatus; status: TransactionStatus;
isDirty: boolean;
} }
export const initialTransactionState: TransactionState = { uid: null, status: TransactionStatus.NotStarted }; export const initialTransactionState: TransactionState = {
uid: null,
status: TransactionStatus.NotStarted,
isDirty: false,
};
const transactionSlice = createSlice({ const transactionSlice = createSlice({
name: 'templating/transaction', name: 'templating/transaction',
@ -32,10 +45,28 @@ const transactionSlice = createSlice({
variablesClearTransaction: (state, action: PayloadAction<undefined>) => { variablesClearTransaction: (state, action: PayloadAction<undefined>) => {
state.uid = null; state.uid = null;
state.status = TransactionStatus.NotStarted; state.status = TransactionStatus.NotStarted;
state.isDirty = false;
}, },
}, },
extraReducers: (builder) =>
builder.addMatcher(actionAffectsDirtyState, (state, action) => {
if (state.status === TransactionStatus.Completed) {
state.isDirty = true;
}
}),
}); });
function actionAffectsDirtyState(action: AnyAction): boolean {
return [
removeVariable.type,
addVariable.type,
changeVariableProp.type,
changeVariableOrder.type,
duplicateVariable.type,
changeVariableType.type,
].includes(action.type);
}
export const { export const {
variablesInitTransaction, variablesInitTransaction,
variablesClearTransaction, variablesClearTransaction,

Loading…
Cancel
Save