View field override (#18572)
## Context This PR introduces overrides for view fields which will be useful for page layout FIELDS widgets fields position/groups/visibility override + restore logic.
This commit is contained in:
+13
-1
@@ -1,9 +1,15 @@
|
||||
import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
|
||||
import {
|
||||
Field,
|
||||
HideField,
|
||||
ObjectType,
|
||||
registerEnumType,
|
||||
} from '@nestjs/graphql';
|
||||
|
||||
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
||||
import { AggregateOperations } from 'twenty-shared/types';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { type ViewFieldOverrides } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
|
||||
|
||||
registerEnumType(AggregateOperations, { name: 'AggregateOperations' });
|
||||
|
||||
@@ -44,4 +50,10 @@ export class ViewFieldDTO {
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
deletedAt?: Date | null;
|
||||
|
||||
@Field(() => Boolean, { nullable: false })
|
||||
isOverridden: boolean;
|
||||
|
||||
@HideField()
|
||||
overrides?: ViewFieldOverrides | null;
|
||||
}
|
||||
|
||||
+14
-3
@@ -10,12 +10,23 @@ import {
|
||||
type Relation,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
import { AggregateOperations } from 'twenty-shared/types';
|
||||
import {
|
||||
AggregateOperations,
|
||||
type SerializedRelation,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ViewFieldGroupEntity } from 'src/engine/metadata-modules/view-field-group/entities/view-field-group.entity';
|
||||
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
|
||||
import { OverridableEntity } from 'src/engine/workspace-manager/types/overridable-entity';
|
||||
|
||||
export type ViewFieldOverrides = {
|
||||
isVisible?: boolean;
|
||||
size?: number;
|
||||
position?: number;
|
||||
aggregateOperation?: AggregateOperations | null;
|
||||
viewFieldGroupId?: SerializedRelation | null;
|
||||
};
|
||||
|
||||
@Entity({ name: 'viewField', schema: 'core' })
|
||||
@Index('IDX_VIEW_FIELD_WORKSPACE_ID_VIEW_ID', ['workspaceId', 'viewId'])
|
||||
@@ -30,7 +41,7 @@ import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-enti
|
||||
},
|
||||
)
|
||||
export class ViewFieldEntity
|
||||
extends SyncableEntity
|
||||
extends OverridableEntity<ViewFieldOverrides>
|
||||
implements Required<ViewFieldEntity>
|
||||
{
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
|
||||
+51
-1
@@ -1,11 +1,24 @@
|
||||
import { UseFilters, UseGuards } from '@nestjs/common';
|
||||
import { Args, Mutation, Query } from '@nestjs/graphql';
|
||||
import {
|
||||
Args,
|
||||
Float,
|
||||
Int,
|
||||
Mutation,
|
||||
Parent,
|
||||
Query,
|
||||
ResolveField,
|
||||
} from '@nestjs/graphql';
|
||||
|
||||
import { AggregateOperations } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorators/metadata-resolver.decorator';
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { resolveOverridableEntityProperty } from 'src/engine/metadata-modules/utils/resolve-overridable-entity-property.util';
|
||||
import { CreateViewFieldInput } from 'src/engine/metadata-modules/view-field/dtos/inputs/create-view-field.input';
|
||||
import { DeleteViewFieldInput } from 'src/engine/metadata-modules/view-field/dtos/inputs/delete-view-field.input';
|
||||
import { DestroyViewFieldInput } from 'src/engine/metadata-modules/view-field/dtos/inputs/destroy-view-field.input';
|
||||
@@ -25,6 +38,43 @@ import { ViewGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/view/
|
||||
export class ViewFieldResolver {
|
||||
constructor(private readonly viewFieldService: ViewFieldService) {}
|
||||
|
||||
@ResolveField(() => Boolean)
|
||||
isVisible(@Parent() viewField: ViewFieldDTO): boolean {
|
||||
return resolveOverridableEntityProperty(viewField, 'isVisible');
|
||||
}
|
||||
|
||||
@ResolveField(() => Int)
|
||||
size(@Parent() viewField: ViewFieldDTO): number {
|
||||
return resolveOverridableEntityProperty(viewField, 'size');
|
||||
}
|
||||
|
||||
@ResolveField(() => Float)
|
||||
position(@Parent() viewField: ViewFieldDTO): number {
|
||||
return resolveOverridableEntityProperty(viewField, 'position');
|
||||
}
|
||||
|
||||
@ResolveField(() => AggregateOperations, { nullable: true })
|
||||
aggregateOperation(
|
||||
@Parent() viewField: ViewFieldDTO,
|
||||
): AggregateOperations | null | undefined {
|
||||
return resolveOverridableEntityProperty(viewField, 'aggregateOperation');
|
||||
}
|
||||
|
||||
@ResolveField(() => UUIDScalarType, { nullable: true })
|
||||
viewFieldGroupId(
|
||||
@Parent() viewField: ViewFieldDTO,
|
||||
): string | null | undefined {
|
||||
return resolveOverridableEntityProperty(viewField, 'viewFieldGroupId');
|
||||
}
|
||||
|
||||
@ResolveField(() => Boolean)
|
||||
isOverridden(@Parent() viewField: ViewFieldDTO): boolean {
|
||||
return (
|
||||
isDefined(viewField.overrides) &&
|
||||
Object.keys(viewField.overrides).length > 0
|
||||
);
|
||||
}
|
||||
|
||||
@Query(() => [ViewFieldDTO])
|
||||
@UseGuards(NoPermissionGuard)
|
||||
async getCoreViewFields(
|
||||
|
||||
+4
@@ -167,6 +167,10 @@ export class ViewFieldService {
|
||||
flatViewFieldMaps: existingFlatViewFieldMaps,
|
||||
flatViewFieldGroupMaps,
|
||||
updateViewFieldInput,
|
||||
callerApplicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
workspaceCustomApplicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+4
@@ -1,3 +1,5 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
|
||||
import { type ViewFieldDTO } from 'src/engine/metadata-modules/view-field/dtos/view-field.dto';
|
||||
|
||||
@@ -8,6 +10,8 @@ export const fromFlatViewFieldToViewFieldDto = (
|
||||
|
||||
return {
|
||||
...rest,
|
||||
isOverridden:
|
||||
isDefined(rest.overrides) && Object.keys(rest.overrides).length > 0,
|
||||
createdAt: new Date(createdAt),
|
||||
updatedAt: new Date(updatedAt),
|
||||
deletedAt: deletedAt ? new Date(deletedAt) : null,
|
||||
|
||||
Reference in New Issue
Block a user