Redesign Object/Field tables (#16844)

Redesign the data model pages for more clarity / better distinction
between fields and relations
This commit is contained in:
Félix Malfait
2025-12-30 09:49:55 +01:00
committed by GitHub
parent 8d130908c2
commit 4f1f0eb177
16 changed files with 571 additions and 200 deletions
@@ -1,8 +1,10 @@
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { useDeleteOneFieldMetadataItem } from '@/object-metadata/hooks/useDeleteOneFieldMetadataItem';
import { useFieldMetadataItem } from '@/object-metadata/hooks/useFieldMetadataItem';
import { useGetRelationMetadata } from '@/object-metadata/hooks/useGetRelationMetadata';
import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
import { isObjectMetadataSettingsReadOnly } from '@/object-record/read-only/utils/isObjectMetadataSettingsReadOnly';
import { SettingsItemTypeTag } from '@/settings/components/SettingsItemTypeTag';
import { RELATION_TYPES } from '@/settings/data-model/constants/RelationTypes';
import { SettingsObjectFieldInactiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldDisabledActionDropdown';
import { settingsObjectFieldsFamilyState } from '@/settings/data-model/object-details/states/settingsObjectFieldsFamilyState';
import { isFieldTypeSupportedInSettings } from '@/settings/data-model/utils/isFieldTypeSupportedInSettings';
@@ -12,7 +14,7 @@ import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
import { useMemo } from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { useRecoilState } from 'recoil';
import { FieldMetadataType, SettingsPath } from 'twenty-shared/types';
import { getSettingsPath, isDefined } from 'twenty-shared/utils';
import {
@@ -26,9 +28,6 @@ import { UndecoratedLink } from 'twenty-ui/navigation';
import { RelationType } from '~/generated-metadata/graphql';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { type SettingsObjectDetailTableItem } from '~/pages/settings/data-model/types/SettingsObjectDetailTableItem';
import { isObjectMetadataSettingsReadOnly } from '@/object-record/read-only/utils/isObjectMetadataSettingsReadOnly';
import { RELATION_TYPES } from '@/settings/data-model/constants/RelationTypes';
import { SettingsObjectFieldDataType } from './SettingsObjectFieldDataType';
type SettingsObjectFieldItemTableRowProps = {
@@ -90,20 +89,13 @@ export const SettingsObjectFieldItemTableRow = ({
status,
}: SettingsObjectFieldItemTableRowProps) => {
const { t } = useLingui();
const { fieldMetadataItem, identifierType, objectMetadataItem } =
const { fieldMetadataItem, objectMetadataItem } =
settingsObjectDetailTableItem;
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const readonly = isObjectMetadataSettingsReadOnly({
objectMetadataItem,
workspaceCustomApplicationId:
currentWorkspace?.workspaceCustomApplication?.id,
});
const isRemoteObjectField = objectMetadataItem.isRemote;
const variant = objectMetadataItem.isCustom ? 'identifier' : 'field-type';
const navigate = useNavigateSettings();
const theme = useTheme();
@@ -167,21 +159,6 @@ export const SettingsObjectFieldItemTableRow = ({
});
};
const typeLabel =
variant === 'field-type'
? isRemoteObjectField
? t`Remote`
: fieldMetadataItem.isCustom
? t`Custom`
: t`Standard`
: variant === 'identifier'
? isDefined(identifierType)
? identifierType === 'label'
? t`Record text`
: t`Record image`
: ''
: '';
if (!isFieldTypeSupported) return null;
const isRelatedObjectLinkable =
@@ -224,7 +201,15 @@ export const SettingsObjectFieldItemTableRow = ({
</StyledNameTableCell>
</UndecoratedLink>
<TableCell>{typeLabel}</TableCell>
<TableCell>
<SettingsItemTypeTag
item={{
isCustom: fieldMetadataItem.isCustom ?? undefined,
isRemote: objectMetadataItem.isRemote,
applicationId: objectMetadataItem.applicationId,
}}
/>
</TableCell>
<TableCell>
<SettingsObjectFieldDataType
Icon={RelationIcon}
@@ -0,0 +1,242 @@
import { useDeleteOneFieldMetadataItem } from '@/object-metadata/hooks/useDeleteOneFieldMetadataItem';
import { useFieldMetadataItem } from '@/object-metadata/hooks/useFieldMetadataItem';
import { useGetRelationMetadata } from '@/object-metadata/hooks/useGetRelationMetadata';
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { isObjectMetadataSettingsReadOnly } from '@/object-record/read-only/utils/isObjectMetadataSettingsReadOnly';
import { SettingsItemTypeTag } from '@/settings/components/SettingsItemTypeTag';
import { RELATION_TYPES } from '@/settings/data-model/constants/RelationTypes';
import { SettingsObjectFieldInactiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldDisabledActionDropdown';
import { TableCell } from '@/ui/layout/table/components/TableCell';
import { TableRow } from '@/ui/layout/table/components/TableRow';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
import { useMemo } from 'react';
import { Link } from 'react-router-dom';
import { FieldMetadataType, SettingsPath } from 'twenty-shared/types';
import { getSettingsPath, isDefined } from 'twenty-shared/utils';
import { IconChevronRight, useIcons } from 'twenty-ui/display';
import { UndecoratedLink } from 'twenty-ui/navigation';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
type SettingsObjectRelationItemTableRowProps = {
fieldMetadataItem: FieldMetadataItem;
objectMetadataItem: ObjectMetadataItem;
};
export const StyledObjectRelationTableRow = styled(TableRow)`
grid-template-columns: 180px 100px 148px 36px;
`;
const StyledNameTableCell = styled(TableCell)`
color: ${({ theme }) => theme.font.color.primary};
gap: ${({ theme }) => theme.spacing(2)};
`;
const StyledNameContainer = styled.div`
display: flex;
align-items: center;
flex: 1;
min-width: 0;
gap: ${({ theme }) => theme.spacing(1)};
`;
const StyledNameLabel = styled.div`
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
`;
const StyledInactiveLabel = styled.span`
color: ${({ theme }) => theme.font.color.extraLight};
font-size: ${({ theme }) => theme.font.size.sm};
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
flex: 0 999 auto;
min-width: 48px;
&::before {
content: '·';
margin-right: ${({ theme }) => theme.spacing(1)};
}
`;
const StyledIconTableCell = styled(TableCell)`
justify-content: center;
padding-right: ${({ theme }) => theme.spacing(1)};
`;
const StyledIconChevronRight = styled(IconChevronRight)`
color: ${({ theme }) => theme.font.color.tertiary};
`;
const StyledRelationType = styled.div`
align-items: center;
display: flex;
font-size: ${({ theme }) => theme.font.size.sm};
gap: ${({ theme }) => theme.spacing(1)};
`;
const StyledLink = styled(Link)`
color: ${({ theme }) => theme.font.color.primary};
text-decoration: underline;
text-decoration-color: ${({ theme }) => theme.border.color.strong};
text-underline-offset: 2px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
&:hover {
color: ${({ theme }) => theme.color.blue};
text-decoration-color: ${({ theme }) => theme.color.blue};
}
`;
export const SettingsObjectRelationItemTableRow = ({
fieldMetadataItem,
objectMetadataItem,
}: SettingsObjectRelationItemTableRowProps) => {
const { t } = useLingui();
const navigate = useNavigateSettings();
const theme = useTheme();
const { getIcon } = useIcons();
const Icon = getIcon(fieldMetadataItem.icon);
const getRelationMetadata = useGetRelationMetadata();
const { relationObjectMetadataItem, relationType } =
useMemo(
() => getRelationMetadata({ fieldMetadataItem }),
[fieldMetadataItem, getRelationMetadata],
) ?? {};
const readonly = isObjectMetadataSettingsReadOnly({
objectMetadataItem,
});
const { activateMetadataField } = useFieldMetadataItem();
const { deleteOneFieldMetadataItem } = useDeleteOneFieldMetadataItem();
const linkToNavigate = getSettingsPath(SettingsPath.ObjectFieldEdit, {
objectNamePlural: objectMetadataItem.namePlural,
fieldName: fieldMetadataItem.name,
});
// eslint-disable-next-line @nx/workspace-no-navigate-prefer-link
const navigateToFieldEdit = () =>
navigate(SettingsPath.ObjectFieldEdit, {
objectNamePlural: objectMetadataItem.namePlural,
fieldName: fieldMetadataItem.name,
});
const isRelatedObjectLinkable =
isDefined(relationObjectMetadataItem?.namePlural) &&
!relationObjectMetadataItem.isSystem;
const morphRelationCount = fieldMetadataItem.morphRelations?.length;
const relationTypeLabel = (() => {
if (fieldMetadataItem.type === FieldMetadataType.MORPH_RELATION) {
return t`${morphRelationCount} Objects`;
}
if (isDefined(relationType) === true) {
return RELATION_TYPES[relationType].label;
}
return '';
})();
const RelationIcon = relationType
? RELATION_TYPES[relationType].Icon
: undefined;
const targetObjectLabel =
isRelatedObjectLinkable && relationObjectMetadataItem
? relationObjectMetadataItem.labelPlural
: fieldMetadataItem.label;
return (
// eslint-disable-next-line @nx/workspace-no-navigate-prefer-link
<StyledObjectRelationTableRow onClick={navigateToFieldEdit}>
<StyledNameTableCell>
{!!Icon && (
<Icon
style={{ minWidth: theme.icon.size.md }}
size={theme.icon.size.md}
stroke={theme.icon.stroke.sm}
/>
)}
<StyledNameContainer>
{isRelatedObjectLinkable ? (
<StyledLink
to={getSettingsPath(SettingsPath.ObjectDetail, {
objectNamePlural: relationObjectMetadataItem.namePlural,
})}
onClick={(event) => event.stopPropagation()}
title={targetObjectLabel}
>
{targetObjectLabel}
</StyledLink>
) : (
<StyledNameLabel title={targetObjectLabel}>
{targetObjectLabel}
</StyledNameLabel>
)}
{!fieldMetadataItem.isActive && (
<StyledInactiveLabel>{t`Deactivated`}</StyledInactiveLabel>
)}
</StyledNameContainer>
</StyledNameTableCell>
<TableCell>
<SettingsItemTypeTag
item={{
isCustom: fieldMetadataItem.isCustom ?? undefined,
isRemote: objectMetadataItem.isRemote,
applicationId: objectMetadataItem.applicationId,
}}
/>
</TableCell>
<TableCell>
<StyledRelationType>
{RelationIcon && (
<RelationIcon
size={theme.icon.size.sm}
stroke={theme.icon.stroke.sm}
/>
)}
{relationTypeLabel}
</StyledRelationType>
</TableCell>
<StyledIconTableCell>
{fieldMetadataItem.isActive ? (
<UndecoratedLink to={linkToNavigate}>
<StyledIconChevronRight
size={theme.icon.size.md}
stroke={theme.icon.stroke.sm}
/>
</UndecoratedLink>
) : (
<SettingsObjectFieldInactiveActionDropdown
isCustomField={fieldMetadataItem.isCustom === true}
readonly={readonly}
fieldMetadataItemId={fieldMetadataItem.id}
onEdit={navigateToFieldEdit}
onActivate={() =>
activateMetadataField(fieldMetadataItem.id, objectMetadataItem.id)
}
onDelete={() =>
deleteOneFieldMetadataItem({
idToDelete: fieldMetadataItem.id,
objectMetadataId: objectMetadataItem.id,
})
}
/>
)}
</StyledIconTableCell>
</StyledObjectRelationTableRow>
);
};
@@ -0,0 +1,167 @@
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { SettingsTextInput } from '@/ui/input/components/SettingsTextInput';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { SortableTableHeader } from '@/ui/layout/table/components/SortableTableHeader';
import { Table } from '@/ui/layout/table/components/Table';
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
import { useSortedArray } from '@/ui/layout/table/hooks/useSortedArray';
import { type TableMetadata } from '@/ui/layout/table/types/TableMetadata';
import styled from '@emotion/styled';
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react/macro';
import { useMemo, useState } from 'react';
import { FieldMetadataType } from 'twenty-shared/types';
import { IconArchive, IconFilter, IconSearch } from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
import { MenuItemToggle } from 'twenty-ui/navigation';
import { normalizeSearchText } from '~/utils/normalizeSearchText';
import {
SettingsObjectRelationItemTableRow,
StyledObjectRelationTableRow,
} from './SettingsObjectRelationItemTableRow';
const StyledSearchAndFilterContainer = styled.div`
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
padding-bottom: ${({ theme }) => theme.spacing(2)};
width: 100%;
`;
const StyledSearchInput = styled(SettingsTextInput)`
flex: 1;
`;
const SETTINGS_OBJECT_RELATION_TABLE_METADATA: TableMetadata<FieldMetadataItem> =
{
tableId: 'settingsObjectRelations',
fields: [
{
fieldLabel: msg`Name`,
fieldName: 'label',
fieldType: 'string',
align: 'left',
},
{
fieldLabel: msg`App`,
fieldName: 'isCustom',
fieldType: 'string',
align: 'left',
},
{
fieldLabel: msg`Type`,
fieldName: 'type',
fieldType: 'string',
align: 'left',
},
],
initialSort: {
fieldName: 'label',
orderBy: 'AscNullsLast',
},
};
type SettingsObjectRelationsTableProps = {
objectMetadataItem: ObjectMetadataItem;
};
export const SettingsObjectRelationsTable = ({
objectMetadataItem,
}: SettingsObjectRelationsTableProps) => {
const { t } = useLingui();
const [searchTerm, setSearchTerm] = useState('');
const [showInactive, setShowInactive] = useState(true);
const tableMetadata = SETTINGS_OBJECT_RELATION_TABLE_METADATA;
const relationFields = useMemo(() => {
return objectMetadataItem.fields.filter(
(field) =>
!field.isSystem &&
(field.type === FieldMetadataType.RELATION ||
field.type === FieldMetadataType.MORPH_RELATION),
);
}, [objectMetadataItem.fields]);
const sortedRelationFields = useSortedArray(relationFields, tableMetadata);
const filteredRelationFields = useMemo(() => {
const searchNormalized = normalizeSearchText(searchTerm);
return sortedRelationFields.filter((field) => {
const matchesActiveFilter = showInactive || field.isActive;
const matchesSearch = normalizeSearchText(field.label).includes(
searchNormalized,
);
return matchesActiveFilter && matchesSearch;
});
}, [sortedRelationFields, searchTerm, showInactive]);
if (relationFields.length === 0) {
return null;
}
return (
<>
<StyledSearchAndFilterContainer>
<StyledSearchInput
instanceId="object-relation-table-search"
LeftIcon={IconSearch}
placeholder={t`Search a field...`}
value={searchTerm}
onChange={setSearchTerm}
/>
<Dropdown
dropdownId="settings-relations-filter-dropdown"
dropdownPlacement="bottom-end"
dropdownOffset={{ x: 0, y: 8 }}
clickableComponent={
<Button
Icon={IconFilter}
size="medium"
variant="secondary"
accent="default"
ariaLabel={t`Filter`}
/>
}
dropdownComponents={
<DropdownContent>
<DropdownMenuItemsContainer>
<MenuItemToggle
LeftIcon={IconArchive}
onToggleChange={() => setShowInactive(!showInactive)}
toggled={showInactive}
text={t`Inactive`}
toggleSize="small"
/>
</DropdownMenuItemsContainer>
</DropdownContent>
}
/>
</StyledSearchAndFilterContainer>
<Table>
<StyledObjectRelationTableRow>
{tableMetadata.fields.map((item) => (
<SortableTableHeader
key={item.fieldName}
fieldName={item.fieldName}
label={t(item.fieldLabel)}
tableId={tableMetadata.tableId}
initialSort={tableMetadata.initialSort}
/>
))}
<TableHeader></TableHeader>
</StyledObjectRelationTableRow>
{filteredRelationFields.map((fieldMetadataItem) => (
<SettingsObjectRelationItemTableRow
key={fieldMetadataItem.id}
fieldMetadataItem={fieldMetadataItem}
objectMetadataItem={objectMetadataItem}
/>
))}
</Table>
</>
);
};
@@ -1,4 +1,3 @@
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { SettingsDataModelObjectAboutForm } from '@/settings/data-model/objects/forms/components/SettingsDataModelObjectAboutForm';
@@ -8,7 +7,7 @@ import {
} from '@/settings/data-model/validation-schemas/settingsDataModelObjectAboutFormSchema';
import { zodResolver } from '@hookform/resolvers/zod';
import { FormProvider, useForm } from 'react-hook-form';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { useSetRecoilState } from 'recoil';
import { SettingsPath } from 'twenty-shared/types';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { updatedObjectNamePluralState } from '~/pages/settings/data-model/states/updatedObjectNamePluralState';
@@ -21,11 +20,8 @@ type SettingsUpdateDataModelObjectAboutFormProps = {
export const SettingsUpdateDataModelObjectAboutForm = ({
objectMetadataItem,
}: SettingsUpdateDataModelObjectAboutFormProps) => {
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const readonly = isObjectMetadataSettingsReadOnly({
objectMetadataItem,
workspaceCustomApplicationId:
currentWorkspace?.workspaceCustomApplication?.id,
});
const navigate = useNavigateSettings();
const setUpdatedObjectNamePlural = useSetRecoilState(
@@ -1,19 +1,17 @@
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { SettingsPath } from 'twenty-shared/types';
import { getSettingsPath } from 'twenty-shared/utils';
import { SettingsObjectFieldTable } from '~/pages/settings/data-model/SettingsObjectFieldTable';
import { isObjectMetadataSettingsReadOnly } from '@/object-record/read-only/utils/isObjectMetadataSettingsReadOnly';
import { SettingsObjectRelationsTable } from '@/settings/data-model/object-details/components/SettingsObjectRelationsTable';
import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
import { FieldMetadataType, SettingsPath } from 'twenty-shared/types';
import { getSettingsPath } from 'twenty-shared/utils';
import { H2Title, IconPlus } from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
import { Section } from 'twenty-ui/layout';
import { UndecoratedLink } from 'twenty-ui/navigation';
import { isObjectMetadataSettingsReadOnly } from '@/object-record/read-only/utils/isObjectMetadataSettingsReadOnly';
import { useRecoilValue } from 'recoil';
import { SettingsObjectFieldTable } from '~/pages/settings/data-model/SettingsObjectFieldTable';
const StyledDiv = styled.div`
const StyledButtonContainer = styled.div`
display: flex;
justify-content: flex-end;
padding-top: ${({ theme }) => theme.spacing(2)};
@@ -24,42 +22,78 @@ type ObjectFieldsProps = {
};
export const ObjectFields = ({ objectMetadataItem }: ObjectFieldsProps) => {
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const readonly = isObjectMetadataSettingsReadOnly({
objectMetadataItem,
workspaceCustomApplicationId:
currentWorkspace?.workspaceCustomApplication?.id,
});
const { t } = useLingui();
const objectLabelSingular = objectMetadataItem.labelSingular;
const hasRelations = objectMetadataItem.fields.some(
(field) =>
!field.isSystem &&
(field.type === FieldMetadataType.RELATION ||
field.type === FieldMetadataType.MORPH_RELATION),
);
return (
<Section>
<H2Title
title={t`Fields`}
description={t`Customise the fields available in the ${objectLabelSingular} views.`}
/>
<SettingsObjectFieldTable
objectMetadataItem={objectMetadataItem}
mode="view"
/>
{!readonly && (
<StyledDiv>
<UndecoratedLink
to={getSettingsPath(SettingsPath.ObjectNewFieldSelect, {
objectNamePlural: objectMetadataItem.namePlural,
})}
>
<Button
Icon={IconPlus}
title={t`Add Field`}
size="small"
variant="secondary"
/>
</UndecoratedLink>
</StyledDiv>
<>
{hasRelations && (
<Section>
<H2Title
title={t`Relations`}
description={t`Relation between this object and other objects`}
/>
<SettingsObjectRelationsTable
objectMetadataItem={objectMetadataItem}
/>
<StyledButtonContainer>
{!readonly && (
<UndecoratedLink
to={getSettingsPath(
SettingsPath.ObjectNewFieldConfigure,
{ objectNamePlural: objectMetadataItem.namePlural },
{ fieldType: FieldMetadataType.MORPH_RELATION },
)}
>
<Button
Icon={IconPlus}
title={t`Add relation`}
size="small"
variant="secondary"
/>
</UndecoratedLink>
)}
</StyledButtonContainer>
</Section>
)}
</Section>
<Section>
<H2Title
title={t`Fields`}
description={t`Customise the fields available in the ${objectLabelSingular} views and their display order in the ${objectLabelSingular} detail view and menus.`}
/>
<SettingsObjectFieldTable
objectMetadataItem={objectMetadataItem}
mode="view"
excludeRelations
/>
<StyledButtonContainer>
{!readonly && (
<UndecoratedLink
to={getSettingsPath(SettingsPath.ObjectNewFieldSelect, {
objectNamePlural: objectMetadataItem.namePlural,
})}
>
<Button
Icon={IconPlus}
title={t`Add Field`}
size="small"
variant="secondary"
/>
</UndecoratedLink>
)}
</StyledButtonContainer>
</Section>
</>
);
};
@@ -1,6 +1,5 @@
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { useDeleteOneObjectMetadataItem } from '@/object-metadata/hooks/useDeleteOneObjectMetadataItem';
import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem';
import { isObjectMetadataSettingsReadOnly } from '@/object-record/read-only/utils/isObjectMetadataSettingsReadOnly';
@@ -11,7 +10,6 @@ import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModa
import { useModal } from '@/ui/layout/modal/hooks/useModal';
import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
import { useRecoilValue } from 'recoil';
import { SettingsPath } from 'twenty-shared/types';
import { H2Title, IconArchive, IconTrash } from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
@@ -47,11 +45,8 @@ export const ObjectSettings = ({
setIsDeleting,
}: ObjectSettingsProps) => {
const { t } = useLingui();
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const readonly = isObjectMetadataSettingsReadOnly({
objectMetadataItem,
workspaceCustomApplicationId:
currentWorkspace?.workspaceCustomApplication?.id,
});
const navigate = useNavigateSettings();
const { updateOneObjectMetadataItem } = useUpdateOneObjectMetadataItem();
@@ -1,4 +1,3 @@
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getActiveFieldMetadataItems } from '@/object-metadata/utils/getActiveFieldMetadataItems';
@@ -11,7 +10,6 @@ import { t } from '@lingui/core/macro';
import { useMemo } from 'react';
import { Controller, useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
import { useRecoilValue } from 'recoil';
import { isLabelIdentifierFieldMetadataTypes } from 'twenty-shared/utils';
import { IconCircleOff, IconPlus, useIcons } from 'twenty-ui/display';
import { type SelectOption } from 'twenty-ui/input';
@@ -44,11 +42,8 @@ const StyledContainer = styled.div`
export const SettingsDataModelObjectIdentifiersForm = ({
objectMetadataItem,
}: SettingsDataModelObjectIdentifiersFormProps) => {
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const readonly = isObjectMetadataSettingsReadOnly({
objectMetadataItem,
workspaceCustomApplicationId:
currentWorkspace?.workspaceCustomApplication?.id,
});
const formConfig = useForm<SettingsDataModelObjectIdentifiersFormValues>({
mode: 'onTouched',