diff --git a/app/actions/contact_identify_action.rb b/app/actions/contact_identify_action.rb index 655c6bc1c..746d1bfec 100644 --- a/app/actions/contact_identify_action.rb +++ b/app/actions/contact_identify_action.rb @@ -52,12 +52,11 @@ class ContactIdentifyAction end def update_contact - custom_attributes = params[:custom_attributes] ? @contact.custom_attributes.merge(params[:custom_attributes]) : @contact.custom_attributes # blank identifier or email will throw unique index error # TODO: replace reject { |_k, v| v.blank? } with compact_blank when rails is upgraded @contact.update!(params.slice(:name, :email, :identifier, :phone_number).reject do |_k, v| v.blank? - end.merge({ custom_attributes: custom_attributes })) + end.merge({ custom_attributes: custom_attributes, additional_attributes: additional_attributes })) ContactAvatarJob.perform_later(@contact, params[:avatar_url]) if params[:avatar_url].present? end @@ -68,4 +67,16 @@ class ContactIdentifyAction mergee_contact: merge_contact ).perform end + + def custom_attributes + params[:custom_attributes] ? @contact.custom_attributes.deep_merge(params[:custom_attributes].stringify_keys) : @contact.custom_attributes + end + + def additional_attributes + if params[:additional_attributes] + @contact.additional_attributes.deep_merge(params[:additional_attributes].stringify_keys) + else + @contact.additional_attributes + end + end end diff --git a/app/controllers/api/v1/widget/contacts_controller.rb b/app/controllers/api/v1/widget/contacts_controller.rb index d745c4153..fbc303a4f 100644 --- a/app/controllers/api/v1/widget/contacts_controller.rb +++ b/app/controllers/api/v1/widget/contacts_controller.rb @@ -46,6 +46,7 @@ class Api::V1::Widget::ContactsController < Api::V1::Widget::BaseController end def permitted_params - params.permit(:website_token, :identifier, :identifier_hash, :email, :name, :avatar_url, :phone_number, custom_attributes: {}) + params.permit(:website_token, :identifier, :identifier_hash, :email, :name, :avatar_url, :phone_number, custom_attributes: {}, + additional_attributes: {}) end end diff --git a/app/javascript/widget/store/modules/contacts.js b/app/javascript/widget/store/modules/contacts.js index 79fb36de6..ef146ce72 100644 --- a/app/javascript/widget/store/modules/contacts.js +++ b/app/javascript/widget/store/modules/contacts.js @@ -24,17 +24,38 @@ export const actions = { }, update: async ({ dispatch }, { identifier, user: userObject }) => { try { + const { + email, + name, + avatar_url, + identifier_hash, + phone_number, + company_name, + city, + country_code, + description, + custom_attributes, + social_profiles, + } = userObject; const user = { - email: userObject.email, - name: userObject.name, - avatar_url: userObject.avatar_url, - identifier_hash: userObject.identifier_hash, - phone_number: userObject.phone_number, + email, + name, + avatar_url, + identifier_hash, + phone_number, + additional_attributes: { + company_name, + city, + description, + country_code, + social_profiles, + }, + custom_attributes, }; await ContactsAPI.update(identifier, user); dispatch('get'); - if (userObject.identifier_hash) { + if (identifier_hash) { dispatch('conversation/clearConversations', {}, { root: true }); dispatch('conversation/fetchOldConversations', {}, { root: true }); } diff --git a/spec/actions/contact_identify_action_spec.rb b/spec/actions/contact_identify_action_spec.rb index 71c1b274a..ad109a0ea 100644 --- a/spec/actions/contact_identify_action_spec.rb +++ b/spec/actions/contact_identify_action_spec.rb @@ -6,7 +6,10 @@ describe ::ContactIdentifyAction do let!(:account) { create(:account) } let(:custom_attributes) { { test: 'test', test1: 'test1' } } let!(:contact) { create(:contact, account: account, custom_attributes: custom_attributes) } - let(:params) { { name: 'test', identifier: 'test_id', custom_attributes: { test: 'new test', test2: 'test2' } } } + let(:params) do + { name: 'test', identifier: 'test_id', additional_attributes: { location: 'Bengaulru', company_name: 'Meta' }, + custom_attributes: { test: 'new test', test2: 'test2' } } + end describe '#perform' do it 'updates the contact' do @@ -15,9 +18,18 @@ describe ::ContactIdentifyAction do expect(contact.reload.name).to eq 'test' # custom attributes are merged properly without overwriting existing ones expect(contact.custom_attributes).to eq({ 'test' => 'new test', 'test1' => 'test1', 'test2' => 'test2' }) + expect(contact.additional_attributes).to eq({ 'company_name' => 'Meta', 'location' => 'Bengaulru' }) expect(contact.reload.identifier).to eq 'test_id' end + it 'merge deeply nested additional attributes' do + create(:contact, account: account, identifier: '', email: 'test@test.com', + additional_attributes: { location: 'Bengaulru', company_name: 'Meta', social_profiles: { linkedin: 'saras' } }) + params = { email: 'test@test.com', additional_attributes: { social_profiles: { twitter: 'saras' } } } + result = described_class.new(contact: contact, params: params).perform + expect(result.additional_attributes['social_profiles']).to eq({ 'linkedin' => 'saras', 'twitter' => 'saras' }) + end + it 'enques avatar job when avatar url parameter is passed' do params = { name: 'test', avatar_url: 'https://chatwoot-assets.local/sample.png' } expect(ContactAvatarJob).to receive(:perform_later).with(contact, params[:avatar_url]).once