diff --git a/app/javascript/dashboard/routes/dashboard/contacts/components/ContactLabels.vue b/app/javascript/dashboard/routes/dashboard/contacts/components/ContactLabels.vue index 8ac65b462..04c79561f 100644 --- a/app/javascript/dashboard/routes/dashboard/contacts/components/ContactLabels.vue +++ b/app/javascript/dashboard/routes/dashboard/contacts/components/ContactLabels.vue @@ -24,12 +24,12 @@ export default { computed: { savedLabels() { - const result = this.$store.getters['contactLabels/getContactLabels']( - this.contactId + const availableContactLabels = this.$store.getters[ + 'contactLabels/getContactLabels' + ](this.contactId); + return this.allLabels.filter(({ title }) => + availableContactLabels.includes(title) ); - return result.map(value => { - return this.allLabels.find(label => label.title === value); - }); }, ...mapGetters({ diff --git a/app/jobs/labels/update_job.rb b/app/jobs/labels/update_job.rb new file mode 100644 index 000000000..8834c97cc --- /dev/null +++ b/app/jobs/labels/update_job.rb @@ -0,0 +1,11 @@ +class Labels::UpdateJob < ApplicationJob + queue_as :default + + def perform(new_label_title, old_label_title, account_id) + Labels::UpdateService.new( + new_label_title: new_label_title, + old_label_title: old_label_title, + account_id: account_id + ).perform + end +end diff --git a/app/models/label.rb b/app/models/label.rb index b53260f58..9b551141d 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -25,6 +25,8 @@ class Label < ApplicationRecord format: { with: UNICODE_CHARACTER_NUMBER_HYPHEN_UNDERSCORE }, uniqueness: { scope: :account_id } + after_update_commit :update_associated_models + before_validation do self.title = title.downcase if attribute_present?('title') end @@ -40,4 +42,12 @@ class Label < ApplicationRecord def events account.events.where(conversation_id: conversations.pluck(:id)) end + + private + + def update_associated_models + return unless title_previously_changed? + + Labels::UpdateJob.perform_later(title, title_previously_was, account_id) + end end diff --git a/app/services/labels/update_service.rb b/app/services/labels/update_service.rb new file mode 100644 index 000000000..300331b09 --- /dev/null +++ b/app/services/labels/update_service.rb @@ -0,0 +1,35 @@ +class Labels::UpdateService + pattr_initialize [:new_label_title!, :old_label_title!, :account_id!] + + def perform + tagged_conversations.find_in_batches do |conversation_batch| + conversation_batch.each do |conversation| + conversation.label_list.remove(old_label_title) + conversation.label_list.add(new_label_title) + conversation.save! + end + end + + tagged_contacts.find_in_batches do |contact_batch| + contact_batch.each do |contact| + contact.label_list.remove(old_label_title) + contact.label_list.add(new_label_title) + contact.save! + end + end + end + + private + + def tagged_conversations + account.conversations.tagged_with(old_label_title) + end + + def tagged_contacts + account.contacts.tagged_with(old_label_title) + end + + def account + @account ||= Account.find(account_id) + end +end diff --git a/spec/jobs/labels/update_job_spec.rb b/spec/jobs/labels/update_job_spec.rb new file mode 100644 index 000000000..16692b2c3 --- /dev/null +++ b/spec/jobs/labels/update_job_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +RSpec.describe Labels::UpdateJob, type: :job do + subject(:job) { described_class.perform_later(new_label_title, old_label_title, account_id) } + + let(:new_label_title) { 'new-title' } + let(:old_label_title) { 'old-title' } + let(:account_id) { 1 } + + it 'queues the job' do + expect { job }.to have_enqueued_job(described_class) + .with(new_label_title, old_label_title, account_id) + .on_queue('default') + end +end diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb index 215e9d5a6..bd8b6ad19 100644 --- a/spec/models/label_spec.rb +++ b/spec/models/label_spec.rb @@ -39,4 +39,20 @@ RSpec.describe Label, type: :model do expect(duplicate_label.valid?).to eq false end end + + describe '.after_update_commit' do + let(:label) { create(:label) } + + it 'calls update job' do + expect(Labels::UpdateJob).to receive(:perform_later).with('new-title', label.title, label.account_id) + + label.update(title: 'new-title') + end + + it 'does not call update job if title is not updated' do + expect(Labels::UpdateJob).not_to receive(:perform_later) + + label.update(description: 'new-description') + end + end end diff --git a/spec/services/labels/update_service_spec.rb b/spec/services/labels/update_service_spec.rb new file mode 100644 index 000000000..a71ec3271 --- /dev/null +++ b/spec/services/labels/update_service_spec.rb @@ -0,0 +1,32 @@ +require 'rails_helper' + +describe Labels::UpdateService do + let(:account) { create(:account) } + let(:conversation) { create(:conversation, account: account) } + let(:label) { create(:label, account: account) } + let(:contact) { conversation.contact } + + before do + conversation.label_list.add(label.title) + conversation.save! + + contact.label_list.add(label.title) + contact.save! + end + + describe '#perform' do + it 'updates associated conversations/contacts labels' do + expect(conversation.label_list).to eq([label.title]) + expect(contact.label_list).to eq([label.title]) + + described_class.new( + new_label_title: 'updated-label-title', + old_label_title: label.title, + account_id: account.id + ).perform + + expect(conversation.reload.label_list).to eq(['updated-label-title']) + expect(contact.reload.label_list).to eq(['updated-label-title']) + end + end +end