mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-18 14:38:32 +00:00
handles references mapping with new associations
This commit is contained in:
parent
2a85e4eab1
commit
2c38b85368
5 changed files with 138 additions and 69 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
53
server/src/helpers/import_export.helpers.ts
Normal file
53
server/src/helpers/import_export.helpers.ts
Normal 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);
|
||||
}
|
||||
|
|
@ -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];
|
||||
|
|
|
|||
Loading…
Reference in a new issue