[DASHBOARDS] Allow dashboards to be restored (#17042)
This PR introduces a few changes: - Add three actions: see deleted dashboards, destroy dashboard and restore dashboard - Remove the soft delete and restore on all the page layout entities - Cascade the destruction of a dashboard to a page layout Video QA: https://github.com/user-attachments/assets/ab993b11-dd9c-4e88-880c-92691a521cc2
This commit is contained in:
+21
-8
@@ -54,10 +54,10 @@ export class PageLayoutWidgetController {
|
||||
);
|
||||
}
|
||||
|
||||
return this.pageLayoutWidgetService.findByPageLayoutTabId(
|
||||
workspace.id,
|
||||
return this.pageLayoutWidgetService.findByPageLayoutTabId({
|
||||
workspaceId: workspace.id,
|
||||
pageLayoutTabId,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@@ -66,7 +66,10 @@ export class PageLayoutWidgetController {
|
||||
@Param('id') id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<PageLayoutWidgetDTO | null> {
|
||||
return this.pageLayoutWidgetService.findByIdOrThrow(id, workspace.id);
|
||||
return this.pageLayoutWidgetService.findByIdOrThrow({
|
||||
id,
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
}
|
||||
|
||||
@Post()
|
||||
@@ -75,7 +78,10 @@ export class PageLayoutWidgetController {
|
||||
@Body() input: CreatePageLayoutWidgetInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<PageLayoutWidgetDTO> {
|
||||
return this.pageLayoutWidgetService.create(input, workspace.id);
|
||||
return this.pageLayoutWidgetService.create({
|
||||
input,
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
@@ -85,7 +91,11 @@ export class PageLayoutWidgetController {
|
||||
@Body() input: UpdatePageLayoutWidgetInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<PageLayoutWidgetDTO> {
|
||||
return this.pageLayoutWidgetService.update(id, workspace.id, input);
|
||||
return this.pageLayoutWidgetService.update({
|
||||
id,
|
||||
workspaceId: workspace.id,
|
||||
updateData: input,
|
||||
});
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
@@ -93,7 +103,10 @@ export class PageLayoutWidgetController {
|
||||
async delete(
|
||||
@Param('id') id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<PageLayoutWidgetDTO> {
|
||||
return this.pageLayoutWidgetService.delete(id, workspace.id);
|
||||
): Promise<boolean> {
|
||||
return this.pageLayoutWidgetService.destroy({
|
||||
id,
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+20
-25
@@ -45,10 +45,10 @@ export class PageLayoutWidgetResolver {
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@Args('pageLayoutTabId', { type: () => String }) pageLayoutTabId: string,
|
||||
): Promise<PageLayoutWidgetDTO[]> {
|
||||
return this.pageLayoutWidgetService.findByPageLayoutTabId(
|
||||
workspace.id,
|
||||
return this.pageLayoutWidgetService.findByPageLayoutTabId({
|
||||
workspaceId: workspace.id,
|
||||
pageLayoutTabId,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@Query(() => PageLayoutWidgetDTO)
|
||||
@@ -57,7 +57,10 @@ export class PageLayoutWidgetResolver {
|
||||
@Args('id', { type: () => String }) id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<PageLayoutWidgetDTO> {
|
||||
return this.pageLayoutWidgetService.findByIdOrThrow(id, workspace.id);
|
||||
return this.pageLayoutWidgetService.findByIdOrThrow({
|
||||
id,
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
}
|
||||
|
||||
@Mutation(() => PageLayoutWidgetDTO)
|
||||
@@ -66,7 +69,10 @@ export class PageLayoutWidgetResolver {
|
||||
@Args('input') input: CreatePageLayoutWidgetInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<PageLayoutWidgetDTO> {
|
||||
return this.pageLayoutWidgetService.create(input, workspace.id);
|
||||
return this.pageLayoutWidgetService.create({
|
||||
input,
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
}
|
||||
|
||||
@Mutation(() => PageLayoutWidgetDTO)
|
||||
@@ -76,16 +82,11 @@ export class PageLayoutWidgetResolver {
|
||||
@Args('input') input: UpdatePageLayoutWidgetInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<PageLayoutWidgetDTO> {
|
||||
return this.pageLayoutWidgetService.update(id, workspace.id, input);
|
||||
}
|
||||
|
||||
@Mutation(() => PageLayoutWidgetDTO)
|
||||
@UseGuards(SettingsPermissionGuard(PermissionFlagType.LAYOUTS))
|
||||
async deletePageLayoutWidget(
|
||||
@Args('id', { type: () => String }) id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<PageLayoutWidgetDTO> {
|
||||
return this.pageLayoutWidgetService.delete(id, workspace.id);
|
||||
return this.pageLayoutWidgetService.update({
|
||||
id,
|
||||
workspaceId: workspace.id,
|
||||
updateData: input,
|
||||
});
|
||||
}
|
||||
|
||||
@Mutation(() => Boolean)
|
||||
@@ -94,16 +95,10 @@ export class PageLayoutWidgetResolver {
|
||||
@Args('id', { type: () => String }) id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<boolean> {
|
||||
return this.pageLayoutWidgetService.destroy(id, workspace.id);
|
||||
}
|
||||
|
||||
@Mutation(() => PageLayoutWidgetDTO)
|
||||
@UseGuards(SettingsPermissionGuard(PermissionFlagType.LAYOUTS))
|
||||
async restorePageLayoutWidget(
|
||||
@Args('id', { type: () => String }) id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<PageLayoutWidgetDTO> {
|
||||
return this.pageLayoutWidgetService.restore(id, workspace.id);
|
||||
return this.pageLayoutWidgetService.destroy({
|
||||
id,
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
}
|
||||
|
||||
@ResolveField(() => WidgetConfiguration, { nullable: true })
|
||||
|
||||
+38
-95
@@ -8,9 +8,7 @@ import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-m
|
||||
import { FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
|
||||
import { FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate } from 'src/engine/metadata-modules/flat-page-layout-widget/utils/from-create-page-layout-widget-input-to-flat-page-layout-widget-to-create.util';
|
||||
import { fromDeletePageLayoutWidgetInputToFlatPageLayoutWidgetOrThrow } from 'src/engine/metadata-modules/flat-page-layout-widget/utils/from-delete-page-layout-widget-input-to-flat-page-layout-widget-or-throw.util';
|
||||
import { fromDestroyPageLayoutWidgetInputToFlatPageLayoutWidgetOrThrow } from 'src/engine/metadata-modules/flat-page-layout-widget/utils/from-destroy-page-layout-widget-input-to-flat-page-layout-widget-or-throw.util';
|
||||
import { fromRestorePageLayoutWidgetInputToFlatPageLayoutWidgetOrThrow } from 'src/engine/metadata-modules/flat-page-layout-widget/utils/from-restore-page-layout-widget-input-to-flat-page-layout-widget-or-throw.util';
|
||||
import {
|
||||
fromUpdatePageLayoutWidgetInputToFlatPageLayoutWidgetToUpdateOrThrow,
|
||||
type UpdatePageLayoutWidgetInputWithId,
|
||||
@@ -87,10 +85,13 @@ export class PageLayoutWidgetService {
|
||||
}
|
||||
}
|
||||
|
||||
async findByPageLayoutTabId(
|
||||
workspaceId: string,
|
||||
pageLayoutTabId: string,
|
||||
): Promise<PageLayoutWidgetDTO[]> {
|
||||
async findByPageLayoutTabId({
|
||||
workspaceId,
|
||||
pageLayoutTabId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
pageLayoutTabId: string;
|
||||
}): Promise<PageLayoutWidgetDTO[]> {
|
||||
const flatPageLayoutWidgetMaps =
|
||||
await this.getFlatPageLayoutWidgetMaps(workspaceId);
|
||||
|
||||
@@ -109,10 +110,13 @@ export class PageLayoutWidgetService {
|
||||
.map(fromFlatPageLayoutWidgetToPageLayoutWidgetDto);
|
||||
}
|
||||
|
||||
async findByIdOrThrow(
|
||||
id: string,
|
||||
workspaceId: string,
|
||||
): Promise<PageLayoutWidgetDTO> {
|
||||
async findByIdOrThrow({
|
||||
id,
|
||||
workspaceId,
|
||||
}: {
|
||||
id: string;
|
||||
workspaceId: string;
|
||||
}): Promise<PageLayoutWidgetDTO> {
|
||||
const flatPageLayoutWidgetMaps =
|
||||
await this.getFlatPageLayoutWidgetMaps(workspaceId);
|
||||
|
||||
@@ -131,10 +135,13 @@ export class PageLayoutWidgetService {
|
||||
return fromFlatPageLayoutWidgetToPageLayoutWidgetDto(flatWidget);
|
||||
}
|
||||
|
||||
async create(
|
||||
createPageLayoutWidgetInput: CreatePageLayoutWidgetInput,
|
||||
workspaceId: string,
|
||||
): Promise<PageLayoutWidgetDTO> {
|
||||
async create({
|
||||
input,
|
||||
workspaceId,
|
||||
}: {
|
||||
input: CreatePageLayoutWidgetInput;
|
||||
workspaceId: string;
|
||||
}): Promise<PageLayoutWidgetDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
@@ -142,7 +149,7 @@ export class PageLayoutWidgetService {
|
||||
|
||||
const flatPageLayoutWidgetToCreate =
|
||||
fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate({
|
||||
createPageLayoutWidgetInput,
|
||||
createPageLayoutWidgetInput: input,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
});
|
||||
@@ -174,11 +181,15 @@ export class PageLayoutWidgetService {
|
||||
return fromFlatPageLayoutWidgetToPageLayoutWidgetDto(createdWidget);
|
||||
}
|
||||
|
||||
async update(
|
||||
id: string,
|
||||
workspaceId: string,
|
||||
updateData: UpdatePageLayoutWidgetInput,
|
||||
): Promise<PageLayoutWidgetDTO> {
|
||||
async update({
|
||||
id,
|
||||
workspaceId,
|
||||
updateData,
|
||||
}: {
|
||||
id: string;
|
||||
workspaceId: string;
|
||||
updateData: UpdatePageLayoutWidgetInput;
|
||||
}): Promise<PageLayoutWidgetDTO> {
|
||||
const existingFlatPageLayoutWidgetMaps =
|
||||
await this.getFlatPageLayoutWidgetMaps(workspaceId);
|
||||
|
||||
@@ -252,44 +263,13 @@ export class PageLayoutWidgetService {
|
||||
return existingWidget;
|
||||
}
|
||||
|
||||
async delete(id: string, workspaceId: string): Promise<PageLayoutWidgetDTO> {
|
||||
const existingFlatPageLayoutWidgetMaps =
|
||||
await this.getFlatPageLayoutWidgetMaps(workspaceId);
|
||||
|
||||
const flatPageLayoutWidgetToDelete =
|
||||
fromDeletePageLayoutWidgetInputToFlatPageLayoutWidgetOrThrow({
|
||||
deletePageLayoutWidgetInput: { id },
|
||||
flatPageLayoutWidgetMaps: existingFlatPageLayoutWidgetMaps,
|
||||
});
|
||||
|
||||
await this.validateAndRunWidgetMigration({
|
||||
workspaceId,
|
||||
operations: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToUpdate: [flatPageLayoutWidgetToDelete],
|
||||
flatEntityToDelete: [],
|
||||
},
|
||||
errorMessage:
|
||||
'Multiple validation errors occurred while deleting page layout widget',
|
||||
});
|
||||
|
||||
const recomputedMaps = await this.getFlatPageLayoutWidgetMaps(workspaceId);
|
||||
|
||||
const deletedWidget = findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: id,
|
||||
flatEntityMaps: recomputedMaps,
|
||||
});
|
||||
|
||||
await this.dashboardSyncService.updateLinkedDashboardsUpdatedAtByWidgetId({
|
||||
widgetId: id,
|
||||
workspaceId,
|
||||
updatedAt: new Date(deletedWidget.updatedAt),
|
||||
});
|
||||
|
||||
return fromFlatPageLayoutWidgetToPageLayoutWidgetDto(deletedWidget);
|
||||
}
|
||||
|
||||
async destroy(id: string, workspaceId: string): Promise<boolean> {
|
||||
async destroy({
|
||||
id,
|
||||
workspaceId,
|
||||
}: {
|
||||
id: string;
|
||||
workspaceId: string;
|
||||
}): Promise<boolean> {
|
||||
const existingFlatPageLayoutWidgetMaps =
|
||||
await this.getFlatPageLayoutWidgetMaps(workspaceId);
|
||||
|
||||
@@ -318,41 +298,4 @@ export class PageLayoutWidgetService {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async restore(id: string, workspaceId: string): Promise<PageLayoutWidgetDTO> {
|
||||
const existingFlatPageLayoutWidgetMaps =
|
||||
await this.getFlatPageLayoutWidgetMaps(workspaceId);
|
||||
|
||||
const flatPageLayoutWidgetToRestore =
|
||||
fromRestorePageLayoutWidgetInputToFlatPageLayoutWidgetOrThrow({
|
||||
restorePageLayoutWidgetInput: { id },
|
||||
flatPageLayoutWidgetMaps: existingFlatPageLayoutWidgetMaps,
|
||||
});
|
||||
|
||||
await this.validateAndRunWidgetMigration({
|
||||
workspaceId,
|
||||
operations: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToUpdate: [flatPageLayoutWidgetToRestore],
|
||||
flatEntityToDelete: [],
|
||||
},
|
||||
errorMessage:
|
||||
'Multiple validation errors occurred while restoring page layout widget',
|
||||
});
|
||||
|
||||
const recomputedMaps = await this.getFlatPageLayoutWidgetMaps(workspaceId);
|
||||
|
||||
const restoredWidget = findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: id,
|
||||
flatEntityMaps: recomputedMaps,
|
||||
});
|
||||
|
||||
await this.dashboardSyncService.updateLinkedDashboardsUpdatedAtByWidgetId({
|
||||
widgetId: id,
|
||||
workspaceId,
|
||||
updatedAt: new Date(restoredWidget.updatedAt),
|
||||
});
|
||||
|
||||
return fromFlatPageLayoutWidgetToPageLayoutWidgetDto(restoredWidget);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user