feat: set field as custom object label identifier in Object Detail (#3360)

* feat: set field as custom object label identifier in Object Detail

Closes #3302

* feat: prevent disabling Object label identitifer field in back-end

* refactor: review - extract isLabelIdentifier variable
This commit is contained in:
Thaïs
2024-01-17 08:19:41 -03:00
committed by GitHub
parent 8864528d55
commit 96d990e275
12 changed files with 166 additions and 79 deletions

View File

@ -8,6 +8,7 @@ import { useMapToObjectRecordIdentifier } from '@/object-metadata/hooks/useMapTo
import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { getBasePathToShowPage } from '@/object-metadata/utils/getBasePathToShowPage';
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
import { useGenerateCreateManyRecordMutation } from '@/object-record/hooks/useGenerateCreateManyRecordMutation';
import { useGenerateCreateOneRecordMutation } from '@/object-record/hooks/useGenerateCreateOneRecordMutation';
@ -120,9 +121,8 @@ export const useObjectMetadataItem = (
objectMetadataItem,
});
const labelIdentifierFieldMetadata = objectMetadataItem.fields.find(
({ name }) => name === 'name',
);
const labelIdentifierFieldMetadata =
getLabelIdentifierFieldMetadataItem(objectMetadataItem);
const basePathToShowPage = getBasePathToShowPage({
objectMetadataItem,

View File

@ -51,7 +51,12 @@ export const useObjectMetadataItemForSettings = () => {
const editObjectMetadataItem = (
input: Pick<
ObjectMetadataItem,
'id' | 'labelPlural' | 'labelSingular' | 'icon' | 'description'
| 'description'
| 'icon'
| 'id'
| 'labelIdentifierFieldMetadataId'
| 'labelPlural'
| 'labelSingular'
>,
) =>
updateOneObjectMetadataItem({

View File

@ -5,11 +5,17 @@ import { ObjectMetadataItem } from '../types/ObjectMetadataItem';
export const formatObjectMetadataItemInput = (
input: Pick<
ObjectMetadataItem,
'labelPlural' | 'labelSingular' | 'icon' | 'description'
| 'description'
| 'icon'
| 'labelIdentifierFieldMetadataId'
| 'labelPlural'
| 'labelSingular'
>,
) => ({
description: input.description?.trim() ?? null,
icon: input.icon,
labelIdentifierFieldMetadataId:
input.labelIdentifierFieldMetadataId?.trim() ?? null,
labelPlural: input.labelPlural.trim(),
labelSingular: input.labelSingular.trim(),
namePlural: toCamelCase(input.labelPlural.trim()),

View File

@ -1,12 +1,13 @@
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
export const getLabelIdentifierFieldMetadataItem = (
objectMetadataItem: ObjectMetadataItem,
): FieldMetadataItem | undefined => {
return objectMetadataItem.fields.find(
(field) =>
field.id === objectMetadataItem.labelIdentifierFieldMetadataId ||
field.name === 'name',
): FieldMetadataItem | undefined =>
objectMetadataItem.fields.find((fieldMetadataItem) =>
isLabelIdentifierField({
fieldMetadataItem,
objectMetadataItem,
}),
);
};

View File

@ -1,17 +1,15 @@
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { OrderBy } from '@/object-metadata/types/OrderBy';
import { OrderByField } from '@/object-metadata/types/OrderByField';
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
import { FieldMetadataType } from '~/generated-metadata/graphql';
export const getObjectOrderByField = (
objectMetadataItem: ObjectMetadataItem,
orderBy?: OrderBy | null,
): OrderByField => {
const labelIdentifierFieldMetadata = objectMetadataItem.fields.find(
(field) =>
field.id === objectMetadataItem.labelIdentifierFieldMetadataId ||
field.name === 'name',
);
const labelIdentifierFieldMetadata =
getLabelIdentifierFieldMetadataItem(objectMetadataItem);
if (labelIdentifierFieldMetadata) {
switch (labelIdentifierFieldMetadata.type) {

View File

@ -13,8 +13,7 @@ export const isLabelIdentifierField = ({
ObjectMetadataItem,
'labelIdentifierFieldMetadataId'
>;
}) => {
return isDefined(objectMetadataItem.labelIdentifierFieldMetadataId)
}) =>
isDefined(objectMetadataItem.labelIdentifierFieldMetadataId)
? fieldMetadataItem.id === objectMetadataItem.labelIdentifierFieldMetadataId
: fieldMetadataItem.name === DEFAULT_LABEL_IDENTIFIER_FIELD_NAME;
};

View File

@ -1,6 +1,7 @@
import { useContext } from 'react';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope';
import { contextMenuIsOpenState } from '@/ui/navigation/context-menu/states/contextMenuIsOpenState';
@ -65,9 +66,16 @@ export const RecordTableCellContainer = ({
useUpdateRecord: () => [updateRecord, {}],
hotkeyScope: customHotkeyScope,
basePathToShowPage: objectMetadataConfig?.basePathToShowPage,
isLabelIdentifier:
columnDefinition.fieldMetadataId ===
objectMetadataConfig?.labelIdentifierFieldMetadataId,
isLabelIdentifier: isLabelIdentifierField({
fieldMetadataItem: {
id: columnDefinition.fieldMetadataId,
name: columnDefinition.metadata.fieldName,
},
objectMetadataItem: {
labelIdentifierFieldMetadataId:
objectMetadataConfig?.labelIdentifierFieldMetadataId,
},
}),
}}
>
<RecordTableCell customHotkeyScope={{ scope: customHotkeyScope }} />

View File

@ -3,6 +3,7 @@ import {
IconDotsVertical,
IconEye,
IconPencil,
IconTextSize,
} from '@/ui/display/icon';
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
@ -15,6 +16,7 @@ type SettingsObjectFieldActiveActionDropdownProps = {
isCustomField?: boolean;
onDisable?: () => void;
onEdit: () => void;
onSetAsLabelIdentifier?: () => void;
scopeKey: string;
};
@ -22,6 +24,7 @@ export const SettingsObjectFieldActiveActionDropdown = ({
isCustomField,
onDisable,
onEdit,
onSetAsLabelIdentifier,
scopeKey,
}: SettingsObjectFieldActiveActionDropdownProps) => {
const dropdownId = `${scopeKey}-settings-field-active-action-dropdown`;
@ -38,6 +41,11 @@ export const SettingsObjectFieldActiveActionDropdown = ({
closeDropdown();
};
const handleSetAsLabelIdentifier = () => {
onSetAsLabelIdentifier?.();
closeDropdown();
};
return (
<Dropdown
dropdownId={dropdownId}
@ -52,6 +60,13 @@ export const SettingsObjectFieldActiveActionDropdown = ({
LeftIcon={isCustomField ? IconPencil : IconEye}
onClick={handleEdit}
/>
{!!onSetAsLabelIdentifier && (
<MenuItem
text="Set as record text"
LeftIcon={IconTextSize}
onClick={handleSetAsLabelIdentifier}
/>
)}
{!!onDisable && (
<MenuItem
text="Disable"