[DASHBOARDS] Fix dashboard duplication createdBy (#16999)
Fixes https://github.com/twentyhq/core-team-issues/issues/2032 ## Before https://github.com/user-attachments/assets/5804d3e7-1c03-4eb9-9203-64656438f5d1 ## After https://github.com/user-attachments/assets/9f96458c-d2a5-481a-b6b2-4d88f0daa98a
This commit is contained in:
@@ -1,12 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { DashboardSyncService } from 'src/engine/metadata-modules/dashboard/services/dashboard-sync.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
|
||||
|
||||
@Module({
|
||||
imports: [TwentyORMModule, WorkspaceManyOrAllFlatEntityMapsCacheModule],
|
||||
providers: [DashboardSyncService],
|
||||
exports: [DashboardSyncService],
|
||||
})
|
||||
export class DashboardModule {}
|
||||
-256
@@ -1,256 +0,0 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { buildSystemAuthContext } from 'src/engine/twenty-orm/utils/build-system-auth-context.util';
|
||||
|
||||
@Injectable()
|
||||
export class DashboardSyncService {
|
||||
private readonly logger = new Logger(DashboardSyncService.name);
|
||||
|
||||
constructor(
|
||||
private readonly globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
|
||||
private readonly workspaceManyOrAllFlatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
) {}
|
||||
|
||||
private async isPageLayoutOfTypeDashboard({
|
||||
pageLayoutId,
|
||||
workspaceId,
|
||||
}: {
|
||||
pageLayoutId: string;
|
||||
workspaceId: string;
|
||||
}): Promise<boolean> {
|
||||
const { flatPageLayoutMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatPageLayoutMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const pageLayout = flatPageLayoutMaps.byId[pageLayoutId];
|
||||
|
||||
return (
|
||||
isDefined(pageLayout) && pageLayout.type === PageLayoutType.DASHBOARD
|
||||
);
|
||||
}
|
||||
|
||||
async updateLinkedDashboardsUpdatedAtByPageLayoutId({
|
||||
pageLayoutId,
|
||||
workspaceId,
|
||||
updatedAt,
|
||||
}: {
|
||||
pageLayoutId: string;
|
||||
workspaceId: string;
|
||||
updatedAt: Date;
|
||||
}): Promise<void> {
|
||||
const isDashboard = await this.isPageLayoutOfTypeDashboard({
|
||||
pageLayoutId,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
if (!isDashboard) {
|
||||
return;
|
||||
}
|
||||
|
||||
const authContext = buildSystemAuthContext(workspaceId);
|
||||
|
||||
try {
|
||||
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
|
||||
authContext,
|
||||
async () => {
|
||||
const dashboardRepository =
|
||||
await this.globalWorkspaceOrmManager.getRepository(
|
||||
workspaceId,
|
||||
'dashboard',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
await dashboardRepository.update({ pageLayoutId }, { updatedAt });
|
||||
},
|
||||
);
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
`Failed to update dashboard updatedAt for page layout ${pageLayoutId}: ${error}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async softDeleteLinkedDashboardsByPageLayoutId({
|
||||
pageLayoutId,
|
||||
workspaceId,
|
||||
deletedAt,
|
||||
}: {
|
||||
pageLayoutId: string;
|
||||
workspaceId: string;
|
||||
deletedAt: Date;
|
||||
}): Promise<void> {
|
||||
const isDashboard = await this.isPageLayoutOfTypeDashboard({
|
||||
pageLayoutId,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
if (!isDashboard) {
|
||||
return;
|
||||
}
|
||||
|
||||
const authContext = buildSystemAuthContext(workspaceId);
|
||||
|
||||
try {
|
||||
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
|
||||
authContext,
|
||||
async () => {
|
||||
const dashboardRepository =
|
||||
await this.globalWorkspaceOrmManager.getRepository(
|
||||
workspaceId,
|
||||
'dashboard',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
await dashboardRepository.update({ pageLayoutId }, { deletedAt });
|
||||
},
|
||||
);
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
`Failed to soft delete dashboards for page layout ${pageLayoutId}: ${error}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async restoreLinkedDashboardsByPageLayoutId({
|
||||
pageLayoutId,
|
||||
workspaceId,
|
||||
}: {
|
||||
pageLayoutId: string;
|
||||
workspaceId: string;
|
||||
}): Promise<void> {
|
||||
const isDashboard = await this.isPageLayoutOfTypeDashboard({
|
||||
pageLayoutId,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
if (!isDashboard) {
|
||||
return;
|
||||
}
|
||||
|
||||
const authContext = buildSystemAuthContext(workspaceId);
|
||||
|
||||
try {
|
||||
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
|
||||
authContext,
|
||||
async () => {
|
||||
const dashboardRepository =
|
||||
await this.globalWorkspaceOrmManager.getRepository(
|
||||
workspaceId,
|
||||
'dashboard',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
await dashboardRepository.update(
|
||||
{ pageLayoutId },
|
||||
{ deletedAt: null },
|
||||
);
|
||||
},
|
||||
);
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
`Failed to restore dashboards for page layout ${pageLayoutId}: ${error}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async updateLinkedDashboardsUpdatedAtByTabId({
|
||||
tabId,
|
||||
workspaceId,
|
||||
updatedAt,
|
||||
}: {
|
||||
tabId: string;
|
||||
workspaceId: string;
|
||||
updatedAt: Date;
|
||||
}): Promise<void> {
|
||||
const { flatPageLayoutTabMaps, flatPageLayoutMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatPageLayoutTabMaps', 'flatPageLayoutMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const tab = flatPageLayoutTabMaps.byId[tabId];
|
||||
|
||||
if (!isDefined(tab)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pageLayout = flatPageLayoutMaps.byId[tab.pageLayoutId];
|
||||
|
||||
if (
|
||||
!isDefined(pageLayout) ||
|
||||
pageLayout.type !== PageLayoutType.DASHBOARD
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.updateLinkedDashboardsUpdatedAtByPageLayoutId({
|
||||
pageLayoutId: tab.pageLayoutId,
|
||||
workspaceId,
|
||||
updatedAt,
|
||||
});
|
||||
}
|
||||
|
||||
async updateLinkedDashboardsUpdatedAtByWidgetId({
|
||||
widgetId,
|
||||
workspaceId,
|
||||
updatedAt,
|
||||
}: {
|
||||
widgetId: string;
|
||||
workspaceId: string;
|
||||
updatedAt: Date;
|
||||
}): Promise<void> {
|
||||
const {
|
||||
flatPageLayoutWidgetMaps,
|
||||
flatPageLayoutTabMaps,
|
||||
flatPageLayoutMaps,
|
||||
} =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: [
|
||||
'flatPageLayoutWidgetMaps',
|
||||
'flatPageLayoutTabMaps',
|
||||
'flatPageLayoutMaps',
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
const widget = flatPageLayoutWidgetMaps.byId[widgetId];
|
||||
|
||||
if (!isDefined(widget)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tab = flatPageLayoutTabMaps.byId[widget.pageLayoutTabId];
|
||||
|
||||
if (!isDefined(tab)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pageLayout = flatPageLayoutMaps.byId[tab.pageLayoutId];
|
||||
|
||||
if (
|
||||
!isDefined(pageLayout) ||
|
||||
pageLayout.type !== PageLayoutType.DASHBOARD
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.updateLinkedDashboardsUpdatedAtByPageLayoutId({
|
||||
pageLayoutId: tab.pageLayoutId,
|
||||
workspaceId,
|
||||
updatedAt,
|
||||
});
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -4,7 +4,6 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DashboardModule } from 'src/engine/metadata-modules/dashboard/dashboard.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { FlatPageLayoutTabModule } from 'src/engine/metadata-modules/flat-page-layout-tab/flat-page-layout-tab.module';
|
||||
import { FlatPageLayoutWidgetModule } from 'src/engine/metadata-modules/flat-page-layout-widget/flat-page-layout-widget.module';
|
||||
@@ -17,6 +16,7 @@ import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
|
||||
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||
import { WorkspaceMigrationBuilderGraphqlApiExceptionInterceptor } from 'src/engine/workspace-manager/workspace-migration-v2/interceptors/workspace-migration-builder-graphql-api-exception.interceptor';
|
||||
import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module';
|
||||
import { DashboardSyncModule } from 'src/modules/dashboard-sync/dashboard-sync.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -30,7 +30,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
FlatPageLayoutTabModule,
|
||||
FlatPageLayoutWidgetModule,
|
||||
ApplicationModule,
|
||||
DashboardModule,
|
||||
DashboardSyncModule,
|
||||
],
|
||||
controllers: [PageLayoutTabController],
|
||||
providers: [
|
||||
|
||||
+1
-1
@@ -3,7 +3,6 @@ import { Injectable } from '@nestjs/common';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { DashboardSyncService } from 'src/engine/metadata-modules/dashboard/services/dashboard-sync.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { FlatPageLayoutTabMaps } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab-maps.type';
|
||||
@@ -30,6 +29,7 @@ import { fromFlatPageLayoutTabToPageLayoutTabDto } from 'src/engine/metadata-mod
|
||||
import { fromFlatPageLayoutTabWithWidgetsToPageLayoutTabDto } from 'src/engine/metadata-modules/page-layout-tab/utils/from-flat-page-layout-tab-with-widgets-to-page-layout-tab-dto.util';
|
||||
import { WorkspaceMigrationBuilderExceptionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/exceptions/workspace-migration-builder-exception-v2';
|
||||
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service';
|
||||
import { DashboardSyncService } from 'src/modules/dashboard-sync/services/dashboard-sync.service';
|
||||
|
||||
@Injectable()
|
||||
export class PageLayoutTabService {
|
||||
|
||||
+2
-2
@@ -4,7 +4,6 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DashboardModule } from 'src/engine/metadata-modules/dashboard/dashboard.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { FlatPageLayoutWidgetModule } from 'src/engine/metadata-modules/flat-page-layout-widget/flat-page-layout-widget.module';
|
||||
import { PageLayoutWidgetController } from 'src/engine/metadata-modules/page-layout-widget/controllers/page-layout-widget.controller';
|
||||
@@ -16,6 +15,7 @@ import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
|
||||
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||
import { WorkspaceMigrationBuilderGraphqlApiExceptionInterceptor } from 'src/engine/workspace-manager/workspace-migration-v2/interceptors/workspace-migration-builder-graphql-api-exception.interceptor';
|
||||
import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module';
|
||||
import { DashboardSyncModule } from 'src/modules/dashboard-sync/dashboard-sync.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -28,7 +28,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
FlatPageLayoutWidgetModule,
|
||||
ApplicationModule,
|
||||
DashboardModule,
|
||||
DashboardSyncModule,
|
||||
],
|
||||
controllers: [PageLayoutWidgetController],
|
||||
providers: [
|
||||
|
||||
+1
-1
@@ -3,7 +3,6 @@ import { Injectable } from '@nestjs/common';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { DashboardSyncService } from 'src/engine/metadata-modules/dashboard/services/dashboard-sync.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
|
||||
@@ -29,6 +28,7 @@ import { fromFlatPageLayoutWidgetToPageLayoutWidgetDto } from 'src/engine/metada
|
||||
import { validateWidgetGridPosition } from 'src/engine/metadata-modules/page-layout-widget/utils/validate-widget-grid-position.util';
|
||||
import { WorkspaceMigrationBuilderExceptionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/exceptions/workspace-migration-builder-exception-v2';
|
||||
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service';
|
||||
import { DashboardSyncService } from 'src/modules/dashboard-sync/services/dashboard-sync.service';
|
||||
|
||||
type WidgetMigrationOperations = {
|
||||
flatEntityToCreate: FlatPageLayoutWidget[];
|
||||
|
||||
+2
-2
@@ -5,7 +5,6 @@ import { ApplicationModule } from 'src/engine/core-modules/application/applicati
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { I18nModule } from 'src/engine/core-modules/i18n/i18n.module';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DashboardModule } from 'src/engine/metadata-modules/dashboard/dashboard.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { FlatPageLayoutTabModule } from 'src/engine/metadata-modules/flat-page-layout-tab/flat-page-layout-tab.module';
|
||||
import { FlatPageLayoutWidgetModule } from 'src/engine/metadata-modules/flat-page-layout-widget/flat-page-layout-widget.module';
|
||||
@@ -23,6 +22,7 @@ import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
|
||||
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||
import { WorkspaceMigrationBuilderGraphqlApiExceptionInterceptor } from 'src/engine/workspace-manager/workspace-migration-v2/interceptors/workspace-migration-builder-graphql-api-exception.interceptor';
|
||||
import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module';
|
||||
import { DashboardSyncModule } from 'src/modules/dashboard-sync/dashboard-sync.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -40,7 +40,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
ApplicationModule,
|
||||
PageLayoutTabModule,
|
||||
PageLayoutWidgetModule,
|
||||
DashboardModule,
|
||||
DashboardSyncModule,
|
||||
],
|
||||
controllers: [PageLayoutController],
|
||||
providers: [
|
||||
|
||||
+1
-1
@@ -4,7 +4,6 @@ import { computeDiffBetweenObjects, isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { DashboardSyncService } from 'src/engine/metadata-modules/dashboard/services/dashboard-sync.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { FLAT_PAGE_LAYOUT_TAB_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout-tab/constants/flat-page-layout-tab-editable-properties.constant';
|
||||
@@ -28,6 +27,7 @@ import {
|
||||
import { fromFlatPageLayoutWithTabsAndWidgetsToPageLayoutDto } from 'src/engine/metadata-modules/page-layout/utils/from-flat-page-layout-with-tabs-and-widgets-to-page-layout-dto.util';
|
||||
import { WorkspaceMigrationBuilderExceptionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/exceptions/workspace-migration-builder-exception-v2';
|
||||
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service';
|
||||
import { DashboardSyncService } from 'src/modules/dashboard-sync/services/dashboard-sync.service';
|
||||
|
||||
type UpdatePageLayoutWithTabsParams = {
|
||||
id: string;
|
||||
|
||||
+1
-1
@@ -4,7 +4,6 @@ import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { DashboardSyncService } from 'src/engine/metadata-modules/dashboard/services/dashboard-sync.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { type FlatPageLayoutTabMaps } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab-maps.type';
|
||||
@@ -35,6 +34,7 @@ import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspac
|
||||
import { buildSystemAuthContext } from 'src/engine/twenty-orm/utils/build-system-auth-context.util';
|
||||
import { WorkspaceMigrationBuilderExceptionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/exceptions/workspace-migration-builder-exception-v2';
|
||||
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service';
|
||||
import { DashboardSyncService } from 'src/modules/dashboard-sync/services/dashboard-sync.service';
|
||||
|
||||
@Injectable()
|
||||
export class PageLayoutService {
|
||||
|
||||
Reference in New Issue
Block a user