From 91d02d037ab24db7f4f6bb2e9e1cd2be645341f6 Mon Sep 17 00:00:00 2001 From: Jonathan ARNAULT Date: Fri, 26 Jul 2024 15:43:05 +0200 Subject: [PATCH 1/3] Fix(crm): Add create contact button to company even if there is no contacts attached to it --- examples/crm/src/companies/CompanyShow.tsx | 55 +++++++++++----------- examples/crm/src/contacts/Avatar.tsx | 10 ++-- examples/crm/src/dataProvider.ts | 17 +++++++ 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/examples/crm/src/companies/CompanyShow.tsx b/examples/crm/src/companies/CompanyShow.tsx index 8c7f069bfb..61bf43ab98 100644 --- a/examples/crm/src/companies/CompanyShow.tsx +++ b/examples/crm/src/companies/CompanyShow.tsx @@ -85,15 +85,15 @@ const CompanyShowContent = () => { textColor="primary" onChange={handleTabChange} > - {record.nb_contacts && ( - - )} + {record.nb_deals && ( { - {record.nb_contacts ? ( - - + + - + {record.nb_contacts && ( { 'last_seen', ]} /> - - - - - - ) : null} + )} + + + + + {record.nb_deals ? ( { const record = useRecordContext(props); - if (!record) return null; + // If we come from company page, the record is defined (to pass the company as a prop), + // but neither of those fields are and this lead to an error when creating contact. + if (!record?.avatar && !record?.first_name && !record?.last_name) { + return null; + } return ( - {record.first_name.charAt(0)} - {record.last_name.charAt(0)} + {record.first_name?.charAt(0)} + {record.last_name?.charAt(0)} ); }; diff --git a/examples/crm/src/dataProvider.ts b/examples/crm/src/dataProvider.ts index bb58352333..e408ae366f 100644 --- a/examples/crm/src/dataProvider.ts +++ b/examples/crm/src/dataProvider.ts @@ -258,6 +258,23 @@ export const dataProvider = withLifecycleCallbacks( beforeCreate: async (params, dataProvider) => { return processContactAvatar(params, dataProvider); }, + afterCreate: async (result, dataProvider) => { + const { data: company } = await dataProvider.getOne( + 'companies', + { + id: result.data.company_id, + } + ); + await dataProvider.update('companies', { + id: company.id, + data: { + nb_contacts: (company.nb_contacts ?? 0) + 1, + }, + previousData: company, + }); + + return result; + }, beforeUpdate: async params => { return processContactAvatar(params, dataProvider); }, From dabf9a4283e1da8903b8a13f47b8f187988f0d18 Mon Sep 17 00:00:00 2001 From: Jonathan ARNAULT Date: Fri, 26 Jul 2024 15:56:34 +0200 Subject: [PATCH 2/3] Fix(crm): Update contact count and deal count when deleting an entity --- examples/crm/src/companies/CompanyShow.tsx | 2 +- examples/crm/src/dataProvider.ts | 34 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/examples/crm/src/companies/CompanyShow.tsx b/examples/crm/src/companies/CompanyShow.tsx index 61bf43ab98..bcd5734848 100644 --- a/examples/crm/src/companies/CompanyShow.tsx +++ b/examples/crm/src/companies/CompanyShow.tsx @@ -120,7 +120,7 @@ const CompanyShowContent = () => { spacing={2} mt={1} > - {record.nb_contacts && ( + {!!record.nb_contacts && ( { return processContactAvatar(params, dataProvider); }, + afterDelete: async (result, dataProvider) => { + const { data: company } = await dataProvider.getOne( + 'companies', + { + id: result.data.company_id, + } + ); + await dataProvider.update('companies', { + id: company.id, + data: { + nb_contacts: (company.nb_contacts ?? 1) - 1, + }, + previousData: company, + }); + + return result; + }, } satisfies ResourceCallbacks, { resource: 'contactNotes', @@ -467,6 +484,23 @@ export const dataProvider = withLifecycleCallbacks( }, }; }, + afterDelete: async (result, dataProvider) => { + const { data: company } = await dataProvider.getOne( + 'companies', + { + id: result.data.company_id, + } + ); + await dataProvider.update('companies', { + id: company.id, + data: { + nb_deals: (company.nb_deals ?? 1) - 1, + }, + previousData: company, + }); + + return result; + }, } satisfies ResourceCallbacks, ] ); From 5fb70220b4412ecd957cdaff706efa4e01a3751c Mon Sep 17 00:00:00 2001 From: Jonathan ARNAULT Date: Mon, 29 Jul 2024 15:16:39 +0200 Subject: [PATCH 3/3] Fix(crm): Factorize updateCompany in data provider --- examples/crm/src/dataProvider.ts | 89 ++++++++++++-------------------- 1 file changed, 33 insertions(+), 56 deletions(-) diff --git a/examples/crm/src/dataProvider.ts b/examples/crm/src/dataProvider.ts index 477728f010..10da5a0cac 100644 --- a/examples/crm/src/dataProvider.ts +++ b/examples/crm/src/dataProvider.ts @@ -158,6 +158,23 @@ const dataProviderWithCustomMethod = { export type CustomDataProvider = typeof dataProviderWithCustomMethod; +async function updateCompany( + companyId: Identifier, + updateFn: (company: Company) => Partial +) { + const { data: company } = await dataProvider.getOne('companies', { + id: companyId, + }); + + return await dataProvider.update('companies', { + id: companyId, + data: { + ...updateFn(company), + }, + previousData: company, + }); +} + export const dataProvider = withLifecycleCallbacks( dataProviderWithCustomMethod, [ @@ -258,40 +275,20 @@ export const dataProvider = withLifecycleCallbacks( beforeCreate: async (params, dataProvider) => { return processContactAvatar(params, dataProvider); }, - afterCreate: async (result, dataProvider) => { - const { data: company } = await dataProvider.getOne( - 'companies', - { - id: result.data.company_id, - } - ); - await dataProvider.update('companies', { - id: company.id, - data: { - nb_contacts: (company.nb_contacts ?? 0) + 1, - }, - previousData: company, - }); + afterCreate: async result => { + await updateCompany(result.data.company_id, company => ({ + nb_contacts: (company.nb_contacts ?? 0) + 1, + })); return result; }, beforeUpdate: async params => { return processContactAvatar(params, dataProvider); }, - afterDelete: async (result, dataProvider) => { - const { data: company } = await dataProvider.getOne( - 'companies', - { - id: result.data.company_id, - } - ); - await dataProvider.update('companies', { - id: company.id, - data: { - nb_contacts: (company.nb_contacts ?? 1) - 1, - }, - previousData: company, - }); + afterDelete: async result => { + await updateCompany(result.data.company_id, company => ({ + nb_contacts: (company.nb_contacts ?? 1) - 1, + })); return result; }, @@ -458,20 +455,10 @@ export const dataProvider = withLifecycleCallbacks( }, }; }, - afterCreate: async (result, dataProvider) => { - const { data: company } = await dataProvider.getOne( - 'companies', - { - id: result.data.company_id, - } - ); - await dataProvider.update('companies', { - id: company.id, - data: { - nb_deals: (company.nb_deals ?? 0) + 1, - }, - previousData: company, - }); + afterCreate: async result => { + await updateCompany(result.data.company_id, company => ({ + nb_deals: (company.nb_deals ?? 0) + 1, + })); return result; }, @@ -484,20 +471,10 @@ export const dataProvider = withLifecycleCallbacks( }, }; }, - afterDelete: async (result, dataProvider) => { - const { data: company } = await dataProvider.getOne( - 'companies', - { - id: result.data.company_id, - } - ); - await dataProvider.update('companies', { - id: company.id, - data: { - nb_deals: (company.nb_deals ?? 1) - 1, - }, - previousData: company, - }); + afterDelete: async result => { + await updateCompany(result.data.company_id, company => ({ + nb_deals: (company.nb_deals ?? 1) - 1, + })); return result; },