mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 08:58:26 +00:00
move outbound calls to top level
This commit is contained in:
parent
19850ea69e
commit
a9ed8de7be
5 changed files with 191 additions and 137 deletions
|
|
@ -7,18 +7,32 @@ import config from 'config';
|
|||
import { safelyParseJSON, stripTrailingSlash, redirectToDashboard, getSubpath, getWorkspaceId } from '@/_helpers/utils';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useAppDataActions } from '@/_stores/appDataStore';
|
||||
import Spinner from '@/_ui/Spinner';
|
||||
|
||||
const AppLoaderComponent = (props) => {
|
||||
const params = useParams();
|
||||
const appId = params.id;
|
||||
|
||||
const [shouldLoadApp, setShouldLoadApp] = React.useState(false);
|
||||
|
||||
const { updateState } = useAppDataActions();
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
useEffect(() => loadAppDetails(), []);
|
||||
|
||||
const loadAppDetails = () => {
|
||||
appService.getApp(appId, 'edit').catch((error) => {
|
||||
handleError(error);
|
||||
});
|
||||
appService
|
||||
.getApp(appId, 'edit')
|
||||
.then((data) => {
|
||||
updateState({
|
||||
app: data,
|
||||
});
|
||||
setShouldLoadApp(true);
|
||||
})
|
||||
.catch((error) => {
|
||||
handleError(error);
|
||||
});
|
||||
};
|
||||
|
||||
const switchOrganization = (orgId) => {
|
||||
|
|
@ -63,7 +77,13 @@ const AppLoaderComponent = (props) => {
|
|||
}
|
||||
};
|
||||
|
||||
return config.ENABLE_MULTIPLAYER_EDITING ? <RealtimeEditor {...props} /> : <Editor {...props} />;
|
||||
if (!shouldLoadApp) return <Spinner />;
|
||||
|
||||
return config.ENABLE_MULTIPLAYER_EDITING ? (
|
||||
<RealtimeEditor {...props} shouldLoadApp={shouldLoadApp} />
|
||||
) : (
|
||||
<Editor {...props} shouldLoadApp={shouldLoadApp} />
|
||||
);
|
||||
};
|
||||
|
||||
export const AppLoader = withTranslation()(AppLoaderComponent);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import cx from 'classnames';
|
||||
import { appVersionService, appEnvironmentService } from '@/_services';
|
||||
import { appVersionService } from '@/_services';
|
||||
import { CustomSelect } from './CustomSelect';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
|
|
@ -12,7 +12,6 @@ export const AppVersionsManager = function ({
|
|||
setAppDefinitionFromVersion,
|
||||
onVersionDelete,
|
||||
}) {
|
||||
const [appVersions, setAppVersions] = useState([]);
|
||||
const [appVersionStatus, setGetAppVersionStatus] = useState('');
|
||||
const [deleteVersion, setDeleteVersion] = useState({
|
||||
versionId: '',
|
||||
|
|
@ -20,29 +19,16 @@ export const AppVersionsManager = function ({
|
|||
showModal: false,
|
||||
});
|
||||
|
||||
const { editingVersion } = useAppVersionStore(
|
||||
const { editingVersion, appVersions, setAppVersions } = useAppVersionStore(
|
||||
(state) => ({
|
||||
editingVersion: state.editingVersion,
|
||||
appVersions: state.appVersions,
|
||||
setAppVersions: state.actions?.setAppVersions,
|
||||
}),
|
||||
shallow
|
||||
);
|
||||
const darkMode = localStorage.getItem('darkMode') === 'true';
|
||||
|
||||
useEffect(() => {
|
||||
setGetAppVersionStatus('loading');
|
||||
appEnvironmentService
|
||||
.getVersionsByEnvironment(appId)
|
||||
.then((data) => {
|
||||
setAppVersions(data.appVersions);
|
||||
setGetAppVersionStatus('success');
|
||||
})
|
||||
.catch((error) => {
|
||||
toast.error(error);
|
||||
setGetAppVersionStatus('failure');
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const selectVersion = (id) => {
|
||||
appVersionService
|
||||
.getOne(appId, id)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
||||
import { appService, authenticationService, appVersionService, orgEnvironmentVariableService } from '@/_services';
|
||||
import {
|
||||
appService,
|
||||
authenticationService,
|
||||
appVersionService,
|
||||
orgEnvironmentVariableService,
|
||||
appEnvironmentService,
|
||||
} from '@/_services';
|
||||
import { DndProvider } from 'react-dnd';
|
||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||
import _, {
|
||||
|
|
@ -55,19 +61,19 @@ import { withRouter } from '@/_hoc/withRouter';
|
|||
import { ReleasedVersionError } from './AppVersionsManager/ReleasedVersionError';
|
||||
import { useDataSourcesStore } from '@/_stores/dataSourcesStore';
|
||||
import { useDataQueries, useDataQueriesStore } from '@/_stores/dataQueriesStore';
|
||||
import { useAppVersionStore } from '@/_stores/appVersionStore';
|
||||
import { useAppVersionStore, useAppVersionActions } from '@/_stores/appVersionStore';
|
||||
import { useQueryPanelStore } from '@/_stores/queryPanelStore';
|
||||
import { useCurrentStateStore, useCurrentState } from '@/_stores/currentStateStore';
|
||||
import { computeAppDiff, resetAllStores } from '@/_stores/utils';
|
||||
import { setCookie } from '@/_helpers/cookie';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { useEditorActions, useEditorState, useEditorStore } from '@/_stores/editorStore';
|
||||
import { useAppDataActions, useAppDataStore, useAppInfo } from '@/_stores/appDataStore';
|
||||
import { useAppDataActions, useAppInfo } from '@/_stores/appDataStore';
|
||||
import { useMounted } from '@/_hooks/use-mount';
|
||||
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { diff } from 'deep-object-diff';
|
||||
import { camelizeKeys, decamelizeKeys } from 'humps';
|
||||
import { camelizeKeys } from 'humps';
|
||||
|
||||
setAutoFreeze(false);
|
||||
enablePatches();
|
||||
|
|
@ -78,12 +84,88 @@ function setWindowTitle(name) {
|
|||
|
||||
const decimalToHex = (alpha) => (alpha === 0 ? '00' : Math.round(255 * alpha).toString(16));
|
||||
|
||||
const buildComponentMetaDefinition = (components = {}, events = []) => {
|
||||
for (const componentId in components) {
|
||||
const currentComponentData = components[componentId];
|
||||
const componentEvents = events
|
||||
.filter((event) => event.sourceId === componentId)
|
||||
?.map((event) => ({ ...event.event, id: event.id }));
|
||||
const componentMeta = componentTypes.find((comp) => currentComponentData.component.component === comp.component);
|
||||
|
||||
const mergedDefinition = {
|
||||
...componentMeta.definition,
|
||||
events: componentEvents,
|
||||
properties: {
|
||||
...componentMeta.definition.properties,
|
||||
...currentComponentData?.component.definition.properties,
|
||||
},
|
||||
|
||||
styles: {
|
||||
...componentMeta.definition.styles,
|
||||
...currentComponentData?.component.definition.styles,
|
||||
},
|
||||
validations: {
|
||||
...componentMeta.definition.validations,
|
||||
...currentComponentData?.component.definition.validations,
|
||||
},
|
||||
};
|
||||
|
||||
const mergedComponent = {
|
||||
component: {
|
||||
...componentMeta,
|
||||
...currentComponentData.component,
|
||||
},
|
||||
layouts: {
|
||||
...currentComponentData.layouts,
|
||||
},
|
||||
withDefaultChildren: componentMeta.withDefaultChildren ?? false,
|
||||
};
|
||||
|
||||
mergedComponent.component.definition = mergedDefinition;
|
||||
|
||||
components[componentId] = mergedComponent;
|
||||
}
|
||||
|
||||
return components;
|
||||
};
|
||||
|
||||
const buildAppDefinition = (data) => {
|
||||
const editingVersion = _.omit(camelizeKeys(data.editing_version), ['definition', 'updatedAt', 'createdAt', 'name']);
|
||||
|
||||
editingVersion['currentVersionId'] = editingVersion.id;
|
||||
_.unset(editingVersion, 'id');
|
||||
|
||||
const eventsData = data?.events;
|
||||
|
||||
const pages = data.pages.reduce((acc, page) => {
|
||||
const currentComponents = buildComponentMetaDefinition(_.cloneDeep(page?.components), eventsData);
|
||||
|
||||
page.components = currentComponents;
|
||||
|
||||
acc[page.id] = page;
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const appJSON = {
|
||||
globalSettings: editingVersion.globalSettings,
|
||||
homePageId: editingVersion.homePageId,
|
||||
showHideViewerNavigation: editingVersion.showHideViewerNavigation ?? true,
|
||||
pages: pages,
|
||||
};
|
||||
|
||||
return appJSON;
|
||||
};
|
||||
|
||||
const EditorComponent = (props) => {
|
||||
const { socket } = createWebsocketConnection(props?.params?.id);
|
||||
const mounted = useMounted();
|
||||
|
||||
const { updateState, updateAppDefinitionDiff, updateAppVersion } = useAppDataActions();
|
||||
const { updateEditorState, updateQueryConfirmationList } = useEditorActions();
|
||||
|
||||
const { setAppVersions } = useAppVersionActions();
|
||||
|
||||
const {
|
||||
noOfVersionsSupported,
|
||||
appDefinition,
|
||||
|
|
@ -104,8 +186,18 @@ const EditorComponent = (props) => {
|
|||
|
||||
const dataQueries = useDataQueries();
|
||||
|
||||
const { isMaintenanceOn, appId, app, currentUser, currentVersionId, appDefinitionDiff, appDiffOptions, events } =
|
||||
useAppInfo();
|
||||
const {
|
||||
isMaintenanceOn,
|
||||
appId,
|
||||
app,
|
||||
appName,
|
||||
slug,
|
||||
currentUser,
|
||||
currentVersionId,
|
||||
appDefinitionDiff,
|
||||
appDiffOptions,
|
||||
events,
|
||||
} = useAppInfo();
|
||||
|
||||
const [currentPageId, setCurrentPageId] = useState(null);
|
||||
const [zoomLevel, setZoomLevel] = useState(1);
|
||||
|
|
@ -299,8 +391,9 @@ const EditorComponent = (props) => {
|
|||
const $componentDidMount = async () => {
|
||||
window.addEventListener('message', handleMessage);
|
||||
|
||||
await fetchApp(props.params.pageHandle, true);
|
||||
|
||||
await fetchApps(0);
|
||||
await fetchApp(props.params.pageHandle);
|
||||
await fetchOrgEnvironmentVariables();
|
||||
initComponentVersioning();
|
||||
initRealtimeSave();
|
||||
|
|
@ -323,6 +416,9 @@ const EditorComponent = (props) => {
|
|||
|
||||
updateState({ appId: props?.params?.id });
|
||||
useCurrentStateStore.getState().actions.setCurrentState({ globals });
|
||||
|
||||
getCanvasWidth();
|
||||
initEditorWalkThrough();
|
||||
};
|
||||
|
||||
const fetchDataQueries = async (id, selectFirstQuery = false, runQueriesOnAppLoad = false) => {
|
||||
|
|
@ -604,94 +700,36 @@ const EditorComponent = (props) => {
|
|||
|
||||
//!--------
|
||||
|
||||
const buildComponentMetaDefinition = (components = {}, events = []) => {
|
||||
for (const componentId in components) {
|
||||
const currentComponentData = components[componentId];
|
||||
const componentEvents = events
|
||||
.filter((event) => event.sourceId === componentId)
|
||||
?.map((event) => ({ ...event.event, id: event.id }));
|
||||
const componentMeta = componentTypes.find((comp) => currentComponentData.component.component === comp.component);
|
||||
|
||||
const mergedDefinition = {
|
||||
...componentMeta.definition,
|
||||
events: componentEvents,
|
||||
properties: {
|
||||
...componentMeta.definition.properties,
|
||||
...currentComponentData?.component.definition.properties,
|
||||
},
|
||||
|
||||
styles: {
|
||||
...componentMeta.definition.styles,
|
||||
...currentComponentData?.component.definition.styles,
|
||||
},
|
||||
validations: {
|
||||
...componentMeta.definition.validations,
|
||||
...currentComponentData?.component.definition.validations,
|
||||
},
|
||||
};
|
||||
|
||||
const mergedComponent = {
|
||||
component: {
|
||||
...componentMeta,
|
||||
...currentComponentData.component,
|
||||
},
|
||||
layouts: {
|
||||
...currentComponentData.layouts,
|
||||
},
|
||||
withDefaultChildren: componentMeta.withDefaultChildren ?? false,
|
||||
};
|
||||
|
||||
mergedComponent.component.definition = mergedDefinition;
|
||||
|
||||
components[componentId] = mergedComponent;
|
||||
}
|
||||
|
||||
return components;
|
||||
};
|
||||
|
||||
const buildAppDefinition = (data) => {
|
||||
const editingVersion = _.omit(camelizeKeys(data.editing_version), ['definition', 'updatedAt', 'createdAt', 'name']);
|
||||
|
||||
editingVersion['currentVersionId'] = editingVersion.id;
|
||||
_.unset(editingVersion, 'id');
|
||||
|
||||
const eventsData = data?.events;
|
||||
|
||||
const pages = data.pages.reduce((acc, page) => {
|
||||
const currentComponents = buildComponentMetaDefinition(_.cloneDeep(page?.components), eventsData);
|
||||
|
||||
page.components = currentComponents;
|
||||
|
||||
acc[page.id] = page;
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const appJSON = {
|
||||
globalSettings: editingVersion.globalSettings,
|
||||
homePageId: editingVersion.homePageId,
|
||||
showHideViewerNavigation: editingVersion.showHideViewerNavigation ?? true,
|
||||
pages: pages,
|
||||
};
|
||||
|
||||
return appJSON;
|
||||
};
|
||||
|
||||
//****** */
|
||||
|
||||
const fetchApp = async (startingPageHandle) => {
|
||||
const fetchApp = async (startingPageHandle, onMount = false) => {
|
||||
const _appId = props?.params?.id;
|
||||
|
||||
const callBack = async (data) => {
|
||||
useAppVersionStore.getState().actions.updateEditingVersion(data.editing_version);
|
||||
useAppVersionStore.getState().actions.updateReleasedVersionId(data.current_version_id);
|
||||
|
||||
const appVersions = await appEnvironmentService.getVersionsByEnvironment(data?.id);
|
||||
setAppVersions(appVersions.appVersions);
|
||||
|
||||
updateState({
|
||||
slug: data.slug,
|
||||
isMaintenanceOn: data?.is_maintenance_on,
|
||||
organizationId: data?.organization_id,
|
||||
isPublic: data?.is_public,
|
||||
appName: data?.name,
|
||||
userId: data?.user_id,
|
||||
appId: data?.id,
|
||||
events: data.events,
|
||||
});
|
||||
|
||||
await fetchDataSources(data.editing_version?.id);
|
||||
await fetchDataQueries(data.editing_version?.id, true, true);
|
||||
|
||||
const appDefData = buildAppDefinition(data);
|
||||
|
||||
const appJson = appDefData;
|
||||
const pages = data.pages;
|
||||
const events = data.events;
|
||||
|
||||
const startingPageId = pages.filter((page) => page.handle === startingPageHandle)[0]?.id;
|
||||
const homePageId = !startingPageId || startingPageId === 'null' ? appJson.homePageId : startingPageId;
|
||||
|
|
@ -705,18 +743,6 @@ const EditorComponent = (props) => {
|
|||
|
||||
setCurrentPageId(homePageId);
|
||||
|
||||
updateState({
|
||||
app: data,
|
||||
slug: data.slug,
|
||||
isMaintenanceOn: data?.is_maintenance_on,
|
||||
organizationId: data?.organization_id,
|
||||
isPublic: data?.is_public,
|
||||
appName: data?.name,
|
||||
userId: data?.user_id,
|
||||
appId: data?.id,
|
||||
events: events,
|
||||
});
|
||||
|
||||
useCurrentStateStore.getState().actions.setCurrentState({
|
||||
page: currentpageData,
|
||||
});
|
||||
|
|
@ -729,17 +755,13 @@ const EditorComponent = (props) => {
|
|||
for (const event of appJson.pages[homePageId]?.events ?? []) {
|
||||
await handleEvent(event.eventId, event);
|
||||
}
|
||||
getCanvasWidth();
|
||||
};
|
||||
|
||||
updateState({
|
||||
isLoading: true,
|
||||
});
|
||||
|
||||
await appService
|
||||
.getApp(_appId)
|
||||
.then(callBack)
|
||||
.finally(() => initEditorWalkThrough());
|
||||
if (!onMount) {
|
||||
await appService.getApp(_appId).then(callBack);
|
||||
} else {
|
||||
callBack(app);
|
||||
}
|
||||
};
|
||||
|
||||
// !--------
|
||||
|
|
@ -1498,12 +1520,27 @@ const EditorComponent = (props) => {
|
|||
: '';
|
||||
const deviceWindowWidth = 450;
|
||||
|
||||
if (!appDefinition?.homePageId) {
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="editor wrapper">
|
||||
<div className="editor__loading">
|
||||
<div className="editor__loading__spinner">{/* <Spinner /> */}</div>
|
||||
<div className="editor__loading__text">Loading...</div>
|
||||
<div className="apploader">
|
||||
<div className="col col-* editor-center-wrapper">
|
||||
<div className="editor-center">
|
||||
<div className="canvas">
|
||||
<div className="mt-5 d-flex flex-column">
|
||||
<div className="mb-1">
|
||||
<Skeleton width={'150px'} height={15} className="skeleton" />
|
||||
</div>
|
||||
{Array.from(Array(4)).map((_item, index) => (
|
||||
<Skeleton key={index} width={'300px'} height={10} className="skeleton" />
|
||||
))}
|
||||
<div className="align-self-end">
|
||||
<Skeleton width={'100px'} className="skeleton" />
|
||||
</div>
|
||||
<Skeleton className="skeleton mt-4" />
|
||||
<Skeleton height={'150px'} className="skeleton mt-2" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -1541,6 +1578,10 @@ const EditorComponent = (props) => {
|
|||
onVersionRelease={onVersionRelease}
|
||||
saveEditingVersion={saveEditingVersion}
|
||||
onVersionDelete={onVersionDelete}
|
||||
isMaintenanceOn={isMaintenanceOn}
|
||||
appName={appName}
|
||||
appId={appId}
|
||||
slug={slug}
|
||||
/>
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
<div className="sub-section">
|
||||
|
|
@ -1558,9 +1599,9 @@ const EditorComponent = (props) => {
|
|||
appDefinition={{
|
||||
components: appDefinition?.pages[currentPageId]?.components ?? {},
|
||||
selectedComponent: selectedComponents ? selectedComponents[selectedComponents.length - 1] : {},
|
||||
pages: appDefinition?.pages,
|
||||
homePageId: appDefinition.homePageId,
|
||||
showViewerNavigation: appDefinition.showViewerNavigation,
|
||||
pages: appDefinition?.pages ?? {},
|
||||
homePageId: appDefinition?.homePageId ?? null,
|
||||
showViewerNavigation: appDefinition?.showViewerNavigation,
|
||||
}}
|
||||
setSelectedComponent={setSelectedComponent}
|
||||
removeComponent={removeComponent}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import config from 'config';
|
|||
import { useUpdatePresence } from '@y-presence/react';
|
||||
import { useAppVersionStore } from '@/_stores/appVersionStore';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { useAppDataActions, useAppInfo, useCurrentUser } from '@/_stores/appDataStore';
|
||||
import { useAppDataActions, useCurrentUser } from '@/_stores/appDataStore';
|
||||
|
||||
export default function EditorHeader({
|
||||
darkMode,
|
||||
|
|
@ -34,11 +34,13 @@ export default function EditorHeader({
|
|||
onVersionRelease,
|
||||
saveEditingVersion,
|
||||
onVersionDelete,
|
||||
isMaintenanceOn,
|
||||
appName,
|
||||
appId,
|
||||
slug,
|
||||
}) {
|
||||
const currentUser = useCurrentUser();
|
||||
|
||||
const { isMaintenanceOn, appName, appId, slug } = useAppInfo();
|
||||
|
||||
const { updateState } = useAppDataActions();
|
||||
|
||||
const handleSlugChange = (newSlug) => {
|
||||
|
|
@ -54,6 +56,7 @@ export default function EditorHeader({
|
|||
);
|
||||
|
||||
const updatePresence = useUpdatePresence();
|
||||
|
||||
useEffect(() => {
|
||||
const initialPresence = {
|
||||
firstName: currentUser?.first_name ?? '',
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ const initialState = {
|
|||
isUserEditingTheVersion: false,
|
||||
releasedVersionId: null,
|
||||
isVersionReleased: false,
|
||||
appVersions: [],
|
||||
};
|
||||
|
||||
export const useAppVersionStore = create(
|
||||
|
|
@ -21,8 +22,11 @@ export const useAppVersionStore = create(
|
|||
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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue