refactor: rename ObjectMetadataItem to EnrichedObjectMetadataItem and clean up metadata flows (#18830)
## Summary - Renames `ObjectMetadataItem` to `EnrichedObjectMetadataItem` across the entire frontend (~440 files) to clarify that this type includes derived fields (`readableFields`, `updatableFields`, nested `fields[]`, `indexMetadatas[]`) computed at read time from the metadata store - Creates `splitObjectMetadataGqlResponse` that goes directly from a GraphQL `ObjectMetadataItemsQuery` response to flat store items (combining the old `mapPaginatedObjectMetadataItemsToObjectMetadataItems` + `splitObjectMetadataItemWithRelated` two-step flow into one call) - Removes `ObjectMetadataItemWithRelated` type and all "WithRelated" naming - Renames `generatedMockObjectMetadataItems` to `generateTestEnrichedObjectMetadataItemsMock` to make it clear this is test-only enriched data - Deletes `useLoadMockedObjectMetadataItems` hook (consolidated into `useLoadMockedMinimalMetadata`) - Ensures nothing destined for the metadata store computes `readableFields`/`updatableFields` (preventing the localStorage bloat from #18809) ## Type hierarchy (before → after) **Before:** ``` ObjectMetadataItemsQuery → mapPaginated → ObjectMetadataItemWithRelated → enrich → ObjectMetadataItem → split → FlatObjectMetadataItem (store) ``` **After:** ``` ObjectMetadataItemsQuery → splitObjectMetadataGqlResponse → FlatObjectMetadataItem (store) → mapPaginated + enrich (tests only) → EnrichedObjectMetadataItem ``` ## Test plan - [x] `npx nx typecheck twenty-front` passes - [x] `npx nx test twenty-front` passes (767 suites, 4505 tests) - [x] `npx nx lint twenty-front` passes - [ ] CI checks pass Made with [Cursor](https://cursor.com)
This commit is contained in:
+3
-3
@@ -2,7 +2,7 @@ import { t } from '@lingui/core/macro';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem';
|
||||
import {
|
||||
IconBox,
|
||||
OverflowingTextWithTooltip,
|
||||
@@ -14,7 +14,7 @@ import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
export type SettingsDataModelObjectPreviewProps = {
|
||||
className?: string;
|
||||
objectMetadataItems: Pick<
|
||||
ObjectMetadataItem,
|
||||
EnrichedObjectMetadataItem,
|
||||
'icon' | 'labelSingular' | 'labelPlural' | 'isCustom' | 'isRemote'
|
||||
>[];
|
||||
pluralizeLabel?: boolean;
|
||||
@@ -55,7 +55,7 @@ const StyledSeparator = styled.div`
|
||||
|
||||
type SettingsDataModelObjectPreviewItemProps = {
|
||||
objectMetadataItem: Pick<
|
||||
ObjectMetadataItem,
|
||||
EnrichedObjectMetadataItem,
|
||||
'icon' | 'labelSingular' | 'labelPlural' | 'isCustom' | 'isRemote'
|
||||
>;
|
||||
pluralizeLabel: boolean;
|
||||
|
||||
+5
-5
@@ -1,4 +1,4 @@
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem';
|
||||
import { AdvancedSettingsWrapper } from '@/settings/components/AdvancedSettingsWrapper';
|
||||
import { SettingsOptionCardContentToggle } from '@/settings/components/SettingsOptions/SettingsOptionCardContentToggle';
|
||||
import { OBJECT_NAME_MAXIMUM_LENGTH } from '@/settings/data-model/constants/ObjectNameMaximumLength';
|
||||
@@ -29,9 +29,9 @@ import { computeMetadataNamesFromLabels } from '~/pages/settings/data-model/util
|
||||
|
||||
type SettingsDataModelObjectAboutFormProps = {
|
||||
disableEdition?: boolean;
|
||||
objectMetadataItem?: ObjectMetadataItem;
|
||||
objectMetadataItem?: EnrichedObjectMetadataItem;
|
||||
onNewDirtyField?: () => void;
|
||||
conflictingObjectMetadataItem?: ObjectMetadataItem;
|
||||
conflictingObjectMetadataItem?: EnrichedObjectMetadataItem;
|
||||
};
|
||||
|
||||
const StyledInputsContainer = styled.div`
|
||||
@@ -299,7 +299,7 @@ export const SettingsDataModelObjectAboutForm = ({
|
||||
{
|
||||
label: t`API Name (Singular)`,
|
||||
fieldName:
|
||||
'nameSingular' as const satisfies StringKeyOf<ObjectMetadataItem>,
|
||||
'nameSingular' as const satisfies StringKeyOf<EnrichedObjectMetadataItem>,
|
||||
placeholder: `listing`,
|
||||
defaultValue: objectMetadataItem?.nameSingular ?? '',
|
||||
disableEdition:
|
||||
@@ -309,7 +309,7 @@ export const SettingsDataModelObjectAboutForm = ({
|
||||
{
|
||||
label: t`API Name (Plural)`,
|
||||
fieldName:
|
||||
'namePlural' as const satisfies StringKeyOf<ObjectMetadataItem>,
|
||||
'namePlural' as const satisfies StringKeyOf<EnrichedObjectMetadataItem>,
|
||||
placeholder: `listings`,
|
||||
defaultValue: objectMetadataItem?.namePlural ?? '',
|
||||
disableEdition:
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem';
|
||||
import { getActiveFieldMetadataItems } from '@/object-metadata/utils/getActiveFieldMetadataItems';
|
||||
import { objectMetadataItemSchema } from '@/object-metadata/validation-schemas/objectMetadataItemSchema';
|
||||
import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly';
|
||||
@@ -28,7 +28,7 @@ export type SettingsDataModelObjectIdentifiersFormValues = z.infer<
|
||||
export type SettingsDataModelObjectIdentifiers =
|
||||
keyof SettingsDataModelObjectIdentifiersFormValues;
|
||||
type SettingsDataModelObjectIdentifiersFormProps = {
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
objectMetadataItem: EnrichedObjectMetadataItem;
|
||||
};
|
||||
const LABEL_IDENTIFIER_FIELD_METADATA_ID: SettingsDataModelObjectIdentifiers =
|
||||
'labelIdentifierFieldMetadataId';
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { styled } from '@linaria/react';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem';
|
||||
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
|
||||
import { SettingsDataModelCardTitle } from '@/settings/data-model/components/SettingsDataModelCardTitle';
|
||||
import { SettingsDataModelFieldPreviewWidget } from '@/settings/data-model/fields/preview/components/SettingsDataModelFieldPreviewWidget';
|
||||
@@ -12,7 +12,7 @@ import { Card, CardContent } from 'twenty-ui/layout';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
type SettingsDataModelObjectSettingsFormCardProps = {
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
objectMetadataItem: EnrichedObjectMetadataItem;
|
||||
};
|
||||
|
||||
const StyledTopCardContentContainer = styled.div`
|
||||
|
||||
+5
-4
@@ -6,11 +6,12 @@ import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorato
|
||||
|
||||
import { SettingsDataModelObjectAboutForm } from '@/settings/data-model/objects/forms/components/SettingsDataModelObjectAboutForm';
|
||||
import { ComponentDecorator } from 'twenty-ui/testing';
|
||||
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
|
||||
import { getTestEnrichedObjectMetadataItemsMock } from '~/testing/utils/getTestEnrichedObjectMetadataItemsMock';
|
||||
|
||||
const mockedCompanyObjectMetadataItem = generatedMockObjectMetadataItems.find(
|
||||
(item) => item.nameSingular === 'company',
|
||||
);
|
||||
const mockedCompanyObjectMetadataItem =
|
||||
getTestEnrichedObjectMetadataItemsMock().find(
|
||||
(item) => item.nameSingular === 'company',
|
||||
);
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
flex: 1;
|
||||
|
||||
Reference in New Issue
Block a user