diff --git a/frontend/src/Editor/EditorFunc.jsx b/frontend/src/Editor/EditorFunc.jsx index ef57fd09de..207fd770a8 100644 --- a/frontend/src/Editor/EditorFunc.jsx +++ b/frontend/src/Editor/EditorFunc.jsx @@ -716,6 +716,10 @@ const EditorComponent = (props) => { isUpdatingEditorStateInProcess: false, }); + if (versionSwitched) { + props?.navigate(`/${getWorkspaceId()}/apps/${appId}/${appJson.pages[homePageId]?.handle}`); + } + await useDataSourcesStore.getState().actions.fetchGlobalDataSources(data?.organization_id); await fetchDataSources(data.editing_version?.id); await fetchDataQueries(data.editing_version?.id, true, true); @@ -871,33 +875,28 @@ const EditorComponent = (props) => { const newComponentIds = Object.keys(componentUpdateDiff); - const mappedEvents = []; - newComponentIds.forEach((componentId) => { const sourceComponentId = getKeyFromComponentMap(componentMap, componentId); if (!sourceComponentId) return; - const componentEvents = events.filter((event) => event.sourceId === sourceComponentId); + appVersionService + .findAllEventsWithSourceId(appId, currentVersionId, sourceComponentId) + .then((componentEvents) => { + if (!componentEvents) return; + componentEvents.forEach((event) => { + const newEvent = { + event: { + ...event?.event, + }, + eventType: event?.target, + attachedTo: componentMap[event?.sourceId], + index: event?.index, + }; - mappedEvents.push(...componentEvents); + createAppVersionEventHandlers(newEvent); + }); + }); }); - - if (mappedEvents.length === 0) return; - - return Promise.all( - mappedEvents.map((event) => { - const newEvent = { - event: { - ...event?.event, - }, - eventType: event?.target, - attachedTo: componentMap[event?.sourceId], - index: event?.index, - }; - - createAppVersionEventHandlers(newEvent); - }) - ); }; const saveEditingVersion = (isUserSwitchedVersion = false) => { diff --git a/frontend/src/Editor/Inspector/Inspector.jsx b/frontend/src/Editor/Inspector/Inspector.jsx index f08f02424b..b98ae05050 100644 --- a/frontend/src/Editor/Inspector/Inspector.jsx +++ b/frontend/src/Editor/Inspector/Inspector.jsx @@ -99,13 +99,6 @@ export const Inspector = ({ componentNameRef.current = newComponentName; }, [newComponentName]); - useEffect(() => { - return () => { - handleComponentNameChange(componentNameRef.current); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - const validateComponentName = (name) => { const isValid = !Object.values(allComponents) .map((component) => component.component.name) diff --git a/frontend/src/_services/appVersion.service.js b/frontend/src/_services/appVersion.service.js index f55fb9a115..69e4a9eba2 100644 --- a/frontend/src/_services/appVersion.service.js +++ b/frontend/src/_services/appVersion.service.js @@ -13,6 +13,7 @@ export const appVersionService = { createAppVersionEventHandler, deleteAppVersionEventHandler, clonePage, + findAllEventsWithSourceId, }; function getAll(appId) { @@ -155,3 +156,17 @@ function clonePage(appId, versionId, pageId) { handleResponse ); } + +function findAllEventsWithSourceId(appId, versionId, sourceId) { + const requestOptions = { + method: 'GET', + headers: authHeader(), + credentials: 'include', + }; + + return fetch( + `${config.apiUrl}/v2/apps/${appId}/versions/${versionId}/events${sourceId ? `?sourceId=${sourceId}` : ''} + `, + requestOptions + ).then(handleResponse); +} diff --git a/frontend/src/_stores/utils.js b/frontend/src/_stores/utils.js index 32a8cfb708..14dfd41a7e 100644 --- a/frontend/src/_stores/utils.js +++ b/frontend/src/_stores/utils.js @@ -112,11 +112,26 @@ export const computeComponentPropertyDiff = (appDiff, definition, opts) => { if (!opts?.isParamFromTableColumn) { return appDiff; } - const path = generatePath(appDiff, 'columns') || generatePath(appDiff, 'actions'); + const columnsPath = generatePath(appDiff, 'columns'); + const actionsPath = generatePath(appDiff, 'actions'); + const deletionHistoryPath = generatePath(appDiff, 'columnDeletionHistory'); - const value2 = getValueFromJson(definition, path); + let _diff = _.cloneDeep(appDiff); - const _diff = updateValueInJson(_.cloneDeep(appDiff), path, value2); + if (columnsPath) { + const columnsValue = getValueFromJson(definition, columnsPath); + _diff = updateValueInJson(_diff, columnsPath, columnsValue); + } + + if (actionsPath) { + const actionsValue = getValueFromJson(definition, actionsPath); + _diff = updateValueInJson(_diff, actionsPath, actionsValue); + } + + if (deletionHistoryPath) { + const deletionHistoryValue = getValueFromJson(definition, deletionHistoryPath); + _diff = updateValueInJson(_diff, deletionHistoryPath, deletionHistoryValue); + } return _diff; }; diff --git a/server/data-migrations/1697473340856-MigrateAppsDefinitionSchemaTransition.ts b/server/data-migrations/1697473340856-MigrateAppsDefinitionSchemaTransition.ts index d90faa240a..20169cd23a 100644 --- a/server/data-migrations/1697473340856-MigrateAppsDefinitionSchemaTransition.ts +++ b/server/data-migrations/1697473340856-MigrateAppsDefinitionSchemaTransition.ts @@ -215,6 +215,9 @@ export class MigrateAppsDefinitionSchemaTransition1697473340856 implements Migra transformedComponent.properties = componentData.definition.properties || {}; transformedComponent.styles = componentData.definition.styles || {}; transformedComponent.validation = componentData.definition.validation || {}; + transformedComponent.general = componentData.definition.general || {}; + transformedComponent.generalStyles = componentData.definition.generalStyles || {}; + transformedComponent.displayPreferences = componentData.definition.others || {}; transformedComponent.parent = data[componentId].parent || null; transformedComponents.push(transformedComponent); diff --git a/server/src/controllers/apps.controller.v2.ts b/server/src/controllers/apps.controller.v2.ts index aa3b791466..5d3e3ff4f9 100644 --- a/server/src/controllers/apps.controller.v2.ts +++ b/server/src/controllers/apps.controller.v2.ts @@ -406,6 +406,27 @@ export class AppsControllerV2 { } // events api + + @UseGuards(JwtAuthGuard) + @UseInterceptors(ValidAppInterceptor) + @Get(':id/versions/:versionId/events') + async getEvents(@User() user, @Param('id') id, @Param('versionId') versionId, @Query('sourceId') sourceId) { + 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('viewApp', app)) { + throw new ForbiddenException('You do not have permissions to perform this action'); + } + + return this.eventService.findAllEventsWithSourceId(sourceId); + } + @UseGuards(JwtAuthGuard) @UseInterceptors(ValidAppInterceptor) @Post(':id/versions/:versionId/events') diff --git a/server/src/services/app_import_export.service.ts b/server/src/services/app_import_export.service.ts index 259ab9587a..7c82f29172 100644 --- a/server/src/services/app_import_export.service.ts +++ b/server/src/services/app_import_export.service.ts @@ -1508,6 +1508,9 @@ function transformComponentData(data: object, componentEvents: any[]): Component transformedComponent.properties = componentData.definition.properties || {}; transformedComponent.styles = componentData.definition.styles || {}; transformedComponent.validation = componentData.definition.validation || {}; + transformedComponent.general = componentData.definition.general || {}; + transformedComponent.generalStyles = componentData.definition.generalStyles || {}; + transformedComponent.displayPreferences = componentData.definition.others || {}; transformedComponent.parent = data[componentId].parent || null; transformedComponents.push(transformedComponent); diff --git a/server/src/services/apps.service.ts b/server/src/services/apps.service.ts index 92df0026d2..cdbd421ee3 100644 --- a/server/src/services/apps.service.ts +++ b/server/src/services/apps.service.ts @@ -533,6 +533,9 @@ export class AppsService { newComponent.properties = component.properties; newComponent.styles = component.styles; newComponent.validation = component.validation; + newComponent.general = component.general; + newComponent.generalStyles = component.generalStyles; + newComponent.displayPreferences = component.displayPreferences; newComponent.parent = component.parent ? parentId : null; newComponent.page = savedPage; @@ -630,7 +633,7 @@ export class AppsService { where: { appVersionId: versionFrom?.id, target: 'data_query' }, }); - if (dataSources?.length) { + if (dataSources?.length > 0) { for (const dataSource of dataSources) { const dataSourceParams: Partial = { name: dataSource.name, @@ -672,71 +675,65 @@ export class AppsService { newDataQueries.push(newQuery); } } + } - if (globalQueries?.length) { - for (const globalQuery of globalQueries) { - const dataQueryParams = { - name: globalQuery.name, - options: globalQuery.options, - dataSourceId: globalQuery.dataSourceId, - appVersionId: appVersion.id, - }; + if (globalQueries?.length > 0) { + for (const globalQuery of globalQueries) { + const dataQueryParams = { + name: globalQuery.name, + options: globalQuery.options, + dataSourceId: globalQuery.dataSourceId, + appVersionId: appVersion.id, + }; - const newQuery = await manager.save(manager.create(DataQuery, dataQueryParams)); - const dataQueryEvents = allEvents.filter((event) => event.sourceId === globalQuery.id); + const newQuery = await manager.save(manager.create(DataQuery, dataQueryParams)); + const dataQueryEvents = allEvents.filter((event) => event.sourceId === globalQuery.id); - dataQueryEvents.forEach(async (event, index) => { - const newEvent = new EventHandler(); + dataQueryEvents.forEach(async (event, index) => { + const newEvent = new EventHandler(); - newEvent.id = uuid.v4(); - newEvent.name = event.name; - newEvent.sourceId = newQuery.id; - newEvent.target = event.target; - newEvent.event = event.event; - newEvent.index = event.index ?? index; - newEvent.appVersionId = appVersion.id; + newEvent.id = uuid.v4(); + newEvent.name = event.name; + newEvent.sourceId = newQuery.id; + newEvent.target = event.target; + newEvent.event = event.event; + newEvent.index = event.index ?? index; + newEvent.appVersionId = appVersion.id; - await manager.save(newEvent); - }); - oldDataQueryToNewMapping[globalQuery.id] = newQuery.id; - newDataQueries.push(newQuery); - } + await manager.save(newEvent); + }); + oldDataQueryToNewMapping[globalQuery.id] = newQuery.id; + newDataQueries.push(newQuery); } + } - for (const newQuery of newDataQueries) { - const newOptions = this.replaceDataQueryOptionsWithNewDataQueryIds( - newQuery.options, - oldDataQueryToNewMapping + for (const newQuery of newDataQueries) { + const newOptions = this.replaceDataQueryOptionsWithNewDataQueryIds(newQuery.options, oldDataQueryToNewMapping); + newQuery.options = newOptions; + + await manager.save(newQuery); + } + + appVersion.definition = this.replaceDataQueryIdWithinDefinitions(appVersion.definition, oldDataQueryToNewMapping); + await manager.save(appVersion); + + for (const appEnvironment of appEnvironments) { + for (const dataSource of dataSources) { + const dataSourceOption = await manager.findOneOrFail(DataSourceOptions, { + where: { dataSourceId: dataSource.id, environmentId: appEnvironment.id }, + }); + + const convertedOptions = this.convertToArrayOfKeyValuePairs(dataSourceOption.options); + const newOptions = await this.dataSourcesService.parseOptionsForCreate(convertedOptions, false, manager); + await this.setNewCredentialValueFromOldValue(newOptions, convertedOptions, manager); + + await manager.save( + manager.create(DataSourceOptions, { + options: newOptions, + dataSourceId: dataSourceMapping[dataSource.id], + environmentId: appEnvironment.id, + }) ); - newQuery.options = newOptions; - - await manager.save(newQuery); - } - - appVersion.definition = this.replaceDataQueryIdWithinDefinitions( - appVersion.definition, - oldDataQueryToNewMapping - ); - await manager.save(appVersion); - - for (const appEnvironment of appEnvironments) { - for (const dataSource of dataSources) { - const dataSourceOption = await manager.findOneOrFail(DataSourceOptions, { - where: { dataSourceId: dataSource.id, environmentId: appEnvironment.id }, - }); - - const convertedOptions = this.convertToArrayOfKeyValuePairs(dataSourceOption.options); - const newOptions = await this.dataSourcesService.parseOptionsForCreate(convertedOptions, false, manager); - await this.setNewCredentialValueFromOldValue(newOptions, convertedOptions, manager); - - await manager.save( - manager.create(DataSourceOptions, { - options: newOptions, - dataSourceId: dataSourceMapping[dataSource.id], - environmentId: appEnvironment.id, - }) - ); - } } } } diff --git a/server/src/services/components.service.ts b/server/src/services/components.service.ts index 52edd6b115..476137c20c 100644 --- a/server/src/services/components.service.ts +++ b/server/src/services/components.service.ts @@ -199,6 +199,8 @@ export class ComponentsService { transformedComponent.styles = componentData.styles || {}; transformedComponent.validation = componentData.validation || {}; transformedComponent.displayPreferences = componentData.others || null; + transformedComponent.general = componentData.general || null; + transformedComponent.generalStyles = componentData.generalStyles || null; transformedComponents.push(transformedComponent); }