mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 08:58:26 +00:00
fixes: duplicate pages
This commit is contained in:
parent
fb08f52554
commit
aa632e3070
4 changed files with 117 additions and 61 deletions
|
|
@ -1262,74 +1262,31 @@ const EditorComponent = (props) => {
|
|||
});
|
||||
};
|
||||
|
||||
const clonePage = (pageId) => {
|
||||
const copyOfAppDefinition = JSON.parse(JSON.stringify(appDefinition));
|
||||
const clonePage = async (pageId) => {
|
||||
await appVersionService.clonePage(appId, editingVersion?.id, pageId).then((data) => {
|
||||
const copyOfAppDefinition = JSON.parse(JSON.stringify(appDefinition));
|
||||
|
||||
updateEditorState({
|
||||
isUpdatingEditorStateInProcess: true,
|
||||
});
|
||||
const pages = data.pages.reduce((acc, page) => {
|
||||
const currentComponents = buildComponentMetaDefinition(_.cloneDeep(page?.components));
|
||||
|
||||
const currentPage = copyOfAppDefinition.pages[pageId];
|
||||
const newPageId = uuid();
|
||||
let newPageName = `${currentPage.name} (copy)`;
|
||||
let newPageHandle = `${currentPage.handle}-copy`;
|
||||
let i = 1;
|
||||
while (
|
||||
!isNull(copyOfAppDefinition.pages[pageId]?.pages) &&
|
||||
!isUndefined(copyOfAppDefinition.pages[pageId]?.pages) &&
|
||||
Object.values(copyOfAppDefinition.pages[pageId]?.pages)?.some((page) => page.handle === newPageHandle)
|
||||
) {
|
||||
newPageName = `${currentPage.name} (copy ${i})`;
|
||||
newPageHandle = `${currentPage.handle}-copy-${i}`;
|
||||
i++;
|
||||
}
|
||||
page.components = currentComponents;
|
||||
|
||||
acc[page.id] = page;
|
||||
|
||||
const newPageData = cloneDeep(currentPage);
|
||||
const oldToNewIdMapping = {};
|
||||
if (!isEmpty(currentPage?.components)) {
|
||||
newPageData.components = Object.keys(newPageData.components).reduce((acc, key) => {
|
||||
const newComponentId = uuid();
|
||||
acc[newComponentId] = newPageData.components[key];
|
||||
acc[newComponentId].id = newComponentId;
|
||||
oldToNewIdMapping[key] = newComponentId;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
Object.values(newPageData.components).map((comp) => {
|
||||
if (comp.parent) {
|
||||
let newParentId = oldToNewIdMapping[comp.parent];
|
||||
if (newParentId) {
|
||||
comp.parent = newParentId;
|
||||
} else {
|
||||
const oldParentId = Object.keys(oldToNewIdMapping).find(
|
||||
(parentId) =>
|
||||
comp.parent.startsWith(parentId) &&
|
||||
['Tabs', 'Calendar'].includes(currentPage?.components[parentId]?.component?.component)
|
||||
);
|
||||
const childTabId = comp.parent.split('-').at(-1);
|
||||
comp.parent = `${oldToNewIdMapping[oldParentId]}-${childTabId}`;
|
||||
}
|
||||
}
|
||||
return comp;
|
||||
const newAppDefinition = {
|
||||
...copyOfAppDefinition,
|
||||
pages: {
|
||||
...copyOfAppDefinition.pages,
|
||||
...pages,
|
||||
},
|
||||
};
|
||||
updateState({
|
||||
events: data.events,
|
||||
});
|
||||
}
|
||||
|
||||
const newPage = {
|
||||
...newPageData,
|
||||
name: newPageName,
|
||||
handle: newPageHandle,
|
||||
};
|
||||
|
||||
const newAppDefinition = {
|
||||
...copyOfAppDefinition,
|
||||
pages: {
|
||||
...copyOfAppDefinition.pages,
|
||||
[newPageId]: newPage,
|
||||
},
|
||||
};
|
||||
|
||||
appDefinitionChanged(newAppDefinition, {
|
||||
pageDefinitionChanged: true,
|
||||
appDefinitionChanged(newAppDefinition);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ export const appVersionService = {
|
|||
saveAppVersionEventHandlers,
|
||||
createAppVersionEventHandler,
|
||||
deleteAppVersionEventHandler,
|
||||
clonePage,
|
||||
};
|
||||
|
||||
function getAll(appId) {
|
||||
|
|
@ -142,3 +143,14 @@ function deleteAppVersionEventHandler(appId, versionId, eventId) {
|
|||
handleResponse
|
||||
);
|
||||
}
|
||||
|
||||
function clonePage(appId, versionId, pageId) {
|
||||
const requestOptions = {
|
||||
method: 'POST',
|
||||
headers: authHeader(),
|
||||
credentials: 'include',
|
||||
};
|
||||
return fetch(`${config.apiUrl}/v2/apps/${appId}/versions/${versionId}/pages/${pageId}/clone`, requestOptions).then(
|
||||
handleResponse
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -263,6 +263,22 @@ export class AppsControllerV2 {
|
|||
|
||||
await this.pageService.createPage(createPageDto, versionId);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(ValidAppInterceptor)
|
||||
@Post(':id/versions/:versionId/pages/:pageId/clone')
|
||||
async clonePage(@User() user, @Param('id') id, @Param('versionId') versionId, @Param('pageId') pageId) {
|
||||
const version = await this.appsService.findVersion(versionId);
|
||||
const app = version.app;
|
||||
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');
|
||||
}
|
||||
|
||||
return await this.pageService.clonePage(pageId, versionId);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(ValidAppInterceptor)
|
||||
@Put(':id/versions/:versionId/pages')
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ import { CreatePageDto, UpdatePageDto } from '@dto/pages.dto';
|
|||
import { AppsService } from './apps.service';
|
||||
import { dbTransactionWrap } 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';
|
||||
import { EventHandler } from 'src/entities/event_handler.entity';
|
||||
|
||||
@Injectable()
|
||||
export class PageService {
|
||||
|
|
@ -49,6 +52,74 @@ export class PageService {
|
|||
return this.pageRepository.save(newPage);
|
||||
}
|
||||
|
||||
async clonePage(pageId: string, appVersionId: string) {
|
||||
const pageToClone = await this.pageRepository.findOne(pageId);
|
||||
|
||||
if (!pageToClone) {
|
||||
throw new Error('Page not found');
|
||||
}
|
||||
|
||||
const newPage = new Page();
|
||||
newPage.name = `${pageToClone.name} copy`;
|
||||
newPage.handle = `${pageToClone.handle}-copy`;
|
||||
newPage.index = pageToClone.index + 1;
|
||||
newPage.appVersionId = appVersionId;
|
||||
|
||||
const clonedpage = await this.pageRepository.save(newPage);
|
||||
|
||||
await this.clonePageEventsAndComponents(pageId, clonedpage.id, appVersionId);
|
||||
|
||||
const pages = await this.findPagesForVersion(appVersionId);
|
||||
const events = await this.eventHandlerService.findEventsForVersion(appVersionId);
|
||||
|
||||
return { pages, events };
|
||||
}
|
||||
|
||||
async clonePageEventsAndComponents(pageId: string, clonePageId: string, appVersionId: string) {
|
||||
return dbTransactionWrap(async (manager: EntityManager) => {
|
||||
const pageComponents = await manager.find(Component, { pageId });
|
||||
const pageEvents = await this.eventHandlerService.findAllEventsWithSourceId(pageId);
|
||||
|
||||
// Clone events
|
||||
await Promise.all(
|
||||
pageEvents.map(async (event) => {
|
||||
const clonedEvent = { ...event, id: undefined, sourceId: clonePageId };
|
||||
await manager.save(EventHandler, clonedEvent);
|
||||
})
|
||||
);
|
||||
|
||||
// Clone components
|
||||
const clonedComponents = await Promise.all(
|
||||
pageComponents.map(async (component) => {
|
||||
const clonedComponent = { ...component, id: undefined, pageId: clonePageId };
|
||||
const newComponent = await manager.save(Component, clonedComponent);
|
||||
|
||||
const componentLayouts = await manager.find(Layout, { componentId: component.id });
|
||||
const clonedLayouts = componentLayouts.map((layout) => ({
|
||||
...layout,
|
||||
id: undefined,
|
||||
componentId: newComponent.id,
|
||||
}));
|
||||
|
||||
// Clone component events
|
||||
const clonedComponentEvents = await this.eventHandlerService.findAllEventsWithSourceId(component.id);
|
||||
const clonedEvents = clonedComponentEvents.map((event) => ({
|
||||
...event,
|
||||
id: undefined,
|
||||
sourceId: newComponent.id,
|
||||
}));
|
||||
|
||||
await manager.save(Layout, clonedLayouts);
|
||||
await manager.save(EventHandler, clonedEvents);
|
||||
|
||||
return newComponent;
|
||||
})
|
||||
);
|
||||
|
||||
return clonedComponents;
|
||||
});
|
||||
}
|
||||
|
||||
async updatePage(pageUpdates: UpdatePageDto) {
|
||||
if (Object.keys(pageUpdates.diff).length > 1) {
|
||||
return this.updatePagesOrder(pageUpdates.diff);
|
||||
|
|
|
|||
Loading…
Reference in a new issue