Files
twenty/packages/twenty-server/src/modules/dashboard/services/dashboard-duplication.service.ts
T

146 lines
4.9 KiB
TypeScript

import { Injectable, Logger } from '@nestjs/common';
import { appendCopySuffix, isDefined } from 'twenty-shared/utils';
import { ActorFromAuthContextService } from 'src/engine/core-modules/actor/services/actor-from-auth-context.service';
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
import { PageLayoutDuplicationService } from 'src/engine/metadata-modules/page-layout/services/page-layout-duplication.service';
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { DuplicatedDashboardDTO } from 'src/modules/dashboard/dtos/duplicated-dashboard.dto';
import {
DashboardException,
DashboardExceptionCode,
DashboardExceptionMessageKey,
generateDashboardExceptionMessage,
} from 'src/modules/dashboard/exceptions/dashboard.exception';
import { DashboardWorkspaceEntity } from 'src/modules/dashboard/standard-objects/dashboard.workspace-entity';
@Injectable()
export class DashboardDuplicationService {
private readonly logger = new Logger(DashboardDuplicationService.name);
constructor(
private readonly pageLayoutDuplicationService: PageLayoutDuplicationService,
private readonly globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
private readonly actorFromAuthContextService: ActorFromAuthContextService,
) {}
async duplicateDashboard(
dashboardId: string,
authContext: WorkspaceAuthContext,
): Promise<DuplicatedDashboardDTO> {
const workspace = authContext.workspace;
const workspaceId = workspace.id;
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
async () => {
const dashboardRepository =
await this.globalWorkspaceOrmManager.getRepository<DashboardWorkspaceEntity>(
workspaceId,
'dashboard',
{ shouldBypassPermissionChecks: true },
);
const originalDashboard = await dashboardRepository.findOne({
where: { id: dashboardId },
});
if (!isDefined(originalDashboard)) {
throw new DashboardException(
generateDashboardExceptionMessage(
DashboardExceptionMessageKey.DASHBOARD_NOT_FOUND,
dashboardId,
),
DashboardExceptionCode.DASHBOARD_NOT_FOUND,
);
}
if (!isDefined(originalDashboard.pageLayoutId)) {
throw new DashboardException(
generateDashboardExceptionMessage(
DashboardExceptionMessageKey.PAGE_LAYOUT_NOT_FOUND,
dashboardId,
),
DashboardExceptionCode.PAGE_LAYOUT_NOT_FOUND,
);
}
try {
const newPageLayout =
await this.pageLayoutDuplicationService.duplicate({
pageLayoutId: originalDashboard.pageLayoutId,
workspaceId,
});
const newDashboard = await this.createDuplicatedDashboard(
originalDashboard,
newPageLayout.id,
dashboardRepository,
authContext,
);
return {
id: newDashboard.id,
title: newDashboard.title,
pageLayoutId: newDashboard.pageLayoutId,
position: newDashboard.position,
createdAt: newDashboard.createdAt,
updatedAt: newDashboard.updatedAt,
};
} catch (error) {
this.logger.error(
`Failed to duplicate dashboard ${dashboardId}: ${error.message}`,
error.stack,
);
throw error;
}
},
authContext,
);
}
private async createDuplicatedDashboard(
originalDashboard: DashboardWorkspaceEntity,
newPageLayoutId: string,
dashboardRepository: WorkspaceRepository<DashboardWorkspaceEntity>,
authContext: WorkspaceAuthContext,
): Promise<DashboardWorkspaceEntity> {
const newTitle = appendCopySuffix(originalDashboard.title ?? '');
const [recordWithActor] =
await this.actorFromAuthContextService.injectActorFieldsOnCreate({
records: [
{
title: newTitle,
pageLayoutId: newPageLayoutId,
position: originalDashboard.position,
},
],
objectMetadataNameSingular: 'dashboard',
authContext,
});
const insertResult = await dashboardRepository.insert(recordWithActor);
const newDashboardId = insertResult.identifiers[0].id;
const newDashboard = await dashboardRepository.findOne({
where: { id: newDashboardId },
});
if (!isDefined(newDashboard)) {
throw new DashboardException(
generateDashboardExceptionMessage(
DashboardExceptionMessageKey.DASHBOARD_DUPLICATION_FAILED,
'Failed to retrieve created dashboard',
),
DashboardExceptionCode.DASHBOARD_DUPLICATION_FAILED,
);
}
return newDashboard;
}
}