diff --git a/app/controllers/api/v1/accounts/contacts/labels_controller.rb b/app/controllers/api/v1/accounts/contacts/labels_controller.rb new file mode 100644 index 000000000..41640978f --- /dev/null +++ b/app/controllers/api/v1/accounts/contacts/labels_controller.rb @@ -0,0 +1,13 @@ +class Api::V1::Accounts::Contacts::LabelsController < Api::V1::Accounts::BaseController + include LabelConcern + + private + + def model + @model ||= Current.account.contacts.find(params[:contact_id]) + end + + def permitted_params + params.permit(:contact_id, :labels) + end +end diff --git a/app/controllers/api/v1/accounts/conversations/labels_controller.rb b/app/controllers/api/v1/accounts/conversations/labels_controller.rb index 306544200..b84d030d8 100644 --- a/app/controllers/api/v1/accounts/conversations/labels_controller.rb +++ b/app/controllers/api/v1/accounts/conversations/labels_controller.rb @@ -1,11 +1,13 @@ class Api::V1::Accounts::Conversations::LabelsController < Api::V1::Accounts::Conversations::BaseController - def create - @conversation.update_labels(params[:labels]) - @labels = @conversation.label_list + include LabelConcern + + private + + def model + @model ||= @conversation end - # all labels of the current conversation - def index - @labels = @conversation.label_list + def permitted_params + params.permit(:conversation_id, :labels) end end diff --git a/app/controllers/concerns/label_concern.rb b/app/controllers/concerns/label_concern.rb new file mode 100644 index 000000000..194f063be --- /dev/null +++ b/app/controllers/concerns/label_concern.rb @@ -0,0 +1,10 @@ +module LabelConcern + def create + model.update_labels(permitted_params[:labels]) + @labels = model.label_list + end + + def index + @labels = model.label_list + end +end diff --git a/app/models/concerns/labelable.rb b/app/models/concerns/labelable.rb new file mode 100644 index 000000000..4e654fdd4 --- /dev/null +++ b/app/models/concerns/labelable.rb @@ -0,0 +1,11 @@ +module Labelable + extend ActiveSupport::Concern + + included do + acts_as_taggable_on :labels + end + + def update_labels(labels = nil) + update!(label_list: labels) + end +end diff --git a/app/models/contact.rb b/app/models/contact.rb index 82ece1176..f62ffc1f8 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -26,6 +26,7 @@ class Contact < ApplicationRecord include Pubsubable include Avatarable include AvailabilityStatusable + include Labelable validates :account_id, presence: true validates :email, allow_blank: true, uniqueness: { scope: [:account_id], case_sensitive: false } diff --git a/app/models/conversation.rb b/app/models/conversation.rb index 3a90d1f82..f6ba5c3cc 100644 --- a/app/models/conversation.rb +++ b/app/models/conversation.rb @@ -32,6 +32,8 @@ # class Conversation < ApplicationRecord + include Labelable + validates :account_id, presence: true validates :inbox_id, presence: true @@ -57,8 +59,6 @@ class Conversation < ApplicationRecord after_create_commit :notify_conversation_creation, :queue_conversation_auto_resolution_job after_save :run_round_robin - acts_as_taggable_on :labels - delegate :auto_resolve_duration, to: :account def can_reply? @@ -75,10 +75,6 @@ class Conversation < ApplicationRecord update!(assignee: agent) end - def update_labels(labels = nil) - update!(label_list: labels) - end - def toggle_status # FIXME: implement state machine with aasm self.status = open? ? :resolved : :open diff --git a/app/views/api/v1/accounts/contacts/labels/create.json.jbuilder b/app/views/api/v1/accounts/contacts/labels/create.json.jbuilder new file mode 100644 index 000000000..b47f0870f --- /dev/null +++ b/app/views/api/v1/accounts/contacts/labels/create.json.jbuilder @@ -0,0 +1 @@ +json.payload @labels diff --git a/app/views/api/v1/accounts/contacts/labels/index.json.jbuilder b/app/views/api/v1/accounts/contacts/labels/index.json.jbuilder new file mode 100644 index 000000000..b47f0870f --- /dev/null +++ b/app/views/api/v1/accounts/contacts/labels/index.json.jbuilder @@ -0,0 +1 @@ +json.payload @labels diff --git a/config/routes.rb b/config/routes.rb index dcec9aa4b..1b461fa95 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -71,6 +71,7 @@ Rails.application.routes.draw do scope module: :contacts do resources :conversations, only: [:index] resources :contact_inboxes, only: [:create] + resources :labels, only: [:create, :index] end end diff --git a/spec/controllers/api/v1/accounts/contacts/labels_controller_spec.rb b/spec/controllers/api/v1/accounts/contacts/labels_controller_spec.rb new file mode 100644 index 000000000..55303c79b --- /dev/null +++ b/spec/controllers/api/v1/accounts/contacts/labels_controller_spec.rb @@ -0,0 +1,67 @@ +require 'rails_helper' + +RSpec.describe 'Contact Label API', type: :request do + let(:account) { create(:account) } + + describe 'GET /api/v1/accounts/{account.id}/contacts//labels' do + let(:contact) { create(:contact, account: account) } + + before do + contact.update_labels('label1, label2') + end + + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + get api_v1_account_contact_labels_url(account_id: account.id, contact_id: contact.id) + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + let(:agent) { create(:user, account: account, role: :agent) } + + it 'returns all the labels for the contact' do + get api_v1_account_contact_labels_url(account_id: account.id, contact_id: contact.id), + headers: agent.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + expect(response.body).to include('label1') + expect(response.body).to include('label2') + end + end + end + + describe 'POST /api/v1/accounts/{account.id}/contacts//labels' do + let(:contact) { create(:contact, account: account) } + + before do + contact.update_labels('label1, label2') + end + + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + post api_v1_account_contact_labels_url(account_id: account.id, contact_id: contact.id), + params: { labels: 'label3,label4' }, + as: :json + + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + let(:agent) { create(:user, account: account, role: :agent) } + + it 'creates labels for the contact' do + post api_v1_account_contact_labels_url(account_id: account.id, contact_id: contact.id), + params: { labels: 'label3,label4' }, + headers: agent.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + expect(response.body).to include('label3') + expect(response.body).to include('label4') + end + end + end +end