From 615018654ac5bd2073ac5d957d72c9a217073db8 Mon Sep 17 00:00:00 2001 From: Emilien Chauvet Date: Thu, 24 Aug 2023 17:29:26 +0200 Subject: [PATCH] Add optimistic rendering for table relations (#1296) * Add optimistic rendering for table relations * fix pr * fix pr * fix pr * Fix PR --------- Co-authored-by: Charles Bochet --- .../components/CompanyPickerCell.tsx | 15 +++-- .../hooks/useFilteredSearchCompanyQuery.ts | 17 +++--- .../GenericEditableRelationCellEditMode.tsx | 61 +++++++++++++++++-- .../ui/table/hooks/useUpdateEntityField.ts | 2 +- 4 files changed, 74 insertions(+), 21 deletions(-) diff --git a/front/src/modules/companies/components/CompanyPickerCell.tsx b/front/src/modules/companies/components/CompanyPickerCell.tsx index 28b6550b1..4e6f58d0e 100644 --- a/front/src/modules/companies/components/CompanyPickerCell.tsx +++ b/front/src/modules/companies/components/CompanyPickerCell.tsx @@ -12,12 +12,16 @@ import { useInsertOneCompanyMutation } from '~/generated/graphql'; export type OwnProps = { companyId: string | null; - onSubmit: (newCompany: EntityForSelect | null) => void; + onSubmit: (newCompany: CompanyPickerSelectedCompany | null) => void; onCancel?: () => void; createModeEnabled?: boolean; width?: number; }; +export type CompanyPickerSelectedCompany = EntityForSelect & { + domainName: string; +}; + export function CompanyPickerCell({ companyId, onSubmit, @@ -42,10 +46,10 @@ export function CompanyPickerCell({ selectedIds: [companyId ?? ''], }); - async function handleEntitySelected( - entity: EntityForSelect | null | undefined, + async function handleCompanySelected( + company: CompanyPickerSelectedCompany | null | undefined, ) { - onSubmit(entity ?? null); + onSubmit(company ?? null); } function handleStartCreation() { @@ -69,6 +73,7 @@ export function CompanyPickerCell({ id: companyCreated.id, name: companyCreated.name, entityType: Entity.Company, + domainName: companyCreated.domainName, }); setIsCreating(false); } @@ -86,7 +91,7 @@ export function CompanyPickerCell({ width={width} onCreate={createModeEnabled ? handleStartCreation : undefined} onCancel={onCancel} - onEntitySelected={handleEntitySelected} + onEntitySelected={handleCompanySelected} entities={{ entitiesToSelect: companies.entitiesToSelect, selectedEntity: companies.selectedEntities[0], diff --git a/front/src/modules/companies/hooks/useFilteredSearchCompanyQuery.ts b/front/src/modules/companies/hooks/useFilteredSearchCompanyQuery.ts index 5d5e63637..fd082445c 100644 --- a/front/src/modules/companies/hooks/useFilteredSearchCompanyQuery.ts +++ b/front/src/modules/companies/hooks/useFilteredSearchCompanyQuery.ts @@ -1,5 +1,4 @@ import { ActivityTargetableEntityType } from '@/activities/types/ActivityTargetableEntity'; -import { ActivityTargetableEntityForSelect } from '@/activities/types/ActivityTargetableEntityForSelect'; import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery'; import { useSearchCompanyQuery } from '~/generated/graphql'; import { getLogoUrlFromDomainName } from '~/utils'; @@ -18,14 +17,14 @@ export function useFilteredSearchCompanyQuery({ searchOnFields: ['name'], orderByField: 'name', selectedIds: selectedIds, - mappingFunction: (company) => - ({ - id: company.id, - entityType: ActivityTargetableEntityType.Company, - name: company.name, - avatarUrl: getLogoUrlFromDomainName(company.domainName), - avatarType: 'squared', - } as ActivityTargetableEntityForSelect), + mappingFunction: (company) => ({ + id: company.id, + entityType: ActivityTargetableEntityType.Company, + name: company.name, + avatarUrl: getLogoUrlFromDomainName(company.domainName), + domainName: company.domainName, + avatarType: 'squared', + }), searchFilter, limit, }); diff --git a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableRelationCellEditMode.tsx b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableRelationCellEditMode.tsx index b9ef34bda..dc27b45c4 100644 --- a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableRelationCellEditMode.tsx +++ b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableRelationCellEditMode.tsx @@ -1,6 +1,9 @@ import { useRecoilState } from 'recoil'; -import { CompanyPickerCell } from '@/companies/components/CompanyPickerCell'; +import { + CompanyPickerCell, + CompanyPickerSelectedCompany, +} from '@/companies/components/CompanyPickerCell'; import { ViewFieldDefinition, ViewFieldRelationMetadata, @@ -22,21 +25,67 @@ export function GenericEditableRelationCellEditMode({ viewField }: OwnProps) { const { closeEditableCell } = useEditableCell(); - const [fieldValueEntity] = useRecoilState( + const [fieldValueEntity, setFieldValueEntity] = useRecoilState( tableEntityFieldFamilySelector({ entityId: currentRowEntityId ?? '', fieldName: viewField.metadata.fieldName, }), ); - const updateEntityField = useUpdateEntityField(); - function handleEntitySubmit(newFieldEntity: EntityForSelect | null) { + function updateCachedPersonField(newFieldEntity: EntityForSelect | null) { + if (newFieldEntity === null) { + return; + } + setFieldValueEntity({ + avatarUrl: newFieldEntity?.avatarUrl ?? '', + entityType: Entity.Company, + id: newFieldEntity?.id ?? '', + displayName: newFieldEntity?.name ?? '', + }); + } + + function updateCachedCompanyField( + newFieldEntity: CompanyPickerSelectedCompany | null, + ) { + if (newFieldEntity === null) { + return; + } + + setFieldValueEntity({ + id: newFieldEntity?.id ?? '', + name: newFieldEntity?.name ?? '', + domainName: newFieldEntity?.domainName ?? '', + }); + } + + function handleCompanySubmit( + newFieldEntity: CompanyPickerSelectedCompany | null, + ) { + if ( + newFieldEntity && + newFieldEntity?.id !== fieldValueEntity?.id && + currentRowEntityId && + updateEntityField + ) { + updateCachedCompanyField(newFieldEntity); + updateEntityField( + currentRowEntityId, + viewField, + newFieldEntity, + ); + } + + closeEditableCell(); + } + + function handlePersonSubmit(newFieldEntity: EntityForSelect | null) { if ( newFieldEntity?.id !== fieldValueEntity?.id && currentRowEntityId && updateEntityField ) { + updateCachedPersonField(newFieldEntity); updateEntityField(currentRowEntityId, viewField, newFieldEntity); } @@ -52,7 +101,7 @@ export function GenericEditableRelationCellEditMode({ viewField }: OwnProps) { return ( diff --git a/front/src/modules/ui/table/hooks/useUpdateEntityField.ts b/front/src/modules/ui/table/hooks/useUpdateEntityField.ts index 1c9d74613..bc1e59a54 100644 --- a/front/src/modules/ui/table/hooks/useUpdateEntityField.ts +++ b/front/src/modules/ui/table/hooks/useUpdateEntityField.ts @@ -46,7 +46,7 @@ import { EntityUpdateMutationContext } from '../contexts/EntityUpdateMutationHoo export function useUpdateEntityField() { const updateEntity = useContext(EntityUpdateMutationContext); - return function updatePeopleField< + return function updateEntityField< MetadataType extends ViewFieldMetadata, ValueType extends MetadataType extends ViewFieldDoubleTextMetadata ? ViewFieldDoubleTextValue