Refactor read only object and fields (#13936)

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
neo773
2025-08-19 21:40:35 +05:30
committed by GitHub
parent bb7cd1baa1
commit 3ef94f6e8c
114 changed files with 1274 additions and 483 deletions
@@ -4,6 +4,7 @@ import { FieldMetadataType } from 'twenty-shared/types';
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsPrimaryField } from 'src/engine/twenty-orm/decorators/workspace-is-primary-field.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
@@ -19,6 +20,7 @@ export abstract class BaseWorkspaceEntity {
icon: 'Icon123',
})
@WorkspaceIsPrimaryField()
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
id: string;
@@ -33,6 +35,7 @@ export abstract class BaseWorkspaceEntity {
displayFormat: DateDisplayFormat.RELATIVE,
},
})
@WorkspaceIsFieldUIReadOnly()
createdAt: string;
@WorkspaceField({
@@ -46,6 +49,7 @@ export abstract class BaseWorkspaceEntity {
displayFormat: DateDisplayFormat.RELATIVE,
},
})
@WorkspaceIsFieldUIReadOnly()
updatedAt: string;
@WorkspaceField({
@@ -59,5 +63,6 @@ export abstract class BaseWorkspaceEntity {
},
})
@WorkspaceIsNullable()
@WorkspaceIsFieldUIReadOnly()
deletedAt: string | null;
}
@@ -12,6 +12,7 @@ import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity
import { WorkspaceCustomEntity } from 'src/engine/twenty-orm/decorators/workspace-custom-entity.decorator';
import { WorkspaceFieldIndex } from 'src/engine/twenty-orm/decorators/workspace-field-index.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
@@ -52,6 +53,7 @@ export class CustomWorkspaceEntity extends BaseWorkspaceEntity {
defaultValue: 0,
})
@WorkspaceIsSystem()
@WorkspaceIsFieldUIReadOnly()
position: number;
@WorkspaceField({
@@ -61,6 +63,7 @@ export class CustomWorkspaceEntity extends BaseWorkspaceEntity {
icon: 'IconCreativeCommonsSa',
description: msg`The creator of the record`,
})
@WorkspaceIsFieldUIReadOnly()
createdBy: ActorMetadata;
@WorkspaceRelation({
@@ -158,6 +161,7 @@ export class CustomWorkspaceEntity extends BaseWorkspaceEntity {
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
@WorkspaceIsFieldUIReadOnly()
@WorkspaceFieldIndex({ indexType: IndexType.GIN })
searchVector: string;
}
@@ -42,6 +42,11 @@ export function WorkspaceEntity(
'workspace:is-searchable-metadata-args',
target,
) ?? false;
const isUIReadOnly =
TypedReflect.getMetadata(
'workspace:is-object-ui-readonly-metadata-args',
target,
) ?? false;
const objectName = convertClassNameToObjectMetadataName(target.name);
@@ -60,6 +65,7 @@ export function WorkspaceEntity(
shortcut: options.shortcut,
isAuditLogged,
isSystem,
isUIReadOnly,
gate,
duplicateCriteria,
isSearchable,
@@ -52,6 +52,12 @@ export function WorkspaceField<T extends FieldMetadataType>(
object,
propertyKey.toString(),
) ?? false;
const isUIReadOnly =
TypedReflect.getMetadata(
'workspace:is-field-ui-readonly-metadata-args',
object,
propertyKey.toString(),
) ?? false;
const gate = TypedReflect.getMetadata(
'workspace:gate-metadata-args',
object,
@@ -91,6 +97,7 @@ export function WorkspaceField<T extends FieldMetadataType>(
isPrimary,
isNullable,
isSystem,
isUIReadOnly,
gate,
isDeprecated,
isUnique,
@@ -0,0 +1,16 @@
import { TypedReflect } from 'src/utils/typed-reflect';
export function WorkspaceIsFieldUIReadOnly() {
return function (target: object, propertyKey?: string | symbol): void {
if (propertyKey === undefined) {
throw new Error('This decorator should be used with a field not a class');
}
TypedReflect.defineMetadata(
'workspace:is-field-ui-readonly-metadata-args',
true,
target,
propertyKey.toString(),
);
};
}
@@ -0,0 +1,11 @@
import { TypedReflect } from 'src/utils/typed-reflect';
export function WorkspaceIsObjectUIReadOnly() {
return function (target: object): void {
TypedReflect.defineMetadata(
'workspace:is-object-ui-readonly-metadata-args',
true,
target,
);
};
}
@@ -58,6 +58,12 @@ export function WorkspaceRelation<TClass extends object>(
object,
propertyKey.toString(),
) ?? false;
const isUIReadOnly =
TypedReflect.getMetadata(
'workspace:is-field-ui-readonly-metadata-args',
object,
propertyKey.toString(),
) ?? false;
const gate = TypedReflect.getMetadata(
'workspace:gate-metadata-args',
object,
@@ -89,6 +95,7 @@ export function WorkspaceRelation<TClass extends object>(
isPrimary,
isNullable,
isSystem,
isUIReadOnly,
gate,
isLabelSyncedWithName,
});
@@ -53,6 +53,11 @@ export interface WorkspaceEntityMetadataArgs {
*/
readonly isSystem: boolean;
/**
* Is UI read-only object.
*/
readonly isUIReadOnly: boolean;
/**
* Entity gate.
*/
@@ -71,6 +71,11 @@ export interface WorkspaceFieldMetadataArgs {
*/
readonly isSystem: boolean;
/**
* Is UI read-only field.
*/
readonly isUIReadOnly: boolean;
/**
* Is nullable field.
*/
@@ -70,6 +70,11 @@ export interface WorkspaceRelationMetadataArgs {
*/
readonly isSystem: boolean;
/**
* Is UI read-only field.
*/
readonly isUIReadOnly: boolean;
/**
* Is nullable field.
*/