handles references mapping with new associations

This commit is contained in:
arpitnath 2024-03-27 02:11:58 +05:30
parent 2a85e4eab1
commit 2c38b85368
5 changed files with 138 additions and 69 deletions

View file

@ -782,29 +782,17 @@ const EditorComponent = (props) => {
let dataQueries = JSON.parse(JSON.stringify(useDataQueriesStore.getState().dataQueries));
let allEvents = JSON.parse(JSON.stringify(useAppDataStore.getState().events));
const entityReferencesInComponentDefinitions = findAllEntityReferences(currentComponents, [])
?.map((entity) => {
if (entity && isValidUUID(entity)) {
return entity;
}
})
?.filter((e) => e !== undefined);
const entityReferencesInComponentDefinitions = findAllEntityReferences(currentComponents, [])?.filter(
(entity) => entity && isValidUUID(entity)
);
const entityReferencesInQueryoOptions = findAllEntityReferences(dataQueries, [])
?.map((entity) => {
if (entity && isValidUUID(entity)) {
return entity;
}
})
?.filter((e) => e !== undefined);
const entityReferencesInQueryoOptions = findAllEntityReferences(dataQueries, [])?.filter(
(entity) => entity && isValidUUID(entity)
);
const entityReferencesInEvents = findAllEntityReferences(allEvents, [])
?.map((entity) => {
if (entity && isValidUUID(entity)) {
return entity;
}
})
?.filter((e) => e !== undefined);
const entityReferencesInEvents = findAllEntityReferences(allEvents, [])?.filter(
(entity) => entity && isValidUUID(entity)
);
const manager = useResolveStore.getState().referenceMapper;

View file

@ -214,29 +214,17 @@ class ViewerComponent extends React.Component {
let allDataQueries = this.state.dataQueries || [];
let newComponentDefinition = JSON.parse(JSON.stringify(components));
const entityReferencesInComponentDefinitions = findAllEntityReferences(newComponentDefinition, [])
?.map((entity) => {
if (entity && isValidUUID(entity)) {
return entity;
}
})
?.filter((e) => e !== undefined);
const entityReferencesInComponentDefinitions = findAllEntityReferences(newComponentDefinition, [])?.filter(
(entity) => entity && isValidUUID(entity)
);
const entityReferencesInQueryoOptions = findAllEntityReferences(allDataQueries, [])
?.map((entity) => {
if (entity && isValidUUID(entity)) {
return entity;
}
})
?.filter((e) => e !== undefined);
const entityReferencesInQueryoOptions = findAllEntityReferences(allDataQueries, [])?.filter(
(entity) => entity && isValidUUID(entity)
);
const entityReferencesInEvents = findAllEntityReferences(allEvents, [])
?.map((entity) => {
if (entity && isValidUUID(entity)) {
return entity;
}
})
?.filter((e) => e !== undefined);
const entityReferencesInEvents = findAllEntityReferences(allEvents, [])?.filter(
(entity) => entity && isValidUUID(entity)
);
const manager = useResolveStore.getState().referenceMapper;

View file

@ -111,13 +111,9 @@ export const useAppDataStore = create(
}
});
const entityReferencesInEvents = findAllEntityReferences(updatedEvents, [])
?.map((entity) => {
if (entity && isValidUUID(entity)) {
return entity;
}
})
?.filter((e) => e !== undefined);
const entityReferencesInEvents = findAllEntityReferences(updatedEvents, [])?.filter(
(entity) => entity && isValidUUID(entity)
);
const manager = useResolveStore.getState().referenceMapper;
let newEvents = JSON.parse(JSON.stringify(updatedEvents));

View file

@ -0,0 +1,53 @@
export function updateEntityReferences(node, resourceMapping: Record<string, string> = {}) {
if (typeof node === 'object') {
for (const key in node) {
let value = node[key];
if (typeof value === 'string' && value.includes('{{') && value.includes('}}')) {
const referenceExists = value;
if (referenceExists) {
const ref = value.replace('{{', '').replace('}}', '');
const entityName = ref.split('.')[1];
if (resourceMapping[entityName]) {
const newValue = value.replace(entityName, resourceMapping[entityName]);
node[key] = newValue;
}
}
} else if (typeof value === 'object') {
value = updateEntityReferences(value, resourceMapping);
}
}
}
return node;
}
export function findAllEntityReferences(node, allRefs): [] {
if (typeof node === 'object') {
for (const key in node) {
const value = node[key];
if (typeof value === 'string' && value.includes('{{') && value.includes('}}')) {
const referenceExists = value;
if (referenceExists) {
const ref = value.replace('{{', '').replace('}}', '');
const entityName = ref.split('.')[1];
allRefs.push(entityName);
}
} else if (typeof value === 'object') {
findAllEntityReferences(value, allRefs);
}
}
}
return allRefs;
}
export function isValidUUID(uuid) {
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
return uuidRegex.test(uuid);
}

View file

