mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 17:08:34 +00:00
handle page swich
- on page switch, reset resolver stores for new references and hints to get updated - on current state initated on page switch should not out setting up updating resolver store to micro task - refactored and optimised the core functions to find references associated as graph
This commit is contained in:
parent
59de1703ac
commit
a4a033cc6f
7 changed files with 171 additions and 143 deletions
|
|
@ -200,7 +200,6 @@ const resolveMultiDynamicReferences = (code, lookupTable) => {
|
|||
|
||||
resolvedValue = resolvedValue.replace(variable, res);
|
||||
} else {
|
||||
const currentState = useCurrentStateStore.getState();
|
||||
const [resolvedCode] = resolveCode(variableToResolve, {}, true, [], true);
|
||||
|
||||
resolvedValue = resolvedCode;
|
||||
|
|
@ -241,7 +240,10 @@ export const resolveReferences = (query, validationSchema, customResolvers = {})
|
|||
if (value.startsWith('#') || value.includes('table-')) {
|
||||
value = JSON.stringify(value);
|
||||
}
|
||||
const { toResolveReference, jsExpression, jsExpMatch } = inferJSExpAndReferences(value, lookupTable.hints);
|
||||
const { toResolveReference, jsExpression, jsExpMatch } =
|
||||
lookupTable.hints || lookupTable.hints.has
|
||||
? inferJSExpAndReferences(value, lookupTable.hints)
|
||||
: { toResolveReference: null, jsExpression: null, jsExpMatch: null };
|
||||
|
||||
if (!jsExpMatch && toResolveReference && lookupTable.hints.has(toResolveReference)) {
|
||||
const idToLookUp = lookupTable.hints.get(toResolveReference);
|
||||
|
|
@ -307,7 +309,7 @@ const inferJSExpAndReferences = (code, hintsMap) => {
|
|||
const potentialReference = referenceChain ? referenceChain + '.' + segment : segment;
|
||||
|
||||
// Check if the potential reference exists in hintsMap
|
||||
if (hintsMap.has(potentialReference)) {
|
||||
if (hintsMap.has && hintsMap.has(potentialReference)) {
|
||||
// If it does, update the referenceChain
|
||||
referenceChain = potentialReference;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -632,8 +632,18 @@ const EditorComponent = (props) => {
|
|||
props.switchDarkMode(newMode);
|
||||
};
|
||||
|
||||
const handleEvent = React.useCallback((eventName, event, options) => {
|
||||
return onEvent(getEditorRef(), eventName, event, options, 'edit');
|
||||
const handleEvent = React.useCallback((eventName, events, options) => {
|
||||
const latestEvents = useAppDataStore.getState().events;
|
||||
const filteredEvents = latestEvents.filter((event) => {
|
||||
const foundEvent = events.find((e) => e.id === event.id);
|
||||
return foundEvent && foundEvent.name === eventName;
|
||||
});
|
||||
|
||||
try {
|
||||
return onEvent(getEditorRef(), eventName, filteredEvents, options, 'edit');
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
|
|
@ -765,117 +775,9 @@ const EditorComponent = (props) => {
|
|||
await fetchDataSources(data.editing_version?.id),
|
||||
await fetchDataQueries(data.editing_version?.id, true, true),
|
||||
])
|
||||
.then(() => {
|
||||
useCurrentStateStore.getState().actions.setEditorReady(true);
|
||||
|
||||
const currentPageId = useEditorStore.getState().currentPageId;
|
||||
const currentComponents = useEditorStore.getState().appDefinition?.pages?.[currentPageId]?.components;
|
||||
|
||||
const referenceManager = useResolveStore.getState().referenceMapper;
|
||||
|
||||
const newComponents = Object.keys(currentComponents).map((componentId) => {
|
||||
const component = currentComponents[componentId];
|
||||
|
||||
if (!referenceManager.get(componentId)) {
|
||||
return {
|
||||
id: componentId,
|
||||
name: component.component.name,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
useResolveStore.getState().actions.addEntitiesToMap(newComponents);
|
||||
})
|
||||
.then(() => {
|
||||
const currentPageId = useEditorStore.getState().currentPageId;
|
||||
const currentComponents = useEditorStore.getState().appDefinition?.pages?.[currentPageId]?.components;
|
||||
let dataQueries = JSON.parse(JSON.stringify(useDataQueriesStore.getState().dataQueries));
|
||||
let allEvents = JSON.parse(JSON.stringify(useAppDataStore.getState().events));
|
||||
|
||||
const entityReferencesInComponentDefinitions = findAllEntityReferences(currentComponents, [])?.filter(
|
||||
(entity) => entity && isValidUUID(entity)
|
||||
);
|
||||
|
||||
const entityReferencesInQueryOptions = findAllEntityReferences(dataQueries, [])?.filter(
|
||||
(entity) => entity && isValidUUID(entity)
|
||||
);
|
||||
|
||||
const entityReferencesInEvents = findAllEntityReferences(allEvents, [])?.filter(
|
||||
(entity) => entity && isValidUUID(entity)
|
||||
);
|
||||
|
||||
const manager = useResolveStore.getState().referenceMapper;
|
||||
|
||||
if (
|
||||
Array.isArray(entityReferencesInComponentDefinitions) &&
|
||||
entityReferencesInComponentDefinitions?.length > 0
|
||||
) {
|
||||
let newComponentDefinition = JSON.parse(JSON.stringify(currentComponents));
|
||||
|
||||
entityReferencesInComponentDefinitions.forEach((entity) => {
|
||||
const entityrefExists = manager.has(entity);
|
||||
|
||||
if (entityrefExists) {
|
||||
const value = manager.get(entity);
|
||||
newComponentDefinition = dfs(newComponentDefinition, entity, value);
|
||||
}
|
||||
});
|
||||
|
||||
const newAppDefinition = produce(appJson, (draft) => {
|
||||
draft.pages[homePageId].components = newComponentDefinition;
|
||||
});
|
||||
|
||||
updateEditorState({
|
||||
isUpdatingEditorStateInProcess: false,
|
||||
appDefinition: newAppDefinition,
|
||||
});
|
||||
}
|
||||
|
||||
if (Array.isArray(entityReferencesInQueryOptions) && entityReferencesInQueryOptions?.length > 0) {
|
||||
let newQueryOptions = {};
|
||||
dataQueries?.forEach((query) => {
|
||||
newQueryOptions[query.id] = query.options;
|
||||
``;
|
||||
});
|
||||
|
||||
entityReferencesInQueryOptions.forEach((entity) => {
|
||||
const entityrefExists = manager.has(entity);
|
||||
|
||||
if (entityrefExists) {
|
||||
const value = manager.get(entity);
|
||||
newQueryOptions = dfs(newQueryOptions, entity, value);
|
||||
}
|
||||
});
|
||||
|
||||
dataQueries = dataQueries.map((query) => {
|
||||
const queryId = query.id;
|
||||
const dqOptions = newQueryOptions[queryId];
|
||||
|
||||
return {
|
||||
...query,
|
||||
options: dqOptions,
|
||||
};
|
||||
});
|
||||
|
||||
useDataQueriesStore.getState().actions.setDataQueries(dataQueries, 'mappingUpdate');
|
||||
}
|
||||
|
||||
if (Array.isArray(entityReferencesInEvents) && entityReferencesInEvents?.length > 0) {
|
||||
let newEvents = JSON.parse(JSON.stringify(allEvents));
|
||||
|
||||
entityReferencesInEvents.forEach((entity) => {
|
||||
const entityrefExists = manager.has(entity);
|
||||
|
||||
if (entityrefExists) {
|
||||
const value = manager.get(entity);
|
||||
newEvents = dfs(newEvents, entity, value);
|
||||
}
|
||||
});
|
||||
|
||||
updateState({
|
||||
events: newEvents,
|
||||
});
|
||||
}
|
||||
.then(async () => {
|
||||
await onEditorLoad(appJson, homePageId);
|
||||
updateEntityReferences(appJson, homePageId);
|
||||
})
|
||||
.finally(async () => {
|
||||
const currentPageEvents = data.events.filter(
|
||||
|
|
@ -1478,6 +1380,117 @@ const EditorComponent = (props) => {
|
|||
}
|
||||
};
|
||||
|
||||
const onEditorLoad = (appJson, pageId, isPageSwitch = false) => {
|
||||
useCurrentStateStore.getState().actions.setEditorReady(true);
|
||||
const currentComponents = appJson?.pages?.[pageId]?.components;
|
||||
|
||||
const referenceManager = useResolveStore.getState().referenceMapper;
|
||||
|
||||
const newComponents = Object.keys(currentComponents).map((componentId) => {
|
||||
const component = currentComponents[componentId];
|
||||
|
||||
if (isPageSwitch || !referenceManager.get(componentId)) {
|
||||
return {
|
||||
id: componentId,
|
||||
name: component.component.name,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
useResolveStore.getState().actions.addEntitiesToMap(newComponents);
|
||||
};
|
||||
|
||||
const updateEntityReferences = (appJson, pageId) => {
|
||||
const currentComponents = appJson?.pages?.[pageId]?.components;
|
||||
|
||||
let dataQueries = JSON.parse(JSON.stringify(useDataQueriesStore.getState().dataQueries));
|
||||
let allEvents = JSON.parse(JSON.stringify(useAppDataStore.getState().events));
|
||||
|
||||
const entityReferencesInComponentDefinitions = findAllEntityReferences(currentComponents, [])?.filter(
|
||||
(entity) => entity && isValidUUID(entity)
|
||||
);
|
||||
|
||||
const entityReferencesInQueryOptions = findAllEntityReferences(dataQueries, [])?.filter(
|
||||
(entity) => entity && isValidUUID(entity)
|
||||
);
|
||||
|
||||
const entityReferencesInEvents = findAllEntityReferences(allEvents, [])?.filter(
|
||||
(entity) => entity && isValidUUID(entity)
|
||||
);
|
||||
|
||||
const manager = useResolveStore.getState().referenceMapper;
|
||||
|
||||
if (Array.isArray(entityReferencesInComponentDefinitions) && entityReferencesInComponentDefinitions?.length > 0) {
|
||||
let newComponentDefinition = JSON.parse(JSON.stringify(currentComponents));
|
||||
|
||||
entityReferencesInComponentDefinitions.forEach((entity) => {
|
||||
const entityrefExists = manager.has(entity);
|
||||
|
||||
if (entityrefExists) {
|
||||
const value = manager.get(entity);
|
||||
newComponentDefinition = dfs(newComponentDefinition, entity, value);
|
||||
}
|
||||
});
|
||||
|
||||
const newAppDefinition = produce(appJson, (draft) => {
|
||||
draft.pages[pageId].components = newComponentDefinition;
|
||||
});
|
||||
|
||||
handleLowPriorityWork(() => {
|
||||
updateEditorState({
|
||||
isUpdatingEditorStateInProcess: false,
|
||||
appDefinition: newAppDefinition,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (Array.isArray(entityReferencesInQueryOptions) && entityReferencesInQueryOptions?.length > 0) {
|
||||
let newQueryOptions = {};
|
||||
dataQueries?.forEach((query) => {
|
||||
newQueryOptions[query.id] = query.options;
|
||||
``;
|
||||
});
|
||||
|
||||
entityReferencesInQueryOptions.forEach((entity) => {
|
||||
const entityrefExists = manager.has(entity);
|
||||
|
||||
if (entityrefExists) {
|
||||
const value = manager.get(entity);
|
||||
newQueryOptions = dfs(newQueryOptions, entity, value);
|
||||
}
|
||||
});
|
||||
|
||||
dataQueries = dataQueries.map((query) => {
|
||||
const queryId = query.id;
|
||||
const dqOptions = newQueryOptions[queryId];
|
||||
|
||||
return {
|
||||
...query,
|
||||
options: dqOptions,
|
||||
};
|
||||
});
|
||||
|
||||
useDataQueriesStore.getState().actions.setDataQueries(dataQueries, 'mappingUpdate');
|
||||
}
|
||||
|
||||
if (Array.isArray(entityReferencesInEvents) && entityReferencesInEvents?.length > 0) {
|
||||
let newEvents = JSON.parse(JSON.stringify(allEvents));
|
||||
|
||||
entityReferencesInEvents.forEach((entity) => {
|
||||
const entityrefExists = manager.has(entity);
|
||||
|
||||
if (entityrefExists) {
|
||||
const value = manager.get(entity);
|
||||
newEvents = dfs(newEvents, entity, value);
|
||||
}
|
||||
});
|
||||
|
||||
updateState({
|
||||
events: newEvents,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const removeComponents = () => {
|
||||
const selectedComponents = useEditorStore.getState()?.selectedComponents;
|
||||
if (!isVersionReleased && selectedComponents?.length > 1) {
|
||||
|
|
@ -1592,7 +1605,9 @@ const EditorComponent = (props) => {
|
|||
});
|
||||
};
|
||||
|
||||
const switchPage = (pageId, queryParams = []) => {
|
||||
const switchPage = async (pageId, queryParams = []) => {
|
||||
useCurrentStateStore.getState().actions.setEditorReady(false);
|
||||
useResolveStore.getState().actions.resetStore();
|
||||
// This are fetched from store to handle runQueriesOnAppLoad
|
||||
const currentPageId = useEditorStore.getState().currentPageId;
|
||||
const appDefinition = useEditorStore.getState().appDefinition;
|
||||
|
|
@ -1619,7 +1634,13 @@ const EditorComponent = (props) => {
|
|||
...currentState.globals,
|
||||
urlparams: JSON.parse(JSON.stringify(queryString.parse(queryParamsString))),
|
||||
};
|
||||
|
||||
useCurrentStateStore.getState().actions.setCurrentState({ globals, page });
|
||||
useResolveStore.getState().actions.pageSwitched(true);
|
||||
|
||||
await onEditorLoad(appDefinition, pageId, true);
|
||||
updateEntityReferences(appDefinition, pageId);
|
||||
useResolveStore.getState().actions.updateJSHints();
|
||||
|
||||
setCurrentPageId(pageId);
|
||||
|
||||
|
|
|
|||
|
|
@ -174,7 +174,11 @@ export function findComponentsWithReferences(components, changedCurrentState) {
|
|||
return componentIdsWithReferences;
|
||||
}
|
||||
|
||||
export function handleLowPriorityWork(callback, timeout = null) {
|
||||
export function handleLowPriorityWork(callback, timeout = null, immediate = false) {
|
||||
if (immediate) {
|
||||
callback();
|
||||
}
|
||||
|
||||
const options = timeout ? { timeout } : {};
|
||||
window.requestIdleCallback(callback, options);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,15 +3,8 @@ import { useRef, useEffect } from 'react';
|
|||
function useRenderCount(componentName) {
|
||||
const renderCountRef = useRef(0);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
console.log(`--Component ${componentName} rendered unmounting ${renderCountRef.current} times.`);
|
||||
};
|
||||
}, []);
|
||||
|
||||
renderCountRef.current++;
|
||||
|
||||
console.log(`CountingRender- Component ${componentName} rendered ${renderCountRef.current} times.`);
|
||||
return renderCountRef.current;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ export const useAppDataStore = create(
|
|||
updateEditingVersion: (version) => set(() => ({ editingVersion: version })),
|
||||
updateApps: (apps) => set(() => ({ apps: apps })),
|
||||
updateState: (state) => set((prev) => ({ ...prev, ...state })),
|
||||
|
||||
updateAppDefinitionDiff: (appDefinitionDiff) => set(() => ({ appDefinitionDiff: appDefinitionDiff })),
|
||||
updateAppVersion: (appId, versionId, pageId, appDefinitionDiff, isUserSwitchedVersion = false) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
import { shallow } from 'zustand/shallow';
|
||||
import { create, zustandDevTools } from './utils';
|
||||
import _, { debounce, merge, omit } from 'lodash';
|
||||
import _, { omit } from 'lodash';
|
||||
import { useResolveStore } from './resolverStore';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { diff } from 'deep-object-diff';
|
||||
import { useEditorStore } from './editorStore';
|
||||
import { handleLowPriorityWork } from '@/_helpers/editorHelpers';
|
||||
|
||||
const initialState = {
|
||||
|
|
@ -88,19 +85,26 @@ useCurrentStateStore.subscribe((state) => {
|
|||
const isStoreIntialized = useResolveStore.getState().storeReady;
|
||||
|
||||
if (!isStoreIntialized) {
|
||||
handleLowPriorityWork(() => {
|
||||
useResolveStore.getState().actions.updateAppSuggestions({
|
||||
queries: state.queries,
|
||||
components: state.components,
|
||||
globals: state.globals,
|
||||
page: state.page,
|
||||
variables: state.variables,
|
||||
client: state.client,
|
||||
server: state.server,
|
||||
constants: state.constants,
|
||||
});
|
||||
});
|
||||
console.log('Resolver store initialized with current state.');
|
||||
const isPageSwitched = useResolveStore.getState().isPageSwitched;
|
||||
|
||||
handleLowPriorityWork(
|
||||
() => {
|
||||
useResolveStore.getState().actions.updateAppSuggestions({
|
||||
queries: state.queries,
|
||||
components: state.components,
|
||||
globals: state.globals,
|
||||
page: state.page,
|
||||
variables: state.variables,
|
||||
client: state.client,
|
||||
server: state.server,
|
||||
constants: state.constants,
|
||||
});
|
||||
useResolveStore.getState().actions.pageSwitched(false);
|
||||
},
|
||||
null,
|
||||
isPageSwitched
|
||||
);
|
||||
|
||||
return useResolveStore.getState().actions.updateStoreState({ storeReady: true });
|
||||
}
|
||||
}, shallow);
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ const initialState = {
|
|||
},
|
||||
lastUpdatedRefs: [],
|
||||
referenceMapper: new ReferencesBiMap(),
|
||||
isPageSwitched: false,
|
||||
};
|
||||
|
||||
export const useResolveStore = create(
|
||||
|
|
@ -69,6 +70,10 @@ export const useResolveStore = create(
|
|||
updateStoreState: (state) => {
|
||||
set(() => ({ ...state, storeReady: true }));
|
||||
},
|
||||
resetStore: () => {
|
||||
set(() => initialState);
|
||||
},
|
||||
pageSwitched: (bool) => set(() => ({ isPageSwitched: bool })),
|
||||
updateAppSuggestions: (refState) => {
|
||||
const { suggestionList, hintsMap, resolvedRefs } = createReferencesLookup(refState, false, true);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue