Files
twenty/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.entity.ts
AFCMS 52cf6f4795 Allow to edit labels of standard objects (#10922)
Fixes #10793

This PR is a work in progress.

**Still left to fix:**

- [x] When disabling synchronization of labels / api names, the edited
labels should be set to the English version. Currently the client just
send the localized versions together with the `isLabelSyncedWithName`
change. Could be an easy fix.
- [ ] Sometimes flipping the switch don't trigger the update function,
may be a regression as it seems to affect the custom objects too.
- [ ] There is a frontend problem where the labels inputs don't reflect
the changes made. When enabling back synchronisation after editing
labels, they are correctly back to their base values (backend,
navigation breadcrumb, etc) but the label inputs still have the old
values (switching pages will put them back to normal). I suspect this
could be linked to the above problem.
- [ ] API names are still displayed for standard objects per (kept them
for debugging, trivial fix)
- [ ] `SettingsDataModelObjectAboutForm` have a `disableEdition`
parameter which is now used only for a few fields, not sure if it's
worth keeping because it's a bit misleading since it doesn't "disable"
much?
- [ ] I don't know what these do, but I have seen "Remote" object types.
Not sure if they work with my patch or not (I don't know how to test
them)
- [ ] Make it work with metadata synchronisation


**What should work:**

- Disabling synchronization of standard objects should work, label
inputs should no longer be disabled
- Modifying labels should work
- Enabling back synchronization should reset back the labels to the base
value and disable the label inputs again (minus the mentioned display
bug)
- The synchronisation switch should still work as expected for custom
objects
- Creating custom objects should still work (it uses the same form)

---------

Signed-off-by: AFCMS <afcm.contact@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2025-03-24 20:19:52 +01:00

151 lines
4.1 KiB
TypeScript

import {
Column,
CreateDateColumn,
Entity,
ManyToOne,
OneToMany,
PrimaryGeneratedColumn,
Relation,
Unique,
UpdateDateColumn,
} from 'typeorm';
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
import { WorkspaceEntityDuplicateCriteria } from 'src/engine/api/graphql/workspace-query-builder/types/workspace-entity-duplicate-criteria.type';
import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
import { ObjectStandardOverridesDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-standard-overrides.dto';
import { ObjectPermissionsEntity } from 'src/engine/metadata-modules/object-permissions/object-permissions.entity';
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
@Entity('objectMetadata')
@Unique('IndexOnNameSingularAndWorkspaceIdUnique', [
'nameSingular',
'workspaceId',
])
@Unique('IndexOnNamePluralAndWorkspaceIdUnique', ['namePlural', 'workspaceId'])
export class ObjectMetadataEntity implements ObjectMetadataInterface {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ nullable: true, type: 'uuid' })
standardId: string | null;
@Column({ nullable: false, type: 'uuid' })
dataSourceId: string;
@Column({ nullable: false })
nameSingular: string;
@Column({ nullable: false })
namePlural: string;
@Column({ nullable: false })
labelSingular: string;
@Column({ nullable: false })
labelPlural: string;
@Column({ nullable: true, type: 'text' })
description: string;
@Column({ nullable: true })
icon: string;
@Column({ type: 'jsonb', nullable: true })
standardOverrides?: ObjectStandardOverridesDTO;
@Column({ nullable: false })
targetTableName: string;
@Column({ default: false })
isCustom: boolean;
@Column({ default: false })
isRemote: boolean;
@Column({ default: false })
isActive: boolean;
@Column({ default: false })
isSystem: boolean;
@Column({ default: true })
isAuditLogged: boolean;
@Column({ default: false })
isSearchable: boolean;
@Column({ type: 'jsonb', nullable: true })
duplicateCriteria?: WorkspaceEntityDuplicateCriteria[];
@Column({ nullable: true })
shortcut: string;
@Column({ nullable: true, type: 'uuid' })
labelIdentifierFieldMetadataId?: string | null;
@Column({ nullable: true, type: 'uuid' })
imageIdentifierFieldMetadataId?: string | null;
@Column({ default: false })
isLabelSyncedWithName: boolean;
@Column({ nullable: false, type: 'uuid' })
workspaceId: string;
@OneToMany(() => FieldMetadataEntity, (field) => field.object, {
cascade: true,
})
fields: Relation<FieldMetadataEntity[]>;
@OneToMany(() => IndexMetadataEntity, (index) => index.objectMetadata, {
cascade: true,
})
indexMetadatas: Relation<IndexMetadataEntity[]>;
@OneToMany(
() => RelationMetadataEntity,
(relation: RelationMetadataEntity) => relation.fromObjectMetadata,
{
cascade: true,
},
)
fromRelations: Relation<RelationMetadataEntity[]>;
@OneToMany(
() => RelationMetadataEntity,
(relation: RelationMetadataEntity) => relation.toObjectMetadata,
{
cascade: true,
},
)
toRelations: Relation<RelationMetadataEntity[]>;
@OneToMany(
() => FieldMetadataEntity,
(field) => field.relationTargetObjectMetadataId,
)
targetRelationFields: Relation<FieldMetadataEntity[]>;
@ManyToOne(() => DataSourceEntity, (dataSource) => dataSource.objects, {
onDelete: 'CASCADE',
})
dataSource: Relation<DataSourceEntity>;
@CreateDateColumn({ type: 'timestamptz' })
createdAt: Date;
@UpdateDateColumn({ type: 'timestamptz' })
updatedAt: Date;
@OneToMany(
() => ObjectPermissionsEntity,
(objectPermissions: ObjectPermissionsEntity) =>
objectPermissions.objectMetadata,
)
objectPermissions: Relation<ObjectPermissionsEntity[]>;
}