mirror of
https://github.com/lingble/chatwoot.git
synced 2025-10-29 18:22:53 +00:00
feat: Conversation and contact endpoint (#3198)
This commit is contained in:
@@ -50,6 +50,10 @@ class Api::V1::Accounts::ContactsController < Api::V1::Accounts::BaseController
|
||||
|
||||
def show; end
|
||||
|
||||
def filter
|
||||
@contacts = Current.account.contacts.limit(10)
|
||||
end
|
||||
|
||||
def contactable_inboxes
|
||||
@all_contactable_inboxes = Contacts::ContactableInboxesService.new(contact: @contact).get
|
||||
@contactable_inboxes = @all_contactable_inboxes.select { |contactable_inbox| policy(contactable_inbox[:inbox]).show? }
|
||||
|
||||
@@ -2,7 +2,7 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro
|
||||
include Events::Types
|
||||
include DateRangeHelper
|
||||
|
||||
before_action :conversation, except: [:index, :meta, :search, :create]
|
||||
before_action :conversation, except: [:index, :meta, :search, :create, :filter]
|
||||
before_action :contact_inbox, only: [:create]
|
||||
|
||||
def index
|
||||
@@ -31,6 +31,10 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro
|
||||
|
||||
def show; end
|
||||
|
||||
def filter
|
||||
@conversations = Current.account.conversations.limit(10)
|
||||
end
|
||||
|
||||
def mute
|
||||
@conversation.mute!
|
||||
head :ok
|
||||
|
||||
@@ -15,6 +15,10 @@ class ContactPolicy < ApplicationPolicy
|
||||
true
|
||||
end
|
||||
|
||||
def filter?
|
||||
true
|
||||
end
|
||||
|
||||
def update?
|
||||
true
|
||||
end
|
||||
|
||||
3
app/views/api/v1/accounts/contacts/filter.json.jbuilder
Normal file
3
app/views/api/v1/accounts/contacts/filter.json.jbuilder
Normal file
@@ -0,0 +1,3 @@
|
||||
json.array! @contacts do |contact|
|
||||
json.partial! 'api/v1/models/contact.json.jbuilder', resource: contact
|
||||
end
|
||||
@@ -0,0 +1,3 @@
|
||||
json.array! @conversations do |conversation|
|
||||
json.partial! 'api/v1/models/conversation.json.jbuilder', conversation: conversation
|
||||
end
|
||||
@@ -5,26 +5,6 @@ json.meta do
|
||||
end
|
||||
json.payload do
|
||||
json.array! @conversations do |conversation|
|
||||
json.id conversation.display_id
|
||||
json.created_at conversation.created_at.to_i
|
||||
json.contact do
|
||||
json.id conversation.contact.id
|
||||
json.name conversation.contact.name
|
||||
end
|
||||
json.inbox do
|
||||
json.id conversation.inbox.id
|
||||
json.name conversation.inbox.name
|
||||
json.channel_type conversation.inbox.channel_type
|
||||
end
|
||||
json.messages do
|
||||
json.array! conversation.messages do |message|
|
||||
json.content message.content
|
||||
json.id message.id
|
||||
json.sender_name message.sender.name if message.sender
|
||||
json.message_type message.message_type_before_type_cast
|
||||
json.created_at message.created_at.to_i
|
||||
end
|
||||
end
|
||||
json.account_id conversation.account_id
|
||||
json.partial! 'api/v1/models/conversation.json.jbuilder', conversation: conversation
|
||||
end
|
||||
end
|
||||
|
||||
21
app/views/api/v1/models/_conversation.json.jbuilder
Normal file
21
app/views/api/v1/models/_conversation.json.jbuilder
Normal file
@@ -0,0 +1,21 @@
|
||||
json.id conversation.display_id
|
||||
json.created_at conversation.created_at.to_i
|
||||
json.contact do
|
||||
json.id conversation.contact.id
|
||||
json.name conversation.contact.name
|
||||
end
|
||||
json.inbox do
|
||||
json.id conversation.inbox.id
|
||||
json.name conversation.inbox.name
|
||||
json.channel_type conversation.inbox.channel_type
|
||||
end
|
||||
json.messages do
|
||||
json.array! conversation.messages do |message|
|
||||
json.content message.content
|
||||
json.id message.id
|
||||
json.sender_name message.sender.name if message.sender
|
||||
json.message_type message.message_type_before_type_cast
|
||||
json.created_at message.created_at.to_i
|
||||
end
|
||||
end
|
||||
json.account_id conversation.account_id
|
||||
@@ -58,8 +58,11 @@ Rails.application.routes.draw do
|
||||
resource :twilio_channel, only: [:create]
|
||||
end
|
||||
resources :conversations, only: [:index, :create, :show] do
|
||||
get 'meta', on: :collection
|
||||
get 'search', on: :collection
|
||||
collection do
|
||||
get :meta
|
||||
get :search
|
||||
get :filter
|
||||
end
|
||||
scope module: :conversations do
|
||||
resources :messages, only: [:index, :create, :destroy]
|
||||
resources :assignments, only: [:create]
|
||||
@@ -80,6 +83,7 @@ Rails.application.routes.draw do
|
||||
collection do
|
||||
get :active
|
||||
get :search
|
||||
get :filter
|
||||
post :import
|
||||
end
|
||||
member do
|
||||
|
||||
92
lib/filters/conversation_filters.json
Normal file
92
lib/filters/conversation_filters.json
Normal file
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"conversations": [
|
||||
{
|
||||
"attribute_key": "status",
|
||||
"attribute_name": "Status",
|
||||
"input_type": "multi_select",
|
||||
"data_type": "text",
|
||||
"filter_operators": [ "equal_to", "not_equal_to" ],
|
||||
"attribute_type": "standard"
|
||||
},
|
||||
{
|
||||
"attribute_key": "assigne",
|
||||
"attribute_name": "Assignee Name",
|
||||
"input_type": "search_box with name tags/plain text",
|
||||
"data_type": "text",
|
||||
"filter_operators": [ "equal_to", "not_equal_to", "contains", "does_not_contain", "is_present", "is_not_present" ],
|
||||
"attribute_type": "standard"
|
||||
},
|
||||
{
|
||||
"attribute_key": "contact",
|
||||
"attribute_name": "Contact Name",
|
||||
"input_type": "plain_text",
|
||||
"data_type": "text",
|
||||
"filter_operators": [ "equal_to", "not_equal_to", "contains", "does_not_contain", "is_present", "is_not_present" ],
|
||||
"attribute_type": "standard"
|
||||
},
|
||||
{
|
||||
"attribute_key": "inbox",
|
||||
"attribute_name": "Inbox Name",
|
||||
"input_type": "search_box",
|
||||
"data_type": "text",
|
||||
"filter_operators": [ "equal_to", "not_equal_to", "contains", "does_not_contain", "is_present", "is_not_present" ],
|
||||
"attribute_type": "standard"
|
||||
},
|
||||
{
|
||||
"attribute_key": "team_id",
|
||||
"attribute_name": "Team Name",
|
||||
"input_type": "search_box",
|
||||
"data_type": "number",
|
||||
"filter_operators": [ "equal_to", "not_equal_to", "contains", "does_not_contain", "is_present", "is_not_present" ],
|
||||
"attribute_type": "standard"
|
||||
},
|
||||
{
|
||||
"attribute_key": "id",
|
||||
"attribute_name": "Conversation Identifier",
|
||||
"input_type": "textbox",
|
||||
"data_type": "Number",
|
||||
"filter_operators": [ "equal_to", "not_equal_to", "contains", "does_not_contain", "is_present", "is_not_present" ],
|
||||
"attribute_type": "standard"
|
||||
},
|
||||
{
|
||||
"attribute_key": "campaign_id",
|
||||
"attribute_name": "Campaign Name",
|
||||
"input_type": "textbox",
|
||||
"data_type": "Number",
|
||||
"filter_operators": [ "equal_to", "not_equal_to", "contains", "does_not_contain", "is_present", "is_not_present" ],
|
||||
"attribute_type": "standard"
|
||||
},
|
||||
{
|
||||
"attribute_key": "labels",
|
||||
"attribute_name": "Labels",
|
||||
"input_type": "tags",
|
||||
"data_type": "text",
|
||||
"filter_operators": ["exactly_equal_to", "contains", "does_not_contain" ],
|
||||
"attribute_type": "standard"
|
||||
},
|
||||
{
|
||||
"attribute_key": "browser",
|
||||
"attribute_name": "browser",
|
||||
"input_type": "textbox",
|
||||
"data_type": "text",
|
||||
"filter_operators": [ "equal_to", "not_equal_to", "contains", "does_not_contain" ],
|
||||
"attribute_type": "additional_attributes"
|
||||
},
|
||||
{
|
||||
"attribute_key": "country_code",
|
||||
"attribute_name": "Country Name",
|
||||
"input_type": "textbox",
|
||||
"data_type": "text",
|
||||
"filter_operators": [ "equal_to", "not_equal_to", "contains", "does_not_contain", "present", "is_not_present" ],
|
||||
"attribute_type": "additional_attributes"
|
||||
},
|
||||
{
|
||||
"attribute_key": "referer",
|
||||
"attribute_name": "Referer link",
|
||||
"input_type": "textbox",
|
||||
"data_type": "link",
|
||||
"filter_operators": [ "equal_to", "not_equal_to", "contains", "does_not_contain", "present", "is_not_present" ],
|
||||
"attribute_type": "additional_attributes"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -218,6 +218,33 @@ RSpec.describe 'Contacts API', type: :request do
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/contacts/filter' do
|
||||
context 'when it is an unauthenticated user' do
|
||||
it 'returns unauthorized' do
|
||||
get "/api/v1/accounts/#{account.id}/contacts/filter"
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
let(:admin) { create(:user, account: account, role: :administrator) }
|
||||
let!(:contact1) { create(:contact, :with_email, account: account) }
|
||||
let!(:contact2) { create(:contact, :with_email, name: 'testcontact', account: account, email: 'test@test.com') }
|
||||
|
||||
it 'returns all contacts when query is empty' do
|
||||
get "/api/v1/accounts/#{account.id}/contacts/filter",
|
||||
params: { q: [] },
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.body).to include(contact2.email)
|
||||
expect(response.body).to include(contact1.email)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/contacts/:id' do
|
||||
let!(:contact) { create(:contact, account: account) }
|
||||
|
||||
|
||||
@@ -109,6 +109,40 @@ RSpec.describe 'Conversations API', type: :request do
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/conversations/filter' do
|
||||
context 'when it is an unauthenticated user' do
|
||||
it 'returns unauthorized' do
|
||||
get "/api/v1/accounts/#{account.id}/conversations/filter", params: { q: 'test' }
|
||||
|
||||
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) }
|
||||
|
||||
before do
|
||||
conversation = create(:conversation, account: account)
|
||||
create(:message, conversation: conversation, account: account, content: 'test1')
|
||||
create(:message, conversation: conversation, account: account, content: 'test2')
|
||||
create(:inbox_member, user: agent, inbox: conversation.inbox)
|
||||
end
|
||||
|
||||
it 'returns all conversations with empty query' do
|
||||
get "/api/v1/accounts/#{account.id}/conversations/filter",
|
||||
headers: agent.create_new_auth_token,
|
||||
params: { q: 'test1' },
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
response_data = JSON.parse(response.body, symbolize_names: true)
|
||||
|
||||
expect(response_data.count).to eq(1)
|
||||
expect(response_data[0][:messages][0][:content]).to include(Message.first.content)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/conversations/:id' do
|
||||
let(:conversation) { create(:conversation, account: account) }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user