@ -32,6 +32,7 @@ import { Component } from 'src/entities/component.entity';
import { Layout } from 'src/entities/layout.entity';
import { EventHandler, Target } from 'src/entities/event_handler.entity';
import { v4 as uuid } from 'uuid';
import { findAllEntityReferences, isValidUUID, updateEntityReferences } from 'src/helpers/import_export.helpers';
interface AppResourceMappings {
defaultDataSourceIdMapping: Record<string, string>;
@ -237,21 +238,20 @@ export class AppImportExportService {
? true
: isTooljetVersionWithNormalizedAppDefinitionSchem(importedAppTooljetVersion);
const shouldUpdateForGridCompatibility = !cloning;
const importedApp = await this.createImportedAppForUser(this.entityManager, schemaUnifiedAppParams, user);
await this.setupImportedAppAssociations(
const resourceMapping = await this.setupImportedAppAssociations(
this.entityManager,
importedApp,
schemaUnifiedAppParams,
user,
externalResourceMappings,
isNormalizedAppDefinitionSchema,
shouldUpdateForGridCompatibility,
tooljetVersion
);
await this.createAdminGroupPermissions(this.entityManager, importedApp);
await this.updateEntityReferencesForImportedApp(this.entityManager, resourceMapping);
// NOTE: App slug updation callback doesn't work while wrapped in transaction
// hence updating slug explicitly
@ -262,6 +262,64 @@ export class AppImportExportService {
return importedApp;
}
async updateEntityReferencesForImportedApp(manager: EntityManager, resourceMapping: AppResourceMappings) {
const mappings = { ...resourceMapping.componentsMapping, ...resourceMapping.dataQueryMapping };
const newComponentIds = Object.values(resourceMapping.componentsMapping);
const newQueriesIds = Object.values(resourceMapping.dataQueryMapping);
if (newComponentIds.length > 0) {
const components = await manager
.createQueryBuilder(Component, 'components')
.where('components.id IN(:...componentIds)', { componentIds: newComponentIds })
.select([
'components.id',
'components.properties',
'components.styles',
'components.general',
'components.validation',
'components.generalStyles',
'components.displayPreferences',
])
.getMany();
const toUpdateComponents = components.filter((component) => {
const entityReferencesInComponentDefinitions = findAllEntityReferences(component, []).filter(
(entity) => entity && isValidUUID(entity)
);
if (entityReferencesInComponentDefinitions.length > 0) {
return updateEntityReferences(component, mappings);
}
});
if (!isEmpty(toUpdateComponents)) {
await manager.save(toUpdateComponents);
}
}
if (newQueriesIds.length > 0) {
const dataQueries = await manager
.createQueryBuilder(DataQuery, 'dataQueries')
.where('dataQueries.id IN(:...dataQueryIds)', { dataQueryIds: newQueriesIds })
.select(['dataQueries.id', 'dataQueries.options'])
.getMany();
const toUpdateDataQueries = dataQueries.filter((dataQuery) => {
const entityReferencesInQueryOptions = findAllEntityReferences(dataQuery, []).filter(
(entity) => entity && isValidUUID(entity)
);
if (entityReferencesInQueryOptions.length > 0) {
return updateEntityReferences(dataQuery, mappings);
}
});
if (!isEmpty(toUpdateDataQueries)) {
await manager.save(toUpdateDataQueries);
}
}
}
async createImportedAppForUser(manager: EntityManager, appParams: any, user: User): Promise<App> {
return await catchDbException(async () => {
const importedApp = manager.create(App, {
@ -328,7 +386,6 @@ export class AppImportExportService {
user: User,
externalResourceMappings: Record<string, unknown>,
isNormalizedAppDefinitionSchema: boolean,
shouldUpdateForGridCompatibility: boolean,
tooljetVersion: string
) {
// Old version without app version
@ -393,7 +450,6 @@ export class AppImportExportService {
importingPages,
importingComponents,
importingEvents,
shouldUpdateForGridCompatibility,
tooljetVersion
);
@ -599,7 +655,6 @@ export class AppImportExportService {
importingPages: Page[],
importingComponents: Component[],
importingEvents: EventHandler[],
shouldUpdateForGridCompatibility: boolean,
tooljetVersion: string
): Promise<AppResourceMappings> {
appResourceMappings = { ...appResourceMappings };
@ -894,18 +949,6 @@ export class AppImportExportService {
);
}
// const appVersionIds = Object.values(appResourceMappings.appVersionMapping);
// for (const appVersionId of appVersionIds) {
// await this.updateEventActionsForNewVersionWithNewMappingIds(
// manager,
// appVersionId,
// appResourceMappings.dataQueryMapping,
// appResourceMappings.componentsMapping,
// appResourceMappings.pagesMapping
// );
// }
return appResourceMappings;
}
@ -1656,9 +1699,10 @@ export class AppImportExportService {
.createQueryBuilder(EventHandler, 'event')
.where('event.appVersionId = :versionId', { versionId })
.getMany();
const mappings = { ...oldDataQueryToNewMapping, ...oldComponentToNewComponentMapping } as Record<string, string>;
for (const event of allEvents) {
const eventDefinition = event.event;
const eventDefinition = updateEntityReferences(event.event, mappings);
if (eventDefinition?.actionId === 'run-query' && oldDataQueryToNewMapping[eventDefinition.queryId]) {
eventDefinition.queryId = oldDataQueryToNewMapping[eventDefinition.queryId];