@adaptabletools/adaptable
Version:
Powerful AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
127 lines (126 loc) • 5.18 kB
JavaScript
import { isArray } from '../../Utilities/Extensions/ArrayExtensions';
import { isObject, merge, mergeWith, } from '../../Utilities/Extensions/ObjectExtensions';
import { AdaptableLogger } from '../../agGrid/AdaptableLogger';
import AdaptableHelper from '../../Utilities/Helpers/AdaptableHelper';
function customizer(objValue, srcValue) {
if (isArray(objValue)) {
if (!Array.isArray(srcValue)) {
return srcValue;
}
const length = srcValue ? srcValue.length : null;
const result = mergeWith(objValue, srcValue, customizer);
if (length != null) {
result.length = length;
}
return result;
}
}
export function AddStateSource(stateObject = {}, source) {
const traverseStateObject = (object) => {
Object.values(object).forEach((value) => {
if (AdaptableHelper.isAdaptableObject(value) && value.Source == null) {
value.Source = source;
}
if (value !== null && typeof value === 'object') {
traverseStateObject(value);
}
});
};
traverseStateObject(stateObject);
return stateObject;
}
export function ProcessKeepUserDefinedRevision(configState, currentUserState) {
const traverseStateObject = (configObject, stateObject) => {
Object.entries(configObject).forEach(([key, configValue]) => {
const stateValue = stateObject[key];
if (Array.isArray(configValue) && Array.isArray(stateValue)) {
const userDefinedItems = stateValue.filter((item) => {
return AdaptableHelper.isAdaptableObject(item) && item.Source !== 'InitialState';
});
configObject[key] = configValue.concat(userDefinedItems);
}
else {
if (configValue !== null &&
typeof configValue === 'object' &&
typeof stateValue === 'object') {
traverseStateObject(configValue, stateValue);
}
}
});
};
traverseStateObject(configState, currentUserState);
return configState;
}
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
export function MergeStateFunction(oldState, newState) {
if (newState === '') {
newState = {};
}
const initialState = AddStateSource(oldState, 'InitialState');
let state = newState;
if (!state || typeof state !== 'object') {
AdaptableLogger.consoleWarnBase('State is something different than expected; expected an object, but received: ', state);
state = {};
}
for (const initialStateModuleName in initialState) {
if (!state[initialStateModuleName]) {
const { Revision, ...moduleState } = initialState[initialStateModuleName];
state[initialStateModuleName] = moduleState;
}
}
for (const stateModuleName in state) {
if (initialState[stateModuleName] != undefined) {
const stateRevision = state[stateModuleName].Revision ?? 0;
const initialStateRevision = initialState[stateModuleName].Revision ?? 0;
const stateRevisionKey = typeof stateRevision === 'object' ? stateRevision.Key : stateRevision;
const initialStateRevisionBehaviour = typeof initialStateRevision === 'object' ? initialStateRevision.Behavior : 'Override';
const initialStateRevisionKey = typeof initialStateRevision === 'object' ? initialStateRevision.Key : initialStateRevision;
if (initialStateRevisionKey > stateRevisionKey) {
if (initialStateRevisionBehaviour === 'Override') {
state[stateModuleName] = initialState[stateModuleName];
}
else {
state[stateModuleName] = ProcessKeepUserDefinedRevision(deepClone(initialState[stateModuleName]), state[stateModuleName]);
}
}
}
}
const finalState = AddStateSource(state, 'User');
return finalState;
}
export function MergeState(oldState, newState) {
const result = Object.assign({}, oldState);
for (const key in newState) {
if (!newState.hasOwnProperty(key)) {
continue;
}
const value = newState[key];
if (!result.hasOwnProperty(key)) {
result[key] = isObject(value) && !Array.isArray(value) ? merge({}, value) : value;
continue;
}
const oldValue = result[key];
if (isObject(value) && !Array.isArray(value)) {
result[key] = mergeWith({}, oldValue, value, customizer);
}
else {
result[key] = value;
}
}
return result;
}
let initialState;
export const mergeReducer = (rootReducer, LOAD_STATE_TYPE) => {
let finalReducer = rootReducer;
finalReducer = (state, action) => {
if (action.type === LOAD_STATE_TYPE) {
initialState = initialState ?? state;
state = MergeState(initialState, action.State);
action.State = state;
}
return rootReducer(state, action);
};
return finalReducer;
};