Reset Tab Page Layout (#19453)
## Context - Add "Reset to default" for page layout tabs and widgets — backend mutation resets overrides, reactivates deactivated children, and deletes custom children - Fix override write bug where mutating an overridable property (e.g. widget title) on a standard-app entity incorrectly overwrote the base column instead of writing to the overrides JSONB — PageLayoutUpdateService now uses resolveFlatEntityOverridableProperties for accurate diffing and routes properties through sanitizeOverridableEntityInput - Deprecate isOverridden - We need more time to think about this feature. Currently this adds too much complexity for a very small benefit https://github.com/user-attachments/assets/a84546c8-1e15-4d9e-a489-0825cf8b8ed2
This commit is contained in:
+5
-2
@@ -55,8 +55,11 @@ export class PageLayoutTabDTO {
|
||||
@Field(() => Date, { nullable: true })
|
||||
deletedAt?: Date | null;
|
||||
|
||||
@Field(() => Boolean, { nullable: false })
|
||||
isOverridden: boolean;
|
||||
@Field(() => Boolean, {
|
||||
nullable: true,
|
||||
deprecationReason: 'isOverridden is deprecated',
|
||||
})
|
||||
isOverridden?: boolean;
|
||||
|
||||
@HideField()
|
||||
overrides?: PageLayoutTabOverrides | null;
|
||||
|
||||
+1
-20
@@ -7,7 +7,6 @@ import {
|
||||
import {
|
||||
Args,
|
||||
Context,
|
||||
Float,
|
||||
Mutation,
|
||||
Parent,
|
||||
Query,
|
||||
@@ -15,7 +14,6 @@ import {
|
||||
} from '@nestjs/graphql';
|
||||
|
||||
import { PermissionFlagType } from 'twenty-shared/constants';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorators/metadata-resolver.decorator';
|
||||
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
|
||||
@@ -32,7 +30,6 @@ import { PageLayoutTabDTO } from 'src/engine/metadata-modules/page-layout-tab/dt
|
||||
import { PageLayoutTabService } from 'src/engine/metadata-modules/page-layout-tab/services/page-layout-tab.service';
|
||||
import { resolvePageLayoutTabTitle } from 'src/engine/metadata-modules/page-layout-tab/utils/resolve-page-layout-tab-title.util';
|
||||
import { PageLayoutGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/page-layout/utils/page-layout-graphql-api-exception.filter';
|
||||
import { resolveOverridableEntityProperty } from 'src/engine/metadata-modules/utils/resolve-overridable-entity-property.util';
|
||||
import { WorkspaceMigrationGraphqlApiExceptionInterceptor } from 'src/engine/workspace-manager/workspace-migration/interceptors/workspace-migration-graphql-api-exception.interceptor';
|
||||
|
||||
@MetadataResolver(() => PageLayoutTabDTO)
|
||||
@@ -51,31 +48,15 @@ export class PageLayoutTabResolver {
|
||||
@Parent() tab: PageLayoutTabDTO,
|
||||
@Context() context: I18nContext,
|
||||
): Promise<string> {
|
||||
const resolvedTitle = resolveOverridableEntityProperty(tab, 'title');
|
||||
const i18n = this.i18nService.getI18nInstance(context.req.locale);
|
||||
|
||||
return resolvePageLayoutTabTitle({
|
||||
title: resolvedTitle,
|
||||
title: tab.title,
|
||||
applicationId: tab.applicationId,
|
||||
i18nInstance: i18n,
|
||||
});
|
||||
}
|
||||
|
||||
@ResolveField(() => Float)
|
||||
position(@Parent() tab: PageLayoutTabDTO): number {
|
||||
return resolveOverridableEntityProperty(tab, 'position');
|
||||
}
|
||||
|
||||
@ResolveField(() => String, { nullable: true })
|
||||
icon(@Parent() tab: PageLayoutTabDTO): string | null | undefined {
|
||||
return resolveOverridableEntityProperty(tab, 'icon');
|
||||
}
|
||||
|
||||
@ResolveField(() => Boolean)
|
||||
isOverridden(@Parent() tab: PageLayoutTabDTO): boolean {
|
||||
return isDefined(tab.overrides) && Object.keys(tab.overrides).length > 0;
|
||||
}
|
||||
|
||||
@Query(() => [PageLayoutTabDTO])
|
||||
@UseGuards(NoPermissionGuard)
|
||||
async getPageLayoutTabs(
|
||||
|
||||
+3
-4
@@ -1,5 +1,3 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
|
||||
import { type PageLayoutTabDTO } from 'src/engine/metadata-modules/page-layout-tab/dtos/page-layout-tab.dto';
|
||||
|
||||
@@ -11,13 +9,14 @@ export const fromFlatPageLayoutTabToPageLayoutTabDto = (
|
||||
updatedAt,
|
||||
deletedAt,
|
||||
widgetIds: _widgetIds,
|
||||
overrides,
|
||||
...rest
|
||||
} = flatPageLayoutTab;
|
||||
|
||||
return {
|
||||
...rest,
|
||||
isOverridden:
|
||||
isDefined(rest.overrides) && Object.keys(rest.overrides).length > 0,
|
||||
...(overrides ?? {}),
|
||||
isOverridden: false,
|
||||
createdAt: new Date(createdAt),
|
||||
updatedAt: new Date(updatedAt),
|
||||
deletedAt: deletedAt ? new Date(deletedAt) : null,
|
||||
|
||||
Reference in New Issue
Block a user