mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-22 16:38:21 +00:00
Superstore based state management architecture (#8678)
* Add a new type of component called "Module" * Introduce superstore and load editorStore from it * Load queryPanelStore from superstore * Load useDataQueriesStore from superstore * Load datasourcesStore from superstore * Load currentStateStore from superstore * Load appversionStore from superstore * Load appDataStore from superstore * Refactor superstore * Module component and module mode in Viewer * Create module in dashboard * Remove unnecessary code
This commit is contained in:
parent
291a955fec
commit
653078feb0
27 changed files with 1672 additions and 1107 deletions
|
|
@ -69,6 +69,7 @@ import { useTranslation } from 'react-i18next';
|
|||
import { useCurrentState } from '@/_stores/currentStateStore';
|
||||
import { useAppInfo } from '@/_stores/appDataStore';
|
||||
import WidgetIcon from '@/../assets/images/icons/widgets';
|
||||
import { useModuleName } from '../_contexts/ModuleContext';
|
||||
|
||||
const AllComponents = {
|
||||
Button,
|
||||
|
|
@ -153,6 +154,7 @@ export const Box = memo(
|
|||
const { t } = useTranslation();
|
||||
const backgroundColor = yellow ? 'yellow' : '';
|
||||
const currentState = useCurrentState();
|
||||
const moduleName = useModuleName();
|
||||
|
||||
let styles = {
|
||||
height: '100%',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* eslint-disable import/no-named-as-default */
|
||||
import React, { useCallback, useState, useEffect, useRef, useMemo } from 'react';
|
||||
import React, { useCallback, useState, useEffect, useRef, useMemo, useContext } from 'react';
|
||||
import cx from 'classnames';
|
||||
import { useDrop, useDragLayer } from 'react-dnd';
|
||||
import { ItemTypes } from './ItemTypes';
|
||||
|
|
@ -17,8 +17,10 @@ import { addComponents, addNewWidgetToTheEditor } from '@/_helpers/appUtils';
|
|||
import { useCurrentState } from '@/_stores/currentStateStore';
|
||||
import { useAppVersionStore } from '@/_stores/appVersionStore';
|
||||
import { useEditorStore } from '@/_stores/editorStore';
|
||||
import { useSuperStore } from '@/_stores/superStore';
|
||||
import { useAppInfo } from '@/_stores/appDataStore';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { ModuleContext } from '../_contexts/ModuleContext';
|
||||
import _ from 'lodash';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { diff } from 'deep-object-diff';
|
||||
|
|
@ -51,6 +53,8 @@ export const Container = ({
|
|||
// redundant save on app definition load
|
||||
const firstUpdate = useRef(true);
|
||||
|
||||
const moduleName = useContext(ModuleContext);
|
||||
|
||||
const { showComments, currentLayout } = useEditorStore(
|
||||
(state) => ({
|
||||
showComments: state?.showComments,
|
||||
|
|
@ -334,7 +338,8 @@ export const Container = ({
|
|||
|
||||
let newBoxes = { ...boxes };
|
||||
|
||||
for (const selectedComponent of useEditorStore.getState().selectedComponents) {
|
||||
for (const selectedComponent of useSuperStore.getState().modules[moduleName].useEditorStore.getState()
|
||||
.selectedComponents) {
|
||||
newBoxes = produce(newBoxes, (draft) => {
|
||||
if (draft[selectedComponent.id]) {
|
||||
const topOffset = draft[selectedComponent.id].layouts[currentLayout].top;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
||||
import React, { useEffect, useLayoutEffect, useRef, useState, useContext } from 'react';
|
||||
import {
|
||||
appService,
|
||||
authenticationService,
|
||||
|
|
@ -32,6 +32,7 @@ import {
|
|||
buildComponentMetaDefinition,
|
||||
} from '@/_helpers/appUtils';
|
||||
import { Confirm } from './Viewer/Confirm';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { Tooltip as ReactTooltip } from 'react-tooltip';
|
||||
import CommentNotifications from './CommentNotifications';
|
||||
import { WidgetManager } from './WidgetManager';
|
||||
|
|
@ -54,7 +55,6 @@ import { ReleasedVersionError } from './AppVersionsManager/ReleasedVersionError'
|
|||
import { useDataSourcesStore } from '@/_stores/dataSourcesStore';
|
||||
import { useDataQueriesStore } from '@/_stores/dataQueriesStore';
|
||||
import { useAppVersionStore, useAppVersionActions, useAppVersionState } from '@/_stores/appVersionStore';
|
||||
import { useQueryPanelStore } from '@/_stores/queryPanelStore';
|
||||
import { useCurrentStateStore, useCurrentState, getCurrentState } from '@/_stores/currentStateStore';
|
||||
import { computeAppDiff, computeComponentPropertyDiff, isParamFromTableColumn, resetAllStores } from '@/_stores/utils';
|
||||
import { setCookie } from '@/_helpers/cookie';
|
||||
|
|
@ -70,6 +70,8 @@ import useDebouncedArrowKeyPress from '@/_hooks/useDebouncedArrowKeyPress';
|
|||
import { getQueryParams } from '@/_helpers/routes';
|
||||
import RightSidebarTabManager from './RightSidebarTabManager';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { ModuleContext } from '../_contexts/ModuleContext';
|
||||
import { useSuperStore } from '../_stores/superStore';
|
||||
|
||||
setAutoFreeze(false);
|
||||
enablePatches();
|
||||
|
|
@ -81,6 +83,7 @@ function setWindowTitle(name) {
|
|||
const decimalToHex = (alpha) => (alpha === 0 ? '00' : Math.round(255 * alpha).toString(16));
|
||||
|
||||
const EditorComponent = (props) => {
|
||||
const moduleName = useContext(ModuleContext);
|
||||
const { socket } = createWebsocketConnection(props?.params?.id);
|
||||
const isSocketOpen = useSocketOpen(socket);
|
||||
const mounted = useMounted();
|
||||
|
|
@ -220,18 +223,21 @@ const EditorComponent = (props) => {
|
|||
updateState({
|
||||
currentUser: appUserDetails,
|
||||
});
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
globals: {
|
||||
...currentState.globals,
|
||||
theme: { name: props?.darkMode ? 'dark' : 'light' },
|
||||
urlparams: JSON.parse(JSON.stringify(queryString.parse(props.location.search))),
|
||||
currentUser: userVars,
|
||||
/* Constant value.it will only change for viewer */
|
||||
mode: {
|
||||
value: 'edit',
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
globals: {
|
||||
...currentState.globals,
|
||||
theme: { name: props?.darkMode ? 'dark' : 'light' },
|
||||
urlparams: JSON.parse(JSON.stringify(queryString.parse(props.location.search))),
|
||||
currentUser: userVars,
|
||||
/* Constant value.it will only change for viewer */
|
||||
mode: {
|
||||
value: 'edit',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -243,7 +249,7 @@ const EditorComponent = (props) => {
|
|||
socket && socket?.close();
|
||||
subscription.unsubscribe();
|
||||
if (config.ENABLE_MULTIPLAYER_EDITING) props?.provider?.disconnect();
|
||||
useEditorStore.getState().actions.setIsEditorActive(false);
|
||||
useSuperStore.getState().modules[moduleName].useEditorStore.getState().actions.setIsEditorActive(false);
|
||||
prevAppDefinition.current = null;
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
|
@ -261,9 +267,9 @@ const EditorComponent = (props) => {
|
|||
if (mounted && didAppDefinitionChanged && currentPageId) {
|
||||
const components = appDefinition?.pages[currentPageId]?.components || {};
|
||||
|
||||
computeComponentState(components);
|
||||
computeComponentState(components, moduleName);
|
||||
|
||||
if (useEditorStore.getState().isUpdatingEditorStateInProcess) {
|
||||
if (useSuperStore.getState().modules[moduleName].useEditorStore.getState().isUpdatingEditorStateInProcess) {
|
||||
autoSave();
|
||||
}
|
||||
}
|
||||
|
|
@ -273,7 +279,7 @@ const EditorComponent = (props) => {
|
|||
useEffect(
|
||||
() => {
|
||||
const components = appDefinition?.pages?.[currentPageId]?.components || {};
|
||||
computeComponentState(components);
|
||||
computeComponentState(components, moduleName);
|
||||
},
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[currentPageId]
|
||||
|
|
@ -299,7 +305,7 @@ const EditorComponent = (props) => {
|
|||
|
||||
useEffect(() => {
|
||||
if (mounted) {
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
useSuperStore.getState().modules[moduleName].useCurrentStateStore.getState().actions.setCurrentState({
|
||||
layout: currentLayout,
|
||||
});
|
||||
}
|
||||
|
|
@ -328,12 +334,14 @@ const EditorComponent = (props) => {
|
|||
|
||||
const getEditorRef = () => {
|
||||
const editorRef = {
|
||||
appDefinition: useEditorStore.getState().appDefinition,
|
||||
queryConfirmationList: useEditorStore.getState().queryConfirmationList,
|
||||
appDefinition: useSuperStore.getState().modules[moduleName].useEditorStore.getState().appDefinition,
|
||||
queryConfirmationList: useSuperStore.getState().modules[moduleName].useEditorStore.getState()
|
||||
.queryConfirmationList,
|
||||
updateQueryConfirmationList: updateQueryConfirmationList,
|
||||
navigate: props.navigate,
|
||||
switchPage: switchPage,
|
||||
currentPageId: useEditorStore.getState().currentPageId,
|
||||
currentPageId: useSuperStore.getState().modules[moduleName].useEditorStore.getState().currentPageId,
|
||||
moduleName,
|
||||
};
|
||||
return editorRef;
|
||||
};
|
||||
|
|
@ -363,7 +371,7 @@ const EditorComponent = (props) => {
|
|||
}
|
||||
});
|
||||
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
useSuperStore.getState().modules[moduleName].useCurrentStateStore.getState().actions.setCurrentState({
|
||||
server: server_variables,
|
||||
client: client_variables,
|
||||
});
|
||||
|
|
@ -379,7 +387,7 @@ const EditorComponent = (props) => {
|
|||
orgConstants[constant.name] = constantValue;
|
||||
});
|
||||
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
useSuperStore.getState().modules[moduleName].useCurrentStateStore.getState().actions.setCurrentState({
|
||||
constants: orgConstants,
|
||||
});
|
||||
});
|
||||
|
|
@ -480,18 +488,22 @@ const EditorComponent = (props) => {
|
|||
};
|
||||
|
||||
const fetchDataQueries = async (id, selectFirstQuery = false, runQueriesOnAppLoad = false) => {
|
||||
await useDataQueriesStore
|
||||
await useSuperStore
|
||||
.getState()
|
||||
.actions.fetchDataQueries(id, selectFirstQuery, runQueriesOnAppLoad, getEditorRef());
|
||||
.modules[moduleName].useDataQueriesStore.getState()
|
||||
.actions.fetchDataQueries(id, selectFirstQuery, runQueriesOnAppLoad, getEditorRef(), moduleName);
|
||||
};
|
||||
|
||||
const fetchDataSources = (id) => {
|
||||
useDataSourcesStore.getState().actions.fetchDataSources(id);
|
||||
useSuperStore.getState().modules[moduleName].useDataSourcesStore.getState().actions.fetchDataSources(id);
|
||||
};
|
||||
|
||||
const fetchGlobalDataSources = () => {
|
||||
const { current_organization_id: organizationId } = currentUser;
|
||||
useDataSourcesStore.getState().actions.fetchGlobalDataSources(organizationId);
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useDataSourcesStore.getState()
|
||||
.actions.fetchGlobalDataSources(organizationId);
|
||||
};
|
||||
|
||||
const onVersionDelete = () => {
|
||||
|
|
@ -562,18 +574,21 @@ const EditorComponent = (props) => {
|
|||
const computeCanvasContainerHeight = () => {
|
||||
// 45 = (height of header)
|
||||
// 85 = (the height of the query panel header when minimised) + (height of header)
|
||||
return `calc(${100}% - ${Math.max(useQueryPanelStore.getState().queryPanelHeight + 45, 85)}px)`;
|
||||
return `calc(${100}% - ${Math.max(
|
||||
useSuperStore.getState().modules[moduleName].useQueryPanelStore.getState().queryPanelHeight + 45,
|
||||
85
|
||||
)}px)`;
|
||||
};
|
||||
|
||||
const handleQueryPaneDragging = (bool) => setIsQueryPaneDragging(bool);
|
||||
const handleQueryPaneExpanding = (bool) => setIsQueryPaneExpanded(bool);
|
||||
|
||||
const handleOnComponentOptionChanged = (component, optionName, value) => {
|
||||
return onComponentOptionChanged(component, optionName, value);
|
||||
return onComponentOptionChanged(moduleName, component, optionName, value);
|
||||
};
|
||||
|
||||
const handleOnComponentOptionsChanged = (component, options) => {
|
||||
return onComponentOptionsChanged(component, options);
|
||||
return onComponentOptionsChanged(moduleName, component, options);
|
||||
};
|
||||
|
||||
const handleComponentClick = (id, component) => {
|
||||
|
|
@ -584,21 +599,24 @@ const EditorComponent = (props) => {
|
|||
|
||||
const sideBarDebugger = {
|
||||
error: (data) => {
|
||||
debuggerActions.error(data);
|
||||
debuggerActions.error(data, moduleName);
|
||||
},
|
||||
flush: () => {
|
||||
debuggerActions.flush();
|
||||
debuggerActions.flush(moduleName);
|
||||
},
|
||||
generateErrorLogs: (errors) => debuggerActions.generateErrorLogs(errors),
|
||||
generateErrorLogs: (errors) => debuggerActions.generateErrorLogs(errors, moduleName),
|
||||
};
|
||||
|
||||
const changeDarkMode = (newMode) => {
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
globals: {
|
||||
...currentState.globals,
|
||||
theme: { name: newMode ? 'dark' : 'light' },
|
||||
},
|
||||
});
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
globals: {
|
||||
...currentState.globals,
|
||||
theme: { name: newMode ? 'dark' : 'light' },
|
||||
},
|
||||
});
|
||||
props.switchDarkMode(newMode);
|
||||
};
|
||||
|
||||
|
|
@ -613,7 +631,10 @@ const EditorComponent = (props) => {
|
|||
};
|
||||
|
||||
const setSelectedComponent = (id, component, multiSelect = false) => {
|
||||
const isAlreadySelected = useEditorStore.getState()?.selectedComponents.find((component) => component.id === id);
|
||||
const isAlreadySelected = useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useEditorStore.getState()
|
||||
?.selectedComponents.find((component) => component.id === id);
|
||||
|
||||
if (!isAlreadySelected) {
|
||||
setSelectedComponents([{ id, component }], multiSelect);
|
||||
|
|
@ -621,7 +642,10 @@ const EditorComponent = (props) => {
|
|||
};
|
||||
|
||||
const onVersionRelease = (versionId) => {
|
||||
useAppVersionStore.getState().actions.updateReleasedVersionId(versionId);
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useAppVersionStore.getState()
|
||||
.actions.updateReleasedVersionId(versionId);
|
||||
|
||||
if (socket instanceof WebSocket && socket?.readyState === WebSocket.OPEN) {
|
||||
socket.send(
|
||||
|
|
@ -673,9 +697,15 @@ const EditorComponent = (props) => {
|
|||
|
||||
const callBack = async (data, startingPageHandle, versionSwitched = false) => {
|
||||
setWindowTitle(data.name);
|
||||
useAppVersionStore.getState().actions.updateEditingVersion(data.editing_version);
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useAppVersionStore.getState()
|
||||
.actions.updateEditingVersion(data.editing_version);
|
||||
if (!releasedVersionId || !versionSwitched) {
|
||||
useAppVersionStore.getState().actions.updateReleasedVersionId(data.current_version_id);
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useAppVersionStore.getState()
|
||||
.actions.updateReleasedVersionId(data.current_version_id);
|
||||
}
|
||||
|
||||
const appVersions = await appEnvironmentService.getVersionsByEnvironment(data?.id);
|
||||
|
|
@ -712,7 +742,7 @@ const EditorComponent = (props) => {
|
|||
|
||||
setCurrentPageId(homePageId);
|
||||
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
useSuperStore.getState().modules[moduleName].useCurrentStateStore.getState().actions.setCurrentState({
|
||||
page: currentpageData,
|
||||
});
|
||||
|
||||
|
|
@ -730,7 +760,10 @@ const EditorComponent = (props) => {
|
|||
});
|
||||
}
|
||||
|
||||
await useDataSourcesStore.getState().actions.fetchGlobalDataSources(data?.organization_id);
|
||||
await useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useDataSourcesStore.getState()
|
||||
.actions.fetchGlobalDataSources(data?.organization_id);
|
||||
await fetchDataSources(data.editing_version?.id);
|
||||
await fetchDataQueries(data.editing_version?.id, true, true);
|
||||
const currentPageEvents = data.events.filter((event) => event.target === 'page' && event.sourceId === homePageId);
|
||||
|
|
@ -786,11 +819,13 @@ const EditorComponent = (props) => {
|
|||
});
|
||||
}
|
||||
let updatedAppDefinition;
|
||||
const copyOfAppDefinition = JSON.parse(JSON.stringify(useEditorStore.getState().appDefinition));
|
||||
const copyOfAppDefinition = JSON.parse(
|
||||
JSON.stringify(useSuperStore.getState().modules[moduleName].useEditorStore.getState().appDefinition)
|
||||
);
|
||||
|
||||
if (opts?.skipYmapUpdate && opts?.currentSessionId !== currentSessionId) {
|
||||
updatedAppDefinition = produce(copyOfAppDefinition, (draft) => {
|
||||
const _currentPageId = useEditorStore.getState().currentPageId;
|
||||
const _currentPageId = useSuperStore.getState().modules[moduleName].useEditorStore.getState().currentPageId;
|
||||
if (opts?.componentDeleting) {
|
||||
const currentPageComponentIds = Object.keys(copyOfAppDefinition.pages[_currentPageId]?.components);
|
||||
const newComponentIds = Object.keys(newDefinition.pages[_currentPageId]?.components);
|
||||
|
|
@ -928,7 +963,7 @@ const EditorComponent = (props) => {
|
|||
};
|
||||
|
||||
const saveEditingVersion = (isUserSwitchedVersion = false) => {
|
||||
const editingVersion = useAppVersionStore.getState().editingVersion;
|
||||
const editingVersion = useSuperStore.getState().modules[moduleName].useAppVersionStore.getState().editingVersion;
|
||||
if (isVersionReleased && !isUserSwitchedVersion) {
|
||||
updateEditorState({
|
||||
isUpdatingEditorStateInProcess: false,
|
||||
|
|
@ -958,7 +993,10 @@ const EditorComponent = (props) => {
|
|||
...editingVersion,
|
||||
...{ definition: appDefinition },
|
||||
};
|
||||
useAppVersionStore.getState().actions.updateEditingVersion(_editingVersion);
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useAppVersionStore.getState()
|
||||
.actions.updateEditingVersion(_editingVersion);
|
||||
|
||||
if (config.ENABLE_MULTIPLAYER_EDITING) {
|
||||
props.ymap?.set('appDef', {
|
||||
|
|
@ -1131,7 +1169,10 @@ const EditorComponent = (props) => {
|
|||
|
||||
const componentDefinitionChanged = (componentDefinition, props) => {
|
||||
if (isVersionReleased) {
|
||||
useAppVersionStore.getState().actions.enableReleasedVersionPopupState();
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useAppVersionStore.getState()
|
||||
.actions.enableReleasedVersionPopupState();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1189,7 +1230,10 @@ const EditorComponent = (props) => {
|
|||
componentDeleted: true,
|
||||
});
|
||||
} else {
|
||||
useAppVersionStore.getState().actions.enableReleasedVersionPopupState();
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useAppVersionStore.getState()
|
||||
.actions.enableReleasedVersionPopupState();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1197,7 +1241,9 @@ const EditorComponent = (props) => {
|
|||
const gridWidth = (1 * 100) / 43; // width of the canvas grid in percentage
|
||||
const _appDefinition = _.cloneDeep(appDefinition);
|
||||
let newComponents = _appDefinition?.pages[currentPageId].components;
|
||||
const selectedComponents = useEditorStore.getState()?.selectedComponents;
|
||||
const selectedComponents = useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useEditorStore.getState()?.selectedComponents;
|
||||
|
||||
for (const selectedComponent of selectedComponents) {
|
||||
let top = newComponents[selectedComponent.id].layouts[currentLayout].top;
|
||||
|
|
@ -1229,7 +1275,7 @@ const EditorComponent = (props) => {
|
|||
|
||||
const copyComponents = () =>
|
||||
cloneComponents(
|
||||
useEditorStore.getState()?.selectedComponents,
|
||||
useSuperStore.getState().modules[moduleName].useEditorStore.getState()?.selectedComponents,
|
||||
appDefinition,
|
||||
currentPageId,
|
||||
appDefinitionChanged,
|
||||
|
|
@ -1238,13 +1284,16 @@ const EditorComponent = (props) => {
|
|||
|
||||
const cutComponents = () => {
|
||||
if (isVersionReleased) {
|
||||
useAppVersionStore.getState().actions.enableReleasedVersionPopupState();
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useAppVersionStore.getState()
|
||||
.actions.enableReleasedVersionPopupState();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
cloneComponents(
|
||||
useEditorStore.getState()?.selectedComponents,
|
||||
useSuperStore.getState().modules[moduleName].useEditorStore.getState()?.selectedComponents,
|
||||
appDefinition,
|
||||
currentPageId,
|
||||
appDefinitionChanged,
|
||||
|
|
@ -1255,11 +1304,14 @@ const EditorComponent = (props) => {
|
|||
|
||||
const cloningComponents = () => {
|
||||
if (isVersionReleased) {
|
||||
useAppVersionStore.getState().actions.enableReleasedVersionPopupState();
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useAppVersionStore.getState()
|
||||
.actions.enableReleasedVersionPopupState();
|
||||
return;
|
||||
}
|
||||
cloneComponents(
|
||||
useEditorStore.getState()?.selectedComponents,
|
||||
useSuperStore.getState().modules[moduleName].useEditorStore.getState()?.selectedComponents,
|
||||
appDefinition,
|
||||
currentPageId,
|
||||
appDefinitionChanged,
|
||||
|
|
@ -1269,7 +1321,7 @@ const EditorComponent = (props) => {
|
|||
};
|
||||
|
||||
const handleEditorEscapeKeyPress = () => {
|
||||
if (useEditorStore.getState()?.selectedComponents?.length > 0) {
|
||||
if (useSuperStore.getState().modules[moduleName].useEditorStore.getState()?.selectedComponents?.length > 0) {
|
||||
updateEditorState({
|
||||
selectedComponents: [],
|
||||
});
|
||||
|
|
@ -1277,7 +1329,9 @@ const EditorComponent = (props) => {
|
|||
};
|
||||
|
||||
const removeComponents = () => {
|
||||
const selectedComponents = useEditorStore.getState()?.selectedComponents;
|
||||
const selectedComponents = useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useEditorStore.getState()?.selectedComponents;
|
||||
if (!isVersionReleased && selectedComponents?.length > 1) {
|
||||
let newDefinition = cloneDeep(appDefinition);
|
||||
|
||||
|
|
@ -1293,7 +1347,10 @@ const EditorComponent = (props) => {
|
|||
});
|
||||
}
|
||||
} else if (isVersionReleased) {
|
||||
useAppVersionStore.getState().actions.enableReleasedVersionPopupState();
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useAppVersionStore.getState()
|
||||
.actions.enableReleasedVersionPopupState();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1376,11 +1433,14 @@ const EditorComponent = (props) => {
|
|||
const globals = {
|
||||
...currentState.globals,
|
||||
};
|
||||
useCurrentStateStore.getState().actions.setCurrentState({ globals, page });
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({ globals, page });
|
||||
};
|
||||
|
||||
const navigateToPage = (queryParams = [], handle) => {
|
||||
const appId = useAppDataStore.getState()?.appId;
|
||||
const appId = useSuperStore.getState().modules[moduleName].useAppDataStore.getState()?.appId;
|
||||
const queryParamsString = queryParams.map(([key, value]) => `${key}=${value}`).join('&');
|
||||
|
||||
props?.navigate(`/${getWorkspaceId()}/apps/${slug ?? appId}/${handle}?${queryParamsString}`, {
|
||||
|
|
@ -1392,9 +1452,9 @@ const EditorComponent = (props) => {
|
|||
|
||||
const switchPage = (pageId, queryParams = []) => {
|
||||
// This are fetched from store to handle runQueriesOnAppLoad
|
||||
const currentPageId = useEditorStore.getState().currentPageId;
|
||||
const appDefinition = useEditorStore.getState().appDefinition;
|
||||
const pageHandle = getCurrentState().pageHandle;
|
||||
const currentPageId = useSuperStore.getState().modules[moduleName].useEditorStore.getState().currentPageId;
|
||||
const appDefinition = useSuperStore.getState().modules[moduleName].useEditorStore.getState().appDefinition;
|
||||
const pageHandle = getCurrentState(moduleName).pageHandle;
|
||||
|
||||
if (currentPageId === pageId && pageHandle === appDefinition?.pages[pageId]?.handle) {
|
||||
return;
|
||||
|
|
@ -1417,7 +1477,10 @@ const EditorComponent = (props) => {
|
|||
...currentState.globals,
|
||||
urlparams: JSON.parse(JSON.stringify(queryString.parse(queryParamsString))),
|
||||
};
|
||||
useCurrentStateStore.getState().actions.setCurrentState({ globals, page });
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({ globals, page });
|
||||
|
||||
setCurrentPageId(pageId);
|
||||
|
||||
|
|
@ -1646,7 +1709,7 @@ const EditorComponent = (props) => {
|
|||
const handleCanvasContainerMouseUp = (e) => {
|
||||
if (
|
||||
['real-canvas', 'modal'].includes(e.target.className) &&
|
||||
useEditorStore.getState()?.selectedComponents?.length
|
||||
useSuperStore.getState().modules[moduleName].useEditorStore.getState()?.selectedComponents?.length
|
||||
) {
|
||||
setSelectedComponents(EMPTY_ARRAY);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import React, { useCallback, memo } from 'react';
|
||||
import React, { useCallback, memo, useContext } from 'react';
|
||||
import Selecto from 'react-selecto';
|
||||
import { useEditorStore, EMPTY_ARRAY } from '@/_stores/editorStore';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { useSuperStore } from '../_stores/superStore';
|
||||
import { ModuleContext } from '../_contexts/ModuleContext';
|
||||
|
||||
const EditorSelecto = ({
|
||||
selectionRef,
|
||||
|
|
@ -20,11 +22,19 @@ const EditorSelecto = ({
|
|||
shallow
|
||||
);
|
||||
|
||||
const moduleName = useContext(ModuleContext);
|
||||
|
||||
const onAreaSelectionStart = useCallback(
|
||||
(e) => {
|
||||
const isMultiSelect = e.inputEvent.shiftKey || useEditorStore.getState().selectedComponents.length > 0;
|
||||
const isMultiSelect =
|
||||
e.inputEvent.shiftKey ||
|
||||
useSuperStore.getState().modules[moduleName].useEditorStore.getState().selectedComponents.length > 0;
|
||||
setSelectionInProgress(true);
|
||||
setSelectedComponents([...(isMultiSelect ? useEditorStore.getState().selectedComponents : EMPTY_ARRAY)]);
|
||||
setSelectedComponents([
|
||||
...(isMultiSelect
|
||||
? useSuperStore.getState().modules[moduleName].useEditorStore.getState().selectedComponents
|
||||
: EMPTY_ARRAY),
|
||||
]);
|
||||
},
|
||||
[setSelectionInProgress, setSelectedComponents]
|
||||
);
|
||||
|
|
@ -33,7 +43,7 @@ const EditorSelecto = ({
|
|||
e.added.forEach((el) => {
|
||||
el.classList.add('resizer-select');
|
||||
});
|
||||
if (useEditorStore.getState().selectionInProgress) {
|
||||
if (useSuperStore.getState().modules[moduleName].useEditorStore.getState().selectionInProgress) {
|
||||
e.removed.forEach((el) => {
|
||||
el.classList.remove('resizer-select');
|
||||
});
|
||||
|
|
@ -68,7 +78,8 @@ const EditorSelecto = ({
|
|||
(e) => {
|
||||
if (selectionDragRef.current) {
|
||||
e.stop();
|
||||
useEditorStore.getState().selectionInProgress && setSelectionInProgress(false);
|
||||
useSuperStore.getState().modules[moduleName].useEditorStore.getState().selectionInProgress &&
|
||||
setSelectionInProgress(false);
|
||||
}
|
||||
},
|
||||
[setSelectionInProgress, selectionDragRef]
|
||||
|
|
@ -76,7 +87,8 @@ const EditorSelecto = ({
|
|||
|
||||
const onAreaSelectionDragEnd = () => {
|
||||
selectionDragRef.current = false;
|
||||
useEditorStore.getState().selectionInProgress && setSelectionInProgress(false);
|
||||
useSuperStore.getState().modules[moduleName].useEditorStore.getState().selectionInProgress &&
|
||||
setSelectionInProgress(false);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -17,8 +17,11 @@ import List from '@/ToolJetUI/List/List';
|
|||
import { capitalize, has } from 'lodash';
|
||||
import NoListItem from './NoListItem';
|
||||
import { ProgramaticallyHandleProperties } from './ProgramaticallyHandleProperties';
|
||||
import { useAppDataStore } from '@/_stores/appDataStore';
|
||||
import { ModuleContext } from '../../../../_contexts/ModuleContext';
|
||||
import { useSuperStore } from '@/_stores/superStore';
|
||||
class TableComponent extends React.Component {
|
||||
static contextType = ModuleContext;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
|
@ -749,13 +752,19 @@ class TableComponent extends React.Component {
|
|||
};
|
||||
|
||||
deleteEvents = (ref, eventTarget) => {
|
||||
const events = useAppDataStore.getState().events.filter((event) => event.target === eventTarget);
|
||||
const events = useSuperStore
|
||||
.getState()
|
||||
.modules[this.context].useAppDataStore.getState()
|
||||
.events.filter((event) => event.target === eventTarget);
|
||||
|
||||
const toDelete = events?.filter((e) => e.event?.ref === ref.ref);
|
||||
|
||||
return new Promise.all(
|
||||
toDelete?.forEach((e) => {
|
||||
return useAppDataStore.getState().actions.deleteAppVersionEventHandler(e.id);
|
||||
return useSuperStore
|
||||
.getState()
|
||||
.modules[this.context].useAppDataStore.getState()
|
||||
.actions.deleteAppVersionEventHandler(e.id);
|
||||
})
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { useState, useEffect } from 'react';
|
||||
import { useCurrentStateStore } from '@/_stores/currentStateStore';
|
||||
import { useModuleName } from '@/_contexts/ModuleContext';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { debuggerActions } from '@/_helpers/appUtils';
|
||||
import { flow } from 'lodash';
|
||||
|
|
@ -11,6 +12,8 @@ const useDebugger = ({ currentPageId, isDebuggerOpen }) => {
|
|||
const [unReadErrorCount, setUnReadErrorCount] = useState({ read: 0, unread: 0 });
|
||||
const [allLog, setAllLog] = useState([]);
|
||||
|
||||
const moduleName = useModuleName();
|
||||
|
||||
const { errors, succededQuery } = useCurrentStateStore(
|
||||
(state) => ({
|
||||
errors: state.errors,
|
||||
|
|
@ -43,7 +46,7 @@ const useDebugger = ({ currentPageId, isDebuggerOpen }) => {
|
|||
(arr) => arr.filter(([key, value]) => value.data?.status),
|
||||
Object.fromEntries,
|
||||
])(errors);
|
||||
const newErrorLogs = debuggerActions.generateErrorLogs(newError);
|
||||
const newErrorLogs = debuggerActions.generateErrorLogs(newError, moduleName);
|
||||
const newPageLevelErrorLogs = newErrorLogs.filter((error) => error.strace === 'page_level');
|
||||
const newAppLevelErrorLogs = newErrorLogs.filter((error) => error.strace === 'app_level');
|
||||
if (newErrorLogs) {
|
||||
|
|
@ -64,19 +67,19 @@ const useDebugger = ({ currentPageId, isDebuggerOpen }) => {
|
|||
};
|
||||
});
|
||||
}
|
||||
debuggerActions.flush();
|
||||
debuggerActions.flush(moduleName);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [JSON.stringify({ errors })]);
|
||||
|
||||
useEffect(() => {
|
||||
const successQueryLogs = debuggerActions.generateQuerySuccessLogs(succededQuery);
|
||||
const successQueryLogs = debuggerActions.generateQuerySuccessLogs(succededQuery, moduleName);
|
||||
if (successQueryLogs?.length) {
|
||||
setAllLog((prevLogs) => {
|
||||
const temp = [...successQueryLogs, ...prevLogs];
|
||||
const sortedDatesDesc = temp.sort((a, b) => moment(b.timestamp).diff(moment(a.timestamp)));
|
||||
return sortedDatesDesc;
|
||||
});
|
||||
debuggerActions.flushAllLog();
|
||||
debuggerActions.flushAllLog(moduleName);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [JSON.stringify({ succededQuery })]);
|
||||
|
|
|
|||
|
|
@ -13,9 +13,12 @@ import SolidIcon from '@/_ui/Icon/SolidIcons';
|
|||
import cx from 'classnames';
|
||||
import { ToolTip } from '@/_components/ToolTip';
|
||||
import { TOOLTIP_MESSAGES } from '@/_helpers/constants';
|
||||
import { useAppDataStore } from '@/_stores/appDataStore';
|
||||
import { useSuperStore } from '../_stores/superStore';
|
||||
import { ModuleContext } from '../_contexts/ModuleContext';
|
||||
|
||||
class ManageAppUsersComponent extends React.Component {
|
||||
static contextType = ModuleContext;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.isUserAdmin = authenticationService.currentSessionValue?.admin;
|
||||
|
|
@ -109,7 +112,10 @@ class ManageAppUsersComponent extends React.Component {
|
|||
ischangingVisibility: true,
|
||||
});
|
||||
|
||||
useAppDataStore.getState().actions.updateState({ isPublic: newState });
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[this.context].useAppDataStore.getState()
|
||||
.actions.updateState({ isPublic: newState });
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
appsService
|
||||
|
|
@ -165,7 +171,10 @@ class ManageAppUsersComponent extends React.Component {
|
|||
});
|
||||
|
||||
replaceEditorURL(value, this.props.pageHandle);
|
||||
useAppDataStore.getState().actions.updateState({ slug: value });
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[this.context].useAppDataStore.getState()
|
||||
.actions.updateState({ slug: value });
|
||||
})
|
||||
.catch(({ error }) => {
|
||||
this.setState({
|
||||
|
|
|
|||
|
|
@ -20,8 +20,10 @@ import { useAppVersionStore } from '@/_stores/appVersionStore';
|
|||
import { shallow } from 'zustand/shallow';
|
||||
import { Tooltip } from 'react-tooltip';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import { useModuleName } from '@/_contexts/ModuleContext';
|
||||
|
||||
export const QueryManagerHeader = forwardRef(({ darkMode, options, editorRef }, ref) => {
|
||||
const moduleName = useModuleName();
|
||||
const { renameQuery } = useDataQueriesActions();
|
||||
const selectedQuery = useSelectedQuery();
|
||||
const selectedDataSource = useSelectedDataSource();
|
||||
|
|
@ -51,7 +53,7 @@ export const QueryManagerHeader = forwardRef(({ darkMode, options, editorRef },
|
|||
return false;
|
||||
}
|
||||
|
||||
const isNewQueryNameAlreadyExists = checkExistingQueryName(newName);
|
||||
const isNewQueryNameAlreadyExists = checkExistingQueryName(newName, moduleName);
|
||||
if (isNewQueryNameAlreadyExists) {
|
||||
toast.error('Query name already exists');
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -10,8 +10,10 @@ import { shallow } from 'zustand/shallow';
|
|||
import Copy from '@/_ui/Icon/solidIcons/Copy';
|
||||
import DataSourceIcon from '../QueryManager/Components/DataSourceIcon';
|
||||
import { isQueryRunnable } from '@/_helpers/utils';
|
||||
import { useModuleName } from '@/_contexts/ModuleContext';
|
||||
|
||||
export const QueryCard = ({ dataQuery, darkMode = false, editorRef, appId }) => {
|
||||
const moduleName = useModuleName();
|
||||
const selectedQuery = useSelectedQuery();
|
||||
const { isDeletingQueryInProcess } = useDataQueriesStore();
|
||||
const { deleteDataQueries, renameQuery, duplicateQuery } = useDataQueriesActions();
|
||||
|
|
@ -42,7 +44,7 @@ export const QueryCard = ({ dataQuery, darkMode = false, editorRef, appId }) =>
|
|||
if (name === newName) {
|
||||
return setRenamingQuery(false);
|
||||
}
|
||||
const isNewQueryNameAlreadyExists = checkExistingQueryName(newName);
|
||||
const isNewQueryNameAlreadyExists = checkExistingQueryName(newName, moduleName);
|
||||
if (newName && !isNewQueryNameAlreadyExists) {
|
||||
renameQuery(dataQuery?.id, newName, editorRef);
|
||||
setRenamingQuery(false);
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
import React, { useState, useRef, useCallback, useEffect } from 'react';
|
||||
import React, { useState, useRef, useCallback, useEffect, useContext } from 'react';
|
||||
import { useEventListener } from '@/_hooks/use-event-listener';
|
||||
import { Tooltip } from 'react-tooltip';
|
||||
import { QueryDataPane } from './QueryDataPane';
|
||||
import QueryManager from '../QueryManager/QueryManager';
|
||||
|
||||
import useWindowResize from '@/_hooks/useWindowResize';
|
||||
import { useQueryPanelStore, useQueryPanelActions } from '@/_stores/queryPanelStore';
|
||||
import { useQueryPanelActions } from '@/_stores/queryPanelStore';
|
||||
import { useDataQueriesStore, useDataQueries } from '@/_stores/dataQueriesStore';
|
||||
import Maximize from '@/_ui/Icon/solidIcons/Maximize';
|
||||
import { cloneDeep, isEmpty, isEqual } from 'lodash';
|
||||
import { ButtonSolid } from '@/_ui/AppButton/AppButton';
|
||||
import { ModuleContext } from '../../_contexts/ModuleContext';
|
||||
import { useSuperStore } from '../../_stores/superStore';
|
||||
|
||||
const QueryPanel = ({
|
||||
dataQueriesChanged,
|
||||
|
|
@ -22,6 +24,7 @@ const QueryPanel = ({
|
|||
onQueryPaneDragging,
|
||||
handleQueryPaneExpanding,
|
||||
}) => {
|
||||
const moduleName = useContext(ModuleContext);
|
||||
const { updateQueryPanelHeight } = useQueryPanelActions();
|
||||
const dataQueries = useDataQueries();
|
||||
const queryManagerPreferences = useRef(JSON.parse(localStorage.getItem('queryManagerPreferences')) ?? {});
|
||||
|
|
@ -37,26 +40,28 @@ const QueryPanel = ({
|
|||
const [windowSize, isWindowResizing] = useWindowResize();
|
||||
|
||||
useEffect(() => {
|
||||
const queryPanelStoreListner = useQueryPanelStore.subscribe(({ selectedQuery }, prevState) => {
|
||||
if (isEmpty(prevState?.selectedQuery) || isEmpty(selectedQuery)) {
|
||||
return;
|
||||
}
|
||||
const queryPanelStoreListner = useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useQueryPanelStore.subscribe(({ selectedQuery }, prevState) => {
|
||||
if (isEmpty(prevState?.selectedQuery) || isEmpty(selectedQuery)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (prevState?.selectedQuery?.id !== selectedQuery.id) {
|
||||
return;
|
||||
}
|
||||
if (prevState?.selectedQuery?.id !== selectedQuery.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
//removing updated_at since this value changes whenever the data is updated in the BE
|
||||
const formattedQuery = cloneDeep(selectedQuery);
|
||||
delete formattedQuery.updated_at;
|
||||
//removing updated_at since this value changes whenever the data is updated in the BE
|
||||
const formattedQuery = cloneDeep(selectedQuery);
|
||||
delete formattedQuery.updated_at;
|
||||
|
||||
const formattedPrevQuery = cloneDeep(prevState?.selectedQuery || {});
|
||||
delete formattedPrevQuery.updated_at;
|
||||
const formattedPrevQuery = cloneDeep(prevState?.selectedQuery || {});
|
||||
delete formattedPrevQuery.updated_at;
|
||||
|
||||
if (!isEqual(formattedQuery, formattedPrevQuery)) {
|
||||
useDataQueriesStore.getState().actions.saveData(selectedQuery);
|
||||
}
|
||||
});
|
||||
if (!isEqual(formattedQuery, formattedPrevQuery)) {
|
||||
useSuperStore.getState().modules[moduleName].useDataQueriesStore.getState().actions.saveData(selectedQuery);
|
||||
}
|
||||
});
|
||||
|
||||
return queryPanelStoreListner;
|
||||
}, []);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* eslint-disable import/no-named-as-default */
|
||||
import React, { useCallback, useState, useEffect, useRef } from 'react';
|
||||
import React, { useCallback, useState, useEffect, useRef, useContext } from 'react';
|
||||
import { useDrop, useDragLayer } from 'react-dnd';
|
||||
import { ItemTypes } from './ItemTypes';
|
||||
import { DraggableBox } from './DraggableBox';
|
||||
|
|
@ -15,9 +15,10 @@ import { useCurrentState } from '@/_stores/currentStateStore';
|
|||
import { useAppVersionStore } from '@/_stores/appVersionStore';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { useMounted } from '@/_hooks/use-mount';
|
||||
import { useEditorStore } from '@/_stores/editorStore';
|
||||
import { useSuperStore } from '@/_stores/superStore';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { diff } from 'deep-object-diff';
|
||||
import { ModuleContext } from '../_contexts/ModuleContext';
|
||||
|
||||
const NO_OF_GRIDS = 43;
|
||||
|
||||
|
|
@ -62,6 +63,8 @@ export const SubContainer = ({
|
|||
Listview: 'listItem',
|
||||
});
|
||||
|
||||
const moduleName = useContext(ModuleContext);
|
||||
|
||||
const customResolverVariable = widgetResolvables[parentComponent?.component];
|
||||
const currentState = useCurrentState();
|
||||
const { enableReleasedVersionPopupState, isVersionReleased } = useAppVersionStore(
|
||||
|
|
@ -402,7 +405,9 @@ export const SubContainer = ({
|
|||
let newBoxes = { ...boxes };
|
||||
|
||||
const subContainerHeight = canvasBounds.height - 30;
|
||||
const selectedComponents = useEditorStore.getState().selectedComponents;
|
||||
const selectedComponents = useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useEditorStore.getState().selectedComponents;
|
||||
|
||||
if (selectedComponents) {
|
||||
for (const selectedComponent of selectedComponents) {
|
||||
|
|
|
|||
|
|
@ -38,8 +38,12 @@ import { shallow } from 'zustand/shallow';
|
|||
import { useAppDataActions, useAppDataStore } from '@/_stores/appDataStore';
|
||||
import { getPreviewQueryParams, redirectToErrorPage } from '@/_helpers/routes';
|
||||
import { ERROR_TYPES } from '@/_helpers/constants';
|
||||
import { useSuperStore } from '../_stores/superStore';
|
||||
import { ModuleContext } from '../_contexts/ModuleContext';
|
||||
|
||||
class ViewerComponent extends React.Component {
|
||||
static contextType = ModuleContext;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
|
@ -69,6 +73,7 @@ class ViewerComponent extends React.Component {
|
|||
navigate: this.props.navigate,
|
||||
switchPage: this.switchPage,
|
||||
currentPageId: this.state.currentPageId,
|
||||
moduleName: this.context,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -158,7 +163,7 @@ class ViewerComponent extends React.Component {
|
|||
const currentPageId = pages.filter((page) => page.handle === startingPageHandle)[0]?.id ?? homePageId;
|
||||
const currentPage = pages.find((page) => page.id === currentPageId);
|
||||
|
||||
useDataQueriesStore.getState().actions.setDataQueries(dataQueries);
|
||||
useSuperStore.getState().modules[this.context].useDataQueriesStore.getState().actions.setDataQueries(dataQueries);
|
||||
this.props.setCurrentState({
|
||||
queries: queryState,
|
||||
components: {},
|
||||
|
|
@ -180,7 +185,10 @@ class ViewerComponent extends React.Component {
|
|||
...variables,
|
||||
...constants,
|
||||
});
|
||||
useEditorStore.getState().actions.toggleCurrentLayout(mobileLayoutHasWidgets ? 'mobile' : 'desktop');
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[this.context].useEditorStore.getState()
|
||||
.actions.toggleCurrentLayout(mobileLayoutHasWidgets ? 'mobile' : 'desktop');
|
||||
this.props.updateState({ events: data.events ?? [] });
|
||||
this.setState(
|
||||
{
|
||||
|
|
@ -201,9 +209,8 @@ class ViewerComponent extends React.Component {
|
|||
() => {
|
||||
const components = appDefData?.pages[currentPageId]?.components || {};
|
||||
|
||||
computeComponentState(components).then(async () => {
|
||||
computeComponentState(components, this.context).then(async () => {
|
||||
this.setState({ initialComputationOfStateDone: true, defaultComponentStateComputed: true });
|
||||
console.log('Default component state computed and set');
|
||||
this.runQueries(dataQueries);
|
||||
|
||||
const currentPageEvents = this.state.events.filter(
|
||||
|
|
@ -237,8 +244,6 @@ class ViewerComponent extends React.Component {
|
|||
variablesResult = constants;
|
||||
}
|
||||
|
||||
console.log('--org constant 2.0', { variablesResult });
|
||||
|
||||
if (variablesResult && Array.isArray(variablesResult)) {
|
||||
variablesResult.map((constant) => {
|
||||
const constantValue = constant.values.find((value) => value.environmentName === 'production')['value'];
|
||||
|
|
@ -317,7 +322,10 @@ class ViewerComponent extends React.Component {
|
|||
};
|
||||
|
||||
updateQueryConfirmationList = (queryConfirmationList) =>
|
||||
useEditorStore.getState().actions.updateQueryConfirmationList(queryConfirmationList);
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[this.context].useEditorStore.getState()
|
||||
.actions.updateQueryConfirmationList(queryConfirmationList);
|
||||
|
||||
setupViewer() {
|
||||
this.subscription = authenticationService.currentSession.subscribe((currentSession) => {
|
||||
|
|
@ -325,9 +333,11 @@ class ViewerComponent extends React.Component {
|
|||
const appId = this.props.id;
|
||||
const versionId = this.props.versionId;
|
||||
|
||||
console.log({ slug, appId, versionId });
|
||||
|
||||
if (currentSession?.load_app && slug) {
|
||||
if (currentSession?.group_permissions) {
|
||||
useAppDataStore.getState().actions.setAppId(appId);
|
||||
useSuperStore.getState().modules[this.context].useAppDataStore.getState().actions.setAppId(appId);
|
||||
|
||||
const currentUser = currentSession.current_user;
|
||||
const userVars = {
|
||||
|
|
@ -376,7 +386,10 @@ class ViewerComponent extends React.Component {
|
|||
componentDidMount() {
|
||||
this.setupViewer();
|
||||
const isMobileDevice = this.state.deviceWindowWidth < 600;
|
||||
useEditorStore.getState().actions.toggleCurrentLayout(isMobileDevice ? 'mobile' : 'desktop');
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[this.context].useEditorStore.getState()
|
||||
.actions.toggleCurrentLayout(isMobileDevice ? 'mobile' : 'desktop');
|
||||
window.addEventListener('message', this.handleMessage);
|
||||
}
|
||||
|
||||
|
|
@ -434,7 +447,10 @@ class ViewerComponent extends React.Component {
|
|||
name: targetPage.name,
|
||||
},
|
||||
async () => {
|
||||
computeComponentState(this.state.appDefinition?.pages[this.state.currentPageId].components).then(async () => {
|
||||
computeComponentState(
|
||||
this.state.appDefinition?.pages[this.state.currentPageId].components,
|
||||
this.context
|
||||
).then(async () => {
|
||||
const currentPageEvents = this.state.events.filter(
|
||||
(event) => event.target === 'page' && event.sourceId === this.state.currentPageId
|
||||
);
|
||||
|
|
@ -547,6 +563,8 @@ class ViewerComponent extends React.Component {
|
|||
canvasWidth,
|
||||
} = this.state;
|
||||
|
||||
const moduleName = this.context;
|
||||
|
||||
const currentCanvasWidth = canvasWidth;
|
||||
const queryConfirmationList = this.props?.queryConfirmationList ?? [];
|
||||
|
||||
|
|
@ -589,89 +607,184 @@ class ViewerComponent extends React.Component {
|
|||
queryConfirmationData={queryConfirmationList[0]}
|
||||
key={queryConfirmationList[0]?.queryName}
|
||||
/>
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
<ViewerNavigation.Header
|
||||
showHeader={!appDefinition.globalSettings?.hideHeader && isAppLoaded}
|
||||
appName={this.state.app?.name ?? null}
|
||||
changeDarkMode={this.changeDarkMode}
|
||||
darkMode={this.props.darkMode}
|
||||
pages={Object.entries(this.state.appDefinition?.pages) ?? []}
|
||||
currentPageId={this.state?.currentPageId ?? this.state.appDefinition?.homePageId}
|
||||
switchPage={this.switchPage}
|
||||
/>
|
||||
<div className="sub-section">
|
||||
<div className="main">
|
||||
<div
|
||||
className="canvas-container align-items-center"
|
||||
style={{
|
||||
background: this.computeCanvasBackgroundColor() || (!this.props.darkMode ? '#EBEBEF' : '#2E3035'),
|
||||
}}
|
||||
>
|
||||
<div className="areas d-flex flex-rows">
|
||||
{appDefinition?.showViewerNavigation && (
|
||||
<ViewerNavigation
|
||||
isMobileDevice={this.props.currentLayout === 'mobile'}
|
||||
canvasBackgroundColor={this.computeCanvasBackgroundColor()}
|
||||
pages={Object.entries(this.state.appDefinition?.pages) ?? []}
|
||||
currentPageId={this.state?.currentPageId ?? this.state.appDefinition?.homePageId}
|
||||
switchPage={this.switchPage}
|
||||
darkMode={this.props.darkMode}
|
||||
/>
|
||||
)}
|
||||
<div className="flex-grow-1 d-flex justify-content-center">
|
||||
<div
|
||||
className="canvas-area"
|
||||
style={{
|
||||
width: currentCanvasWidth,
|
||||
maxWidth: canvasMaxWidth,
|
||||
backgroundColor: this.computeCanvasBackgroundColor(),
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
}}
|
||||
>
|
||||
{defaultComponentStateComputed && (
|
||||
<>
|
||||
{isLoading ? (
|
||||
<div className="mx-auto mt-5 w-50 p-5">
|
||||
<center>
|
||||
<div className="spinner-border text-azure" role="status"></div>
|
||||
</center>
|
||||
</div>
|
||||
) : (
|
||||
<Container
|
||||
appDefinition={appDefinition}
|
||||
appDefinitionChanged={() => false} // function not relevant in viewer
|
||||
snapToGrid={true}
|
||||
appLoading={isLoading}
|
||||
darkMode={this.props.darkMode}
|
||||
onEvent={this.handleEvent}
|
||||
mode="view"
|
||||
deviceWindowWidth={deviceWindowWidth}
|
||||
selectedComponent={this.state.selectedComponent}
|
||||
onComponentClick={(id, component) => {
|
||||
this.setState({
|
||||
selectedComponent: { id, component },
|
||||
});
|
||||
onComponentClick(this, id, component, 'view');
|
||||
}}
|
||||
onComponentOptionChanged={(component, optionName, value) => {
|
||||
return onComponentOptionChanged(component, optionName, value);
|
||||
}}
|
||||
onComponentOptionsChanged={onComponentOptionsChanged}
|
||||
canvasWidth={this.getCanvasWidth()}
|
||||
dataQueries={dataQueries}
|
||||
currentPageId={this.state.currentPageId}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{!this.props.moduleMode && (
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
<ViewerNavigation.Header
|
||||
showHeader={!appDefinition.globalSettings?.hideHeader && isAppLoaded && !this.props.moduleMode}
|
||||
appName={this.state.app?.name ?? null}
|
||||
changeDarkMode={this.changeDarkMode}
|
||||
darkMode={this.props.darkMode}
|
||||
pages={Object.entries(this.state.appDefinition?.pages) ?? []}
|
||||
currentPageId={this.state?.currentPageId ?? this.state.appDefinition?.homePageId}
|
||||
switchPage={this.switchPage}
|
||||
/>
|
||||
<div className="sub-section">
|
||||
<div className="main">
|
||||
<div
|
||||
className="canvas-container align-items-center"
|
||||
style={{
|
||||
background:
|
||||
this.computeCanvasBackgroundColor() || (!this.props.darkMode ? '#EBEBEF' : '#2E3035'),
|
||||
...(this.props.moduleMode ? { top: 0 } : {}),
|
||||
}}
|
||||
>
|
||||
<div className="areas d-flex flex-rows">
|
||||
{appDefinition?.showViewerNavigation && !this.props.moduleMode && (
|
||||
<ViewerNavigation
|
||||
isMobileDevice={this.props.currentLayout === 'mobile'}
|
||||
canvasBackgroundColor={this.computeCanvasBackgroundColor()}
|
||||
pages={Object.entries(this.state.appDefinition?.pages) ?? []}
|
||||
currentPageId={this.state?.currentPageId ?? this.state.appDefinition?.homePageId}
|
||||
switchPage={this.switchPage}
|
||||
darkMode={this.props.darkMode}
|
||||
/>
|
||||
)}
|
||||
<div className="flex-grow-1 d-flex justify-content-center">
|
||||
<div
|
||||
className="canvas-area"
|
||||
style={{
|
||||
width: currentCanvasWidth,
|
||||
maxWidth: canvasMaxWidth,
|
||||
backgroundColor: this.computeCanvasBackgroundColor(),
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
}}
|
||||
>
|
||||
{defaultComponentStateComputed && (
|
||||
<>
|
||||
{isLoading ? (
|
||||
<div className="mx-auto mt-5 w-50 p-5">
|
||||
<center>
|
||||
<div className="spinner-border text-azure" role="status"></div>
|
||||
</center>
|
||||
</div>
|
||||
) : (
|
||||
<Container
|
||||
appDefinition={appDefinition}
|
||||
appDefinitionChanged={() => false} // function not relevant in viewer
|
||||
snapToGrid={true}
|
||||
appLoading={isLoading}
|
||||
darkMode={this.props.darkMode}
|
||||
onEvent={this.handleEvent}
|
||||
mode="view"
|
||||
deviceWindowWidth={deviceWindowWidth}
|
||||
selectedComponent={this.state.selectedComponent}
|
||||
onComponentClick={(id, component) => {
|
||||
this.setState({
|
||||
selectedComponent: { id, component },
|
||||
});
|
||||
onComponentClick(this, id, component, 'view');
|
||||
}}
|
||||
onComponentOptionChanged={(component, optionName, value) => {
|
||||
return onComponentOptionChanged(this.context, component, optionName, value);
|
||||
}}
|
||||
onComponentOptionsChanged={(...props) =>
|
||||
onComponentOptionsChanged(this.context, ...props)
|
||||
}
|
||||
canvasWidth={this.getCanvasWidth()}
|
||||
dataQueries={dataQueries}
|
||||
currentPageId={this.state.currentPageId}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DndProvider>
|
||||
</DndProvider>
|
||||
)}
|
||||
{this.props.moduleMode && (
|
||||
<>
|
||||
<ViewerNavigation.Header
|
||||
showHeader={!appDefinition.globalSettings?.hideHeader && isAppLoaded && !this.props.moduleMode}
|
||||
appName={this.state.app?.name ?? null}
|
||||
changeDarkMode={this.changeDarkMode}
|
||||
darkMode={this.props.darkMode}
|
||||
pages={Object.entries(this.state.appDefinition?.pages) ?? []}
|
||||
currentPageId={this.state?.currentPageId ?? this.state.appDefinition?.homePageId}
|
||||
switchPage={this.switchPage}
|
||||
/>
|
||||
<div className="sub-section">
|
||||
<div className="main">
|
||||
<div
|
||||
className="canvas-container align-items-center"
|
||||
style={{
|
||||
background:
|
||||
this.computeCanvasBackgroundColor() || (!this.props.darkMode ? '#EBEBEF' : '#2E3035'),
|
||||
...(this.props.moduleMode ? { top: 0 } : {}),
|
||||
}}
|
||||
>
|
||||
<div className="areas d-flex flex-rows">
|
||||
{appDefinition?.showViewerNavigation && !this.props.moduleMode && (
|
||||
<ViewerNavigation
|
||||
isMobileDevice={this.props.currentLayout === 'mobile'}
|
||||
canvasBackgroundColor={this.computeCanvasBackgroundColor()}
|
||||
pages={Object.entries(this.state.appDefinition?.pages) ?? []}
|
||||
currentPageId={this.state?.currentPageId ?? this.state.appDefinition?.homePageId}
|
||||
switchPage={this.switchPage}
|
||||
darkMode={this.props.darkMode}
|
||||
/>
|
||||
)}
|
||||
<div className="flex-grow-1 d-flex justify-content-center">
|
||||
<div
|
||||
className="canvas-area"
|
||||
style={{
|
||||
width: currentCanvasWidth,
|
||||
maxWidth: canvasMaxWidth,
|
||||
backgroundColor: this.computeCanvasBackgroundColor(),
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
}}
|
||||
>
|
||||
{defaultComponentStateComputed && (
|
||||
<>
|
||||
{isLoading ? (
|
||||
<div className="mx-auto mt-5 w-50 p-5">
|
||||
<center>
|
||||
<div className="spinner-border text-azure" role="status"></div>
|
||||
</center>
|
||||
</div>
|
||||
) : (
|
||||
<Container
|
||||
appDefinition={appDefinition}
|
||||
appDefinitionChanged={() => false} // function not relevant in viewer
|
||||
snapToGrid={true}
|
||||
appLoading={isLoading}
|
||||
darkMode={this.props.darkMode}
|
||||
onEvent={this.handleEvent}
|
||||
mode="view"
|
||||
deviceWindowWidth={deviceWindowWidth}
|
||||
selectedComponent={this.state.selectedComponent}
|
||||
onComponentClick={(id, component) => {
|
||||
this.setState({
|
||||
selectedComponent: { id, component },
|
||||
});
|
||||
onComponentClick(this, id, component, 'view');
|
||||
}}
|
||||
onComponentOptionChanged={(component, optionName, value) => {
|
||||
return onComponentOptionChanged(this.context, component, optionName, value);
|
||||
}}
|
||||
onComponentOptionsChanged={(...props) =>
|
||||
onComponentOptionsChanged(this.context, ...props)
|
||||
}
|
||||
canvasWidth={this.getCanvasWidth()}
|
||||
dataQueries={dataQueries}
|
||||
currentPageId={this.state.currentPageId}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ class HomePageComponent extends React.Component {
|
|||
showTemplateLibraryModal: false,
|
||||
app: {},
|
||||
showCreateAppModal: false,
|
||||
showCreateModuleModal: false,
|
||||
showCreateAppFromTemplateModal: false,
|
||||
showImportAppModal: false,
|
||||
showCloneAppModal: false,
|
||||
|
|
@ -131,11 +132,11 @@ class HomePageComponent extends React.Component {
|
|||
this.fetchFolders();
|
||||
};
|
||||
|
||||
createApp = async (appName) => {
|
||||
createApp = async (appName, type) => {
|
||||
let _self = this;
|
||||
_self.setState({ creatingApp: true });
|
||||
try {
|
||||
const data = await appsService.createApp({ icon: sample(iconList), name: appName });
|
||||
const data = await appsService.createApp({ icon: sample(iconList), name: appName, type });
|
||||
const workspaceId = getWorkspaceId();
|
||||
_self.props.navigate(`/${workspaceId}/apps/${data.id}`);
|
||||
toast.success('App created successfully!');
|
||||
|
|
@ -540,11 +541,11 @@ class HomePageComponent extends React.Component {
|
|||
};
|
||||
|
||||
openCreateAppModal = () => {
|
||||
this.setState({ showCreateAppModal: true });
|
||||
this.setState({ showCreateAppModal: true, showCreateModuleModal: true });
|
||||
};
|
||||
|
||||
closeCreateAppModal = () => {
|
||||
this.setState({ showCreateAppModal: false });
|
||||
this.setState({ showCreateAppModal: false, showCreateModuleModal: false });
|
||||
};
|
||||
|
||||
render() {
|
||||
|
|
@ -568,6 +569,7 @@ class HomePageComponent extends React.Component {
|
|||
appToBeDeleted,
|
||||
app,
|
||||
showCreateAppModal,
|
||||
showCreateModuleModal,
|
||||
showImportAppModal,
|
||||
fileContent,
|
||||
fileName,
|
||||
|
|
@ -577,13 +579,13 @@ class HomePageComponent extends React.Component {
|
|||
return (
|
||||
<Layout switchDarkMode={this.props.switchDarkMode} darkMode={this.props.darkMode}>
|
||||
<div className="wrapper home-page">
|
||||
{showCreateAppModal && (
|
||||
{(showCreateAppModal || showCreateModuleModal) && (
|
||||
<AppModal
|
||||
closeModal={this.closeCreateAppModal}
|
||||
processApp={this.createApp}
|
||||
processApp={(name) => this.createApp(name, showCreateAppModal ? 'front-end' : 'module')}
|
||||
show={this.openCreateAppModal}
|
||||
title={'Create app'}
|
||||
actionButton={'+ Create app'}
|
||||
title={showCreateAppModal ? 'Create app' : 'Create module'}
|
||||
actionButton={showCreateAppModal ? '+ Create app' : '+ Create module'}
|
||||
actionLoadingButton={'Creating'}
|
||||
/>
|
||||
)}
|
||||
|
|
@ -795,6 +797,13 @@ class HomePageComponent extends React.Component {
|
|||
data-cy="import-option-input"
|
||||
/>
|
||||
</label>
|
||||
<Dropdown.Item
|
||||
className="homepage-dropdown-style tj-text tj-text-xsm"
|
||||
onClick={() => this.setState({ showCreateModuleModal: true })}
|
||||
data-cy="create-module-button"
|
||||
>
|
||||
{this.props.t('homePage.header.createModule', 'Create module')}
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
|
|
|
|||
11
frontend/src/_contexts/ModuleContext.jsx
Normal file
11
frontend/src/_contexts/ModuleContext.jsx
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { createContext, useContext } from 'react';
|
||||
|
||||
export const ModuleContext = createContext(null);
|
||||
|
||||
export const useModuleName = () => {
|
||||
const moduleName = useContext(ModuleContext);
|
||||
|
||||
if (!moduleName) throw Error('useModuleName can only be used inside a ModuleContext');
|
||||
|
||||
return moduleName;
|
||||
};
|
||||
|
|
@ -35,6 +35,7 @@ import { useAppVersionStore } from '@/_stores/appVersionStore';
|
|||
import { camelizeKeys } from 'humps';
|
||||
import { useAppDataStore } from '@/_stores/appDataStore';
|
||||
import { useEditorStore } from '@/_stores/editorStore';
|
||||
import { useSuperStore } from '@/_stores/superStore';
|
||||
|
||||
const ERROR_TYPES = Object.freeze({
|
||||
ReferenceError: 'ReferenceError',
|
||||
|
|
@ -62,9 +63,10 @@ export function setCurrentStateAsync(_ref, changes) {
|
|||
});
|
||||
}
|
||||
|
||||
export function onComponentOptionsChanged(component, options) {
|
||||
export function onComponentOptionsChanged(moduleName, component, options) {
|
||||
const componentName = component.name;
|
||||
const components = getCurrentState().components;
|
||||
console.log({ moduleName });
|
||||
const components = getCurrentState(moduleName).components;
|
||||
let componentData = components[componentName];
|
||||
componentData = componentData || {};
|
||||
|
||||
|
|
@ -72,27 +74,36 @@ export function onComponentOptionsChanged(component, options) {
|
|||
componentData[option[0]] = option[1];
|
||||
}
|
||||
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
components: { ...components, [componentName]: componentData },
|
||||
});
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
components: { ...components, [componentName]: componentData },
|
||||
});
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
export function onComponentOptionChanged(component, option_name, value) {
|
||||
export function onComponentOptionChanged(moduleName, component, option_name, value) {
|
||||
const componentName = component.name;
|
||||
const components = getCurrentState().components;
|
||||
const components = getCurrentState(moduleName).components;
|
||||
let componentData = components[componentName];
|
||||
componentData = componentData || {};
|
||||
componentData[option_name] = value;
|
||||
|
||||
if (option_name !== 'id') {
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
components: { ...components, [componentName]: componentData },
|
||||
});
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
components: { ...components, [componentName]: componentData },
|
||||
});
|
||||
} else if (!componentData?.id) {
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
components: { ...components, [componentName]: componentData },
|
||||
});
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
components: { ...components, [componentName]: componentData },
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
|
|
@ -133,7 +144,7 @@ async function executeRunPycode(_ref, code, query, isPreview, mode) {
|
|||
|
||||
const evaluatePythonCode = async (pyodide) => {
|
||||
let result = {};
|
||||
const currentState = getCurrentState();
|
||||
const currentState = getCurrentState(_ref.moduleName);
|
||||
try {
|
||||
const appStateVars = currentState['variables'] ?? {};
|
||||
|
||||
|
|
@ -284,7 +295,7 @@ export async function runTransformation(
|
|||
|
||||
let result = [];
|
||||
|
||||
const currentState = getCurrentState() || {};
|
||||
const currentState = getCurrentState(_ref.moduleName) || {};
|
||||
|
||||
if (transformationLanguage === 'python') {
|
||||
result = await runPythonTransformation(currentState, data, transformation, query, mode);
|
||||
|
|
@ -364,13 +375,13 @@ function showModal(_ref, modal, show) {
|
|||
const modalMeta = _ref.appDefinition.pages[_ref.currentPageId].components[modalId]; //! NeedToFix
|
||||
|
||||
const _components = {
|
||||
...getCurrentState().components,
|
||||
...getCurrentState(_ref.moduleName).components,
|
||||
[modalMeta.component.name]: {
|
||||
...getCurrentState().components[modalMeta.component.name],
|
||||
...getCurrentState(_ref.moduleName).components[modalMeta.component.name],
|
||||
show: show,
|
||||
},
|
||||
};
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
useSuperStore.getState().modules[_ref.moduleName].useCurrentStateStore.getState().actions.setCurrentState({
|
||||
components: _components,
|
||||
});
|
||||
return Promise.resolve();
|
||||
|
|
@ -402,14 +413,19 @@ export const executeAction = debounce(executeActionWithDebounce);
|
|||
function executeActionWithDebounce(_ref, event, mode, customVariables) {
|
||||
if (event) {
|
||||
if (event.runOnlyIf) {
|
||||
const shouldRun = resolveReferences(event.runOnlyIf, getCurrentState(), undefined, customVariables);
|
||||
const shouldRun = resolveReferences(
|
||||
event.runOnlyIf,
|
||||
getCurrentState(_ref.moduleName),
|
||||
undefined,
|
||||
customVariables
|
||||
);
|
||||
if (!shouldRun) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
switch (event.actionId) {
|
||||
case 'show-alert': {
|
||||
const message = resolveReferences(event.message, getCurrentState(), undefined, customVariables);
|
||||
const message = resolveReferences(event.message, getCurrentState(_ref.moduleName), undefined, customVariables);
|
||||
switch (event.alertType) {
|
||||
case 'success':
|
||||
case 'error':
|
||||
|
|
@ -433,11 +449,15 @@ function executeActionWithDebounce(_ref, event, mode, customVariables) {
|
|||
const resolvedParams = {};
|
||||
if (params) {
|
||||
Object.keys(params).map(
|
||||
(param) => (resolvedParams[param] = resolveReferences(params[param], getCurrentState(), undefined))
|
||||
(param) =>
|
||||
(resolvedParams[param] = resolveReferences(params[param], getCurrentState(_ref.moduleName), undefined))
|
||||
);
|
||||
}
|
||||
const name =
|
||||
useDataQueriesStore.getState().dataQueries.find((query) => query.id === queryId)?.name ?? queryName;
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useDataQueriesStore.getState()
|
||||
.dataQueries.find((query) => query.id === queryId)?.name ?? queryName;
|
||||
return runQuery(_ref, queryId, name, undefined, mode, resolvedParams);
|
||||
}
|
||||
case 'logout': {
|
||||
|
|
@ -445,20 +465,20 @@ function executeActionWithDebounce(_ref, event, mode, customVariables) {
|
|||
}
|
||||
|
||||
case 'open-webpage': {
|
||||
const url = resolveReferences(event.url, getCurrentState(), undefined, customVariables);
|
||||
const url = resolveReferences(event.url, getCurrentState(_ref.moduleName), undefined, customVariables);
|
||||
window.open(url, '_blank');
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
case 'go-to-app': {
|
||||
const slug = resolveReferences(event.slug, getCurrentState(), undefined, customVariables);
|
||||
const slug = resolveReferences(event.slug, getCurrentState(_ref.moduleName), undefined, customVariables);
|
||||
const queryParams = event.queryParams?.reduce(
|
||||
(result, queryParam) => ({
|
||||
...result,
|
||||
...{
|
||||
[resolveReferences(queryParam[0], getCurrentState())]: resolveReferences(
|
||||
[resolveReferences(queryParam[0], getCurrentState(_ref.moduleName))]: resolveReferences(
|
||||
queryParam[1],
|
||||
getCurrentState(),
|
||||
getCurrentState(_ref.moduleName),
|
||||
undefined,
|
||||
customVariables
|
||||
),
|
||||
|
|
@ -492,15 +512,20 @@ function executeActionWithDebounce(_ref, event, mode, customVariables) {
|
|||
return showModal(_ref, event.modal, false);
|
||||
|
||||
case 'copy-to-clipboard': {
|
||||
const contentToCopy = resolveReferences(event.contentToCopy, getCurrentState(), undefined, customVariables);
|
||||
const contentToCopy = resolveReferences(
|
||||
event.contentToCopy,
|
||||
getCurrentState(_ref.moduleName),
|
||||
undefined,
|
||||
customVariables
|
||||
);
|
||||
copyToClipboard(contentToCopy);
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
case 'set-localstorage-value': {
|
||||
const key = resolveReferences(event.key, getCurrentState(), undefined, customVariables);
|
||||
const value = resolveReferences(event.value, getCurrentState(), undefined, customVariables);
|
||||
const key = resolveReferences(event.key, getCurrentState(_ref.moduleName), undefined, customVariables);
|
||||
const value = resolveReferences(event.value, getCurrentState(_ref.moduleName), undefined, customVariables);
|
||||
localStorage.setItem(key, value);
|
||||
|
||||
return Promise.resolve();
|
||||
|
|
@ -508,9 +533,11 @@ function executeActionWithDebounce(_ref, event, mode, customVariables) {
|
|||
|
||||
case 'generate-file': {
|
||||
// const fileType = event.fileType;
|
||||
const data = resolveReferences(event.data, getCurrentState(), undefined, customVariables) ?? [];
|
||||
const fileName = resolveReferences(event.fileName, getCurrentState(), undefined, customVariables) ?? 'data.txt';
|
||||
const fileType = resolveReferences(event.fileType, getCurrentState(), undefined, customVariables) ?? 'csv';
|
||||
const data = resolveReferences(event.data, getCurrentState(_ref.moduleName), undefined, customVariables) ?? [];
|
||||
const fileName =
|
||||
resolveReferences(event.fileName, getCurrentState(_ref.moduleName), undefined, customVariables) ?? 'data.txt';
|
||||
const fileType =
|
||||
resolveReferences(event.fileType, getCurrentState(_ref.moduleName), undefined, customVariables) ?? 'csv';
|
||||
const fileData = {
|
||||
csv: generateCSV,
|
||||
plaintext: (plaintext) => plaintext,
|
||||
|
|
@ -521,57 +548,69 @@ function executeActionWithDebounce(_ref, event, mode, customVariables) {
|
|||
}
|
||||
|
||||
case 'set-table-page': {
|
||||
setTablePageIndex(event.table, event.pageIndex);
|
||||
setTablePageIndex(event.table, event.pageIndex, _ref);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'set-custom-variable': {
|
||||
const key = resolveReferences(event.key, getCurrentState(), undefined, customVariables);
|
||||
const value = resolveReferences(event.value, getCurrentState(), undefined, customVariables);
|
||||
const customAppVariables = { ...getCurrentState().variables };
|
||||
const key = resolveReferences(event.key, getCurrentState(_ref.moduleName), undefined, customVariables);
|
||||
const value = resolveReferences(event.value, getCurrentState(_ref.moduleName), undefined, customVariables);
|
||||
const customAppVariables = { ...getCurrentState(_ref.moduleName).variables };
|
||||
customAppVariables[key] = value;
|
||||
return useCurrentStateStore.getState().actions.setCurrentState({
|
||||
variables: customAppVariables,
|
||||
});
|
||||
return useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
variables: customAppVariables,
|
||||
});
|
||||
}
|
||||
|
||||
case 'unset-custom-variable': {
|
||||
const key = resolveReferences(event.key, getCurrentState(), undefined, customVariables);
|
||||
const customAppVariables = { ...getCurrentState().variables };
|
||||
const key = resolveReferences(event.key, getCurrentState(_ref.moduleName), undefined, customVariables);
|
||||
const customAppVariables = { ...getCurrentState(_ref.moduleName).variables };
|
||||
delete customAppVariables[key];
|
||||
return useCurrentStateStore.getState().actions.setCurrentState({
|
||||
variables: customAppVariables,
|
||||
});
|
||||
return useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
variables: customAppVariables,
|
||||
});
|
||||
}
|
||||
|
||||
case 'set-page-variable': {
|
||||
const key = resolveReferences(event.key, getCurrentState(), undefined, customVariables);
|
||||
const value = resolveReferences(event.value, getCurrentState(), undefined, customVariables);
|
||||
const key = resolveReferences(event.key, getCurrentState(_ref.moduleName), undefined, customVariables);
|
||||
const value = resolveReferences(event.value, getCurrentState(_ref.moduleName), undefined, customVariables);
|
||||
const customPageVariables = {
|
||||
...getCurrentState().page.variables,
|
||||
...getCurrentState(_ref.moduleName).page.variables,
|
||||
[key]: value,
|
||||
};
|
||||
return useCurrentStateStore.getState().actions.setCurrentState({
|
||||
page: {
|
||||
...getCurrentState().page,
|
||||
variables: customPageVariables,
|
||||
},
|
||||
});
|
||||
return useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
page: {
|
||||
...getCurrentState(_ref.moduleName).page,
|
||||
variables: customPageVariables,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
case 'unset-page-variable': {
|
||||
const key = resolveReferences(event.key, getCurrentState(), undefined, customVariables);
|
||||
const customPageVariables = _.omit(getCurrentState().page.variables, key);
|
||||
return useCurrentStateStore.getState().actions.setCurrentState({
|
||||
page: {
|
||||
...getCurrentState().page,
|
||||
variables: customPageVariables,
|
||||
},
|
||||
});
|
||||
const key = resolveReferences(event.key, getCurrentState(_ref.moduleName), undefined, customVariables);
|
||||
const customPageVariables = _.omit(getCurrentState(_ref.moduleName).page.variables, key);
|
||||
return useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
page: {
|
||||
...getCurrentState(_ref.moduleName).page,
|
||||
variables: customPageVariables,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
case 'control-component': {
|
||||
let component = Object.values(getCurrentState()?.components ?? {}).filter(
|
||||
let component = Object.values(getCurrentState(_ref.moduleName)?.components ?? {}).filter(
|
||||
(component) => component.id === event.componentId
|
||||
)[0];
|
||||
let action = '';
|
||||
|
|
@ -579,8 +618,10 @@ function executeActionWithDebounce(_ref, event, mode, customVariables) {
|
|||
// check if component id not found then try to find if its available as child widget else continue
|
||||
// with normal flow finding action
|
||||
if (component == undefined) {
|
||||
component = _ref.appDefinition.pages[getCurrentState()?.page?.id].components[event.componentId].component;
|
||||
const parent = Object.values(getCurrentState()?.components ?? {}).find(
|
||||
component =
|
||||
_ref.appDefinition.pages[getCurrentState(_ref.moduleName)?.page?.id].components[event.componentId]
|
||||
.component;
|
||||
const parent = Object.values(getCurrentState(_ref.moduleName)?.components ?? {}).find(
|
||||
(item) => item.id === component.parent
|
||||
);
|
||||
const child = Object.values(parent?.children).find((item) => item.id === event.componentId);
|
||||
|
|
@ -593,7 +634,7 @@ function executeActionWithDebounce(_ref, event, mode, customVariables) {
|
|||
}
|
||||
actionArguments = _.map(event.componentSpecificActionParams, (param) => ({
|
||||
...param,
|
||||
value: resolveReferences(param.value, getCurrentState(), undefined, customVariables),
|
||||
value: resolveReferences(param.value, getCurrentState(_ref.moduleName), undefined, customVariables),
|
||||
}));
|
||||
const actionPromise = action && action(...actionArguments.map((argument) => argument.value));
|
||||
return actionPromise ?? Promise.resolve();
|
||||
|
|
@ -604,7 +645,10 @@ function executeActionWithDebounce(_ref, event, mode, customVariables) {
|
|||
|
||||
// Don't allow switching to disabled page in editor as well as viewer
|
||||
if (!disabled) {
|
||||
_ref.switchPage(event.pageId, resolveReferences(event.queryParams, getCurrentState(), [], customVariables));
|
||||
_ref.switchPage(
|
||||
event.pageId,
|
||||
resolveReferences(event.queryParams, getCurrentState(_ref.moduleName), [], customVariables)
|
||||
);
|
||||
}
|
||||
if (_ref.appDefinition.pages[event.pageId]) {
|
||||
if (disabled) {
|
||||
|
|
@ -618,7 +662,10 @@ function executeActionWithDebounce(_ref, event, mode, customVariables) {
|
|||
},
|
||||
},
|
||||
};
|
||||
useCurrentStateStore.getState().actions.setErrors(generalProps);
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useCurrentStateStore.getState()
|
||||
.actions.setErrors(generalProps);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -641,44 +688,53 @@ export async function onEvent(_ref, eventName, events, options = {}, mode = 'edi
|
|||
|
||||
if (eventName === 'onTrigger') {
|
||||
const { component, queryId, queryName, parameters } = options;
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
components: {
|
||||
...getCurrentState().components,
|
||||
[component.name]: {
|
||||
...getCurrentState().components[component.name],
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
components: {
|
||||
...getCurrentState(_ref.moduleName).components,
|
||||
[component.name]: {
|
||||
...getCurrentState(_ref.moduleName).components[component.name],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
runQuery(_ref, queryId, queryName, true, mode, parameters);
|
||||
}
|
||||
|
||||
if (eventName === 'onCalendarEventSelect') {
|
||||
const { component, calendarEvent } = options;
|
||||
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
components: {
|
||||
...getCurrentState().components,
|
||||
[component.name]: {
|
||||
...getCurrentState().components[component.name],
|
||||
selectedEvent: { ...calendarEvent },
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
components: {
|
||||
...getCurrentState(_ref.moduleName).components,
|
||||
[component.name]: {
|
||||
...getCurrentState(_ref.moduleName).components[component.name],
|
||||
selectedEvent: { ...calendarEvent },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
executeActionsForEventId(_ref, 'onCalendarEventSelect', events, mode, customVariables);
|
||||
}
|
||||
|
||||
if (eventName === 'onCalendarSlotSelect') {
|
||||
const { component, selectedSlots } = options;
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
components: {
|
||||
...getCurrentState().components,
|
||||
[component.name]: {
|
||||
...getCurrentState().components[component.name],
|
||||
selectedSlots,
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
components: {
|
||||
...getCurrentState(_ref.moduleName).components,
|
||||
[component.name]: {
|
||||
...getCurrentState(_ref.moduleName).components[component.name],
|
||||
selectedSlots,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
executeActionsForEventId(_ref, 'onCalendarSlotSelect', events, mode, customVariables);
|
||||
}
|
||||
|
|
@ -828,9 +884,9 @@ export function getQueryVariables(options, state) {
|
|||
}
|
||||
|
||||
export function previewQuery(_ref, query, calledFromQuery = false, parameters = {}, hasParamSupport = false) {
|
||||
const options = getQueryVariables(query.options, getCurrentState());
|
||||
const options = getQueryVariables(query.options, getCurrentState(_ref.moduleName));
|
||||
|
||||
const queryPanelState = useQueryPanelStore.getState();
|
||||
const queryPanelState = useSuperStore.getState().modules[_ref.moduleName].useQueryPanelStore.getState();
|
||||
const { queryPreviewData } = queryPanelState;
|
||||
const { setPreviewLoading, setPreviewData } = queryPanelState.actions;
|
||||
|
||||
|
|
@ -862,14 +918,14 @@ export function previewQuery(_ref, query, calledFromQuery = false, parameters =
|
|||
hasParamSupport
|
||||
);
|
||||
} else if (query.kind === 'tooljetdb') {
|
||||
queryExecutionPromise = tooljetDbOperations.perform(query, getCurrentState());
|
||||
queryExecutionPromise = tooljetDbOperations.perform(query, getCurrentState(_ref.moduleName));
|
||||
} else if (query.kind === 'runpy') {
|
||||
queryExecutionPromise = executeRunPycode(_ref, query.options.code, query, true, 'edit');
|
||||
} else {
|
||||
queryExecutionPromise = dataqueryService.preview(
|
||||
query,
|
||||
options,
|
||||
useAppVersionStore.getState().editingVersion?.id
|
||||
useSuperStore.getState().modules[_ref.moduleName].useAppVersionStore.getState().editingVersion?.id
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -944,15 +1000,19 @@ export function previewQuery(_ref, query, calledFromQuery = false, parameters =
|
|||
}
|
||||
|
||||
export function runQuery(_ref, queryId, queryName, confirmed = undefined, mode = 'edit', parameters = {}) {
|
||||
const query = useDataQueriesStore.getState().dataQueries.find((query) => query.id === queryId);
|
||||
const queryEvents = useAppDataStore
|
||||
const query = useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useDataQueriesStore.getState()
|
||||
.dataQueries.find((query) => query.id === queryId);
|
||||
const queryEvents = useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useAppDataStore.getState()
|
||||
.events.filter((event) => event.target === 'data_query' && event.sourceId === queryId);
|
||||
|
||||
let dataQuery = {};
|
||||
|
||||
// const { setPreviewLoading, setPreviewData } = useQueryPanelStore.getState().actions;
|
||||
const queryPanelState = useQueryPanelStore.getState();
|
||||
// const { setPreviewLoading, setPreviewData } = useSuperStore.getState().modules[_ref.moduleName].useQueryPanelStore.getState().actions;
|
||||
const queryPanelState = useSuperStore.getState().modules[_ref.moduleName].useQueryPanelStore.getState();
|
||||
const { queryPreviewData } = queryPanelState;
|
||||
const { setPreviewLoading, setPreviewData } = queryPanelState.actions;
|
||||
if (parameters?.shouldSetPreviewData) {
|
||||
|
|
@ -967,11 +1027,12 @@ export function runQuery(_ref, queryId, queryName, confirmed = undefined, mode =
|
|||
return;
|
||||
}
|
||||
|
||||
const options = getQueryVariables(dataQuery.options, getCurrentState());
|
||||
const options = getQueryVariables(dataQuery.options, getCurrentState(_ref.moduleName));
|
||||
|
||||
if (dataQuery.options?.requestConfirmation) {
|
||||
const queryConfirmationList = useEditorStore.getState().queryConfirmationList
|
||||
? [...useEditorStore.getState().queryConfirmationList]
|
||||
const queryConfirmationList = useSuperStore.getState().modules[_ref.moduleName].useEditorStore.getState()
|
||||
.queryConfirmationList
|
||||
? [...useSuperStore.getState().modules[_ref.moduleName].useEditorStore.getState().queryConfirmationList]
|
||||
: [];
|
||||
|
||||
const queryConfirmation = {
|
||||
|
|
@ -993,25 +1054,28 @@ export function runQuery(_ref, queryId, queryName, confirmed = undefined, mode =
|
|||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
return new Promise(function (resolve, reject) {
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
queries: {
|
||||
...getCurrentState().queries,
|
||||
[queryName]: {
|
||||
...getCurrentState().queries[queryName],
|
||||
isLoading: true,
|
||||
data: [],
|
||||
rawData: [],
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
queries: {
|
||||
...getCurrentState(_ref.moduleName).queries,
|
||||
[queryName]: {
|
||||
...getCurrentState(_ref.moduleName).queries[queryName],
|
||||
isLoading: true,
|
||||
data: [],
|
||||
rawData: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: {},
|
||||
});
|
||||
errors: {},
|
||||
});
|
||||
let queryExecutionPromise = null;
|
||||
if (query.kind === 'runjs') {
|
||||
queryExecutionPromise = executeMultilineJS(_self, query.options.code, query?.id, false, mode, parameters);
|
||||
} else if (query.kind === 'runpy') {
|
||||
queryExecutionPromise = executeRunPycode(_self, query.options.code, query, false, mode);
|
||||
} else if (query.kind === 'tooljetdb') {
|
||||
queryExecutionPromise = tooljetDbOperations.perform(query, getCurrentState());
|
||||
queryExecutionPromise = tooljetDbOperations.perform(query, getCurrentState(_ref.moduleName));
|
||||
} else {
|
||||
queryExecutionPromise = dataqueryService.run(queryId, options, query?.options);
|
||||
}
|
||||
|
|
@ -1066,33 +1130,39 @@ export function runQuery(_ref, queryId, queryName, confirmed = undefined, mode =
|
|||
setPreviewData(errorData);
|
||||
}
|
||||
// errorData = query.kind === 'runpy' ? data.data : data;
|
||||
useCurrentStateStore.getState().actions.setErrors({
|
||||
[queryName]: {
|
||||
type: 'query',
|
||||
kind: query.kind,
|
||||
data: errorData,
|
||||
options: options,
|
||||
},
|
||||
});
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useCurrentStateStore.getState()
|
||||
.actions.setErrors({
|
||||
[queryName]: {
|
||||
type: 'query',
|
||||
kind: query.kind,
|
||||
data: errorData,
|
||||
options: options,
|
||||
},
|
||||
});
|
||||
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
queries: {
|
||||
...getCurrentState().queries,
|
||||
[queryName]: _.assign(
|
||||
{
|
||||
...getCurrentState().queries[queryName],
|
||||
isLoading: false,
|
||||
},
|
||||
query.kind === 'restapi'
|
||||
? {
|
||||
request: data.data.requestObject,
|
||||
response: data.data.responseObject,
|
||||
responseHeaders: data.data.responseHeaders,
|
||||
}
|
||||
: {}
|
||||
),
|
||||
},
|
||||
});
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
queries: {
|
||||
...getCurrentState(_ref.moduleName).queries,
|
||||
[queryName]: _.assign(
|
||||
{
|
||||
...getCurrentState(_ref.moduleName).queries[queryName],
|
||||
isLoading: false,
|
||||
},
|
||||
query.kind === 'restapi'
|
||||
? {
|
||||
request: data.data.requestObject,
|
||||
response: data.data.responseObject,
|
||||
responseHeaders: data.data.responseHeaders,
|
||||
}
|
||||
: {}
|
||||
),
|
||||
},
|
||||
});
|
||||
resolve(data);
|
||||
onEvent(_self, 'onDataQueryFailure', queryEvents);
|
||||
if (mode !== 'view') {
|
||||
|
|
@ -1119,23 +1189,29 @@ export function runQuery(_ref, queryId, queryName, confirmed = undefined, mode =
|
|||
'edit'
|
||||
);
|
||||
if (finalData.status === 'failed') {
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
queries: {
|
||||
...getCurrentState().queries,
|
||||
[queryName]: {
|
||||
...getCurrentState().queries[queryName],
|
||||
isLoading: false,
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
queries: {
|
||||
...getCurrentState(_ref.moduleName).queries,
|
||||
[queryName]: {
|
||||
...getCurrentState(_ref.moduleName).queries[queryName],
|
||||
isLoading: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
useCurrentStateStore.getState().actions.setErrors({
|
||||
[queryName]: {
|
||||
type: 'transformations',
|
||||
data: finalData,
|
||||
options: options,
|
||||
},
|
||||
});
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useCurrentStateStore.getState()
|
||||
.actions.setErrors({
|
||||
[queryName]: {
|
||||
type: 'transformations',
|
||||
data: finalData,
|
||||
options: options,
|
||||
},
|
||||
});
|
||||
resolve(finalData);
|
||||
onEvent(_self, 'onDataQueryFailure', queryEvents);
|
||||
return;
|
||||
|
|
@ -1148,61 +1224,69 @@ export function runQuery(_ref, queryId, queryName, confirmed = undefined, mode =
|
|||
duration: notificationDuration,
|
||||
});
|
||||
}
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
queries: {
|
||||
...getCurrentState().queries,
|
||||
[queryName]: _.assign(
|
||||
{
|
||||
...getCurrentState().queries[queryName],
|
||||
isLoading: false,
|
||||
data: finalData,
|
||||
rawData,
|
||||
},
|
||||
query.kind === 'restapi'
|
||||
? {
|
||||
request: data.request,
|
||||
response: data.response,
|
||||
responseHeaders: data.responseHeaders,
|
||||
}
|
||||
: {}
|
||||
),
|
||||
},
|
||||
// Used to generate logs
|
||||
succededQuery: {
|
||||
[queryName]: {
|
||||
type: 'query',
|
||||
kind: query.kind,
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
queries: {
|
||||
...getCurrentState(_ref.moduleName).queries,
|
||||
[queryName]: _.assign(
|
||||
{
|
||||
...getCurrentState(_ref.moduleName).queries[queryName],
|
||||
isLoading: false,
|
||||
data: finalData,
|
||||
rawData,
|
||||
},
|
||||
query.kind === 'restapi'
|
||||
? {
|
||||
request: data.request,
|
||||
response: data.response,
|
||||
responseHeaders: data.responseHeaders,
|
||||
}
|
||||
: {}
|
||||
),
|
||||
},
|
||||
},
|
||||
});
|
||||
// Used to generate logs
|
||||
succededQuery: {
|
||||
[queryName]: {
|
||||
type: 'query',
|
||||
kind: query.kind,
|
||||
},
|
||||
},
|
||||
});
|
||||
resolve({ status: 'ok', data: finalData });
|
||||
onEvent(_self, 'onDataQuerySuccess', queryEvents, mode);
|
||||
}
|
||||
})
|
||||
.catch(({ error }) => {
|
||||
if (mode !== 'view') toast.error(error ?? 'Unknown error');
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
queries: {
|
||||
...getCurrentState().queries,
|
||||
[queryName]: {
|
||||
isLoading: false,
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
queries: {
|
||||
...getCurrentState(_ref.moduleName).queries,
|
||||
[queryName]: {
|
||||
isLoading: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
resolve({ status: 'failed', message: error });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function setTablePageIndex(tableId, index) {
|
||||
export function setTablePageIndex(tableId, index, _ref) {
|
||||
if (_.isEmpty(tableId)) {
|
||||
console.log('No table is associated with this event.');
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const table = Object.entries(getCurrentState().components).filter((entry) => entry[1].id === tableId)[0][1];
|
||||
const newPageIndex = resolveReferences(index, getCurrentState());
|
||||
const table = Object.entries(getCurrentState(_ref.moduleName).components).filter(
|
||||
(entry) => entry[1].id === tableId
|
||||
)[0][1];
|
||||
const newPageIndex = resolveReferences(index, getCurrentState(_ref.moduleName));
|
||||
table.setPage(newPageIndex ?? 1);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
|
@ -1223,10 +1307,10 @@ for computing component state. It replaces the previous try-catch block with
|
|||
a more efficient approach, precomputing the parent component types and using
|
||||
conditional checks for better performance and error handling.*/
|
||||
|
||||
export function computeComponentState(components = {}) {
|
||||
export function computeComponentState(components = {}, moduleName) {
|
||||
try {
|
||||
let componentState = {};
|
||||
const currentComponents = getCurrentState().components;
|
||||
const currentComponents = getCurrentState(moduleName).components;
|
||||
|
||||
// Precompute parent component types
|
||||
const parentComponentTypes = {};
|
||||
|
|
@ -1263,14 +1347,17 @@ export function computeComponentState(components = {}) {
|
|||
}
|
||||
});
|
||||
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
components: {
|
||||
...componentState,
|
||||
},
|
||||
});
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
components: {
|
||||
...componentState,
|
||||
},
|
||||
});
|
||||
|
||||
return new Promise((resolve) => {
|
||||
useEditorStore.getState().actions.updateEditorState({
|
||||
useSuperStore.getState().modules[moduleName].useEditorStore.getState().actions.updateEditorState({
|
||||
defaultComponentStateComputed: true,
|
||||
});
|
||||
resolve();
|
||||
|
|
@ -1294,14 +1381,17 @@ export const getSvgIcon = (key, height = 50, width = 50, iconFile = undefined, s
|
|||
};
|
||||
|
||||
export const debuggerActions = {
|
||||
error: (errors) => {
|
||||
useCurrentStateStore.getState().actions.setErrors({
|
||||
...errors,
|
||||
});
|
||||
error: (errors, moduleName) => {
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useCurrentStateStore.getState()
|
||||
.actions.setErrors({
|
||||
...errors,
|
||||
});
|
||||
},
|
||||
|
||||
flush: () => {
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
flush: (moduleName) => {
|
||||
useSuperStore.getState().modules[moduleName].useCurrentStateStore.getState().actions.setCurrentState({
|
||||
errors: {},
|
||||
});
|
||||
},
|
||||
|
|
@ -1395,8 +1485,8 @@ export const debuggerActions = {
|
|||
});
|
||||
return querySuccesslogs;
|
||||
},
|
||||
flushAllLog: () => {
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
flushAllLog: (moduleName) => {
|
||||
useSuperStore.getState().modules[moduleName].useCurrentStateStore.getState().actions.setCurrentState({
|
||||
succededQuery: {},
|
||||
});
|
||||
},
|
||||
|
|
@ -1437,7 +1527,8 @@ export const cloneComponents = (
|
|||
currentPageId,
|
||||
updateAppDefinition,
|
||||
isCloning = true,
|
||||
isCut = false
|
||||
isCut = false,
|
||||
moduleName
|
||||
) => {
|
||||
if (selectedComponents.length < 1) return getSelectedText();
|
||||
|
||||
|
|
@ -1504,7 +1595,7 @@ export const cloneComponents = (
|
|||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
useEditorStore.getState().actions.updateEditorState({
|
||||
useSuperStore.getState().modules[moduleName].useEditorStore.getState().actions.updateEditorState({
|
||||
currentSidebarTab: 2,
|
||||
});
|
||||
resolve();
|
||||
|
|
@ -1814,8 +1905,11 @@ function convertMapSet(obj) {
|
|||
}
|
||||
}
|
||||
|
||||
export const checkExistingQueryName = (newName) =>
|
||||
useDataQueriesStore.getState().dataQueries.some((query) => query.name === newName);
|
||||
export const checkExistingQueryName = (newName, moduleName) =>
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useDataQueriesStore.getState()
|
||||
.dataQueries.some((query) => query.name === newName);
|
||||
|
||||
export const runQueries = (queries, _ref) => {
|
||||
queries.forEach((query) => {
|
||||
|
|
@ -1825,30 +1919,33 @@ export const runQueries = (queries, _ref) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const computeQueryState = (queries) => {
|
||||
export const computeQueryState = (queries, moduleName) => {
|
||||
let queryState = {};
|
||||
queries.forEach((query) => {
|
||||
if (query.plugin?.plugin_id) {
|
||||
queryState[query.name] = {
|
||||
...query.plugin.manifest_file.data?.source?.exposedVariables,
|
||||
kind: query.plugin.manifest_file.data.source.kind,
|
||||
...getCurrentState().queries[query.name],
|
||||
...getCurrentState(moduleName).queries[query.name],
|
||||
};
|
||||
} else {
|
||||
queryState[query.name] = {
|
||||
...DataSourceTypes.find((source) => source.kind === query.kind)?.exposedVariables,
|
||||
kind: DataSourceTypes.find((source) => source.kind === query.kind)?.kind,
|
||||
...getCurrentState()?.queries[query.name],
|
||||
...getCurrentState(moduleName)?.queries[query.name],
|
||||
};
|
||||
}
|
||||
});
|
||||
const hasDiffQueryState = !_.isEqual(getCurrentState()?.queries, queryState);
|
||||
const hasDiffQueryState = !_.isEqual(getCurrentState(moduleName)?.queries, queryState);
|
||||
if (hasDiffQueryState) {
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
queries: {
|
||||
...queryState,
|
||||
},
|
||||
});
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
queries: {
|
||||
...queryState,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import JSON5 from 'json5';
|
|||
import { previewQuery, executeAction } from '@/_helpers/appUtils';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { authenticationService } from '@/_services/authentication.service';
|
||||
|
||||
import { useSuperStore } from '../_stores/superStore';
|
||||
import { useDataQueriesStore } from '@/_stores/dataQueriesStore';
|
||||
import { getCurrentState } from '@/_stores/currentStateStore';
|
||||
import { getWorkspaceIdOrSlugFromURL, getSubpath, returnWorkspaceIdIfNeed } from './routes';
|
||||
|
|
@ -418,7 +418,7 @@ export async function executeMultilineJS(
|
|||
parameters = {},
|
||||
hasParamSupport = false
|
||||
) {
|
||||
const currentState = getCurrentState();
|
||||
const currentState = getCurrentState(_ref.moduleName);
|
||||
let result = {},
|
||||
error = null;
|
||||
|
||||
|
|
@ -429,7 +429,10 @@ export async function executeMultilineJS(
|
|||
|
||||
const actions = generateAppActions(_ref, queryId, mode, isPreview);
|
||||
|
||||
const queryDetails = useDataQueriesStore.getState().dataQueries.find((q) => q.id === queryId);
|
||||
const queryDetails = useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useDataQueriesStore.getState()
|
||||
.dataQueries.find((q) => q.id === queryId);
|
||||
hasParamSupport = !hasParamSupport ? queryDetails?.options?.hasParamSupport : hasParamSupport;
|
||||
|
||||
const defaultParams =
|
||||
|
|
@ -459,7 +462,10 @@ export async function executeMultilineJS(
|
|||
params = {};
|
||||
}
|
||||
const processedParams = {};
|
||||
const query = useDataQueriesStore.getState().dataQueries.find((q) => q.name === key);
|
||||
const query = useSuperStore
|
||||
.getState()
|
||||
.modules.modules[_ref.moduleName].useDataQueriesStore.getState()
|
||||
.dataQueries.find((q) => q.name === key);
|
||||
query.options.parameters?.forEach((arg) => (processedParams[arg.name] = params[arg.name]));
|
||||
return actions.runQuery(key, processedParams);
|
||||
},
|
||||
|
|
@ -576,14 +582,17 @@ export const generateAppActions = (_ref, queryId, mode, isPreview = false) => {
|
|||
: {};
|
||||
|
||||
const runQuery = (queryName = '', parameters) => {
|
||||
const query = useDataQueriesStore.getState().dataQueries.find((query) => {
|
||||
const isFound = query.name === queryName;
|
||||
if (isPreview) {
|
||||
return isFound;
|
||||
} else {
|
||||
return isFound && isQueryRunnable(query);
|
||||
}
|
||||
});
|
||||
const query = useSuperStore
|
||||
.getState()
|
||||
.modules[_ref.moduleName].useDataQueriesStore.getState()
|
||||
.dataQueries.find((query) => {
|
||||
const isFound = query.name === queryName;
|
||||
if (isPreview) {
|
||||
return isFound;
|
||||
} else {
|
||||
return isFound && isQueryRunnable(query);
|
||||
}
|
||||
});
|
||||
|
||||
const processedParams = {};
|
||||
if (_.isEmpty(query) || queryId === query?.id) {
|
||||
|
|
|
|||
|
|
@ -1,132 +1,147 @@
|
|||
import { appVersionService } from '@/_services';
|
||||
import { create, zustandDevTools } from './utils';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { useContext } from 'react';
|
||||
import { useSuperStore } from './superStore';
|
||||
import { ModuleContext } from '../_contexts/ModuleContext';
|
||||
|
||||
const initialState = {
|
||||
editingVersion: null,
|
||||
currentUser: null,
|
||||
apps: [],
|
||||
appName: null,
|
||||
slug: null,
|
||||
isPublic: null,
|
||||
isMaintenanceOn: null,
|
||||
organizationId: null,
|
||||
currentVersionId: null,
|
||||
userId: null,
|
||||
app: {},
|
||||
components: [],
|
||||
pages: [],
|
||||
layouts: [],
|
||||
events: [],
|
||||
eventHandlers: [],
|
||||
appDefinitionDiff: null,
|
||||
appDiffOptions: {},
|
||||
isSaving: false,
|
||||
appId: null,
|
||||
areOthersOnSameVersionAndPage: false,
|
||||
appVersionPreviewLink: null,
|
||||
};
|
||||
export function createAppDataStore(moduleName) {
|
||||
const initialState = {
|
||||
editingVersion: null,
|
||||
currentUser: null,
|
||||
apps: [],
|
||||
appName: null,
|
||||
slug: null,
|
||||
isPublic: null,
|
||||
isMaintenanceOn: null,
|
||||
organizationId: null,
|
||||
currentVersionId: null,
|
||||
userId: null,
|
||||
app: {},
|
||||
components: [],
|
||||
pages: [],
|
||||
layouts: [],
|
||||
events: [],
|
||||
eventHandlers: [],
|
||||
appDefinitionDiff: null,
|
||||
appDiffOptions: {},
|
||||
isSaving: false,
|
||||
appId: null,
|
||||
areOthersOnSameVersionAndPage: false,
|
||||
appVersionPreviewLink: null,
|
||||
moduleName,
|
||||
};
|
||||
return create(
|
||||
zustandDevTools(
|
||||
(set, get) => ({
|
||||
...initialState,
|
||||
actions: {
|
||||
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) => {
|
||||
get().actions.setIsSaving(true);
|
||||
const isComponentCutProcess = get().appDiffOptions?.componentCut === true;
|
||||
|
||||
export const useAppDataStore = create(
|
||||
zustandDevTools(
|
||||
(set, get) => ({
|
||||
...initialState,
|
||||
actions: {
|
||||
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) => {
|
||||
useAppDataStore.getState().actions.setIsSaving(true);
|
||||
const isComponentCutProcess = get().appDiffOptions?.componentCut === true;
|
||||
appVersionService
|
||||
.autoSaveApp(
|
||||
appId,
|
||||
versionId,
|
||||
appDefinitionDiff.updateDiff,
|
||||
appDefinitionDiff.type,
|
||||
pageId,
|
||||
appDefinitionDiff.operation,
|
||||
isUserSwitchedVersion,
|
||||
isComponentCutProcess
|
||||
)
|
||||
.then(() => {
|
||||
get().actions.setIsSaving(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
get().actions.setIsSaving(false);
|
||||
reject(error);
|
||||
})
|
||||
.finally(() => resolve());
|
||||
});
|
||||
},
|
||||
updateAppVersionEventHandlers: async (events, updateType = 'update') => {
|
||||
get().actions.setIsSaving(true);
|
||||
const appId = get().appId;
|
||||
const versionId = get().currentVersionId;
|
||||
|
||||
appVersionService
|
||||
.autoSaveApp(
|
||||
appId,
|
||||
versionId,
|
||||
appDefinitionDiff.updateDiff,
|
||||
appDefinitionDiff.type,
|
||||
pageId,
|
||||
appDefinitionDiff.operation,
|
||||
isUserSwitchedVersion,
|
||||
isComponentCutProcess
|
||||
)
|
||||
.then(() => {
|
||||
useAppDataStore.getState().actions.setIsSaving(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
useAppDataStore.getState().actions.setIsSaving(false);
|
||||
reject(error);
|
||||
})
|
||||
.finally(() => resolve());
|
||||
});
|
||||
},
|
||||
updateAppVersionEventHandlers: async (events, updateType = 'update') => {
|
||||
useAppDataStore.getState().actions.setIsSaving(true);
|
||||
const appId = get().appId;
|
||||
const versionId = get().currentVersionId;
|
||||
const response = await appVersionService.saveAppVersionEventHandlers(appId, versionId, events, updateType);
|
||||
|
||||
const response = await appVersionService.saveAppVersionEventHandlers(appId, versionId, events, updateType);
|
||||
get().actions.setIsSaving(false);
|
||||
const updatedEvents = get().events;
|
||||
|
||||
useAppDataStore.getState().actions.setIsSaving(false);
|
||||
const updatedEvents = get().events;
|
||||
|
||||
updatedEvents.forEach((e, index) => {
|
||||
const toUpdate = response.find((r) => r.id === e.id);
|
||||
if (toUpdate) {
|
||||
updatedEvents[index] = toUpdate;
|
||||
}
|
||||
});
|
||||
|
||||
set(() => ({ events: updatedEvents }));
|
||||
},
|
||||
|
||||
createAppVersionEventHandlers: async (event) => {
|
||||
useAppDataStore.getState().actions.setIsSaving(true);
|
||||
const appId = get().appId;
|
||||
const versionId = get().currentVersionId;
|
||||
|
||||
const updatedEvents = get().events;
|
||||
const response = await appVersionService.createAppVersionEventHandler(appId, versionId, event);
|
||||
useAppDataStore.getState().actions.setIsSaving(false);
|
||||
updatedEvents.push(response);
|
||||
|
||||
set(() => ({ events: updatedEvents }));
|
||||
},
|
||||
|
||||
deleteAppVersionEventHandler: async (eventId) => {
|
||||
useAppDataStore.getState().actions.setIsSaving(true);
|
||||
const appId = get().appId;
|
||||
const versionId = get().currentVersionId;
|
||||
|
||||
const updatedEvents = get().events;
|
||||
|
||||
const response = await appVersionService.deleteAppVersionEventHandler(appId, versionId, eventId);
|
||||
useAppDataStore.getState().actions.setIsSaving(false);
|
||||
if (response?.affected === 1) {
|
||||
updatedEvents.splice(
|
||||
updatedEvents.findIndex((e) => e.id === eventId),
|
||||
1
|
||||
);
|
||||
updatedEvents.forEach((e, index) => {
|
||||
const toUpdate = response.find((r) => r.id === e.id);
|
||||
if (toUpdate) {
|
||||
updatedEvents[index] = toUpdate;
|
||||
}
|
||||
});
|
||||
|
||||
set(() => ({ events: updatedEvents }));
|
||||
}
|
||||
},
|
||||
autoUpdateEventStore: async (versionId) => {
|
||||
const appId = get().appId;
|
||||
const response = await appVersionService.findAllEventsWithSourceId(appId, versionId);
|
||||
},
|
||||
|
||||
set(() => ({ events: response }));
|
||||
createAppVersionEventHandlers: async (event) => {
|
||||
get().actions.setIsSaving(true);
|
||||
const appId = get().appId;
|
||||
const versionId = get().currentVersionId;
|
||||
|
||||
const updatedEvents = get().events;
|
||||
const response = await appVersionService.createAppVersionEventHandler(appId, versionId, event);
|
||||
get().actions.setIsSaving(false);
|
||||
updatedEvents.push(response);
|
||||
|
||||
set(() => ({ events: updatedEvents }));
|
||||
},
|
||||
|
||||
deleteAppVersionEventHandler: async (eventId) => {
|
||||
get().actions.setIsSaving(true);
|
||||
const appId = get().appId;
|
||||
const versionId = get().currentVersionId;
|
||||
|
||||
const updatedEvents = get().events;
|
||||
|
||||
const response = await appVersionService.deleteAppVersionEventHandler(appId, versionId, eventId);
|
||||
get().actions.setIsSaving(false);
|
||||
if (response?.affected === 1) {
|
||||
updatedEvents.splice(
|
||||
updatedEvents.findIndex((e) => e.id === eventId),
|
||||
1
|
||||
);
|
||||
|
||||
set(() => ({ events: updatedEvents }));
|
||||
}
|
||||
},
|
||||
autoUpdateEventStore: async (versionId) => {
|
||||
const appId = get().appId;
|
||||
const response = await appVersionService.findAllEventsWithSourceId(appId, versionId);
|
||||
|
||||
set(() => ({ events: response }));
|
||||
},
|
||||
setIsSaving: (isSaving) => set(() => ({ isSaving })),
|
||||
setAppId: (appId) => set(() => ({ appId })),
|
||||
setAppPreviewLink: (appVersionPreviewLink) => set(() => ({ appVersionPreviewLink })),
|
||||
},
|
||||
setIsSaving: (isSaving) => set(() => ({ isSaving })),
|
||||
setAppId: (appId) => set(() => ({ appId })),
|
||||
setAppPreviewLink: (appVersionPreviewLink) => set(() => ({ appVersionPreviewLink })),
|
||||
},
|
||||
}),
|
||||
{ name: 'App Data Store' }
|
||||
)
|
||||
);
|
||||
}),
|
||||
{ name: 'App Data Store' }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export const useAppDataStore = (callback, shallow) => {
|
||||
const moduleName = useContext(ModuleContext);
|
||||
|
||||
if (!moduleName) throw Error('module context not available');
|
||||
|
||||
const _useAppDataStore = useSuperStore((state) => state.modules[moduleName].useAppDataStore);
|
||||
|
||||
return _useAppDataStore(callback, shallow);
|
||||
};
|
||||
|
||||
export const useEditingVersion = () => useAppDataStore((state) => state.editingVersion, shallow);
|
||||
export const useIsSaving = () => useAppDataStore((state) => state.isSaving, shallow);
|
||||
|
|
|
|||
|
|
@ -1,33 +1,49 @@
|
|||
import { create, zustandDevTools } from './utils';
|
||||
import { useContext } from 'react';
|
||||
import { useSuperStore } from './superStore';
|
||||
import { ModuleContext } from '../_contexts/ModuleContext';
|
||||
|
||||
const initialState = {
|
||||
editingVersion: null,
|
||||
isUserEditingTheVersion: false,
|
||||
releasedVersionId: null,
|
||||
isVersionReleased: false,
|
||||
appVersions: [],
|
||||
export function createAppVersionStore(moduleName) {
|
||||
const initialState = {
|
||||
editingVersion: null,
|
||||
isUserEditingTheVersion: false,
|
||||
releasedVersionId: null,
|
||||
isVersionReleased: false,
|
||||
appVersions: [],
|
||||
moduleName,
|
||||
};
|
||||
|
||||
return create(
|
||||
zustandDevTools(
|
||||
(set, get) => ({
|
||||
...initialState,
|
||||
actions: {
|
||||
updateEditingVersion: (version) =>
|
||||
set({ editingVersion: version, isVersionReleased: get().releasedVersionId === version?.id }),
|
||||
enableReleasedVersionPopupState: () => set({ isUserEditingTheVersion: true }),
|
||||
disableReleasedVersionPopupState: () => set({ isUserEditingTheVersion: false }),
|
||||
updateReleasedVersionId: (versionId) =>
|
||||
set({
|
||||
releasedVersionId: versionId,
|
||||
isVersionReleased: get().editingVersion?.id ? get().editingVersion?.id === versionId : false,
|
||||
}),
|
||||
setAppVersions: (versions) => set({ appVersions: versions }),
|
||||
},
|
||||
}),
|
||||
{ name: 'App Version Manager Store' }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export const useAppVersionStore = (callback, shallow) => {
|
||||
const moduleName = useContext(ModuleContext);
|
||||
|
||||
if (!moduleName) throw Error('module context not available');
|
||||
|
||||
const _useAppVersionStore = useSuperStore((state) => state.modules[moduleName].useAppVersionStore);
|
||||
|
||||
return _useAppVersionStore(callback, shallow);
|
||||
};
|
||||
|
||||
export const useAppVersionStore = create(
|
||||
zustandDevTools(
|
||||
(set, get) => ({
|
||||
...initialState,
|
||||
actions: {
|
||||
updateEditingVersion: (version) =>
|
||||
set({ editingVersion: version, isVersionReleased: get().releasedVersionId === version?.id }),
|
||||
enableReleasedVersionPopupState: () => set({ isUserEditingTheVersion: true }),
|
||||
disableReleasedVersionPopupState: () => set({ isUserEditingTheVersion: false }),
|
||||
updateReleasedVersionId: (versionId) =>
|
||||
set({
|
||||
releasedVersionId: versionId,
|
||||
isVersionReleased: get().editingVersion?.id ? get().editingVersion?.id === versionId : false,
|
||||
}),
|
||||
setAppVersions: (versions) => set({ appVersions: versions }),
|
||||
},
|
||||
}),
|
||||
{ name: 'App Version Manager Store' }
|
||||
)
|
||||
);
|
||||
|
||||
export const useAppVersionActions = () => useAppVersionStore((state) => state.actions);
|
||||
export const useAppVersionState = () => useAppVersionStore((state) => state);
|
||||
|
|
|
|||
|
|
@ -1,41 +1,57 @@
|
|||
import { shallow } from 'zustand/shallow';
|
||||
import { create, zustandDevTools } from './utils';
|
||||
import { omit } from 'lodash';
|
||||
import { useContext } from 'react';
|
||||
import { useSuperStore } from './superStore';
|
||||
import { ModuleContext } from '../_contexts/ModuleContext';
|
||||
|
||||
const initialState = {
|
||||
queries: {},
|
||||
components: {},
|
||||
globals: {
|
||||
theme: { name: 'light' },
|
||||
urlparams: null,
|
||||
},
|
||||
errors: {},
|
||||
variables: {},
|
||||
client: {},
|
||||
server: {},
|
||||
page: {
|
||||
handle: '',
|
||||
export function createCurrentStateStore(moduleName) {
|
||||
const initialState = {
|
||||
queries: {},
|
||||
components: {},
|
||||
globals: {
|
||||
theme: { name: 'light' },
|
||||
urlparams: null,
|
||||
},
|
||||
errors: {},
|
||||
variables: {},
|
||||
},
|
||||
succededQuery: {},
|
||||
};
|
||||
client: {},
|
||||
server: {},
|
||||
page: {
|
||||
handle: '',
|
||||
variables: {},
|
||||
},
|
||||
succededQuery: {},
|
||||
moduleName,
|
||||
};
|
||||
|
||||
export const useCurrentStateStore = create(
|
||||
zustandDevTools(
|
||||
(set, get) => ({
|
||||
...initialState,
|
||||
actions: {
|
||||
setCurrentState: (currentState) => {
|
||||
set({ ...currentState }, false, { type: 'SET_CURRENT_STATE', currentState });
|
||||
return create(
|
||||
zustandDevTools(
|
||||
(set, get) => ({
|
||||
...initialState,
|
||||
actions: {
|
||||
setCurrentState: (currentState) => {
|
||||
set({ ...currentState }, false, { type: 'SET_CURRENT_STATE', currentState });
|
||||
},
|
||||
setErrors: (error) => {
|
||||
set({ errors: { ...get().errors, ...error } }, false, { type: 'SET_ERRORS', error });
|
||||
},
|
||||
},
|
||||
setErrors: (error) => {
|
||||
set({ errors: { ...get().errors, ...error } }, false, { type: 'SET_ERRORS', error });
|
||||
},
|
||||
},
|
||||
}),
|
||||
{ name: 'Current State' }
|
||||
)
|
||||
);
|
||||
}),
|
||||
{ name: 'Current State' }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export const useCurrentStateStore = (callback, shallow) => {
|
||||
const moduleName = useContext(ModuleContext);
|
||||
|
||||
if (!moduleName) throw Error('module context not available');
|
||||
|
||||
const _useCurrentStateStore = useSuperStore((state) => state.modules[moduleName].useCurrentStateStore);
|
||||
|
||||
return _useCurrentStateStore(callback, shallow);
|
||||
};
|
||||
|
||||
export const useCurrentState = () =>
|
||||
// Omitting 'actions' here because we don't want to expose it to user
|
||||
|
|
@ -55,6 +71,6 @@ export const useCurrentState = () =>
|
|||
};
|
||||
}, shallow);
|
||||
|
||||
export const getCurrentState = () => {
|
||||
return omit(useCurrentStateStore.getState(), 'actions');
|
||||
export const getCurrentState = (moduleName) => {
|
||||
return omit(useSuperStore.getState().modules[moduleName].useCurrentStateStore.getState(), 'actions');
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,353 +3,394 @@ import { getDefaultOptions } from './storeHelper';
|
|||
import { dataqueryService } from '@/_services';
|
||||
// import debounce from 'lodash/debounce';
|
||||
import { useAppDataStore } from '@/_stores/appDataStore';
|
||||
import { useQueryPanelStore } from '@/_stores/queryPanelStore';
|
||||
import { useAppVersionStore } from '@/_stores/appVersionStore';
|
||||
import { runQueries } from '@/_helpers/appUtils';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import _, { isEmpty, throttle } from 'lodash';
|
||||
import { useEditorStore } from './editorStore';
|
||||
import { useSuperStore } from './superStore';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { useCurrentStateStore } from './currentStateStore';
|
||||
import { useContext } from 'react';
|
||||
import { ModuleContext } from '../_contexts/ModuleContext';
|
||||
|
||||
const initialState = {
|
||||
dataQueries: [],
|
||||
sortBy: 'updated_at',
|
||||
sortOrder: 'desc',
|
||||
loadingDataQueries: true,
|
||||
isDeletingQueryInProcess: false,
|
||||
/** TODO: Below two params are primarily used only for websocket invocation post update. Can be removed onece websocket logic is revamped */
|
||||
// isCreatingQueryInProcess: false,
|
||||
creatingQueryInProcessId: null,
|
||||
isUpdatingQueryInProcess: false,
|
||||
/** When a 'Create Data Query' operation is in progress, rename/update API calls are cached in the variable. */
|
||||
queuedActions: {},
|
||||
};
|
||||
export function createDataQueriesStore(moduleName) {
|
||||
const initialState = {
|
||||
dataQueries: [],
|
||||
sortBy: 'updated_at',
|
||||
sortOrder: 'desc',
|
||||
loadingDataQueries: true,
|
||||
isDeletingQueryInProcess: false,
|
||||
/** TODO: Below two params are primarily used only for websocket invocation post update. Can be removed onece websocket logic is revamped */
|
||||
// isCreatingQueryInProcess: false,
|
||||
creatingQueryInProcessId: null,
|
||||
isUpdatingQueryInProcess: false,
|
||||
/** When a 'Create Data Query' operation is in progress, rename/update API calls are cached in the variable. */
|
||||
queuedActions: {},
|
||||
moduleName, // TODOS: change this
|
||||
};
|
||||
|
||||
export const useDataQueriesStore = create(
|
||||
zustandDevTools(
|
||||
(set, get) => ({
|
||||
...initialState,
|
||||
actions: {
|
||||
// TODO: Remove editor state while changing currentState
|
||||
fetchDataQueries: async (appVersionId, selectFirstQuery = false, runQueriesOnAppLoad = false, ref) => {
|
||||
set({ loadingDataQueries: true });
|
||||
const data = await dataqueryService.getAll(appVersionId);
|
||||
set((state) => ({
|
||||
dataQueries: sortByAttribute(data.data_queries, state.sortBy, state.sortOrder),
|
||||
loadingDataQueries: false,
|
||||
}));
|
||||
return create(
|
||||
zustandDevTools(
|
||||
(set, get) => ({
|
||||
...initialState,
|
||||
actions: {
|
||||
// TODO: Remove editor state while changing currentState
|
||||
fetchDataQueries: async (appVersionId, selectFirstQuery = false, runQueriesOnAppLoad = false, ref) => {
|
||||
set({ loadingDataQueries: true });
|
||||
const data = await dataqueryService.getAll(appVersionId);
|
||||
set((state) => ({
|
||||
dataQueries: sortByAttribute(data.data_queries, state.sortBy, state.sortOrder),
|
||||
loadingDataQueries: false,
|
||||
}));
|
||||
|
||||
if (data.data_queries.length !== 0) {
|
||||
const queryConfirmationList = [];
|
||||
const updatedQueries = {};
|
||||
const currentQueries = useCurrentStateStore.getState().queries;
|
||||
if (data.data_queries.length !== 0) {
|
||||
const queryConfirmationList = [];
|
||||
const updatedQueries = {};
|
||||
const currentQueries = useSuperStore
|
||||
.getState()
|
||||
.modules[get().moduleName].useCurrentStateStore.getState().queries;
|
||||
|
||||
data.data_queries.forEach(({ id, name, options }) => {
|
||||
updatedQueries[name] = _.merge(currentQueries[name], { id: id });
|
||||
if (options && options?.requestConfirmation && options?.runOnPageLoad) {
|
||||
queryConfirmationList.push({ queryId: id, queryName: name });
|
||||
data.data_queries.forEach(({ id, name, options }) => {
|
||||
updatedQueries[name] = _.merge(currentQueries[name], { id: id });
|
||||
if (options && options?.requestConfirmation && options?.runOnPageLoad) {
|
||||
queryConfirmationList.push({ queryId: id, queryName: name });
|
||||
}
|
||||
});
|
||||
|
||||
if (queryConfirmationList.length !== 0) {
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[get().moduleName].useEditorStore.getState()
|
||||
.actions.updateQueryConfirmationList(queryConfirmationList);
|
||||
}
|
||||
});
|
||||
|
||||
if (queryConfirmationList.length !== 0) {
|
||||
useEditorStore.getState().actions.updateQueryConfirmationList(queryConfirmationList);
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[get().moduleName].useCurrentStateStore.getState()
|
||||
.actions.setCurrentState({
|
||||
...useSuperStore.getState().modules[get().moduleName].useCurrentStateStore.getState(),
|
||||
queries: updatedQueries,
|
||||
});
|
||||
}
|
||||
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
...useCurrentStateStore.getState(),
|
||||
queries: updatedQueries,
|
||||
});
|
||||
}
|
||||
// Compute query state to be added in the current state
|
||||
const { actions, selectedQuery } = useSuperStore
|
||||
.getState()
|
||||
.modules[get().moduleName].useQueryPanelStore.getState();
|
||||
if (selectFirstQuery) {
|
||||
actions.setSelectedQuery(data.data_queries[0]?.id, data.data_queries[0]);
|
||||
} else if (selectedQuery?.id) {
|
||||
const query = data.data_queries.find((query) => query.id === selectedQuery?.id);
|
||||
actions.setSelectedQuery(query?.id);
|
||||
}
|
||||
|
||||
// Compute query state to be added in the current state
|
||||
const { actions, selectedQuery } = useQueryPanelStore.getState();
|
||||
if (selectFirstQuery) {
|
||||
actions.setSelectedQuery(data.data_queries[0]?.id, data.data_queries[0]);
|
||||
} else if (selectedQuery?.id) {
|
||||
const query = data.data_queries.find((query) => query.id === selectedQuery?.id);
|
||||
actions.setSelectedQuery(query?.id);
|
||||
}
|
||||
|
||||
// Runs query on loading application
|
||||
if (runQueriesOnAppLoad) runQueries(data.data_queries, ref);
|
||||
},
|
||||
setDataQueries: (dataQueries) => set({ dataQueries }),
|
||||
deleteDataQueries: (queryId) => {
|
||||
set({ isDeletingQueryInProcess: true });
|
||||
useAppDataStore.getState().actions.setIsSaving(true);
|
||||
dataqueryService
|
||||
.del(queryId)
|
||||
.then(() => {
|
||||
const { actions } = useQueryPanelStore.getState();
|
||||
const { dataQueries } = useDataQueriesStore.getState();
|
||||
const newSelectedQuery = dataQueries.find((query) => query.id !== queryId);
|
||||
actions.setSelectedQuery(newSelectedQuery?.id || null);
|
||||
if (!newSelectedQuery?.id) {
|
||||
actions.setSelectedDataSource(null);
|
||||
}
|
||||
set((state) => ({
|
||||
isDeletingQueryInProcess: false,
|
||||
dataQueries: state.dataQueries.filter((query) => query.id !== queryId),
|
||||
}));
|
||||
})
|
||||
.catch(() => {
|
||||
set({
|
||||
isDeletingQueryInProcess: false,
|
||||
});
|
||||
})
|
||||
.finally(() => useAppDataStore.getState().actions.setIsSaving(false));
|
||||
},
|
||||
updateDataQuery: (options) => {
|
||||
set({ isUpdatingQueryInProcess: true });
|
||||
const { actions, selectedQuery } = useQueryPanelStore.getState();
|
||||
set((state) => ({
|
||||
isUpdatingQueryInProcess: false,
|
||||
dataQueries: state.dataQueries.map((query) => {
|
||||
if (query.id === selectedQuery.id) {
|
||||
return {
|
||||
...query,
|
||||
options: { ...options },
|
||||
};
|
||||
}
|
||||
return query;
|
||||
}),
|
||||
}));
|
||||
actions.setSelectedQuery(selectedQuery.id);
|
||||
},
|
||||
// createDataQuery: (appId, appVersionId, options, kind, name, selectedDataSource, shouldRunQuery) => {
|
||||
createDataQuery: (selectedDataSource, shouldRunQuery) => {
|
||||
const appVersionId = useAppVersionStore.getState().editingVersion?.id;
|
||||
const appId = useAppDataStore.getState().appId;
|
||||
const { options, name } = getDefaultOptions(selectedDataSource);
|
||||
const kind = selectedDataSource.kind;
|
||||
const tempId = uuidv4();
|
||||
set({ creatingQueryInProcessId: tempId });
|
||||
const { actions, selectedQuery } = useQueryPanelStore.getState();
|
||||
const dataSourceId = selectedDataSource?.id !== 'null' ? selectedDataSource?.id : null;
|
||||
const pluginId = selectedDataSource.pluginId || selectedDataSource.plugin_id;
|
||||
useAppDataStore.getState().actions.setIsSaving(true);
|
||||
const { dataQueries } = useDataQueriesStore.getState();
|
||||
const currDataQueries = [...dataQueries];
|
||||
set(() => ({
|
||||
dataQueries: [
|
||||
{
|
||||
...selectedQuery,
|
||||
data_source_id: dataSourceId,
|
||||
app_version_id: appVersionId,
|
||||
options,
|
||||
name,
|
||||
kind,
|
||||
id: tempId,
|
||||
plugin: selectedDataSource.plugin,
|
||||
},
|
||||
...currDataQueries,
|
||||
],
|
||||
}));
|
||||
actions.setSelectedQuery(tempId);
|
||||
actions.setNameInputFocussed(true);
|
||||
dataqueryService
|
||||
.create(appId, appVersionId, name, kind, options, dataSourceId, pluginId)
|
||||
.then((data) => {
|
||||
set((state) => ({
|
||||
creatingQueryInProcessId: null,
|
||||
dataQueries: state.dataQueries.map((query) => {
|
||||
if (query.id === tempId) {
|
||||
return {
|
||||
...query,
|
||||
id: data.id,
|
||||
data_source_id: dataSourceId,
|
||||
};
|
||||
}
|
||||
return query;
|
||||
}),
|
||||
}));
|
||||
actions.setSelectedQuery(data.id, data);
|
||||
if (shouldRunQuery) actions.setQueryToBeRun(data);
|
||||
|
||||
/** Checks if there is an API call cached. If yes execute it */
|
||||
if (!isEmpty(get()?.queuedActions?.renameQuery)) {
|
||||
get().actions.renameQuery(data.id, get().queuedActions.renameQuery);
|
||||
set({ queuedActions: { ...get().queuedActions, renameQuery: undefined } });
|
||||
}
|
||||
|
||||
if (!isEmpty(get()?.queuedActions?.saveData)) {
|
||||
get().actions.saveData({ ...get().queuedActions.saveData, id: data.id });
|
||||
set({ queuedActions: { ...get().queuedActions, saveData: undefined } });
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
set((state) => ({
|
||||
creatingQueryInProcessId: null,
|
||||
dataQueries: state.dataQueries.filter((query) => query.id !== tempId),
|
||||
}));
|
||||
actions.setSelectedQuery(null);
|
||||
toast.error(`Failed to create query: ${error.message}`);
|
||||
})
|
||||
.finally(() => useAppDataStore.getState().actions.setIsSaving(false));
|
||||
},
|
||||
renameQuery: (id, newName) => {
|
||||
/** If query creation in progress, skips call and pushes the update to queue */
|
||||
if (get().creatingQueryInProcessId === id) {
|
||||
set({ queuedActions: { ...get().queuedActions, renameQuery: newName } });
|
||||
return;
|
||||
}
|
||||
useAppDataStore.getState().actions.setIsSaving(true);
|
||||
/**
|
||||
* Seting name to store before api call for instant UI update and better UX.
|
||||
* Name is again set to state post api call to handle if renaming fails in backend.
|
||||
* */
|
||||
set((state) => ({
|
||||
dataQueries: state.dataQueries.map((query) => (query.id === id ? { ...query, name: newName } : query)),
|
||||
}));
|
||||
dataqueryService
|
||||
.update(id, newName)
|
||||
.then((data) => {
|
||||
set((state) => ({
|
||||
dataQueries: state.dataQueries.map((query) => {
|
||||
if (query.id === id) {
|
||||
return { ...query, name: newName, updated_at: data.updated_at };
|
||||
}
|
||||
return query;
|
||||
}),
|
||||
}));
|
||||
useQueryPanelStore.getState().actions.setSelectedQuery(id);
|
||||
})
|
||||
.finally(() => useAppDataStore.getState().actions.setIsSaving(false));
|
||||
},
|
||||
changeDataQuery: (newDataSource) => {
|
||||
const { selectedQuery } = useQueryPanelStore.getState();
|
||||
set({
|
||||
isUpdatingQueryInProcess: true,
|
||||
});
|
||||
useAppDataStore.getState().actions.setIsSaving(true);
|
||||
dataqueryService
|
||||
.changeQueryDataSource(selectedQuery?.id, newDataSource.id)
|
||||
.then(() => {
|
||||
set((state) => ({
|
||||
isUpdatingQueryInProcess: false,
|
||||
dataQueries: state.dataQueries.map((query) => {
|
||||
if (query?.id === selectedQuery?.id) {
|
||||
return { ...query, dataSourceId: newDataSource?.id, data_source_id: newDataSource?.id };
|
||||
}
|
||||
return query;
|
||||
}),
|
||||
}));
|
||||
useQueryPanelStore.getState().actions.setSelectedQuery(selectedQuery.id);
|
||||
useQueryPanelStore.getState().actions.setSelectedDataSource(newDataSource);
|
||||
})
|
||||
.catch(() => {
|
||||
set({
|
||||
isUpdatingQueryInProcess: false,
|
||||
});
|
||||
})
|
||||
.finally(() => useAppDataStore.getState().actions.setIsSaving(false));
|
||||
},
|
||||
duplicateQuery: (id, appId) => {
|
||||
set({ creatingQueryInProcessId: uuidv4() });
|
||||
const { actions } = useQueryPanelStore.getState();
|
||||
const { dataQueries } = useDataQueriesStore.getState();
|
||||
const queryToClone = { ...dataQueries.find((query) => query.id === id) };
|
||||
let newName = queryToClone.name + '_copy';
|
||||
const names = dataQueries.map(({ name }) => name);
|
||||
let count = 0;
|
||||
while (names.includes(newName)) {
|
||||
count++;
|
||||
newName = queryToClone.name + '_copy' + count.toString();
|
||||
}
|
||||
queryToClone.name = newName;
|
||||
|
||||
useAppDataStore.getState().actions.setIsSaving(true);
|
||||
dataqueryService
|
||||
.create(
|
||||
appId,
|
||||
queryToClone.app_version_id,
|
||||
queryToClone.name,
|
||||
queryToClone.kind,
|
||||
queryToClone.options,
|
||||
queryToClone.data_source_id,
|
||||
queryToClone.pluginId
|
||||
)
|
||||
.then((data) => {
|
||||
set((state) => ({
|
||||
creatingQueryInProcessId: null,
|
||||
dataQueries: [{ ...data, data_source_id: queryToClone.data_source_id }, ...state.dataQueries],
|
||||
}));
|
||||
actions.setSelectedQuery(data.id, { ...data, data_source_id: queryToClone.data_source_id });
|
||||
|
||||
const dataQueryEvents = useAppDataStore
|
||||
.getState()
|
||||
.events?.filter((event) => event.target === 'data_query' && event.sourceId === queryToClone.id);
|
||||
|
||||
if (dataQueryEvents?.length === 0) return;
|
||||
|
||||
return Promise.all(
|
||||
dataQueryEvents.map((event) => {
|
||||
const newEvent = {
|
||||
event: {
|
||||
...event?.event,
|
||||
},
|
||||
eventType: event?.target,
|
||||
attachedTo: data.id,
|
||||
index: event?.index,
|
||||
};
|
||||
useAppDataStore.getState().actions?.createAppVersionEventHandlers(newEvent);
|
||||
})
|
||||
// Runs query on loading application
|
||||
if (runQueriesOnAppLoad) runQueries(data.data_queries, ref);
|
||||
},
|
||||
setDataQueries: (dataQueries) => set({ dataQueries }),
|
||||
deleteDataQueries: (queryId) => {
|
||||
set({ isDeletingQueryInProcess: true });
|
||||
useSuperStore.getState().modules[get().moduleName].useAppDataStore.getState().actions.setIsSaving(true);
|
||||
dataqueryService
|
||||
.del(queryId)
|
||||
.then(() => {
|
||||
const { actions } = useSuperStore.getState().modules[get().moduleName].useQueryPanelStore.getState();
|
||||
const { dataQueries } = get();
|
||||
const newSelectedQuery = dataQueries.find((query) => query.id !== queryId);
|
||||
actions.setSelectedQuery(newSelectedQuery?.id || null);
|
||||
if (!newSelectedQuery?.id) {
|
||||
actions.setSelectedDataSource(null);
|
||||
}
|
||||
set((state) => ({
|
||||
isDeletingQueryInProcess: false,
|
||||
dataQueries: state.dataQueries.filter((query) => query.id !== queryId),
|
||||
}));
|
||||
})
|
||||
.catch(() => {
|
||||
set({
|
||||
isDeletingQueryInProcess: false,
|
||||
});
|
||||
})
|
||||
.finally(() =>
|
||||
useSuperStore.getState().modules[get().moduleName].useAppDataStore.getState().actions.setIsSaving(false)
|
||||
);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('error', error);
|
||||
set({
|
||||
creatingQueryInProcessId: null,
|
||||
});
|
||||
})
|
||||
.finally(() => useAppDataStore.getState().actions.setIsSaving(false));
|
||||
},
|
||||
updateDataQuery: (options) => {
|
||||
set({ isUpdatingQueryInProcess: true });
|
||||
const { actions, selectedQuery } = useSuperStore
|
||||
.getState()
|
||||
.modules[get().moduleName].useQueryPanelStore.getState();
|
||||
set((state) => ({
|
||||
isUpdatingQueryInProcess: false,
|
||||
dataQueries: state.dataQueries.map((query) => {
|
||||
if (query.id === selectedQuery.id) {
|
||||
return {
|
||||
...query,
|
||||
options: { ...options },
|
||||
};
|
||||
}
|
||||
return query;
|
||||
}),
|
||||
}));
|
||||
actions.setSelectedQuery(selectedQuery.id);
|
||||
},
|
||||
// createDataQuery: (appId, appVersionId, options, kind, name, selectedDataSource, shouldRunQuery) => {
|
||||
createDataQuery: (selectedDataSource, shouldRunQuery) => {
|
||||
const appVersionId = useSuperStore.getState().modules[get().moduleName].useAppVersionStore.getState()
|
||||
.editingVersion?.id;
|
||||
const appId = useSuperStore.getState().modules[get().moduleName].useAppDataStore.getState().appId;
|
||||
const { options, name } = getDefaultOptions(selectedDataSource, get().moduleName);
|
||||
const kind = selectedDataSource.kind;
|
||||
const tempId = uuidv4();
|
||||
set({ creatingQueryInProcessId: tempId });
|
||||
const { actions, selectedQuery } = useSuperStore
|
||||
.getState()
|
||||
.modules[get().moduleName].useQueryPanelStore.getState();
|
||||
const dataSourceId = selectedDataSource?.id !== 'null' ? selectedDataSource?.id : null;
|
||||
const pluginId = selectedDataSource.pluginId || selectedDataSource.plugin_id;
|
||||
useSuperStore.getState().modules[get().moduleName].useAppDataStore.getState().actions.setIsSaving(true);
|
||||
const { dataQueries } = get();
|
||||
const currDataQueries = [...dataQueries];
|
||||
set(() => ({
|
||||
dataQueries: [
|
||||
{
|
||||
...selectedQuery,
|
||||
data_source_id: dataSourceId,
|
||||
app_version_id: appVersionId,
|
||||
options,
|
||||
name,
|
||||
kind,
|
||||
id: tempId,
|
||||
plugin: selectedDataSource.plugin,
|
||||
},
|
||||
...currDataQueries,
|
||||
],
|
||||
}));
|
||||
actions.setSelectedQuery(tempId);
|
||||
actions.setNameInputFocussed(true);
|
||||
dataqueryService
|
||||
.create(appId, appVersionId, name, kind, options, dataSourceId, pluginId)
|
||||
.then((data) => {
|
||||
set((state) => ({
|
||||
creatingQueryInProcessId: null,
|
||||
dataQueries: state.dataQueries.map((query) => {
|
||||
if (query.id === tempId) {
|
||||
return {
|
||||
...query,
|
||||
id: data.id,
|
||||
data_source_id: dataSourceId,
|
||||
};
|
||||
}
|
||||
return query;
|
||||
}),
|
||||
}));
|
||||
actions.setSelectedQuery(data.id, data);
|
||||
if (shouldRunQuery) actions.setQueryToBeRun(data);
|
||||
|
||||
/** Checks if there is an API call cached. If yes execute it */
|
||||
if (!isEmpty(get()?.queuedActions?.renameQuery)) {
|
||||
get().actions.renameQuery(data.id, get().queuedActions.renameQuery);
|
||||
set({ queuedActions: { ...get().queuedActions, renameQuery: undefined } });
|
||||
}
|
||||
|
||||
if (!isEmpty(get()?.queuedActions?.saveData)) {
|
||||
get().actions.saveData({ ...get().queuedActions.saveData, id: data.id });
|
||||
set({ queuedActions: { ...get().queuedActions, saveData: undefined } });
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
set((state) => ({
|
||||
creatingQueryInProcessId: null,
|
||||
dataQueries: state.dataQueries.filter((query) => query.id !== tempId),
|
||||
}));
|
||||
actions.setSelectedQuery(null);
|
||||
toast.error(`Failed to create query: ${error.message}`);
|
||||
})
|
||||
.finally(() =>
|
||||
useSuperStore.getState().modules[get().moduleName].useAppDataStore.getState().actions.setIsSaving(false)
|
||||
);
|
||||
},
|
||||
renameQuery: (id, newName) => {
|
||||
/** If query creation in progress, skips call and pushes the update to queue */
|
||||
if (get().creatingQueryInProcessId === id) {
|
||||
set({ queuedActions: { ...get().queuedActions, renameQuery: newName } });
|
||||
return;
|
||||
}
|
||||
useSuperStore.getState().modules[get().moduleName].useAppDataStore.getState().actions.setIsSaving(true);
|
||||
/**
|
||||
* Seting name to store before api call for instant UI update and better UX.
|
||||
* Name is again set to state post api call to handle if renaming fails in backend.
|
||||
* */
|
||||
set((state) => ({
|
||||
dataQueries: state.dataQueries.map((query) => (query.id === id ? { ...query, name: newName } : query)),
|
||||
}));
|
||||
dataqueryService
|
||||
.update(id, newName)
|
||||
.then((data) => {
|
||||
set((state) => ({
|
||||
dataQueries: state.dataQueries.map((query) => {
|
||||
if (query.id === id) {
|
||||
return { ...query, name: newName, updated_at: data.updated_at };
|
||||
}
|
||||
return query;
|
||||
}),
|
||||
}));
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[get().moduleName].useQueryPanelStore.getState()
|
||||
.actions.setSelectedQuery(id);
|
||||
})
|
||||
.finally(() =>
|
||||
useSuperStore.getState().modules[get().moduleName].useAppDataStore.getState().actions.setIsSaving(false)
|
||||
);
|
||||
},
|
||||
changeDataQuery: (newDataSource) => {
|
||||
const { selectedQuery } = useSuperStore.getState().modules[get().moduleName].useQueryPanelStore.getState();
|
||||
set({
|
||||
isUpdatingQueryInProcess: true,
|
||||
});
|
||||
useSuperStore.getState().modules[get().moduleName].useAppDataStore.getState().actions.setIsSaving(true);
|
||||
dataqueryService
|
||||
.changeQueryDataSource(selectedQuery?.id, newDataSource.id)
|
||||
.then(() => {
|
||||
set((state) => ({
|
||||
isUpdatingQueryInProcess: false,
|
||||
dataQueries: state.dataQueries.map((query) => {
|
||||
if (query?.id === selectedQuery?.id) {
|
||||
return { ...query, dataSourceId: newDataSource?.id, data_source_id: newDataSource?.id };
|
||||
}
|
||||
return query;
|
||||
}),
|
||||
}));
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[get().moduleName].useQueryPanelStore.getState()
|
||||
.actions.setSelectedQuery(selectedQuery.id);
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[get().moduleName].useQueryPanelStore.getState()
|
||||
.actions.setSelectedDataSource(newDataSource);
|
||||
})
|
||||
.catch(() => {
|
||||
set({
|
||||
isUpdatingQueryInProcess: false,
|
||||
});
|
||||
})
|
||||
.finally(() =>
|
||||
useSuperStore.getState().modules[get().moduleName].useAppDataStore.getState().actions.setIsSaving(false)
|
||||
);
|
||||
},
|
||||
duplicateQuery: (id, appId) => {
|
||||
set({ creatingQueryInProcessId: uuidv4() });
|
||||
const { actions } = useSuperStore.getState().modules[get().moduleName].useQueryPanelStore.getState();
|
||||
const { dataQueries } = get();
|
||||
const queryToClone = { ...dataQueries.find((query) => query.id === id) };
|
||||
let newName = queryToClone.name + '_copy';
|
||||
const names = dataQueries.map(({ name }) => name);
|
||||
let count = 0;
|
||||
while (names.includes(newName)) {
|
||||
count++;
|
||||
newName = queryToClone.name + '_copy' + count.toString();
|
||||
}
|
||||
queryToClone.name = newName;
|
||||
|
||||
useSuperStore.getState().modules[get().moduleName].useAppDataStore.getState().actions.setIsSaving(true);
|
||||
dataqueryService
|
||||
.create(
|
||||
appId,
|
||||
queryToClone.app_version_id,
|
||||
queryToClone.name,
|
||||
queryToClone.kind,
|
||||
queryToClone.options,
|
||||
queryToClone.data_source_id,
|
||||
queryToClone.pluginId
|
||||
)
|
||||
.then((data) => {
|
||||
set((state) => ({
|
||||
creatingQueryInProcessId: null,
|
||||
dataQueries: [{ ...data, data_source_id: queryToClone.data_source_id }, ...state.dataQueries],
|
||||
}));
|
||||
actions.setSelectedQuery(data.id, { ...data, data_source_id: queryToClone.data_source_id });
|
||||
|
||||
const dataQueryEvents = useAppDataStore
|
||||
.getState()
|
||||
.events?.filter((event) => event.target === 'data_query' && event.sourceId === queryToClone.id);
|
||||
|
||||
if (dataQueryEvents?.length === 0) return;
|
||||
|
||||
return Promise.all(
|
||||
dataQueryEvents.map((event) => {
|
||||
const newEvent = {
|
||||
event: {
|
||||
...event?.event,
|
||||
},
|
||||
eventType: event?.target,
|
||||
attachedTo: data.id,
|
||||
index: event?.index,
|
||||
};
|
||||
useSuperStore
|
||||
.getState()
|
||||
.modules[get().moduleName].useAppDataStore.getState()
|
||||
.actions?.createAppVersionEventHandlers(newEvent);
|
||||
})
|
||||
);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('error', error);
|
||||
set({
|
||||
creatingQueryInProcessId: null,
|
||||
});
|
||||
})
|
||||
.finally(() =>
|
||||
useSuperStore.getState().modules[get().moduleName].useAppDataStore.getState().actions.setIsSaving(false)
|
||||
);
|
||||
},
|
||||
saveData: throttle((newValues) => {
|
||||
/** If query creation in progress, skips call and pushes the update to queue */
|
||||
if (get().creatingQueryInProcessId && get().creatingQueryInProcessId === newValues.id) {
|
||||
set({ queuedActions: { ...get().queuedActions, saveData: newValues } });
|
||||
return;
|
||||
}
|
||||
useSuperStore.getState().modules[get().moduleName].useAppDataStore.getState().actions.setIsSaving(true);
|
||||
set({ isUpdatingQueryInProcess: true });
|
||||
dataqueryService
|
||||
.update(newValues?.id, newValues?.name, newValues?.options)
|
||||
.then((data) => {
|
||||
localStorage.removeItem('transformation');
|
||||
set((state) => ({
|
||||
dataQueries: state.dataQueries.map((query) => {
|
||||
if (query.id === newValues?.id) {
|
||||
return { ...query, updated_at: data.updated_at };
|
||||
}
|
||||
return query;
|
||||
}),
|
||||
isUpdatingQueryInProcess: false,
|
||||
}));
|
||||
})
|
||||
.catch(() => {
|
||||
set({
|
||||
isUpdatingQueryInProcess: false,
|
||||
});
|
||||
})
|
||||
.finally(() =>
|
||||
useSuperStore.getState().modules[get().moduleName].useAppDataStore.getState().actions.setIsSaving(false)
|
||||
);
|
||||
}, 500),
|
||||
sortDataQueries: (sortBy, sortOrder) => {
|
||||
set(({ dataQueries, sortOrder: currSortOrder }) => {
|
||||
const newSortOrder = sortOrder ? sortOrder : currSortOrder === 'asc' ? 'desc' : 'asc';
|
||||
return {
|
||||
sortBy,
|
||||
sortOrder: newSortOrder,
|
||||
dataQueries: sortByAttribute(dataQueries, sortBy, newSortOrder),
|
||||
};
|
||||
});
|
||||
},
|
||||
},
|
||||
saveData: throttle((newValues) => {
|
||||
/** If query creation in progress, skips call and pushes the update to queue */
|
||||
if (get().creatingQueryInProcessId && get().creatingQueryInProcessId === newValues.id) {
|
||||
set({ queuedActions: { ...get().queuedActions, saveData: newValues } });
|
||||
return;
|
||||
}
|
||||
useAppDataStore.getState().actions.setIsSaving(true);
|
||||
set({ isUpdatingQueryInProcess: true });
|
||||
dataqueryService
|
||||
.update(newValues?.id, newValues?.name, newValues?.options)
|
||||
.then((data) => {
|
||||
localStorage.removeItem('transformation');
|
||||
set((state) => ({
|
||||
dataQueries: state.dataQueries.map((query) => {
|
||||
if (query.id === newValues?.id) {
|
||||
return { ...query, updated_at: data.updated_at };
|
||||
}
|
||||
return query;
|
||||
}),
|
||||
isUpdatingQueryInProcess: false,
|
||||
}));
|
||||
})
|
||||
.catch(() => {
|
||||
set({
|
||||
isUpdatingQueryInProcess: false,
|
||||
});
|
||||
})
|
||||
.finally(() => useAppDataStore.getState().actions.setIsSaving(false));
|
||||
}, 500),
|
||||
sortDataQueries: (sortBy, sortOrder) => {
|
||||
set(({ dataQueries, sortOrder: currSortOrder }) => {
|
||||
const newSortOrder = sortOrder ? sortOrder : currSortOrder === 'asc' ? 'desc' : 'asc';
|
||||
return {
|
||||
sortBy,
|
||||
sortOrder: newSortOrder,
|
||||
dataQueries: sortByAttribute(dataQueries, sortBy, newSortOrder),
|
||||
};
|
||||
});
|
||||
},
|
||||
},
|
||||
}),
|
||||
{ name: 'Data Queries Store' }
|
||||
)
|
||||
);
|
||||
}),
|
||||
{ name: 'Data Queries Store' }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const sortByAttribute = (data, sortBy, order) => {
|
||||
if (order === 'asc') {
|
||||
|
|
@ -360,6 +401,19 @@ const sortByAttribute = (data, sortBy, order) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const useDataQueriesStore = (callback, shallow) => {
|
||||
const moduleName = useContext(ModuleContext);
|
||||
|
||||
if (!moduleName)
|
||||
throw Error(
|
||||
'useDataQueriesStore can only be called inside Module context. (hint: Wrap with ModuleContext.Provider)'
|
||||
);
|
||||
|
||||
const _useDataQueriesStore = useSuperStore((state) => state.modules[moduleName].useDataQueriesStore);
|
||||
|
||||
return _useDataQueriesStore(callback, shallow);
|
||||
};
|
||||
|
||||
export const useDataQueries = () => useDataQueriesStore((state) => state.dataQueries, shallow);
|
||||
export const useDataQueriesActions = () => useDataQueriesStore((state) => state.actions);
|
||||
export const useQueryCreationLoading = () => useDataQueriesStore((state) => !!state.creatingQueryInProcessId, shallow);
|
||||
|
|
|
|||
|
|
@ -1,53 +1,69 @@
|
|||
import { create, zustandDevTools } from './utils';
|
||||
import { datasourceService, globalDatasourceService } from '@/_services';
|
||||
import { useContext } from 'react';
|
||||
import { useSuperStore } from './superStore';
|
||||
import { ModuleContext } from '../_contexts/ModuleContext';
|
||||
|
||||
const initialState = {
|
||||
dataSources: [],
|
||||
loadingDataSources: true,
|
||||
globalDataSources: [],
|
||||
globalDataSourceStatus: {
|
||||
isSaving: false,
|
||||
isEditing: false,
|
||||
unSavedModalVisible: false,
|
||||
action: null,
|
||||
saveAction: null,
|
||||
},
|
||||
export function createDataSourcesStore(moduleName) {
|
||||
const initialState = {
|
||||
dataSources: [],
|
||||
loadingDataSources: true,
|
||||
globalDataSources: [],
|
||||
globalDataSourceStatus: {
|
||||
isSaving: false,
|
||||
isEditing: false,
|
||||
unSavedModalVisible: false,
|
||||
action: null,
|
||||
saveAction: null,
|
||||
},
|
||||
moduleName,
|
||||
};
|
||||
|
||||
return create(
|
||||
zustandDevTools(
|
||||
(set, get) => ({
|
||||
...initialState,
|
||||
actions: {
|
||||
fetchDataSources: (appId) => {
|
||||
set({ loadingDataSources: true });
|
||||
datasourceService.getAll(appId).then((data) => {
|
||||
set({
|
||||
dataSources: data.data_sources,
|
||||
loadingDataSources: false,
|
||||
});
|
||||
});
|
||||
},
|
||||
fetchGlobalDataSources: (organizationId) => {
|
||||
globalDatasourceService.getAll(organizationId).then((data) => {
|
||||
set({
|
||||
globalDataSources: data.data_sources,
|
||||
});
|
||||
});
|
||||
},
|
||||
setGlobalDataSourceStatus: (status) =>
|
||||
set({
|
||||
globalDataSourceStatus: {
|
||||
...get().globalDataSourceStatus,
|
||||
...status,
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
{ name: 'Data Source Store' }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export const useDataSourcesStore = (callback, shallow) => {
|
||||
const moduleName = useContext(ModuleContext);
|
||||
|
||||
if (!moduleName) throw Error('module context not available');
|
||||
|
||||
const _useDataSourcesStore = useSuperStore((state) => state.modules[moduleName].useDataSourcesStore);
|
||||
|
||||
return _useDataSourcesStore(callback, shallow);
|
||||
};
|
||||
|
||||
export const useDataSourcesStore = create(
|
||||
zustandDevTools(
|
||||
(set, get) => ({
|
||||
...initialState,
|
||||
actions: {
|
||||
fetchDataSources: (appId) => {
|
||||
set({ loadingDataSources: true });
|
||||
datasourceService.getAll(appId).then((data) => {
|
||||
set({
|
||||
dataSources: data.data_sources,
|
||||
loadingDataSources: false,
|
||||
});
|
||||
});
|
||||
},
|
||||
fetchGlobalDataSources: (organizationId) => {
|
||||
globalDatasourceService.getAll(organizationId).then((data) => {
|
||||
set({
|
||||
globalDataSources: data.data_sources,
|
||||
});
|
||||
});
|
||||
},
|
||||
setGlobalDataSourceStatus: (status) =>
|
||||
set({
|
||||
globalDataSourceStatus: {
|
||||
...get().globalDataSourceStatus,
|
||||
...status,
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
{ name: 'Data Source Store' }
|
||||
)
|
||||
);
|
||||
|
||||
export const useDataSources = () => useDataSourcesStore((state) => state.dataSources);
|
||||
export const useGlobalDataSources = () => useDataSourcesStore((state) => state.globalDataSources);
|
||||
export const useLoadingDataSources = () => useDataSourcesStore((state) => state.loadingDataSources);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import { create } from './utils';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { useContext } from 'react';
|
||||
import { useSuperStore } from './superStore';
|
||||
import { ModuleContext } from '../_contexts/ModuleContext';
|
||||
const STORE_NAME = 'Editor';
|
||||
|
||||
export const EMPTY_ARRAY = [];
|
||||
|
|
@ -14,84 +17,97 @@ const ACTIONS = {
|
|||
SET_IS_EDITOR_ACTIVE: 'SET_IS_EDITOR_ACTIVE',
|
||||
};
|
||||
|
||||
const initialState = {
|
||||
currentLayout: 'desktop',
|
||||
showComments: false,
|
||||
hoveredComponent: '',
|
||||
selectionInProgress: false,
|
||||
selectedComponents: EMPTY_ARRAY,
|
||||
isEditorActive: false,
|
||||
selectedComponent: null,
|
||||
scrollOptions: {
|
||||
container: null,
|
||||
throttleTime: 0,
|
||||
threshold: 0,
|
||||
},
|
||||
canUndo: false,
|
||||
canRedo: false,
|
||||
currentVersion: {},
|
||||
noOfVersionsSupported: 100,
|
||||
appDefinition: {},
|
||||
isUpdatingEditorStateInProcess: false,
|
||||
saveError: false,
|
||||
isLoading: true,
|
||||
defaultComponentStateComputed: false,
|
||||
showLeftSidebar: true,
|
||||
queryConfirmationList: [],
|
||||
currentPageId: null,
|
||||
currentSessionId: uuid(),
|
||||
};
|
||||
|
||||
export const useEditorStore = create(
|
||||
//Redux Dev tools for this store are disabled since its freezing chrome tab
|
||||
(set, get) => ({
|
||||
...initialState,
|
||||
actions: {
|
||||
setShowComments: (showComments) =>
|
||||
set({ showComments }, false, {
|
||||
type: ACTIONS.SET_HOVERED_COMPONENT,
|
||||
showComments,
|
||||
}),
|
||||
toggleComments: () =>
|
||||
set({ showComments: !get().showComments }, false, {
|
||||
type: ACTIONS.TOGGLE_COMMENTS,
|
||||
}),
|
||||
toggleCurrentLayout: (currentLayout) =>
|
||||
set({ currentLayout }, false, {
|
||||
type: ACTIONS.TOGGLE_CURRENT_LAYOUT,
|
||||
currentLayout,
|
||||
}),
|
||||
setIsEditorActive: (isEditorActive) => set(() => ({ isEditorActive })),
|
||||
updateEditorState: (state) => set((prev) => ({ ...prev, ...state })),
|
||||
updateQueryConfirmationList: (queryConfirmationList) => set({ queryConfirmationList }),
|
||||
setHoveredComponent: (hoveredComponent) =>
|
||||
set({ hoveredComponent }, false, {
|
||||
type: ACTIONS.SET_HOVERED_COMPONENT,
|
||||
hoveredComponent,
|
||||
}),
|
||||
setSelectionInProgress: (isSelectionInProgress) => {
|
||||
set(
|
||||
{
|
||||
isSelectionInProgress,
|
||||
},
|
||||
false,
|
||||
{ type: ACTIONS.SET_SELECTION_IN_PROGRESS }
|
||||
);
|
||||
},
|
||||
setSelectedComponents: (selectedComponents, isMulti = false) => {
|
||||
const newSelectedComponents = isMulti
|
||||
? [...get().selectedComponents, ...selectedComponents]
|
||||
: selectedComponents;
|
||||
|
||||
set({
|
||||
selectedComponents: newSelectedComponents,
|
||||
});
|
||||
},
|
||||
setCurrentPageId: (currentPageId) => set({ currentPageId }),
|
||||
export function createEditorStore(moduleName) {
|
||||
const initialState = {
|
||||
currentLayout: 'desktop',
|
||||
showComments: false,
|
||||
hoveredComponent: '',
|
||||
selectionInProgress: false,
|
||||
selectedComponents: [],
|
||||
isEditorActive: false,
|
||||
selectedComponent: null,
|
||||
scrollOptions: {
|
||||
container: null,
|
||||
throttleTime: 0,
|
||||
threshold: 0,
|
||||
},
|
||||
}),
|
||||
{ name: STORE_NAME }
|
||||
);
|
||||
canUndo: false,
|
||||
canRedo: false,
|
||||
currentVersion: {},
|
||||
noOfVersionsSupported: 100,
|
||||
appDefinition: {},
|
||||
isUpdatingEditorStateInProcess: false,
|
||||
saveError: false,
|
||||
isLoading: true,
|
||||
defaultComponentStateComputed: false,
|
||||
showLeftSidebar: true,
|
||||
queryConfirmationList: [],
|
||||
currentPageId: null,
|
||||
currentSessionId: uuid(),
|
||||
moduleName,
|
||||
};
|
||||
|
||||
return create(
|
||||
//Redux Dev tools for this store are disabled since its freezing chrome tab
|
||||
(set, get) => ({
|
||||
...initialState,
|
||||
actions: {
|
||||
setShowComments: (showComments) =>
|
||||
set({ showComments }, false, {
|
||||
type: ACTIONS.SET_HOVERED_COMPONENT,
|
||||
showComments,
|
||||
}),
|
||||
toggleComments: () =>
|
||||
set({ showComments: !get().showComments }, false, {
|
||||
type: ACTIONS.TOGGLE_COMMENTS,
|
||||
}),
|
||||
toggleCurrentLayout: (currentLayout) =>
|
||||
set({ currentLayout }, false, {
|
||||
type: ACTIONS.TOGGLE_CURRENT_LAYOUT,
|
||||
currentLayout,
|
||||
}),
|
||||
setIsEditorActive: (isEditorActive) => set(() => ({ isEditorActive })),
|
||||
updateEditorState: (state) => set((prev) => ({ ...prev, ...state })),
|
||||
updateQueryConfirmationList: (queryConfirmationList) => set({ queryConfirmationList }),
|
||||
setHoveredComponent: (hoveredComponent) =>
|
||||
set({ hoveredComponent }, false, {
|
||||
type: ACTIONS.SET_HOVERED_COMPONENT,
|
||||
hoveredComponent,
|
||||
}),
|
||||
setSelectionInProgress: (isSelectionInProgress) => {
|
||||
set(
|
||||
{
|
||||
isSelectionInProgress,
|
||||
},
|
||||
false,
|
||||
{ type: ACTIONS.SET_SELECTION_IN_PROGRESS }
|
||||
);
|
||||
},
|
||||
setSelectedComponents: (selectedComponents, isMulti = false) => {
|
||||
const newSelectedComponents = isMulti
|
||||
? [...get().selectedComponents, ...selectedComponents]
|
||||
: selectedComponents;
|
||||
|
||||
set({
|
||||
selectedComponents: newSelectedComponents,
|
||||
});
|
||||
},
|
||||
setCurrentPageId: (currentPageId) => set({ currentPageId }),
|
||||
},
|
||||
}),
|
||||
{ name: STORE_NAME }
|
||||
);
|
||||
}
|
||||
|
||||
export const useEditorStore = (callback, shallow) => {
|
||||
const moduleName = useContext(ModuleContext);
|
||||
|
||||
if (!moduleName) throw Error('module context not available');
|
||||
|
||||
const _useEditorStore = useSuperStore((state) => state.modules[moduleName].useEditorStore);
|
||||
|
||||
return _useEditorStore(callback, shallow);
|
||||
};
|
||||
|
||||
export const useEditorActions = () => useEditorStore((state) => state.actions);
|
||||
export const useEditorState = () => useEditorStore((state) => state);
|
||||
|
|
|
|||
|
|
@ -1,45 +1,67 @@
|
|||
import { create, zustandDevTools } from './utils';
|
||||
import { useContext } from 'react';
|
||||
import { ModuleContext } from '../_contexts/ModuleContext';
|
||||
|
||||
import { useDataQueriesStore } from '@/_stores/dataQueriesStore';
|
||||
import { useSuperStore } from '@/_stores/superStore';
|
||||
|
||||
const queryManagerPreferences = JSON.parse(localStorage.getItem('queryManagerPreferences')) ?? {};
|
||||
const initialState = {
|
||||
queryPanelHeight: queryManagerPreferences?.isExpanded ? queryManagerPreferences?.queryPanelHeight : 95 ?? 70,
|
||||
selectedQuery: null,
|
||||
selectedDataSource: null,
|
||||
queryToBeRun: null,
|
||||
previewLoading: false,
|
||||
queryPreviewData: '',
|
||||
showCreateQuery: false,
|
||||
nameInputFocussed: false,
|
||||
};
|
||||
export function createQueryPanelStore(moduleName) {
|
||||
const queryManagerPreferences = JSON.parse(localStorage.getItem('queryManagerPreferences')) ?? {};
|
||||
const initialState = {
|
||||
queryPanelHeight: queryManagerPreferences?.isExpanded ? queryManagerPreferences?.queryPanelHeight : 95 ?? 70,
|
||||
selectedQuery: null,
|
||||
selectedDataSource: null,
|
||||
queryToBeRun: null,
|
||||
previewLoading: false,
|
||||
queryPreviewData: '',
|
||||
showCreateQuery: false,
|
||||
nameInputFocussed: false,
|
||||
moduleName,
|
||||
};
|
||||
|
||||
export const useQueryPanelStore = create(
|
||||
zustandDevTools(
|
||||
(set) => ({
|
||||
...initialState,
|
||||
actions: {
|
||||
updateQueryPanelHeight: (newHeight) => set(() => ({ queryPanelHeight: newHeight })),
|
||||
setSelectedQuery: (queryId) => {
|
||||
set(() => {
|
||||
if (queryId === null) {
|
||||
return { selectedQuery: null };
|
||||
}
|
||||
const query = useDataQueriesStore.getState().dataQueries.find((query) => query.id === queryId);
|
||||
return { selectedQuery: query };
|
||||
});
|
||||
return create(
|
||||
zustandDevTools(
|
||||
(set, get) => ({
|
||||
...initialState,
|
||||
actions: {
|
||||
updateQueryPanelHeight: (newHeight) => set(() => ({ queryPanelHeight: newHeight })),
|
||||
setSelectedQuery: (queryId) => {
|
||||
set(() => {
|
||||
if (queryId === null) {
|
||||
return { selectedQuery: null };
|
||||
}
|
||||
const query = useSuperStore
|
||||
.getState()
|
||||
.modules[get().moduleName].useDataQueriesStore.getState()
|
||||
.dataQueries.find((query) => query.id === queryId);
|
||||
return { selectedQuery: query };
|
||||
});
|
||||
},
|
||||
setSelectedDataSource: (dataSource = null) => set({ selectedDataSource: dataSource }),
|
||||
setQueryToBeRun: (query) => set({ queryToBeRun: query }),
|
||||
setPreviewLoading: (status) => set({ previewLoading: status }),
|
||||
setPreviewData: (data) => set({ queryPreviewData: data }),
|
||||
setShowCreateQuery: (showCreateQuery) => set({ showCreateQuery }),
|
||||
setNameInputFocussed: (nameInputFocussed) => set({ nameInputFocussed }),
|
||||
},
|
||||
setSelectedDataSource: (dataSource = null) => set({ selectedDataSource: dataSource }),
|
||||
setQueryToBeRun: (query) => set({ queryToBeRun: query }),
|
||||
setPreviewLoading: (status) => set({ previewLoading: status }),
|
||||
setPreviewData: (data) => set({ queryPreviewData: data }),
|
||||
setShowCreateQuery: (showCreateQuery) => set({ showCreateQuery }),
|
||||
setNameInputFocussed: (nameInputFocussed) => set({ nameInputFocussed }),
|
||||
},
|
||||
}),
|
||||
{ name: 'Query Panel Store' }
|
||||
)
|
||||
);
|
||||
}),
|
||||
{ name: 'Query Panel Store' }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export const useQueryPanelStore = (callback, shallow) => {
|
||||
const moduleName = useContext(ModuleContext);
|
||||
|
||||
if (!moduleName)
|
||||
throw Error(
|
||||
'useQueryPanelStore can only be called inside Module context. (hint: Wrap with ModuleContext.Provider)'
|
||||
);
|
||||
|
||||
const _useQueryPanelStore = useSuperStore((state) => state.modules[moduleName].useQueryPanelStore);
|
||||
|
||||
return _useQueryPanelStore(callback, shallow);
|
||||
};
|
||||
|
||||
export const usePanelHeight = () => useQueryPanelStore((state) => state.queryPanelHeight);
|
||||
export const useSelectedQuery = () => useQueryPanelStore((state) => state.selectedQuery);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { schemaUnavailableOptions } from '@/Editor/QueryManager/constants';
|
||||
import { allOperations } from '@tooljet/plugins/client';
|
||||
import { capitalize } from 'lodash';
|
||||
import { useDataQueriesStore } from '@/_stores/dataQueriesStore';
|
||||
import { useSuperStore } from './superStore';
|
||||
|
||||
export const getDefaultOptions = (source) => {
|
||||
export const getDefaultOptions = (source, moduleName) => {
|
||||
const isSchemaUnavailable = Object.keys(schemaUnavailableOptions).includes(source.kind);
|
||||
let options = {};
|
||||
|
||||
|
|
@ -36,11 +36,11 @@ export const getDefaultOptions = (source) => {
|
|||
}
|
||||
}
|
||||
|
||||
return { options, name: computeQueryName(source.kind) };
|
||||
return { options, name: computeQueryName(source.kind, moduleName) };
|
||||
};
|
||||
|
||||
const computeQueryName = (kind) => {
|
||||
const dataQueries = useDataQueriesStore.getState().dataQueries;
|
||||
const computeQueryName = (kind, moduleName) => {
|
||||
const dataQueries = useSuperStore.getState().modules[moduleName].useDataQueriesStore.getState().dataQueries;
|
||||
const currentQueriesForKind = dataQueries.filter((query) => query.kind === kind);
|
||||
let currentNumber = currentQueriesForKind.length + 1;
|
||||
|
||||
|
|
|
|||
44
frontend/src/_stores/superStore.js
Normal file
44
frontend/src/_stores/superStore.js
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import { createDataQueriesStore } from './dataQueriesStore';
|
||||
import { createEditorStore } from './editorStore';
|
||||
import { createQueryPanelStore } from './queryPanelStore';
|
||||
import { createDataSourcesStore } from './dataSourcesStore';
|
||||
import { createCurrentStateStore } from './currentStateStore';
|
||||
import { create } from './utils';
|
||||
import { createAppVersionStore } from './appVersionStore';
|
||||
import { createAppDataStore } from './appDataStore';
|
||||
import { omit } from 'lodash';
|
||||
|
||||
const generateModule = (moduleName) => ({
|
||||
useEditorStore: createEditorStore(moduleName),
|
||||
useQueryPanelStore: createQueryPanelStore(moduleName),
|
||||
useDataQueriesStore: createDataQueriesStore(moduleName),
|
||||
useDataSourcesStore: createDataSourcesStore(moduleName),
|
||||
useCurrentStateStore: createCurrentStateStore(moduleName),
|
||||
useAppVersionStore: createAppVersionStore(moduleName),
|
||||
useAppDataStore: createAppDataStore(moduleName),
|
||||
});
|
||||
|
||||
const mainModule = generateModule('#main');
|
||||
|
||||
export const useSuperStore = create((set, get) => ({
|
||||
modules: {
|
||||
'#main': mainModule,
|
||||
},
|
||||
|
||||
createModule: (moduleName) => {
|
||||
const modules = get().modules;
|
||||
const newModules = {
|
||||
...modules,
|
||||
[moduleName]: generateModule(moduleName),
|
||||
};
|
||||
|
||||
set(() => ({ modules: newModules }));
|
||||
return true;
|
||||
},
|
||||
|
||||
destroyModule: (moduleName) => {
|
||||
const modules = get().modules;
|
||||
const newModules = omit(modules, moduleName);
|
||||
set(() => ({ modules: newModules }));
|
||||
},
|
||||
}));
|
||||
|
|
@ -10,6 +10,7 @@ import i18n from 'i18next';
|
|||
import { initReactI18next } from 'react-i18next';
|
||||
// import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
import Backend from 'i18next-http-backend';
|
||||
import { ModuleContext } from './_contexts/ModuleContext';
|
||||
|
||||
const AppWithProfiler = Sentry.withProfiler(App);
|
||||
|
||||
|
|
@ -62,5 +63,12 @@ appService
|
|||
});
|
||||
}
|
||||
})
|
||||
.then(() => render(<AppWithProfiler />, document.getElementById('app')));
|
||||
.then(() =>
|
||||
render(
|
||||
<ModuleContext.Provider value={'#main'}>
|
||||
<AppWithProfiler />
|
||||
</ModuleContext.Provider>,
|
||||
document.getElementById('app')
|
||||
)
|
||||
);
|
||||
// .then(() => createRoot(document.getElementById('app')).render(<AppWithProfiler />));
|
||||
|
|
|
|||
|
|
@ -92,6 +92,8 @@ export class AppsControllerV2 {
|
|||
response['pages'] = pagesForVersion;
|
||||
response['events'] = eventsForVersion;
|
||||
|
||||
console.log({ app });
|
||||
|
||||
//! if editing version exists, camelize the definition
|
||||
if (app.editingVersion && app.editingVersion.definition) {
|
||||
response['editing_version'] = {
|
||||
|
|
|
|||
Loading…
Reference in a new issue