mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 08:58:26 +00:00
fixes: Resolving App Version and Timestamp Update Challenges (#7863)
This commit is contained in:
parent
436980edf5
commit
75086defea
5 changed files with 113 additions and 72 deletions
|
|
@ -188,7 +188,7 @@ export class AppsControllerV2 {
|
|||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
await this.componentsService.update(versionEditDto.diff);
|
||||
await this.componentsService.update(versionEditDto.diff, versionId);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
|
|
@ -212,7 +212,7 @@ export class AppsControllerV2 {
|
|||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
await this.componentsService.delete(versionEditDto.diff);
|
||||
await this.componentsService.delete(versionEditDto.diff, versionId);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
|
|
@ -236,7 +236,7 @@ export class AppsControllerV2 {
|
|||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
await this.componentsService.componentLayoutChange(versionEditDto.diff);
|
||||
await this.componentsService.componentLayoutChange(versionEditDto.diff, versionId);
|
||||
}
|
||||
|
||||
// pages api
|
||||
|
|
@ -300,7 +300,7 @@ 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 });
|
||||
await this.pageService.updatePage({ pageId: updatePageDto.pageId, diff: updatePageDto.diff }, versionId);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
|
|
@ -363,7 +363,7 @@ export class AppsControllerV2 {
|
|||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
return await this.eventService.updateEvent(body?.events, body?.updateType);
|
||||
return await this.eventService.updateEvent(body?.events, body?.updateType, versionId);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
|
|
@ -382,6 +382,6 @@ export class AppsControllerV2 {
|
|||
throw new ForbiddenException('You do not have permissions to perform this action');
|
||||
}
|
||||
|
||||
return await this.eventService.deleteEvent(eventId);
|
||||
return await this.eventService.deleteEvent(eventId, versionId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,6 +80,26 @@ export async function dbTransactionWrap(operation: (...args) => any, manager?: E
|
|||
}
|
||||
}
|
||||
|
||||
export const updateTimestampForAppVersion = async (manager, appVersionId) => {
|
||||
const appVersion = await manager.findOne('app_versions', appVersionId);
|
||||
if (appVersion) {
|
||||
await manager.update('app_versions', appVersionId, { updatedAt: new Date() });
|
||||
}
|
||||
};
|
||||
|
||||
export async function dbTransactionForAppVersionAssociationsUpdate(
|
||||
operation: (...args) => any,
|
||||
appVersionId: string
|
||||
): Promise<any> {
|
||||
return await getManager().transaction(async (manager) => {
|
||||
const result = await operation(manager);
|
||||
|
||||
await updateTimestampForAppVersion(manager, appVersionId);
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
export const defaultAppEnvironments = [{ name: 'production', isDefault: true, priority: 3 }];
|
||||
export async function catchDbException(
|
||||
operation: () => any,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { EntityManager, Repository } from 'typeorm';
|
|||
import { Component } from 'src/entities/component.entity';
|
||||
import { Layout } from 'src/entities/layout.entity';
|
||||
import { Page } from 'src/entities/page.entity';
|
||||
import { dbTransactionWrap } from 'src/helpers/utils.helper';
|
||||
import { dbTransactionForAppVersionAssociationsUpdate, dbTransactionWrap } from 'src/helpers/utils.helper';
|
||||
|
||||
import { EventsService } from './events_handler.service';
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ export class ComponentsService {
|
|||
}
|
||||
|
||||
async create(componentDiff: object, pageId: string, appVersionId: string) {
|
||||
return dbTransactionWrap(async (manager: EntityManager) => {
|
||||
return dbTransactionForAppVersionAssociationsUpdate(async (manager: EntityManager) => {
|
||||
const page = await manager.findOne(Page, {
|
||||
where: { appVersionId, id: pageId },
|
||||
});
|
||||
|
|
@ -58,11 +58,11 @@ export class ComponentsService {
|
|||
await manager.save(Layout, componentLayouts);
|
||||
|
||||
return {};
|
||||
});
|
||||
}, appVersionId);
|
||||
}
|
||||
|
||||
async update(componentDiff: object) {
|
||||
return dbTransactionWrap(async (manager) => {
|
||||
async update(componentDiff: object, appVersionId: string) {
|
||||
return dbTransactionForAppVersionAssociationsUpdate(async (manager) => {
|
||||
for (const componentId in componentDiff) {
|
||||
const { component } = componentDiff[componentId];
|
||||
|
||||
|
|
@ -105,11 +105,11 @@ export class ComponentsService {
|
|||
|
||||
return;
|
||||
}
|
||||
});
|
||||
}, appVersionId);
|
||||
}
|
||||
|
||||
async delete(componentIds: string[]) {
|
||||
return dbTransactionWrap(async (manager: EntityManager) => {
|
||||
async delete(componentIds: string[], appVersionId: string) {
|
||||
return dbTransactionForAppVersionAssociationsUpdate(async (manager: EntityManager) => {
|
||||
const components = await manager.findByIds(Component, componentIds);
|
||||
|
||||
if (!components.length) {
|
||||
|
|
@ -125,11 +125,11 @@ export class ComponentsService {
|
|||
});
|
||||
|
||||
await manager.delete(Component, componentIds);
|
||||
});
|
||||
}, appVersionId);
|
||||
}
|
||||
|
||||
async componentLayoutChange(componenstLayoutDiff: object) {
|
||||
return dbTransactionWrap(async (manager: EntityManager) => {
|
||||
async componentLayoutChange(componenstLayoutDiff: object, appVersionId: string) {
|
||||
return dbTransactionForAppVersionAssociationsUpdate(async (manager: EntityManager) => {
|
||||
for (const componentId in componenstLayoutDiff) {
|
||||
const doesComponentExist = await manager.findAndCount(Component, { id: componentId });
|
||||
|
||||
|
|
@ -155,7 +155,7 @@ export class ComponentsService {
|
|||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}, appVersionId);
|
||||
}
|
||||
|
||||
async getAllComponents(pageId: string) {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { EntityManager, Repository } from 'typeorm';
|
|||
import { Component } from 'src/entities/component.entity';
|
||||
|
||||
import { EventHandler } from 'src/entities/event_handler.entity';
|
||||
import { dbTransactionWrap } from 'src/helpers/utils.helper';
|
||||
import { dbTransactionWrap, dbTransactionForAppVersionAssociationsUpdate } from 'src/helpers/utils.helper';
|
||||
|
||||
@Injectable()
|
||||
export class EventsService {
|
||||
|
|
@ -55,14 +55,14 @@ export class EventsService {
|
|||
index: eventObj.index,
|
||||
};
|
||||
|
||||
return await dbTransactionWrap(async (manager: EntityManager) => {
|
||||
return await dbTransactionForAppVersionAssociationsUpdate(async (manager: EntityManager) => {
|
||||
const event = await manager.save(EventHandler, newEvent);
|
||||
return event;
|
||||
});
|
||||
}, versionId);
|
||||
}
|
||||
|
||||
async updateEvent(events: [], updateType: 'update' | 'reorder') {
|
||||
return await dbTransactionWrap(async (manager: EntityManager) => {
|
||||
async updateEvent(events: [], 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;
|
||||
|
|
@ -91,7 +91,7 @@ export class EventsService {
|
|||
return await manager.save(EventHandler, updatedEvent);
|
||||
})
|
||||
);
|
||||
});
|
||||
}, appVersionId);
|
||||
}
|
||||
|
||||
async updateEventsOrderOnDelete(sourceId: string, deletedIndex: number) {
|
||||
|
|
@ -112,8 +112,8 @@ export class EventsService {
|
|||
});
|
||||
}
|
||||
|
||||
async deleteEvent(eventId: string) {
|
||||
return await dbTransactionWrap(async (manager: EntityManager) => {
|
||||
async deleteEvent(eventId: string, appVersionId: string) {
|
||||
return await dbTransactionForAppVersionAssociationsUpdate(async (manager: EntityManager) => {
|
||||
const event = await manager.findOne(EventHandler, {
|
||||
where: { id: eventId },
|
||||
});
|
||||
|
|
@ -129,6 +129,6 @@ export class EventsService {
|
|||
}
|
||||
await this.updateEventsOrderOnDelete(event.sourceId, event.index);
|
||||
return deleteResponse;
|
||||
});
|
||||
}, appVersionId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { Page } from 'src/entities/page.entity';
|
|||
import { ComponentsService } from './components.service';
|
||||
import { CreatePageDto, UpdatePageDto } from '@dto/pages.dto';
|
||||
import { AppsService } from './apps.service';
|
||||
import { dbTransactionWrap } from 'src/helpers/utils.helper';
|
||||
import { dbTransactionWrap, dbTransactionForAppVersionAssociationsUpdate } from 'src/helpers/utils.helper';
|
||||
import { EventsService } from './events_handler.service';
|
||||
import { Component } from 'src/entities/component.entity';
|
||||
import { Layout } from 'src/entities/layout.entity';
|
||||
|
|
@ -42,54 +42,58 @@ export class PageService {
|
|||
}
|
||||
|
||||
async createPage(page: CreatePageDto, appVersionId: string): Promise<Page> {
|
||||
const newPage = new Page();
|
||||
newPage.id = page.id;
|
||||
newPage.name = page.name;
|
||||
newPage.handle = page.handle;
|
||||
newPage.index = page.index;
|
||||
newPage.appVersionId = appVersionId;
|
||||
return dbTransactionForAppVersionAssociationsUpdate(async (manager) => {
|
||||
const newPage = new Page();
|
||||
newPage.id = page.id;
|
||||
newPage.name = page.name;
|
||||
newPage.handle = page.handle;
|
||||
newPage.index = page.index;
|
||||
newPage.appVersionId = appVersionId;
|
||||
|
||||
return this.pageRepository.save(newPage);
|
||||
return await manager.save(Page, newPage);
|
||||
}, appVersionId);
|
||||
}
|
||||
|
||||
async clonePage(pageId: string, appVersionId: string) {
|
||||
const pageToClone = await this.pageRepository.findOne(pageId);
|
||||
return dbTransactionForAppVersionAssociationsUpdate(async (manager) => {
|
||||
const pageToClone = await manager.findOne(Page, pageId);
|
||||
|
||||
if (!pageToClone) {
|
||||
throw new Error('Page not found');
|
||||
}
|
||||
if (!pageToClone) {
|
||||
throw new Error('Page not found');
|
||||
}
|
||||
|
||||
let pageName = `${pageToClone.name} (copy)`;
|
||||
let pageHandle = `${pageToClone.handle}-copy`;
|
||||
let pageName = `${pageToClone.name} (copy)`;
|
||||
let pageHandle = `${pageToClone.handle}-copy`;
|
||||
|
||||
const allPages = await this.pageRepository.find({ appVersionId });
|
||||
const allPages = await this.pageRepository.find({ appVersionId });
|
||||
|
||||
const pageNameORHandleExists = allPages.filter((page) => {
|
||||
return page.name.includes(pageName) || page.handle.includes(pageHandle);
|
||||
});
|
||||
const pageNameORHandleExists = allPages.filter((page) => {
|
||||
return page.name.includes(pageName) || page.handle.includes(pageHandle);
|
||||
});
|
||||
|
||||
if (pageNameORHandleExists.length > 0) {
|
||||
pageName = `${pageToClone.name} (copy ${pageNameORHandleExists.length})`;
|
||||
pageHandle = `${pageToClone.handle}-copy-${pageNameORHandleExists.length}`;
|
||||
}
|
||||
if (pageNameORHandleExists.length > 0) {
|
||||
pageName = `${pageToClone.name} (copy ${pageNameORHandleExists.length})`;
|
||||
pageHandle = `${pageToClone.handle}-copy-${pageNameORHandleExists.length}`;
|
||||
}
|
||||
|
||||
const newPage = new Page();
|
||||
newPage.name = pageName;
|
||||
newPage.handle = pageHandle;
|
||||
newPage.index = pageToClone.index + 1;
|
||||
newPage.appVersionId = appVersionId;
|
||||
const newPage = new Page();
|
||||
newPage.name = pageName;
|
||||
newPage.handle = pageHandle;
|
||||
newPage.index = pageToClone.index + 1;
|
||||
newPage.appVersionId = appVersionId;
|
||||
|
||||
const clonedpage = await this.pageRepository.save(newPage);
|
||||
const clonedpage = await this.pageRepository.save(newPage);
|
||||
|
||||
await this.clonePageEventsAndComponents(pageId, clonedpage.id, appVersionId);
|
||||
await this.clonePageEventsAndComponents(pageId, clonedpage.id);
|
||||
|
||||
const pages = await this.findPagesForVersion(appVersionId);
|
||||
const events = await this.eventHandlerService.findEventsForVersion(appVersionId);
|
||||
const pages = await this.findPagesForVersion(appVersionId);
|
||||
const events = await this.eventHandlerService.findEventsForVersion(appVersionId);
|
||||
|
||||
return { pages, events };
|
||||
return { pages, events };
|
||||
}, appVersionId);
|
||||
}
|
||||
|
||||
async clonePageEventsAndComponents(pageId: string, clonePageId: string, appVersionId: string) {
|
||||
async clonePageEventsAndComponents(pageId: string, clonePageId: string) {
|
||||
return dbTransactionWrap(async (manager: EntityManager) => {
|
||||
const pageComponents = await manager.find(Component, { pageId });
|
||||
const pageEvents = await this.eventHandlerService.findAllEventsWithSourceId(pageId);
|
||||
|
|
@ -98,6 +102,14 @@ export class PageService {
|
|||
// Clone events
|
||||
await Promise.all(
|
||||
pageEvents.map(async (event) => {
|
||||
const eventDefinition = event.event;
|
||||
|
||||
if (eventDefinition?.actionId === 'control-component') {
|
||||
eventDefinition.componentId = componentsIdMap[eventDefinition.componentId];
|
||||
}
|
||||
|
||||
event.event = eventDefinition;
|
||||
|
||||
const clonedEvent = { ...event, id: undefined, sourceId: clonePageId };
|
||||
await manager.save(EventHandler, clonedEvent);
|
||||
})
|
||||
|
|
@ -119,11 +131,20 @@ export class PageService {
|
|||
|
||||
// Clone component events
|
||||
const clonedComponentEvents = await this.eventHandlerService.findAllEventsWithSourceId(component.id);
|
||||
const clonedEvents = clonedComponentEvents.map((event) => ({
|
||||
...event,
|
||||
id: undefined,
|
||||
sourceId: newComponent.id,
|
||||
}));
|
||||
const clonedEvents = clonedComponentEvents.map((event) => {
|
||||
const eventDefinition = event.event;
|
||||
|
||||
if (eventDefinition?.actionId === 'control-component') {
|
||||
eventDefinition.componentId = componentsIdMap[eventDefinition.componentId];
|
||||
}
|
||||
event.event = eventDefinition;
|
||||
|
||||
return {
|
||||
...event,
|
||||
id: undefined,
|
||||
sourceId: newComponent.id,
|
||||
};
|
||||
});
|
||||
|
||||
await manager.save(Layout, clonedLayouts);
|
||||
await manager.save(EventHandler, clonedEvents);
|
||||
|
|
@ -141,9 +162,9 @@ export class PageService {
|
|||
});
|
||||
}
|
||||
|
||||
async updatePage(pageUpdates: UpdatePageDto) {
|
||||
async updatePage(pageUpdates: UpdatePageDto, appVersionId: string) {
|
||||
if (Object.keys(pageUpdates.diff).length > 1) {
|
||||
return this.updatePagesOrder(pageUpdates.diff);
|
||||
return this.updatePagesOrder(pageUpdates.diff, appVersionId);
|
||||
}
|
||||
|
||||
const currentPage = await this.pageRepository.findOne(pageUpdates.pageId);
|
||||
|
|
@ -154,7 +175,7 @@ export class PageService {
|
|||
return this.pageRepository.update(pageUpdates.pageId, pageUpdates.diff);
|
||||
}
|
||||
|
||||
async updatePagesOrder(pages) {
|
||||
async updatePagesOrder(pages, appVersionId: string) {
|
||||
const pagesToPage = Object.keys(pages).map((pageId) => {
|
||||
return {
|
||||
id: pageId,
|
||||
|
|
@ -162,18 +183,18 @@ export class PageService {
|
|||
};
|
||||
});
|
||||
|
||||
return await dbTransactionWrap(async (manager: EntityManager) => {
|
||||
return await dbTransactionForAppVersionAssociationsUpdate(async (manager: EntityManager) => {
|
||||
await Promise.all(
|
||||
pagesToPage.map(async (page) => {
|
||||
await manager.update(Page, page.id, page);
|
||||
})
|
||||
);
|
||||
});
|
||||
}, appVersionId);
|
||||
}
|
||||
|
||||
async deletePage(pageId: string, appVersionId: string) {
|
||||
const { editingVersion } = await this.appService.findAppFromVersion(appVersionId);
|
||||
return dbTransactionWrap(async (manager: EntityManager) => {
|
||||
return dbTransactionForAppVersionAssociationsUpdate(async (manager: EntityManager) => {
|
||||
const pageExists = await manager.findOne(Page, pageId);
|
||||
|
||||
if (!pageExists) {
|
||||
|
|
@ -200,7 +221,7 @@ export class PageService {
|
|||
await manager.update(Page, page.id, page);
|
||||
})
|
||||
);
|
||||
});
|
||||
}, appVersionId);
|
||||
}
|
||||
|
||||
rearrangePagesOnDelete(pages: Page[], pageDeletedIndex: number) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue