mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 17:08:34 +00:00
appdefinition refactor/cleanup (#7872)
* cleanup controllers and request calls from frontend * removing unwanted console logs and unused variables * revering v1 apis og * adding length validation for page dto * adding dtos for components * updated dtos for components and pages * added dto for event handlers * fixes event handler dto * fixes: page dto * adds/fixes event handlers creating dtp * fixes: event handler service and dtos
This commit is contained in:
parent
790681f921
commit
942c700275
23 changed files with 420 additions and 205 deletions
|
|
@ -23,7 +23,7 @@ const AppLoaderComponent = (props) => {
|
|||
|
||||
const loadAppDetails = () => {
|
||||
appService
|
||||
.getApp(appId, 'edit')
|
||||
.fetchApp(appId, 'edit')
|
||||
.then((data) => {
|
||||
setShouldLoadApp(true);
|
||||
updateState({
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export const AppVersionsManager = function ({ appId, setAppDefinitionFromVersion
|
|||
|
||||
const selectVersion = (id) => {
|
||||
appVersionService
|
||||
.getOne(appId, id)
|
||||
.getAppVersionData(appId, id)
|
||||
.then((data) => {
|
||||
const isCurrentVersionReleased = data.currentVersionId ? true : false;
|
||||
setAppDefinitionFromVersion(data, isCurrentVersionReleased);
|
||||
|
|
@ -83,7 +83,7 @@ export const AppVersionsManager = function ({ appId, setAppDefinitionFromVersion
|
|||
resetDeleteModal();
|
||||
});
|
||||
};
|
||||
|
||||
//this
|
||||
const options = appVersions.map((appVersion) => ({
|
||||
value: appVersion.id,
|
||||
isReleasedVersion: appVersion.id === releasedVersionId,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import ToggleGroup from '@/ToolJetUI/SwitchGroup/ToggleGroup';
|
|||
import ToggleGroupItem from '@/ToolJetUI/SwitchGroup/ToggleGroupItem';
|
||||
import React from 'react';
|
||||
|
||||
const ClientServerSwitch = ({ value, onChange, cyLabel, meta, paramName }) => {
|
||||
const ClientServerSwitch = ({ value, onChange, meta }) => {
|
||||
const options = meta?.options;
|
||||
const defaultValue = value ? 'serverSide' : 'clientSide';
|
||||
const handleChange = (_value) => {
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ const EditorComponent = (props) => {
|
|||
const [currentPageId, setCurrentPageId] = useState(null);
|
||||
const [zoomLevel, setZoomLevel] = useState(1);
|
||||
const [isQueryPaneDragging, setIsQueryPaneDragging] = useState(false);
|
||||
const [isQueryPaneExpanded, setIsQueryPaneExpanded] = useState(false);
|
||||
const [isQueryPaneExpanded, setIsQueryPaneExpanded] = useState(false); //!check where this is used
|
||||
const [selectionInProgress, setSelectionInProgress] = useState(false);
|
||||
const [hoveredComponent, setHoveredComponent] = useState(null);
|
||||
const [editorMarginLeft, setEditorMarginLeft] = useState(0);
|
||||
|
|
@ -157,15 +157,13 @@ const EditorComponent = (props) => {
|
|||
|
||||
useEffect(() => {
|
||||
updateState({ isLoading: true });
|
||||
// 1. Get the current session and current user from the authentication service
|
||||
|
||||
const currentSession = authenticationService.currentSessionValue;
|
||||
const currentUser = currentSession?.current_user;
|
||||
|
||||
// 2. Subscribe to changes in the current session using RxJS observable pattern
|
||||
// Subscribe to changes in the current session using RxJS observable pattern
|
||||
const subscription = authenticationService.currentSession.subscribe((currentSession) => {
|
||||
// 3. Check if the current user and group permissions are available
|
||||
if (currentUser && currentSession?.group_permissions) {
|
||||
// 4. Prepare user details in a format suitable for the application
|
||||
const userVars = {
|
||||
email: currentUser.email,
|
||||
firstName: currentUser.first_name,
|
||||
|
|
@ -239,8 +237,6 @@ const EditorComponent = (props) => {
|
|||
|
||||
useEffect(() => {
|
||||
// This effect runs when lastKeyPressTimestamp changes
|
||||
// You can place your database update logic here
|
||||
// Ensure that you only update the database if the timestamp is recent
|
||||
if (Date.now() - lastKeyPressTimestamp < 500) {
|
||||
updateEditorState({
|
||||
isUpdatingEditorStateInProcess: true,
|
||||
|
|
@ -352,6 +348,7 @@ const EditorComponent = (props) => {
|
|||
});
|
||||
};
|
||||
|
||||
//! websocket events do not work
|
||||
const initEventListeners = () => {
|
||||
socket?.addEventListener('message', (event) => {
|
||||
const data = event.data.replace(/^"(.+(?="$))"$/, '$1');
|
||||
|
|
@ -368,7 +365,6 @@ const EditorComponent = (props) => {
|
|||
window.addEventListener('message', handleMessage);
|
||||
|
||||
await fetchApp(props.params.pageHandle, true);
|
||||
|
||||
await fetchApps(0);
|
||||
await fetchOrgEnvironmentVariables();
|
||||
await fetchOrgEnvironmentConstants();
|
||||
|
|
@ -495,7 +491,6 @@ const EditorComponent = (props) => {
|
|||
const handleQueryPaneDragging = (bool) => setIsQueryPaneDragging(bool);
|
||||
const handleQueryPaneExpanding = (bool) => setIsQueryPaneExpanded(bool);
|
||||
|
||||
//! Needs attention
|
||||
const handleOnComponentOptionChanged = (component, optionName, value) => {
|
||||
return onComponentOptionChanged(component, optionName, value);
|
||||
};
|
||||
|
|
@ -657,15 +652,8 @@ const EditorComponent = (props) => {
|
|||
appDefinitionChanged(newAppDefinition, {
|
||||
globalSettings: true,
|
||||
});
|
||||
|
||||
// props.ymap?.set('appDef', {
|
||||
// newDefinition: appDefinition,
|
||||
// editingVersionId: props.editingVersion?.id,
|
||||
// });
|
||||
// autoSave();
|
||||
};
|
||||
|
||||
//!--------
|
||||
const callBack = async (data, startingPageHandle, versionSwitched = false) => {
|
||||
setWindowTitle(data.name);
|
||||
useAppVersionStore.getState().actions.updateEditingVersion(data.editing_version);
|
||||
|
|
@ -724,28 +712,19 @@ const EditorComponent = (props) => {
|
|||
await handleEvent('onPageLoad', currentPageEvents);
|
||||
};
|
||||
|
||||
//****** */
|
||||
|
||||
const fetchApp = async (startingPageHandle, onMount = false) => {
|
||||
const _appId = props?.params?.id;
|
||||
|
||||
if (!onMount) {
|
||||
await appService.getApp(_appId).then((data) => callBack(data, startingPageHandle));
|
||||
await appService.fetchApp(_appId).then((data) => callBack(data, startingPageHandle));
|
||||
} else {
|
||||
callBack(app, startingPageHandle);
|
||||
}
|
||||
};
|
||||
|
||||
// !--------
|
||||
const setAppDefinitionFromVersion = (appData, isCurrentVersionReleased = true) => {
|
||||
const setAppDefinitionFromVersion = (appData) => {
|
||||
const version = appData?.editing_version?.id;
|
||||
if (version?.id !== editingVersion?.id) {
|
||||
// !Need to fix this
|
||||
// appDefinitionChanged(defaults(version.definition, defaultDefinition(props.darkMode)), {
|
||||
// skipAutoSave: true,
|
||||
// skipYmapUpdate: true,
|
||||
// versionChanged: true,
|
||||
// });
|
||||
if (version?.id === currentVersionId) {
|
||||
updateEditorState({
|
||||
canUndo: false,
|
||||
|
|
@ -758,7 +737,6 @@ const EditorComponent = (props) => {
|
|||
});
|
||||
|
||||
callBack(appData, null, true);
|
||||
|
||||
initComponentVersioning();
|
||||
}
|
||||
};
|
||||
|
|
@ -813,8 +791,6 @@ const EditorComponent = (props) => {
|
|||
|
||||
const diffPatches = diff(appDefinition, updatedAppDefinition);
|
||||
|
||||
console.log('---arpit::---[diffPatches]', { diffPatches });
|
||||
|
||||
const inversePatches = diff(updatedAppDefinition, appDefinition);
|
||||
const shouldUpdate = !_.isEmpty(diffPatches) && !isEqual(appDefinitionDiff, diffPatches);
|
||||
|
||||
|
|
@ -918,7 +894,7 @@ const EditorComponent = (props) => {
|
|||
isUpdatingEditorStateInProcess: false,
|
||||
});
|
||||
} else if (!isEmpty(editingVersion)) {
|
||||
// param diff ofr table columns needs the complte column data or else the json structure is not correct computeComponentPropertyDiff function handles this
|
||||
//! The computeComponentPropertyDiff function manages the calculation of differences in table columns by requiring complete column data. Without this complete data, the resulting JSON structure may be incorrect.
|
||||
const paramDiff = computeComponentPropertyDiff(appDefinitionDiff, appDefinition, appDiffOptions);
|
||||
const updateDiff = computeAppDiff(paramDiff, currentPageId, appDiffOptions, currentLayout);
|
||||
|
||||
|
|
@ -1105,7 +1081,6 @@ const EditorComponent = (props) => {
|
|||
const removeComponent = (componentId) => {
|
||||
if (!isVersionReleased) {
|
||||
let newDefinition = cloneDeep(appDefinition);
|
||||
// Delete child components when parent is deleted
|
||||
|
||||
let childComponents = [];
|
||||
|
||||
|
|
@ -1223,7 +1198,7 @@ const EditorComponent = (props) => {
|
|||
icon: '🗑️',
|
||||
});
|
||||
}
|
||||
// appDefinitionChanged(newDefinition);
|
||||
|
||||
handleInspectorView();
|
||||
} else if (isVersionReleased) {
|
||||
useAppVersionStore.getState().actions.enableReleasedVersionPopupState();
|
||||
|
|
@ -1258,6 +1233,11 @@ const EditorComponent = (props) => {
|
|||
return;
|
||||
}
|
||||
|
||||
if (name.length > 32) {
|
||||
toast.error('Page name cannot be more than 32 characters');
|
||||
return;
|
||||
}
|
||||
|
||||
const pageHandles = Object.values(appDefinition.pages).map((page) => page.handle);
|
||||
|
||||
let newHandle = handle;
|
||||
|
|
@ -1541,8 +1521,6 @@ const EditorComponent = (props) => {
|
|||
});
|
||||
};
|
||||
|
||||
// !-------
|
||||
|
||||
const appVersionPreviewLink = editingVersion
|
||||
? `/applications/${appId}/versions/${editingVersion.id}/${currentState.page.handle}`
|
||||
: '';
|
||||
|
|
@ -1583,6 +1561,7 @@ const EditorComponent = (props) => {
|
|||
);
|
||||
}
|
||||
|
||||
//! Need to move conditionally rendered components to separate components => Widget Manger or Widget Inspector
|
||||
const shouldrenderWidgetInspector =
|
||||
currentSidebarTab === 1 &&
|
||||
selectedComponents?.length === 1 &&
|
||||
|
|
@ -1614,7 +1593,6 @@ const EditorComponent = (props) => {
|
|||
<EditorHeader
|
||||
darkMode={props.darkMode}
|
||||
appDefinition={_.cloneDeep(appDefinition)}
|
||||
// toggleAppMaintenance={toggleAppMaintenance}
|
||||
editingVersion={editingVersion}
|
||||
appVersionPreviewLink={appVersionPreviewLink}
|
||||
canUndo={canUndo}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ export default function EditorHeader({
|
|||
onVersionRelease,
|
||||
saveEditingVersion,
|
||||
onVersionDelete,
|
||||
isMaintenanceOn,
|
||||
slug,
|
||||
darkMode,
|
||||
}) {
|
||||
|
|
|
|||
|
|
@ -12,11 +12,7 @@ import { componentTypes } from '../WidgetManager/components';
|
|||
import Select from '@/_ui/Select';
|
||||
import defaultStyles from '@/_ui/Select/styles';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { useDataQueriesStore } from '@/_stores/dataQueriesStore';
|
||||
import AddRectangle from '@/_ui/Icon/bulkIcons/AddRectangle';
|
||||
import { Tooltip } from 'react-tooltip';
|
||||
import { ButtonSolid } from '@/_ui/AppButton/AppButton';
|
||||
import RunjsParameters from './ActionConfigurationPanels/RunjsParamters';
|
||||
import { useAppDataActions, useAppInfo } from '@/_stores/appDataStore';
|
||||
import { isQueryRunnable } from '@/_helpers/utils';
|
||||
|
|
@ -24,7 +20,6 @@ import { shallow } from 'zustand/shallow';
|
|||
import AddNewButton from '@/ToolJetUI/Buttons/AddNewButton/AddNewButton';
|
||||
import NoListItem from './Components/Table/NoListItem';
|
||||
import ManageEventButton from './ManageEventButton';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
|
||||
export const EventManager = ({
|
||||
sourceId,
|
||||
|
|
@ -37,7 +32,7 @@ export const EventManager = ({
|
|||
pages,
|
||||
hideEmptyEventsAlert,
|
||||
callerQueryId,
|
||||
customEventRefs = {},
|
||||
customEventRefs = undefined,
|
||||
}) => {
|
||||
const dataQueries = useDataQueriesStore(({ dataQueries = [] }) => {
|
||||
if (callerQueryId) {
|
||||
|
|
@ -915,7 +910,7 @@ export const EventManager = ({
|
|||
{events.map((event, index) => {
|
||||
const actionMeta = ActionTypes.find((action) => action.id === event.event.actionId);
|
||||
|
||||
const rowClassName = `card-body p-0 ${focusedEventIndex === index ? ' bg-azure-lt' : ''}`;
|
||||
// const rowClassName = `card-body p-0 ${focusedEventIndex === index ? ' bg-azure-lt' : ''}`;
|
||||
return (
|
||||
<Draggable key={index} draggableId={`${event.eventId}-${index}`} index={index}>
|
||||
{renderDraggable((provided, snapshot) => {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import { EventManager } from '@/Editor/Inspector/EventManager';
|
|||
import { staticDataSources, customToggles, mockDataQueryAsComponent } from '../constants';
|
||||
import { DataSourceTypes } from '../../DataSourceManager/SourceComponents';
|
||||
import { useDataSources, useGlobalDataSources } from '@/_stores/dataSourcesStore';
|
||||
import { useDataQueriesActions, useDataQueriesStore } from '@/_stores/dataQueriesStore';
|
||||
import { useDataQueriesActions } from '@/_stores/dataQueriesStore';
|
||||
import { useSelectedQuery, useSelectedDataSource } from '@/_stores/queryPanelStore';
|
||||
import { useAppVersionStore } from '@/_stores/appVersionStore';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
|
|
|
|||
|
|
@ -8,13 +8,7 @@ import { ConfirmDialog } from '@/_components/ConfirmDialog';
|
|||
import { shallow } from 'zustand/shallow';
|
||||
import { ButtonSolid } from '@/_ui/AppButton/AppButton';
|
||||
|
||||
export const ReleaseVersionButton = function DeployVersionButton({
|
||||
appId,
|
||||
appName,
|
||||
fetchApp,
|
||||
onVersionRelease,
|
||||
saveEditingVersion,
|
||||
}) {
|
||||
export const ReleaseVersionButton = function DeployVersionButton({ appId, appName, fetchApp, onVersionRelease }) {
|
||||
const [isReleasing, setIsReleasing] = useState(false);
|
||||
const { isVersionReleased, editingVersion } = useAppVersionStore(
|
||||
(state) => ({
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ class ViewerComponent extends React.Component {
|
|||
|
||||
loadApplicationBySlug = (slug) => {
|
||||
appService
|
||||
.getAppBySlug(slug)
|
||||
.fetchAppBySlug(slug)
|
||||
.then((data) => {
|
||||
this.setStateForApp(data, true);
|
||||
this.setStateForContainer(data);
|
||||
|
|
@ -302,7 +302,7 @@ class ViewerComponent extends React.Component {
|
|||
|
||||
loadApplicationByVersion = (appId, versionId) => {
|
||||
appService
|
||||
.getAppByVersion(appId, versionId)
|
||||
.fetchAppByVersion(appId, versionId)
|
||||
.then((data) => {
|
||||
this.setStateForApp(data);
|
||||
this.setStateForContainer(data, versionId);
|
||||
|
|
|
|||
|
|
@ -1382,6 +1382,7 @@ const updateNewComponents = (pageId, appDefinition, newComponents, updateAppDefi
|
|||
if (!isCut) {
|
||||
opts.cloningComponent = componentMap;
|
||||
}
|
||||
|
||||
updateAppDefinition(newAppDefinition, opts);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,11 @@ export const appService = {
|
|||
changeIcon,
|
||||
deleteApp,
|
||||
getApp,
|
||||
fetchApp,
|
||||
getAppBySlug,
|
||||
fetchAppBySlug,
|
||||
getAppByVersion,
|
||||
fetchAppByVersion,
|
||||
saveApp,
|
||||
getAppUsers,
|
||||
createAppUser,
|
||||
|
|
@ -124,6 +127,14 @@ function getApp(id, accessType) {
|
|||
);
|
||||
}
|
||||
|
||||
// v2 api for fetching app
|
||||
function fetchApp(id, accessType) {
|
||||
const requestOptions = { method: 'GET', headers: authHeader(), credentials: 'include' };
|
||||
return fetch(`${config.apiUrl}/v2/apps/${id}${accessType ? `?access_type=${accessType}` : ''}`, requestOptions).then(
|
||||
handleResponse
|
||||
);
|
||||
}
|
||||
|
||||
function deleteApp(id) {
|
||||
const requestOptions = { method: 'DELETE', headers: authHeader(), credentials: 'include' };
|
||||
return fetch(`${config.apiUrl}/apps/${id}`, requestOptions).then(handleResponse);
|
||||
|
|
@ -134,10 +145,19 @@ function getAppBySlug(slug) {
|
|||
return fetch(`${config.apiUrl}/apps/slugs/${slug}`, requestOptions).then(handleResponse);
|
||||
}
|
||||
|
||||
function fetchAppBySlug(slug) {
|
||||
const requestOptions = { method: 'GET', headers: authHeader(), credentials: 'include' };
|
||||
return fetch(`${config.apiUrl}/v2/apps/slugs/${slug}`, requestOptions).then(handleResponse);
|
||||
}
|
||||
|
||||
function getAppByVersion(appId, versionId) {
|
||||
const requestOptions = { method: 'GET', headers: authHeader(), credentials: 'include' };
|
||||
return fetch(`${config.apiUrl}/apps/${appId}/versions/${versionId}`, requestOptions).then(handleResponse);
|
||||
}
|
||||
function fetchAppByVersion(appId, versionId) {
|
||||
const requestOptions = { method: 'GET', headers: authHeader(), credentials: 'include' };
|
||||
return fetch(`${config.apiUrl}/v2/apps/${appId}/versions/${versionId}`, requestOptions).then(handleResponse);
|
||||
}
|
||||
|
||||
function saveApp(id, attributes) {
|
||||
const requestOptions = {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { authHeader, handleResponse } from '@/_helpers';
|
|||
export const appVersionService = {
|
||||
getAll,
|
||||
getOne,
|
||||
getAppVersionData,
|
||||
create,
|
||||
del,
|
||||
save,
|
||||
|
|
@ -23,6 +24,10 @@ function getOne(appId, versionId) {
|
|||
const requestOptions = { method: 'GET', headers: authHeader(), credentials: 'include' };
|
||||
return fetch(`${config.apiUrl}/apps/${appId}/versions/${versionId}`, requestOptions).then(handleResponse);
|
||||
}
|
||||
function getAppVersionData(appId, versionId) {
|
||||
const requestOptions = { method: 'GET', headers: authHeader(), credentials: 'include' };
|
||||
return fetch(`${config.apiUrl}/v2/apps/${appId}/versions/${versionId}`, requestOptions).then(handleResponse);
|
||||
}
|
||||
|
||||
function create(appId, versionName, versionFromId) {
|
||||
const body = {
|
||||
|
|
@ -78,10 +83,6 @@ function autoSaveApp(appId, versionId, diff, type, pageId, operation, isUserSwit
|
|||
global_settings: {
|
||||
update: { ...diff },
|
||||
},
|
||||
events: {
|
||||
update: diff,
|
||||
create: diff,
|
||||
},
|
||||
};
|
||||
|
||||
const body = !type
|
||||
|
|
@ -121,7 +122,7 @@ function saveAppVersionEventHandlers(appId, versionId, events, updateType = 'upd
|
|||
|
||||
function createAppVersionEventHandler(appId, versionId, event) {
|
||||
const body = {
|
||||
event,
|
||||
...event,
|
||||
};
|
||||
|
||||
const requestOptions = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useCallback, useState } from 'react';
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import useRouter from '@/_hooks/use-router';
|
||||
import { ToolTip } from '@/_components/ToolTip';
|
||||
|
|
|
|||
|
|
@ -28,16 +28,11 @@ import { EntityManager } from 'typeorm';
|
|||
import { ValidAppInterceptor } from 'src/interceptors/valid.app.interceptor';
|
||||
import { AppDecorator } from 'src/decorators/app.decorator';
|
||||
|
||||
import { PageService } from '@services/page.service';
|
||||
import { EventsService } from '@services/events_handler.service';
|
||||
|
||||
@Controller('apps')
|
||||
export class AppsController {
|
||||
constructor(
|
||||
private appsService: AppsService,
|
||||
private foldersService: FoldersService,
|
||||
private pageService: PageService,
|
||||
private eventsService: EventsService,
|
||||
private appsAbilityFactory: AppsAbilityFactory
|
||||
) {}
|
||||
|
||||
|
|
@ -84,17 +79,11 @@ export class AppsController {
|
|||
}
|
||||
|
||||
const response = decamelizeKeys(app);
|
||||
|
||||
const seralizedQueries = [];
|
||||
const dataQueriesForVersion = app.editingVersion
|
||||
? await this.appsService.findDataQueriesForVersion(app.editingVersion.id)
|
||||
: [];
|
||||
|
||||
const pagesForVersion = app.editingVersion ? await this.pageService.findPagesForVersion(app.editingVersion.id) : [];
|
||||
const eventsForVersion = app.editingVersion
|
||||
? await this.eventsService.findEventsForVersion(app.editingVersion.id)
|
||||
: [];
|
||||
|
||||
// serialize queries
|
||||
for (const query of dataQueriesForVersion) {
|
||||
const decamelizedQuery = decamelizeKeys(query);
|
||||
|
|
@ -104,8 +93,6 @@ export class AppsController {
|
|||
|
||||
response['data_queries'] = seralizedQueries;
|
||||
response['definition'] = app.editingVersion?.definition;
|
||||
response['pages'] = pagesForVersion;
|
||||
response['events'] = eventsForVersion;
|
||||
|
||||
//! if editing version exists, camelize the definition
|
||||
if (app.editingVersion && app.editingVersion.definition) {
|
||||
|
|
@ -136,9 +123,6 @@ export class AppsController {
|
|||
? await this.appsService.findVersion(app.currentVersionId)
|
||||
: await this.appsService.findVersion(app.editingVersion?.id);
|
||||
|
||||
const pagesForVersion = app.editingVersion ? await this.pageService.findPagesForVersion(versionToLoad.id) : [];
|
||||
const eventsForVersion = app.editingVersion ? await this.eventsService.findEventsForVersion(versionToLoad.id) : [];
|
||||
|
||||
// serialize
|
||||
return {
|
||||
current_version_id: app['currentVersionId'],
|
||||
|
|
@ -148,11 +132,6 @@ export class AppsController {
|
|||
is_maintenance_on: app.isMaintenanceOn,
|
||||
name: app.name,
|
||||
slug: app.slug,
|
||||
events: eventsForVersion,
|
||||
pages: pagesForVersion,
|
||||
homePageId: versionToLoad.homePageId,
|
||||
globalSettings: versionToLoad.globalSettings,
|
||||
showViewerNavigation: versionToLoad.showViewerNavigation,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -308,25 +287,7 @@ export class AppsController {
|
|||
);
|
||||
}
|
||||
|
||||
const pagesForVersion = await this.pageService.findPagesForVersion(versionId);
|
||||
const eventsForVersion = await this.eventsService.findEventsForVersion(versionId);
|
||||
|
||||
const appCurrentEditingVersion = JSON.parse(JSON.stringify(appVersion));
|
||||
|
||||
delete appCurrentEditingVersion['app'];
|
||||
|
||||
const appData = {
|
||||
...app,
|
||||
};
|
||||
|
||||
delete appData['editingVersion'];
|
||||
|
||||
return {
|
||||
...appData,
|
||||
editing_version: camelizeKeys(appCurrentEditingVersion),
|
||||
pages: pagesForVersion,
|
||||
events: eventsForVersion,
|
||||
};
|
||||
return { ...appVersion, data_queries: appVersion.dataQueries };
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ import { AppsAbilityFactory } from 'src/modules/casl/abilities/apps-ability.fact
|
|||
import { App } from 'src/entities/app.entity';
|
||||
import { User } from 'src/decorators/user.decorator';
|
||||
|
||||
import { VersionEditDto } from '@dto/version-edit.dto';
|
||||
import { CreatePageDto, UpdatePageDto } from '@dto/pages.dto';
|
||||
import { CreatePageDto, DeletePageDto } from '@dto/pages.dto';
|
||||
import { CreateComponentDto, DeleteComponentDto, UpdateComponentDto, LayoutUpdateDto } from '@dto/component.dto';
|
||||
|
||||
import { ValidAppInterceptor } from 'src/interceptors/valid.app.interceptor';
|
||||
import { AppDecorator } from 'src/decorators/app.decorator';
|
||||
|
|
@ -30,6 +30,7 @@ import { ComponentsService } from '@services/components.service';
|
|||
import { PageService } from '@services/page.service';
|
||||
import { EventsService } from '@services/events_handler.service';
|
||||
import { AppVersionUpdateDto } from '@dto/app-version-update.dto';
|
||||
import { CreateEventHandlerDto, UpdateEventHandlerDto } from '@dto/event-handler.dto';
|
||||
|
||||
@Controller({
|
||||
path: 'apps',
|
||||
|
|
@ -40,6 +41,7 @@ export class AppsControllerV2 {
|
|||
private appsService: AppsService,
|
||||
private componentsService: ComponentsService,
|
||||
private pageService: PageService,
|
||||
private eventsService: EventsService,
|
||||
private eventService: EventsService,
|
||||
private appsAbilityFactory: AppsAbilityFactory
|
||||
) {}
|
||||
|
|
@ -73,6 +75,9 @@ export class AppsControllerV2 {
|
|||
: [];
|
||||
|
||||
const pagesForVersion = app.editingVersion ? await this.pageService.findPagesForVersion(app.editingVersion.id) : [];
|
||||
const eventsForVersion = app.editingVersion
|
||||
? await this.eventsService.findEventsForVersion(app.editingVersion.id)
|
||||
: [];
|
||||
|
||||
// serialize queries
|
||||
for (const query of dataQueriesForVersion) {
|
||||
|
|
@ -84,6 +89,7 @@ export class AppsControllerV2 {
|
|||
response['data_queries'] = seralizedQueries;
|
||||
response['definition'] = app.editingVersion?.definition;
|
||||
response['pages'] = pagesForVersion;
|
||||
response['events'] = eventsForVersion;
|
||||
|
||||
//! if editing version exists, camelize the definition
|
||||
if (app.editingVersion && app.editingVersion.definition) {
|
||||
|
|
@ -95,6 +101,84 @@ export class AppsControllerV2 {
|
|||
return response;
|
||||
}
|
||||
|
||||
async appFromSlug(@User() user, @AppDecorator() app: App) {
|
||||
if (user) {
|
||||
const ability = await this.appsAbilityFactory.appsActions(user, app.id);
|
||||
|
||||
if (!ability.can('viewApp', app)) {
|
||||
throw new ForbiddenException(
|
||||
JSON.stringify({
|
||||
organizationId: app.organizationId,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const versionToLoad = app.currentVersionId
|
||||
? await this.appsService.findVersion(app.currentVersionId)
|
||||
: await this.appsService.findVersion(app.editingVersion?.id);
|
||||
|
||||
const pagesForVersion = app.editingVersion ? await this.pageService.findPagesForVersion(versionToLoad.id) : [];
|
||||
const eventsForVersion = app.editingVersion ? await this.eventsService.findEventsForVersion(versionToLoad.id) : [];
|
||||
|
||||
// serialize
|
||||
return {
|
||||
current_version_id: app['currentVersionId'],
|
||||
data_queries: versionToLoad?.dataQueries,
|
||||
definition: versionToLoad?.definition,
|
||||
is_public: app.isPublic,
|
||||
is_maintenance_on: app.isMaintenanceOn,
|
||||
name: app.name,
|
||||
slug: app.slug,
|
||||
events: eventsForVersion,
|
||||
pages: pagesForVersion,
|
||||
homePageId: versionToLoad.homePageId,
|
||||
globalSettings: versionToLoad.globalSettings,
|
||||
showViewerNavigation: versionToLoad.showViewerNavigation,
|
||||
};
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(ValidAppInterceptor)
|
||||
@Get(':id/versions/:versionId')
|
||||
async version(@User() user, @Param('id') id, @Param('versionId') versionId) {
|
||||
const appVersion = await this.appsService.findVersion(versionId);
|
||||
const app = appVersion.app;
|
||||
|
||||
if (app.id !== id) {
|
||||
throw new BadRequestException();
|
||||
}
|
||||
const ability = await this.appsAbilityFactory.appsActions(user, app.id);
|
||||
|
||||
if (!ability.can('fetchVersions', app)) {
|
||||
throw new ForbiddenException(
|
||||
JSON.stringify({
|
||||
organizationId: app.organizationId,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const pagesForVersion = await this.pageService.findPagesForVersion(versionId);
|
||||
const eventsForVersion = await this.eventsService.findEventsForVersion(versionId);
|
||||
|
||||
const appCurrentEditingVersion = JSON.parse(JSON.stringify(appVersion));
|
||||
|
||||
delete appCurrentEditingVersion['app'];
|
||||
|
||||
const appData = {
|
||||
...app,
|
||||
};
|
||||
|
||||
delete appData['editingVersion'];
|
||||
|
||||
return {
|
||||
...appData,
|
||||
editing_version: camelizeKeys(appCurrentEditingVersion),
|
||||
pages: pagesForVersion,
|
||||
events: eventsForVersion,
|
||||
};
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(ValidAppInterceptor)
|
||||
@Put(':id/versions/:versionId')
|
||||
|
|
@ -118,6 +202,7 @@ export class AppsControllerV2 {
|
|||
|
||||
return await this.appsService.updateAppVersion(version, appVersionUpdateDto);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(ValidAppInterceptor)
|
||||
@Put(':id/versions/:versionId/global_settings')
|
||||
|
|
@ -150,7 +235,7 @@ export class AppsControllerV2 {
|
|||
@User() user,
|
||||
@Param('id') id,
|
||||
@Param('versionId') versionId,
|
||||
@Body() versionEditDto: VersionEditDto
|
||||
@Body() createComponentDto: CreateComponentDto
|
||||
) {
|
||||
const version = await this.appsService.findVersion(versionId);
|
||||
const app = version.app;
|
||||
|
|
@ -164,7 +249,7 @@ export class AppsControllerV2 {
|
|||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
await this.componentsService.create(versionEditDto.diff, versionEditDto.pageId, versionId);
|
||||
await this.componentsService.create(createComponentDto.diff, createComponentDto.pageId, versionId);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
|
|
@ -174,7 +259,7 @@ export class AppsControllerV2 {
|
|||
@User() user,
|
||||
@Param('id') id,
|
||||
@Param('versionId') versionId,
|
||||
@Body() versionEditDto: VersionEditDto
|
||||
@Body() updateComponentDto: UpdateComponentDto
|
||||
) {
|
||||
const version = await this.appsService.findVersion(versionId);
|
||||
const app = version.app;
|
||||
|
|
@ -188,7 +273,7 @@ export class AppsControllerV2 {
|
|||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
await this.componentsService.update(versionEditDto.diff, versionId);
|
||||
await this.componentsService.update(updateComponentDto.diff, versionId);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
|
|
@ -198,7 +283,7 @@ export class AppsControllerV2 {
|
|||
@User() user,
|
||||
@Param('id') id,
|
||||
@Param('versionId') versionId,
|
||||
@Body() versionEditDto: VersionEditDto
|
||||
@Body() deleteComponentDto: DeleteComponentDto
|
||||
) {
|
||||
const version = await this.appsService.findVersion(versionId);
|
||||
const app = version.app;
|
||||
|
|
@ -212,7 +297,7 @@ export class AppsControllerV2 {
|
|||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
await this.componentsService.delete(versionEditDto.diff, versionId);
|
||||
await this.componentsService.delete(deleteComponentDto.diff, versionId);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
|
|
@ -222,7 +307,7 @@ export class AppsControllerV2 {
|
|||
@User() user,
|
||||
@Param('id') id,
|
||||
@Param('versionId') versionId,
|
||||
@Body() versionEditDto: VersionEditDto
|
||||
@Body() updateComponentLayout: LayoutUpdateDto
|
||||
) {
|
||||
const version = await this.appsService.findVersion(versionId);
|
||||
const app = version.app;
|
||||
|
|
@ -236,7 +321,7 @@ export class AppsControllerV2 {
|
|||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
await this.componentsService.componentLayoutChange(versionEditDto.diff, versionId);
|
||||
await this.componentsService.componentLayoutChange(updateComponentLayout.diff, versionId);
|
||||
}
|
||||
|
||||
// pages api
|
||||
|
|
@ -282,11 +367,50 @@ export class AppsControllerV2 {
|
|||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(ValidAppInterceptor)
|
||||
@Put(':id/versions/:versionId/pages')
|
||||
async updatePages(
|
||||
async updatePages(@User() user, @Param('id') id, @Param('versionId') versionId, @Body() updatePageDto) {
|
||||
const version = await this.appsService.findVersion(versionId);
|
||||
const app = version.app;
|
||||
|
||||
if (app.id !== id) {
|
||||
throw new BadRequestException();
|
||||
}
|
||||
const ability = await this.appsAbilityFactory.appsActions(user, id);
|
||||
|
||||
if (!ability.can('updateVersions', app)) {
|
||||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
await this.pageService.updatePage(updatePageDto, versionId);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(ValidAppInterceptor)
|
||||
@Delete(':id/versions/:versionId/pages')
|
||||
async deletePage(@User() user, @Param('id') id, @Param('versionId') versionId, @Body() deletePageDto: DeletePageDto) {
|
||||
const version = await this.appsService.findVersion(versionId);
|
||||
const app = version.app;
|
||||
|
||||
if (app.id !== id) {
|
||||
throw new BadRequestException();
|
||||
}
|
||||
const ability = await this.appsAbilityFactory.appsActions(user, id);
|
||||
|
||||
if (!ability.can('updateVersions', app)) {
|
||||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
await this.pageService.deletePage(deletePageDto.pageId, versionId);
|
||||
}
|
||||
|
||||
// events api
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(ValidAppInterceptor)
|
||||
@Post(':id/versions/:versionId/events')
|
||||
async createEvent(
|
||||
@User() user,
|
||||
@Param('id') id,
|
||||
@Param('versionId') versionId,
|
||||
@Body() updatePageDto: Partial<UpdatePageDto>
|
||||
@Body() createEventHandlerDto: CreateEventHandlerDto
|
||||
) {
|
||||
const version = await this.appsService.findVersion(versionId);
|
||||
const app = version.app;
|
||||
|
|
@ -300,57 +424,17 @@ export class AppsControllerV2 {
|
|||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
await this.pageService.updatePage({ pageId: updatePageDto.pageId, diff: updatePageDto.diff }, versionId);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(ValidAppInterceptor)
|
||||
@Delete(':id/versions/:versionId/pages')
|
||||
async deletePage(@User() user, @Param('id') id, @Param('versionId') versionId, @Body() body) {
|
||||
const version = await this.appsService.findVersion(versionId);
|
||||
const app = version.app;
|
||||
|
||||
if (app.id !== id) {
|
||||
throw new BadRequestException();
|
||||
}
|
||||
const ability = await this.appsAbilityFactory.appsActions(user, id);
|
||||
|
||||
if (!ability.can('updateVersions', app)) {
|
||||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
const { pageId } = body;
|
||||
|
||||
if (pageId) {
|
||||
await this.pageService.deletePage(pageId, versionId);
|
||||
}
|
||||
}
|
||||
|
||||
// events api
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(ValidAppInterceptor)
|
||||
@Post(':id/versions/:versionId/events')
|
||||
async createEvent(@User() user, @Param('id') id, @Param('versionId') versionId, @Body() body) {
|
||||
const version = await this.appsService.findVersion(versionId);
|
||||
const app = version.app;
|
||||
|
||||
if (app.id !== id) {
|
||||
throw new BadRequestException();
|
||||
}
|
||||
const ability = await this.appsAbilityFactory.appsActions(user, id);
|
||||
|
||||
if (!ability.can('updateVersions', app)) {
|
||||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
const { event } = body;
|
||||
|
||||
return this.eventService.createEvent(event, versionId);
|
||||
return this.eventService.createEvent(createEventHandlerDto, versionId);
|
||||
}
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(ValidAppInterceptor)
|
||||
@Put(':id/versions/:versionId/events')
|
||||
async updateEvents(@User() user, @Param('id') id, @Param('versionId') versionId, @Body() body) {
|
||||
async updateEvents(
|
||||
@User() user,
|
||||
@Param('id') id,
|
||||
@Param('versionId') versionId,
|
||||
@Body() updateEventHandlerDto: UpdateEventHandlerDto
|
||||
) {
|
||||
const version = await this.appsService.findVersion(versionId);
|
||||
const app = version.app;
|
||||
|
||||
|
|
@ -363,7 +447,9 @@ export class AppsControllerV2 {
|
|||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
return await this.eventService.updateEvent(body?.events, body?.updateType, versionId);
|
||||
const { events, updateType } = updateEventHandlerDto;
|
||||
|
||||
return await this.eventService.updateEvent(events, updateType, versionId);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { IsBoolean, IsNotEmpty, IsOptional, IsString, MaxLength } from 'class-validator';
|
||||
import { IsBoolean, IsNotEmpty, IsOptional, IsString, IsUUID, MaxLength } from 'class-validator';
|
||||
import { Transform } from 'class-transformer';
|
||||
import { sanitizeInput } from '../helpers/utils.helper';
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ export class AppVersionUpdateDto {
|
|||
@IsOptional()
|
||||
showViewerNavigation: boolean;
|
||||
|
||||
@IsString()
|
||||
@IsUUID()
|
||||
@IsOptional()
|
||||
homePageId: string;
|
||||
|
||||
|
|
|
|||
102
server/src/dto/component.dto.ts
Normal file
102
server/src/dto/component.dto.ts
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
import { Type } from 'class-transformer';
|
||||
import { IsArray, IsBoolean, IsNotEmpty, IsNumber, IsObject, IsOptional, IsString, IsUUID } from 'class-validator';
|
||||
|
||||
export class ComponentLayoutDto {
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
top?: number;
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
left?: number;
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
width?: number;
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
height?: number;
|
||||
}
|
||||
|
||||
export class LayoutData {
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
desktop?: ComponentLayoutDto;
|
||||
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
mobile?: ComponentLayoutDto;
|
||||
}
|
||||
|
||||
class ComponentDto {
|
||||
@IsString()
|
||||
name: string;
|
||||
|
||||
@IsObject()
|
||||
properties: Record<string, any>;
|
||||
|
||||
@IsObject()
|
||||
styles: Record<string, any>;
|
||||
|
||||
@IsObject()
|
||||
validation: Record<string, any>;
|
||||
|
||||
@IsString()
|
||||
type: string;
|
||||
|
||||
@IsObject()
|
||||
others: Record<string, any>;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => ComponentLayoutDto)
|
||||
layouts: ComponentLayoutDto;
|
||||
|
||||
@IsOptional()
|
||||
parent: string;
|
||||
}
|
||||
|
||||
export class CreateComponentDto {
|
||||
@IsBoolean()
|
||||
is_user_switched_version: boolean;
|
||||
|
||||
@IsUUID()
|
||||
pageId: string;
|
||||
|
||||
@IsObject()
|
||||
diff: Record<string, ComponentDto>;
|
||||
}
|
||||
|
||||
export class UpdateComponentDto {
|
||||
@IsBoolean()
|
||||
is_user_switched_version: boolean;
|
||||
|
||||
@IsUUID()
|
||||
pageId: string;
|
||||
|
||||
@IsObject()
|
||||
diff: Record<string, ComponentDto>;
|
||||
}
|
||||
|
||||
export class DeleteComponentDto {
|
||||
@IsBoolean()
|
||||
is_user_switched_version: boolean;
|
||||
|
||||
@IsUUID()
|
||||
pageId: string;
|
||||
|
||||
@IsArray()
|
||||
diff: string[];
|
||||
}
|
||||
|
||||
export class LayoutUpdateDto {
|
||||
@IsBoolean()
|
||||
is_user_switched_version: boolean;
|
||||
|
||||
@IsUUID()
|
||||
pageId: string;
|
||||
|
||||
@IsObject()
|
||||
@IsNotEmpty()
|
||||
diff: Record<string, { layouts: LayoutData }>;
|
||||
}
|
||||
44
server/src/dto/event-handler.dto.ts
Normal file
44
server/src/dto/event-handler.dto.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import { IsArray, IsIn, IsNumber, IsObject, IsString, IsUUID, ValidateNested } from 'class-validator';
|
||||
import { Target } from 'src/entities/event_handler.entity';
|
||||
|
||||
export class CreateEventHandlerDto {
|
||||
@IsObject()
|
||||
event: any;
|
||||
|
||||
@IsString()
|
||||
eventType: Target;
|
||||
|
||||
@IsString()
|
||||
attachedTo: string;
|
||||
|
||||
@IsNumber()
|
||||
index: number;
|
||||
}
|
||||
|
||||
class UpdateEventDiff {
|
||||
@IsString()
|
||||
name: string;
|
||||
|
||||
@IsNumber()
|
||||
index: number;
|
||||
|
||||
@IsObject()
|
||||
@ValidateNested()
|
||||
event: any;
|
||||
}
|
||||
|
||||
export class UpdateEvent {
|
||||
@IsUUID()
|
||||
event_id: string;
|
||||
|
||||
@IsObject()
|
||||
diff: UpdateEventDiff;
|
||||
}
|
||||
|
||||
export class UpdateEventHandlerDto {
|
||||
@IsArray()
|
||||
events: UpdateEvent[];
|
||||
|
||||
@IsIn(['update', 'reorder'])
|
||||
updateType: 'update' | 'reorder';
|
||||
}
|
||||
|
|
@ -1,17 +1,35 @@
|
|||
import { IsNumber, IsString, IsUUID } from 'class-validator';
|
||||
import { IsNotEmpty, IsNumber, IsOptional, IsString, IsUUID, MaxLength } from 'class-validator';
|
||||
|
||||
export class CreatePageDto {
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
id: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@MaxLength(32)
|
||||
name: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@MaxLength(50)
|
||||
handle: string;
|
||||
|
||||
@IsNumber()
|
||||
@IsNotEmpty()
|
||||
index: number;
|
||||
|
||||
@IsOptional()
|
||||
disabled: boolean;
|
||||
|
||||
@IsOptional()
|
||||
hidden: boolean;
|
||||
}
|
||||
|
||||
export class DeletePageDto {
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
pageId: string;
|
||||
}
|
||||
|
||||
export class UpdatePageDto {
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ export class AppEnvironmentService {
|
|||
order: {
|
||||
createdAt: 'DESC',
|
||||
},
|
||||
select: ['id', 'name', 'appId'],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ export class ComponentsService {
|
|||
});
|
||||
|
||||
const newComponents = this.transformComponentData(componentDiff);
|
||||
|
||||
const componentLayouts = [];
|
||||
|
||||
newComponents.forEach((component) => {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { EntityManager, Repository } from 'typeorm';
|
||||
import { Component } from 'src/entities/component.entity';
|
||||
|
||||
import { EventHandler } from 'src/entities/event_handler.entity';
|
||||
import { dbTransactionWrap, dbTransactionForAppVersionAssociationsUpdate } from 'src/helpers/utils.helper';
|
||||
import { CreateEventHandlerDto, UpdateEvent } from '@dto/event-handler.dto';
|
||||
|
||||
@Injectable()
|
||||
export class EventsService {
|
||||
constructor(
|
||||
@InjectRepository(Component)
|
||||
@InjectRepository(EventHandler)
|
||||
private eventsRepository: Repository<EventHandler>
|
||||
) {}
|
||||
|
||||
|
|
@ -23,11 +22,8 @@ export class EventsService {
|
|||
}
|
||||
|
||||
async findAllEventsWithSourceId(sourceId: string): Promise<EventHandler[]> {
|
||||
return dbTransactionWrap(async (manager: EntityManager) => {
|
||||
const allEvents = await manager.find(EventHandler, {
|
||||
where: { sourceId },
|
||||
});
|
||||
return allEvents;
|
||||
return this.eventsRepository.find({
|
||||
where: { sourceId },
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -41,31 +37,38 @@ export class EventsService {
|
|||
});
|
||||
}
|
||||
|
||||
async createEvent(eventObj, versionId) {
|
||||
if (Object.keys(eventObj).length === 0) {
|
||||
return new BadRequestException('No event found');
|
||||
async createEvent(eventHandler: CreateEventHandlerDto, versionId) {
|
||||
if (!eventHandler.attachedTo) {
|
||||
throw new BadRequestException('No attachedTo found');
|
||||
}
|
||||
|
||||
const newEvent = {
|
||||
name: eventObj.event.eventId,
|
||||
sourceId: eventObj.attachedTo,
|
||||
target: eventObj.eventType,
|
||||
event: eventObj.event,
|
||||
appVersionId: versionId,
|
||||
index: eventObj.index,
|
||||
};
|
||||
if (!eventHandler.eventType) {
|
||||
throw new BadRequestException('No eventType found');
|
||||
}
|
||||
|
||||
if (!eventHandler.event) {
|
||||
throw new BadRequestException('No event found');
|
||||
}
|
||||
|
||||
return await dbTransactionForAppVersionAssociationsUpdate(async (manager: EntityManager) => {
|
||||
const newEvent = new EventHandler();
|
||||
newEvent.name = eventHandler.event.eventId;
|
||||
newEvent.sourceId = eventHandler.attachedTo;
|
||||
newEvent.target = eventHandler.eventType;
|
||||
newEvent.event = eventHandler.event;
|
||||
newEvent.index = eventHandler.index;
|
||||
newEvent.appVersionId = versionId;
|
||||
|
||||
const event = await manager.save(EventHandler, newEvent);
|
||||
return event;
|
||||
}, versionId);
|
||||
}
|
||||
|
||||
async updateEvent(events: [], updateType: 'update' | 'reorder', appVersionId: string) {
|
||||
async updateEvent(events: UpdateEvent[], updateType: 'update' | 'reorder', appVersionId: string) {
|
||||
return await dbTransactionForAppVersionAssociationsUpdate(async (manager: EntityManager) => {
|
||||
return await Promise.all(
|
||||
events.map(async (event) => {
|
||||
const { event_id, diff } = event as any;
|
||||
const { event_id, diff } = event;
|
||||
|
||||
const eventDiff = diff?.event;
|
||||
const eventToUpdate = await manager.findOne(EventHandler, {
|
||||
|
|
@ -78,12 +81,13 @@ export class EventsService {
|
|||
|
||||
const updatedEvent = {
|
||||
...eventToUpdate,
|
||||
event: {
|
||||
...eventToUpdate.event,
|
||||
...eventDiff,
|
||||
},
|
||||
};
|
||||
|
||||
if (updateType === 'update') {
|
||||
updatedEvent.name = eventDiff?.eventId;
|
||||
updatedEvent.event = eventDiff;
|
||||
}
|
||||
|
||||
if (updateType === 'reorder') {
|
||||
updatedEvent.index = diff.index;
|
||||
}
|
||||
|
|
@ -96,17 +100,13 @@ export class EventsService {
|
|||
|
||||
async updateEventsOrderOnDelete(sourceId: string, deletedIndex: number) {
|
||||
const allEvents = await this.findAllEventsWithSourceId(sourceId);
|
||||
|
||||
const eventsToUpdate = allEvents.filter((event) => event.index > deletedIndex);
|
||||
|
||||
return await dbTransactionWrap(async (manager: EntityManager) => {
|
||||
return await Promise.all(
|
||||
eventsToUpdate.map(async (event) => {
|
||||
const updatedEvent = {
|
||||
...event,
|
||||
index: event.index - 1,
|
||||
};
|
||||
|
||||
return await manager.save(EventHandler, updatedEvent);
|
||||
return await manager.update(EventHandler, { id: event.id }, { index: event.index - 1 });
|
||||
})
|
||||
);
|
||||
});
|
||||
|
|
@ -118,6 +118,9 @@ export class EventsService {
|
|||
where: { id: eventId },
|
||||
});
|
||||
|
||||
const sourceId = event.sourceId;
|
||||
const deletedIndex = event.index;
|
||||
|
||||
if (!event) {
|
||||
return new BadRequestException('No event found');
|
||||
}
|
||||
|
|
@ -127,7 +130,7 @@ export class EventsService {
|
|||
if (!deleteResponse?.affected) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
await this.updateEventsOrderOnDelete(event.sourceId, event.index);
|
||||
await this.updateEventsOrderOnDelete(sourceId, deletedIndex);
|
||||
return deleteResponse;
|
||||
}, appVersionId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,14 @@ export class PageService {
|
|||
|
||||
event.event = eventDefinition;
|
||||
|
||||
const clonedEvent = { ...event, id: undefined, sourceId: clonePageId };
|
||||
const clonedEvent = new EventHandler();
|
||||
clonedEvent.event = event.event;
|
||||
clonedEvent.index = event.index;
|
||||
clonedEvent.name = event.name;
|
||||
clonedEvent.sourceId = clonePageId;
|
||||
clonedEvent.target = event.target;
|
||||
clonedEvent.appVersionId = event.appVersionId;
|
||||
|
||||
await manager.save(EventHandler, clonedEvent);
|
||||
})
|
||||
);
|
||||
|
|
@ -139,11 +146,15 @@ export class PageService {
|
|||
}
|
||||
event.event = eventDefinition;
|
||||
|
||||
return {
|
||||
...event,
|
||||
id: undefined,
|
||||
sourceId: newComponent.id,
|
||||
};
|
||||
const clonedEvent = new EventHandler();
|
||||
clonedEvent.event = event.event;
|
||||
clonedEvent.index = event.index;
|
||||
clonedEvent.name = event.name;
|
||||
clonedEvent.sourceId = newComponent.id;
|
||||
clonedEvent.target = event.target;
|
||||
clonedEvent.appVersionId = event.appVersionId;
|
||||
|
||||
return clonedEvent;
|
||||
});
|
||||
|
||||
await manager.save(Layout, clonedLayouts);
|
||||
|
|
|
|||
Loading…
Reference in a new issue