diff --git a/front/src/modules/activities/components/ActivityTargetChips.tsx b/front/src/modules/activities/components/ActivityTargetChips.tsx index 8220575f7..6b69c22d6 100644 --- a/front/src/modules/activities/components/ActivityTargetChips.tsx +++ b/front/src/modules/activities/components/ActivityTargetChips.tsx @@ -18,7 +18,7 @@ export const ActivityTargetChips = ({ targets }: { targets?: any }) => { return ( - {targets?.edges?.map(({ company, person }: any) => { + {targets?.map(({ company, person }: any) => { if (company) { return ( & { - activityTargets?: { - edges: Array<{ - node: Pick; - }> | null; - }; - }; + activityId: string; + currentActivityTargets: any[]; }) => { const { createOneObject } = useCreateOneObjectRecord({ objectNameSingular: 'activityTarget', @@ -27,49 +18,56 @@ export const useHandleCheckableActivityTargetChange = ({ return async ( entityValues: Record, - entities: ActivityTargetableEntityForSelect[], + entitiesToSelect: any, + selectedEntities: any, ) => { - if (!activity) { + if (!activityId) { return; } - - const currentEntityIds = activity.activityTargets?.edges - ? activity.activityTargets.edges.map( - ({ node }) => node.personId ?? node.companyId, - ) - : []; - - const entitiesToAdd = entities.filter( - ({ id }) => entityValues[id] && !currentEntityIds.includes(id), + const currentActivityTargetRecordIds = currentActivityTargets.map( + ({ companyId, personId }) => companyId ?? personId ?? '', ); - if (entitiesToAdd.length) { - entitiesToAdd.map((entity) => { + const idsToAdd = Object.entries(entityValues) + .filter( + ([recordId, value]) => + value && !currentActivityTargetRecordIds.includes(recordId), + ) + .map(([id, _]) => id); + + const idsToDelete = Object.entries(entityValues) + .filter(([_, value]) => !value) + .map(([id, _]) => id); + + if (idsToAdd.length) { + idsToAdd.map((id) => { + const entityFromToSelect = entitiesToSelect.filter( + (entity: any) => entity.id === id, + ).length + ? entitiesToSelect.filter((entity: any) => entity.id === id)[0] + : null; + + const entityFromSelected = selectedEntities.filter( + (entity: any) => entity.id === id, + ).length + ? selectedEntities.filter((entity: any) => entity.id === id)[0] + : null; + + const entity = entityFromToSelect ?? entityFromSelected; createOneObject?.({ - activityId: activity.id, - activityTargetInputs: { - id: v4(), - createdAt: new Date().toISOString(), - companyId: entity.entityType === 'Company' ? entity.id : null, - personId: entity.entityType === 'Person' ? entity.id : null, - }, + activityId: activityId, + companyId: entity.record.__typename === 'Company' ? entity.id : null, + personId: entity.record.__typename === 'Person' ? entity.id : null, }); }); } - const activityTargetIdsToDelete = activity.activityTargets?.edges - ? activity.activityTargets.edges - .filter( - ({ node }) => - (node.personId ?? node.companyId) && - !entityValues[node.personId ?? node.companyId ?? ''], - ) - .map(({ node }) => node.id) - : []; - - if (activityTargetIdsToDelete.length) { - activityTargetIdsToDelete.map((id) => { - deleteOneObject?.(id); + if (idsToDelete.length) { + idsToDelete.map((id) => { + const currentActivityTargetId = currentActivityTargets.filter( + ({ companyId, personId }) => companyId === id || personId === id, + )[0].id; + deleteOneObject?.(currentActivityTargetId); }); } }; diff --git a/front/src/modules/activities/inline-cell/components/ActivityTargetInlineCellEditMode.tsx b/front/src/modules/activities/inline-cell/components/ActivityTargetInlineCellEditMode.tsx index 5c4d0d7d5..4af34152a 100644 --- a/front/src/modules/activities/inline-cell/components/ActivityTargetInlineCellEditMode.tsx +++ b/front/src/modules/activities/inline-cell/components/ActivityTargetInlineCellEditMode.tsx @@ -1,20 +1,20 @@ import { useCallback, useMemo, useState } from 'react'; +import { useQuery } from '@apollo/client'; import styled from '@emotion/styled'; import { useHandleCheckableActivityTargetChange } from '@/activities/hooks/useHandleCheckableActivityTargetChange'; import { ActivityTarget } from '@/activities/types/ActivityTarget'; -import { GraphQLActivity } from '@/activities/types/GraphQLActivity'; +import { flatMapAndSortEntityForSelectArrayOfArrayByName } from '@/activities/utils/flatMapAndSortEntityForSelectArrayByName'; +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery'; +import { useRelationPicker } from '@/ui/input/components/internal/relation-picker/hooks/useRelationPicker'; +import { MultipleEntitySelect } from '@/ui/input/relation-picker/components/MultipleEntitySelect'; import { useInlineCell } from '@/ui/object/record-inline-cell/hooks/useInlineCell'; import { assertNotNull } from '~/utils/assert'; type ActivityTargetInlineCellEditModeProps = { - activity?: Pick & { - activityTargets?: { - edges: Array<{ - node: Pick; - }> | null; - }; - }; + activityId: string; + activityTargets: Array>; }; const StyledSelectContainer = styled.div` @@ -24,26 +24,27 @@ const StyledSelectContainer = styled.div` `; export const ActivityTargetInlineCellEditMode = ({ - activity, + activityId, + activityTargets, }: ActivityTargetInlineCellEditModeProps) => { const [searchFilter, setSearchFilter] = useState(''); const initialPeopleIds = useMemo( () => - activity?.activityTargets?.edges - ?.filter(({ node }) => node.personId !== null) - .map(({ node }) => node.personId) + activityTargets + ?.filter(({ personId }) => personId !== null) + .map(({ personId }) => personId) .filter(assertNotNull) ?? [], - [activity?.activityTargets], + [activityTargets], ); const initialCompanyIds = useMemo( () => - activity?.activityTargets?.edges - ?.filter(({ node }) => node.companyId !== null) - .map(({ node }) => node.companyId) + activityTargets + ?.filter(({ companyId }) => companyId !== null) + .map(({ companyId }) => companyId) .filter(assertNotNull) ?? [], - [activity?.activityTargets], + [activityTargets], ); const initialSelectedEntityIds = useMemo( @@ -54,45 +55,92 @@ export const ActivityTargetInlineCellEditMode = ({ [initialPeopleIds, initialCompanyIds], ); + const { findManyQuery: findManyPeopleQuery } = useObjectMetadataItem({ + objectNameSingular: 'person', + }); + + const { findManyQuery: findManyCompaniesQuery } = useObjectMetadataItem({ + objectNameSingular: 'company', + }); + + const useFindManyPeopleQuery = (options: any) => + useQuery(findManyPeopleQuery, options); + + const useFindManyCompaniesQuery = (options: any) => + useQuery(findManyCompaniesQuery, options); + const [selectedEntityIds, setSelectedEntityIds] = useState< Record >(initialSelectedEntityIds); - // const personsForMultiSelect = useFilteredSearchPeopleQuery({ - // searchFilter, - // selectedIds: initialPeopleIds, - // }); + const { identifiersMapper, searchQuery } = useRelationPicker(); - // const companiesForMultiSelect = useFilteredSearchCompanyQuery({ - // searchFilter, - // selectedIds: initialCompanyIds, - // }); + const people = useFilteredSearchEntityQuery({ + queryHook: useFindManyPeopleQuery, + filters: [ + { + fieldNames: searchQuery?.computeFilterFields?.('person') ?? [], + filter: searchFilter, + }, + ], + orderByField: 'createdAt', + mappingFunction: (record: any) => identifiersMapper?.(record, 'person'), + selectedIds: initialPeopleIds, + objectNamePlural: 'people', + limit: 3, + }); - // const selectedEntities = flatMapAndSortEntityForSelectArrayOfArrayByName([ - // personsForMultiSelect.selectedEntities, - // companiesForMultiSelect.selectedEntities, - // ]); + const companies = useFilteredSearchEntityQuery({ + queryHook: useFindManyCompaniesQuery, + filters: [ + { + fieldNames: searchQuery?.computeFilterFields?.('company') ?? [], + filter: searchFilter, + }, + ], + orderByField: 'createdAt', + mappingFunction: (record: any) => identifiersMapper?.(record, 'company'), + selectedIds: initialCompanyIds, + objectNamePlural: 'companies', + limit: 3, + }); - // const filteredSelectedEntities = - // flatMapAndSortEntityForSelectArrayOfArrayByName([ - // personsForMultiSelect.filteredSelectedEntities, - // companiesForMultiSelect.filteredSelectedEntities, - // ]); + const selectedEntities = flatMapAndSortEntityForSelectArrayOfArrayByName([ + people.selectedEntities, + companies.selectedEntities, + ]); - // const entitiesToSelect = flatMapAndSortEntityForSelectArrayOfArrayByName([ - // personsForMultiSelect.entitiesToSelect, - // companiesForMultiSelect.entitiesToSelect, - // ]); + const filteredSelectedEntities = + flatMapAndSortEntityForSelectArrayOfArrayByName([ + people.filteredSelectedEntities, + companies.filteredSelectedEntities, + ]); + + const entitiesToSelect = flatMapAndSortEntityForSelectArrayOfArrayByName([ + people.entitiesToSelect, + companies.entitiesToSelect, + ]); const handleCheckItemsChange = useHandleCheckableActivityTargetChange({ - activity, + activityId, + currentActivityTargets: activityTargets, }); const { closeInlineCell: closeEditableField } = useInlineCell(); const handleSubmit = useCallback(() => { - //handleCheckItemsChange(selectedEntityIds, entitiesToSelect); + handleCheckItemsChange( + selectedEntityIds, + entitiesToSelect, + selectedEntities, + ); closeEditableField(); - }, [closeEditableField]); + }, [ + closeEditableField, + entitiesToSelect, + handleCheckItemsChange, + selectedEntities, + selectedEntityIds, + ]); const handleCancel = () => { closeEditableField(); @@ -100,7 +148,7 @@ export const ActivityTargetInlineCellEditMode = ({ return ( - {/* */} + /> ); }; diff --git a/front/src/modules/activities/inline-cell/components/ActivityTargetsInlineCell.tsx b/front/src/modules/activities/inline-cell/components/ActivityTargetsInlineCell.tsx index c749fad8c..e896131b4 100644 --- a/front/src/modules/activities/inline-cell/components/ActivityTargetsInlineCell.tsx +++ b/front/src/modules/activities/inline-cell/components/ActivityTargetsInlineCell.tsx @@ -2,8 +2,7 @@ import { ActivityTargetChips } from '@/activities/components/ActivityTargetChips import { ActivityTargetInlineCellEditMode } from '@/activities/inline-cell/components/ActivityTargetInlineCellEditMode'; import { ActivityTarget } from '@/activities/types/ActivityTarget'; import { GraphQLActivity } from '@/activities/types/GraphQLActivity'; -import { Company } from '@/companies/types/Company'; -import { Person } from '@/people/types/Person'; +import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords'; import { IconArrowUpRight, IconPencil } from '@/ui/display/icon'; import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope'; import { RecordInlineCellContainer } from '@/ui/object/record-inline-cell/components/RecordInlineCellContainer'; @@ -14,10 +13,7 @@ type ActivityTargetsInlineCellProps = { activity?: Pick & { activityTargets?: { edges: Array<{ - node: Pick & { - person?: Pick | null; - company?: Pick | null; - }; + node: Pick; }> | null; }; }; @@ -26,6 +22,18 @@ type ActivityTargetsInlineCellProps = { export const ActivityTargetsInlineCell = ({ activity, }: ActivityTargetsInlineCellProps) => { + const activityTargetIds = + activity?.activityTargets?.edges?.map( + (activityTarget) => activityTarget.node.id, + ) ?? []; + + const { objects: activityTargets } = useFindManyObjectRecords( + { + objectNamePlural: 'activityTargets', + filter: { id: { in: activityTargetIds } }, + }, + ); + return ( + } label="Relations" - displayModeContent={ - - } + displayModeContent={} isDisplayModeContentEmpty={ activity?.activityTargets?.edges?.length === 0 } diff --git a/front/src/modules/activities/tasks/components/TaskList.tsx b/front/src/modules/activities/tasks/components/TaskList.tsx index 94e919f6c..962d5af5a 100644 --- a/front/src/modules/activities/tasks/components/TaskList.tsx +++ b/front/src/modules/activities/tasks/components/TaskList.tsx @@ -2,6 +2,7 @@ import { ReactElement } from 'react'; import styled from '@emotion/styled'; import { Activity } from '@/activities/types/Activity'; +import { GraphQLActivity } from '@/activities/types/GraphQLActivity'; import { TaskRow } from './TaskRow'; @@ -60,7 +61,7 @@ export const TaskList = ({ title, tasks, button }: TaskListProps) => ( {tasks.map((task) => ( - + ))} diff --git a/front/src/modules/activities/tasks/components/TaskRow.tsx b/front/src/modules/activities/tasks/components/TaskRow.tsx index 39fa9578c..be85620f7 100644 --- a/front/src/modules/activities/tasks/components/TaskRow.tsx +++ b/front/src/modules/activities/tasks/components/TaskRow.tsx @@ -3,7 +3,9 @@ import styled from '@emotion/styled'; import { ActivityTargetChips } from '@/activities/components/ActivityTargetChips'; import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer'; -import { Activity } from '@/activities/types/Activity'; +import { ActivityTarget } from '@/activities/types/ActivityTarget'; +import { GraphQLActivity } from '@/activities/types/GraphQLActivity'; +import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords'; import { IconCalendar, IconComment } from '@/ui/display/icon'; import { OverflowingTextWithTooltip } from '@/ui/display/tooltip/OverflowingTextWithTooltip'; import { Checkbox, CheckboxShape } from '@/ui/input/components/Checkbox'; @@ -61,13 +63,29 @@ const StyledFieldsContainer = styled.div` display: flex; `; -export const TaskRow = ({ task }: { task: Omit }) => { +export const TaskRow = ({ + task, +}: { + task: Omit; +}) => { const theme = useTheme(); const openActivityRightDrawer = useOpenActivityRightDrawer(); const body = JSON.parse(task.body ?? '{}')[0]?.content[0]?.text; const { completeTask } = useCompleteTask(task); + const activityTargetIds = + task?.activityTargets?.edges.map( + (activityTarget) => activityTarget.node.id, + ) ?? []; + + const { objects: activityTargets } = useFindManyObjectRecords( + { + objectNamePlural: 'activityTargets', + filter: { id: { in: activityTargetIds } }, + }, + ); + return ( { @@ -97,7 +115,7 @@ export const TaskRow = ({ task }: { task: Omit }) => { )} - + { objectNamePlural: 'people', filter: { or: [ - { name: { firstName: { like: `%${search}%` } } }, - { name: { firstName: { like: `%${search}%` } } }, + { name: { firstName: { ilike: `%${search}%` } } }, + { name: { firstName: { ilike: `%${search}%` } } }, ], }, limit: 3, @@ -58,7 +58,7 @@ export const CommandMenu = () => { skip: !isCommandMenuOpened, objectNamePlural: 'companies', filter: { - name: { like: `%${search}%` }, + name: { ilike: `%${search}%` }, }, limit: 3, }); diff --git a/front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts b/front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts index 3344cd8f2..db553e7ba 100644 --- a/front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts +++ b/front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts @@ -98,10 +98,8 @@ export const useFilteredSearchEntityQuery = ({ and: searchFilter, }, { - not: { - id: { - in: selectedIds, - }, + id: { + in: selectedIds, }, }, ],