diff --git a/front/src/modules/activities/notes/hooks/useNotes.ts b/front/src/modules/activities/notes/hooks/useNotes.ts index 264ea63e1..c3184b557 100644 --- a/front/src/modules/activities/notes/hooks/useNotes.ts +++ b/front/src/modules/activities/notes/hooks/useNotes.ts @@ -19,7 +19,7 @@ export const useNotes = (entity: ActivityTargetableEntity) => { }; const orderBy = { createdAt: 'AscNullsFirst', - }; + } as any; // TODO: finish typing const { records: notes } = useFindManyRecords({ skip: !activityTargets?.length, diff --git a/front/src/modules/object-metadata/hooks/useGetObjectOrderByField.ts b/front/src/modules/object-metadata/hooks/useGetObjectOrderByField.ts new file mode 100644 index 000000000..bd7bd3702 --- /dev/null +++ b/front/src/modules/object-metadata/hooks/useGetObjectOrderByField.ts @@ -0,0 +1,14 @@ +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { OrderBy } from '@/object-metadata/types/OrderBy'; +import { OrderByField } from '@/object-metadata/types/OrderByField'; +import { getObjectOrderByField } from '@/object-metadata/utils/getObjectOrderByField'; + +export const useGetObjectOrderByField = ({ + objectMetadataItem, +}: { + objectMetadataItem: ObjectMetadataItem; +}) => { + return (orderBy: OrderBy): OrderByField => { + return getObjectOrderByField(objectMetadataItem, orderBy); + }; +}; diff --git a/front/src/modules/object-metadata/hooks/useMapToObjectRecordIdentifier.ts b/front/src/modules/object-metadata/hooks/useMapToObjectRecordIdentifier.ts index 511672c4d..6a5caddd2 100644 --- a/front/src/modules/object-metadata/hooks/useMapToObjectRecordIdentifier.ts +++ b/front/src/modules/object-metadata/hooks/useMapToObjectRecordIdentifier.ts @@ -1,6 +1,7 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { ObjectRecordIdentifier } from '@/object-record/types/ObjectRecordIdentifier'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { getLogoUrlFromDomainName } from '~/utils'; export const useMapToObjectRecordIdentifier = ({ @@ -10,17 +11,6 @@ export const useMapToObjectRecordIdentifier = ({ }) => { return (record: any): ObjectRecordIdentifier => { switch (objectMetadataItem.nameSingular) { - case CoreObjectNameSingular.WorkspaceMember: - case CoreObjectNameSingular.Person: - return { - id: record.id, - name: - (record.name?.firstName ?? '') + - ' ' + - (record.name?.lastName ?? ''), - avatarUrl: record.avatarUrl, - avatarType: 'rounded', - }; case CoreObjectNameSingular.Opportunity: return { id: record.id, @@ -36,9 +26,20 @@ export const useMapToObjectRecordIdentifier = ({ field.name === 'name', ); - const labelIdentifierFieldValue = labelIdentifierFieldMetadata - ? record[labelIdentifierFieldMetadata.name] - : null; + let labelIdentifierFieldValue = ''; + + switch (labelIdentifierFieldMetadata?.type) { + case FieldMetadataType.FullName: { + labelIdentifierFieldValue = `${record.name?.firstName ?? ''} ${ + record.name?.lastName ?? '' + }`; + break; + } + default: + labelIdentifierFieldValue = labelIdentifierFieldMetadata + ? record[labelIdentifierFieldMetadata.name] + : ''; + } const imageIdentifierFieldMetadata = objectMetadataItem.fields.find( (field) => field.id === objectMetadataItem.imageIdentifierFieldMetadataId, diff --git a/front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts b/front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts index 25bc497c4..4dc0aa545 100644 --- a/front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts +++ b/front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts @@ -3,6 +3,7 @@ import { useRecoilValue } from 'recoil'; import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { ObjectMetadataItemNotFoundError } from '@/object-metadata/errors/ObjectMetadataNotFoundError'; +import { useGetObjectOrderByField } from '@/object-metadata/hooks/useGetObjectOrderByField'; import { useMapToObjectRecordIdentifier } from '@/object-metadata/hooks/useMapToObjectRecordIdentifier'; import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; @@ -66,6 +67,10 @@ export const useObjectMetadataItem = ( objectMetadataItem, }); + const getObjectOrderByField = useGetObjectOrderByField({ + objectMetadataItem, + }); + const getRecordFromCache = useGetRecordFromCache({ objectMetadataItem, }); @@ -114,5 +119,6 @@ export const useObjectMetadataItem = ( updateOneRecordMutation, deleteOneRecordMutation, mapToObjectRecordIdentifier, + getObjectOrderByField, }; }; diff --git a/front/src/modules/object-metadata/types/OrderBy.ts b/front/src/modules/object-metadata/types/OrderBy.ts new file mode 100644 index 000000000..72968491c --- /dev/null +++ b/front/src/modules/object-metadata/types/OrderBy.ts @@ -0,0 +1,5 @@ +export type OrderBy = + | 'AscNullsLast' + | 'DescNullsLast' + | 'AscNullsFirst' + | 'DescNullsFirst'; diff --git a/front/src/modules/object-metadata/types/OrderByField.ts b/front/src/modules/object-metadata/types/OrderByField.ts new file mode 100644 index 000000000..c97a74169 --- /dev/null +++ b/front/src/modules/object-metadata/types/OrderByField.ts @@ -0,0 +1,5 @@ +import { OrderBy } from '@/object-metadata/types/OrderBy'; + +export type OrderByField = { + [fieldName: string]: OrderBy | { [subFieldName: string]: OrderBy }; +}; diff --git a/front/src/modules/object-metadata/utils/getObjectOrderByField.ts b/front/src/modules/object-metadata/utils/getObjectOrderByField.ts new file mode 100644 index 000000000..7164656c0 --- /dev/null +++ b/front/src/modules/object-metadata/utils/getObjectOrderByField.ts @@ -0,0 +1,35 @@ +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { OrderBy } from '@/object-metadata/types/OrderBy'; +import { OrderByField } from '@/object-metadata/types/OrderByField'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; + +export const getObjectOrderByField = ( + objectMetadataItem: ObjectMetadataItem, + orderBy: OrderBy, +): OrderByField => { + const labelIdentifierFieldMetadata = objectMetadataItem.fields.find( + (field) => + field.id === objectMetadataItem.labelIdentifierFieldMetadataId || + field.name === 'name', + ); + + if (labelIdentifierFieldMetadata) { + switch (labelIdentifierFieldMetadata.type) { + case FieldMetadataType.FullName: + return { + [labelIdentifierFieldMetadata.name]: { + firstName: orderBy, + lastName: orderBy, + }, + }; + default: + return { + [labelIdentifierFieldMetadata.name]: orderBy, + }; + } + } else { + return { + createdAt: orderBy, + }; + } +}; diff --git a/front/src/modules/object-record/hooks/useFindManyRecords.ts b/front/src/modules/object-record/hooks/useFindManyRecords.ts index f16034719..9314db9d8 100644 --- a/front/src/modules/object-record/hooks/useFindManyRecords.ts +++ b/front/src/modules/object-record/hooks/useFindManyRecords.ts @@ -8,6 +8,7 @@ import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimis import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier'; +import { OrderByField } from '@/object-metadata/types/OrderByField'; import { getRecordOptimisticEffectDefinition } from '@/object-record/graphql/optimistic-effect-definition/getRecordOptimisticEffectDefinition'; import { filterUniqueRecordEdgesByCursor } from '@/object-record/utils/filterUniqueRecordEdgesByCursor'; import { DEFAULT_SEARCH_REQUEST_LIMIT } from '@/search/hooks/useFilteredSearchEntityQuery'; @@ -36,7 +37,7 @@ export const useFindManyRecords = < skip, }: ObjectMetadataItemIdentifier & { filter?: any; - orderBy?: any; + orderBy?: OrderByField; limit?: number; onCompleted?: (data: PaginatedRecordTypeResults) => void; skip?: boolean; diff --git a/front/src/modules/object-record/hooks/useObjectRecordBoard.1.ts b/front/src/modules/object-record/hooks/useObjectRecordBoard.1.ts index e32d12925..bf33af409 100644 --- a/front/src/modules/object-record/hooks/useObjectRecordBoard.1.ts +++ b/front/src/modules/object-record/hooks/useObjectRecordBoard.1.ts @@ -71,7 +71,7 @@ export const useObjectRecordBoard = () => { skip: !savedPipelineSteps.length, objectNameSingular: 'opportunity', filter: filter, - orderBy: orderBy, + orderBy: orderBy as any, // TODO: finish typing onCompleted: useCallback(() => { setIsBoardLoaded(true); }, [setIsBoardLoaded]), diff --git a/front/src/modules/object-record/hooks/useObjectRecordBoard.ts b/front/src/modules/object-record/hooks/useObjectRecordBoard.ts index e32d12925..bf33af409 100644 --- a/front/src/modules/object-record/hooks/useObjectRecordBoard.ts +++ b/front/src/modules/object-record/hooks/useObjectRecordBoard.ts @@ -71,7 +71,7 @@ export const useObjectRecordBoard = () => { skip: !savedPipelineSteps.length, objectNameSingular: 'opportunity', filter: filter, - orderBy: orderBy, + orderBy: orderBy as any, // TODO: finish typing onCompleted: useCallback(() => { setIsBoardLoaded(true); }, [setIsBoardLoaded]), diff --git a/front/src/modules/object-record/hooks/useObjectRecordTable.ts b/front/src/modules/object-record/hooks/useObjectRecordTable.ts index 45a45bc68..a06dce154 100644 --- a/front/src/modules/object-record/hooks/useObjectRecordTable.ts +++ b/front/src/modules/object-record/hooks/useObjectRecordTable.ts @@ -35,10 +35,12 @@ export const useObjectRecordTable = () => { tableFilters, foundObjectMetadataItem?.fields ?? [], ); + + // TODO: finish typing const orderBy = turnSortsIntoOrderBy( tableSorts, foundObjectMetadataItem?.fields ?? [], - ); + ) as any; const { records, loading, fetchMoreRecords, queryStateIdentifier } = useFindManyRecords({ diff --git a/front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx b/front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx index 26a77c097..6dd141808 100644 --- a/front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx +++ b/front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx @@ -31,6 +31,10 @@ export const ObjectFilterDropdownRecordSelect = () => { recordToSelect: SelectableRecord, newSelectedValue: boolean, ) => { + if (loading) { + return; + } + const newSelectedRecordIds = newSelectedValue ? [...objectFilterDropdownSelectedRecordIds, recordToSelect.id] : objectFilterDropdownSelectedRecordIds.filter( diff --git a/front/src/modules/object-record/relation-picker/hooks/useEntitySelectSearch.ts b/front/src/modules/object-record/relation-picker/hooks/useEntitySelectSearch.ts index 58e377d8c..241da3f73 100644 --- a/front/src/modules/object-record/relation-picker/hooks/useEntitySelectSearch.ts +++ b/front/src/modules/object-record/relation-picker/hooks/useEntitySelectSearch.ts @@ -1,6 +1,5 @@ import debounce from 'lodash.debounce'; -import { RelationPickerRecoilScopeContext } from '@/object-record/relation-picker/states/recoil-scope-contexts/RelationPickerRecoilScopeContext'; import { relationPickerPreselectedIdScopedState } from '@/object-record/relation-picker/states/relationPickerPreselectedIdScopedState'; import { relationPickerSearchFilterScopedState } from '@/object-record/relation-picker/states/relationPickerSearchFilterScopedState'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; @@ -8,14 +7,10 @@ import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoi export const useEntitySelectSearch = () => { const [, setRelationPickerPreselectedId] = useRecoilScopedState( relationPickerPreselectedIdScopedState, - RelationPickerRecoilScopeContext, ); const [relationPickerSearchFilter, setRelationPickerSearchFilter] = - useRecoilScopedState( - relationPickerSearchFilterScopedState, - RelationPickerRecoilScopeContext, - ); + useRecoilScopedState(relationPickerSearchFilterScopedState); const debouncedSetSearchFilter = debounce( setRelationPickerSearchFilter, diff --git a/front/src/modules/object-record/select/hooks/useRecordsForSelect.ts b/front/src/modules/object-record/select/hooks/useRecordsForSelect.ts index de5ae39e1..b0bfb04f5 100644 --- a/front/src/modules/object-record/select/hooks/useRecordsForSelect.ts +++ b/front/src/modules/object-record/select/hooks/useRecordsForSelect.ts @@ -1,18 +1,12 @@ import { isNonEmptyString } from '@sniptt/guards'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { OrderBy } from '@/object-metadata/types/OrderBy'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { SelectableRecord } from '@/object-record/select/types/SelectableRecord'; import { getObjectFilterFields } from '@/object-record/select/utils/getObjectFilterFields'; -import { getObjectOrderByField } from '@/object-record/select/utils/getObjectOrderByField'; import { isDefined } from '~/utils/isDefined'; -export type OrderBy = - | 'AscNullsLast' - | 'DescNullsLast' - | 'AscNullsFirst' - | 'DescNullsFirst'; - export const DEFAULT_SEARCH_REQUEST_LIMIT = 60; export const useRecordsForSelect = ({ @@ -30,9 +24,10 @@ export const useRecordsForSelect = ({ excludeEntityIds?: string[]; objectNameSingular: string; }) => { - const { mapToObjectRecordIdentifier } = useObjectMetadataItem({ - objectNameSingular, - }); + const { mapToObjectRecordIdentifier, getObjectOrderByField } = + useObjectMetadataItem({ + objectNameSingular, + }); const filters = [ { @@ -41,7 +36,7 @@ export const useRecordsForSelect = ({ }, ]; - const orderByField = getObjectOrderByField(objectNameSingular); + const orderByField = getObjectOrderByField(sortOrder); const { loading: selectedRecordsLoading, records: selectedRecordsData } = useFindManyRecords({ @@ -50,9 +45,7 @@ export const useRecordsForSelect = ({ in: selectedIds, }, }, - orderBy: { - [orderByField]: sortOrder, - }, + orderBy: orderByField, objectNameSingular, }); @@ -103,9 +96,7 @@ export const useRecordsForSelect = ({ }, ], }, - orderBy: { - [orderByField]: sortOrder, - }, + orderBy: orderByField, objectNameSingular, }); @@ -126,9 +117,7 @@ export const useRecordsForSelect = ({ ], }, limit: limit ?? DEFAULT_SEARCH_REQUEST_LIMIT, - orderBy: { - [orderByField]: sortOrder, - }, + orderBy: orderByField, objectNameSingular, }); diff --git a/front/src/modules/object-record/select/utils/getObjectOrderByField.ts b/front/src/modules/object-record/select/utils/getObjectOrderByField.ts deleted file mode 100644 index 0f33e3fec..000000000 --- a/front/src/modules/object-record/select/utils/getObjectOrderByField.ts +++ /dev/null @@ -1,11 +0,0 @@ -export const getObjectOrderByField = (objectSingleName: string): string => { - if (objectSingleName === 'company') { - return 'name'; - } - - if (['workspaceMember', 'person'].includes(objectSingleName)) { - return 'name.firstName'; - } - - return 'createdAt'; -}; diff --git a/front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts b/front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts index c54864f90..8d900e747 100644 --- a/front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts +++ b/front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts @@ -2,6 +2,7 @@ import { QueryHookOptions, QueryResult } from '@apollo/client'; import { isNonEmptyString } from '@sniptt/guards'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { OrderBy } from '@/object-metadata/types/OrderBy'; import { EntitiesForMultipleEntitySelect } from '@/object-record/relation-picker/components/MultipleEntitySelect'; import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect'; import { mapPaginatedRecordsToRecords } from '@/object-record/utils/mapPaginatedRecordsToRecords'; @@ -10,12 +11,6 @@ import { isDefined } from '~/utils/isDefined'; type SearchFilter = { fieldNames: string[]; filter: string | number }; -export type OrderBy = - | 'AscNullsLast' - | 'DescNullsLast' - | 'AscNullsFirst' - | 'DescNullsFirst'; - export const DEFAULT_SEARCH_REQUEST_LIMIT = 60; // TODO: use this for all search queries, because we need selectedEntities and entitiesToSelect each time we want to search