From 40bea0d95e81e9fee09d6d8d1ba41e459b1d0770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tha=C3=AFs?= Date: Fri, 8 Mar 2024 17:55:30 -0300 Subject: [PATCH] feat: add Settings Object Edit identifiers form (#4300) * feat: add Settings Object Edit identifiers form Closes #3836 * fix: fix wrong imports after renaming directories --- .../LabelIdentifierFieldMetadataTypes.ts | 6 ++ .../utils/getActiveFieldMetadataItems.ts | 9 ++ .../utils/getDisabledFieldMetadataItems.ts | 9 ++ .../components/SettingsDataModelCardTitle.tsx | 11 ++ ...SettingsDataModelObjectIdentifiersForm.tsx | 101 ++++++++++++++++++ ...ettingsDataModelObjectSettingsFormCard.tsx | 47 ++++++-- .../src/modules/ui/display/icon/index.ts | 1 + .../modules/ui/input/components/Select.tsx | 30 ++++-- .../pages/object-record/RecordShowPage.tsx | 2 +- .../data-model/SettingsObjectDetail.tsx | 14 +-- .../data-model/SettingsObjectEdit.tsx | 6 +- 11 files changed, 212 insertions(+), 24 deletions(-) create mode 100644 packages/twenty-front/src/modules/object-metadata/constants/LabelIdentifierFieldMetadataTypes.ts create mode 100644 packages/twenty-front/src/modules/object-metadata/utils/getActiveFieldMetadataItems.ts create mode 100644 packages/twenty-front/src/modules/object-metadata/utils/getDisabledFieldMetadataItems.ts create mode 100644 packages/twenty-front/src/modules/settings/data-model/components/SettingsDataModelCardTitle.tsx create mode 100644 packages/twenty-front/src/modules/settings/data-model/objects/forms/components/SettingsDataModelObjectIdentifiersForm.tsx diff --git a/packages/twenty-front/src/modules/object-metadata/constants/LabelIdentifierFieldMetadataTypes.ts b/packages/twenty-front/src/modules/object-metadata/constants/LabelIdentifierFieldMetadataTypes.ts new file mode 100644 index 0000000000..fe25319198 --- /dev/null +++ b/packages/twenty-front/src/modules/object-metadata/constants/LabelIdentifierFieldMetadataTypes.ts @@ -0,0 +1,6 @@ +import { FieldMetadataType } from '~/generated-metadata/graphql'; + +export const LABEL_IDENTIFIER_FIELD_METADATA_TYPES = [ + FieldMetadataType.Number, + FieldMetadataType.Text, +]; diff --git a/packages/twenty-front/src/modules/object-metadata/utils/getActiveFieldMetadataItems.ts b/packages/twenty-front/src/modules/object-metadata/utils/getActiveFieldMetadataItems.ts new file mode 100644 index 0000000000..e174c2b004 --- /dev/null +++ b/packages/twenty-front/src/modules/object-metadata/utils/getActiveFieldMetadataItems.ts @@ -0,0 +1,9 @@ +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; + +export const getActiveFieldMetadataItems = ( + objectMetadataItem: Pick, +) => + objectMetadataItem.fields.filter( + (fieldMetadataItem) => + fieldMetadataItem.isActive && !fieldMetadataItem.isSystem, + ); diff --git a/packages/twenty-front/src/modules/object-metadata/utils/getDisabledFieldMetadataItems.ts b/packages/twenty-front/src/modules/object-metadata/utils/getDisabledFieldMetadataItems.ts new file mode 100644 index 0000000000..52f781ccc2 --- /dev/null +++ b/packages/twenty-front/src/modules/object-metadata/utils/getDisabledFieldMetadataItems.ts @@ -0,0 +1,9 @@ +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; + +export const getDisabledFieldMetadataItems = ( + objectMetadataItem: Pick, +) => + objectMetadataItem.fields.filter( + (fieldMetadataItem) => + !fieldMetadataItem.isActive && !fieldMetadataItem.isSystem, + ); diff --git a/packages/twenty-front/src/modules/settings/data-model/components/SettingsDataModelCardTitle.tsx b/packages/twenty-front/src/modules/settings/data-model/components/SettingsDataModelCardTitle.tsx new file mode 100644 index 0000000000..9fbc11715a --- /dev/null +++ b/packages/twenty-front/src/modules/settings/data-model/components/SettingsDataModelCardTitle.tsx @@ -0,0 +1,11 @@ +import styled from '@emotion/styled'; + +const StyledTitle = styled.h3` + color: ${({ theme }) => theme.font.color.extraLight}; + font-size: ${({ theme }) => theme.font.size.sm}; + font-weight: ${({ theme }) => theme.font.weight.medium}; + margin: 0; + margin-bottom: ${({ theme }) => theme.spacing(4)}; +`; + +export { StyledTitle as SettingsDataModelCardTitle }; diff --git a/packages/twenty-front/src/modules/settings/data-model/objects/forms/components/SettingsDataModelObjectIdentifiersForm.tsx b/packages/twenty-front/src/modules/settings/data-model/objects/forms/components/SettingsDataModelObjectIdentifiersForm.tsx new file mode 100644 index 0000000000..6762b52693 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/data-model/objects/forms/components/SettingsDataModelObjectIdentifiersForm.tsx @@ -0,0 +1,101 @@ +import { useMemo } from 'react'; +import { Controller, useFormContext } from 'react-hook-form'; +import styled from '@emotion/styled'; +import { z } from 'zod'; + +import { LABEL_IDENTIFIER_FIELD_METADATA_TYPES } from '@/object-metadata/constants/LabelIdentifierFieldMetadataTypes'; +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { getActiveFieldMetadataItems } from '@/object-metadata/utils/getActiveFieldMetadataItems'; +import { objectMetadataItemSchema } from '@/object-metadata/validation-schemas/objectMetadataItemSchema'; +import { IconCircleOff } from '@/ui/display/icon'; +import { useIcons } from '@/ui/display/icon/hooks/useIcons'; +import { Select, SelectOption } from '@/ui/input/components/Select'; + +export const settingsDataModelObjectIdentifiersFormSchema = + objectMetadataItemSchema.pick({ + labelIdentifierFieldMetadataId: true, + imageIdentifierFieldMetadataId: true, + }); + +export type SettingsDataModelObjectIdentifiersFormValues = z.infer< + typeof settingsDataModelObjectIdentifiersFormSchema +>; + +type SettingsDataModelObjectIdentifiersFormProps = { + objectMetadataItem: ObjectMetadataItem; +}; + +const StyledContainer = styled.div` + display: flex; + gap: ${({ theme }) => theme.spacing(4)}; +`; + +export const SettingsDataModelObjectIdentifiersForm = ({ + objectMetadataItem, +}: SettingsDataModelObjectIdentifiersFormProps) => { + const { control } = + useFormContext(); + const { getIcon } = useIcons(); + + const labelIdentifierFieldOptions = useMemo( + () => + getActiveFieldMetadataItems(objectMetadataItem) + .filter( + ({ id, type }) => + LABEL_IDENTIFIER_FIELD_METADATA_TYPES.includes(type) || + objectMetadataItem.labelIdentifierFieldMetadataId === id, + ) + .map>((fieldMetadataItem) => ({ + Icon: getIcon(fieldMetadataItem.icon), + label: fieldMetadataItem.label, + value: fieldMetadataItem.id, + })), + [getIcon, objectMetadataItem], + ); + const imageIdentifierFieldOptions: SelectOption[] = []; + + const emptyOption: SelectOption = { + Icon: IconCircleOff, + label: 'None', + value: null, + }; + + return ( + + {[ + { + label: 'Record label', + fieldName: 'labelIdentifierFieldMetadataId' as const, + options: labelIdentifierFieldOptions, + }, + { + label: 'Record image', + fieldName: 'imageIdentifierFieldMetadataId' as const, + options: imageIdentifierFieldOptions, + }, + ].map(({ fieldName, label, options }) => ( + { + return ( +