fixes: duplicate pages

This commit is contained in:
arpitnath 2023-09-24 22:29:26 +05:30
parent fb08f52554
commit aa632e3070
4 changed files with 117 additions and 61 deletions

View file

@ -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);
});
};

View file

@ -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
);
}

View file

@ -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')

View file

@ -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);