feat: Add filter APIs for Contacts and Conversations (#3264)
This commit is contained in:
@@ -51,7 +51,10 @@ class Api::V1::Accounts::ContactsController < Api::V1::Accounts::BaseController
|
||||
def show; end
|
||||
|
||||
def filter
|
||||
@contacts = Current.account.contacts.limit(10)
|
||||
result = ::Contacts::FilterService.new(params.permit!, current_user).perform
|
||||
contacts = result[:contacts]
|
||||
@contacts_count = result[:count]
|
||||
@contacts = fetch_contacts_with_conversation_count(contacts)
|
||||
end
|
||||
|
||||
def contactable_inboxes
|
||||
|
||||
@@ -32,7 +32,9 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro
|
||||
def show; end
|
||||
|
||||
def filter
|
||||
@conversations = Current.account.conversations.limit(10)
|
||||
result = ::Conversations::FilterService.new(params.permit!, current_user).perform
|
||||
@conversations = result[:conversations]
|
||||
@conversations_count = result[:count]
|
||||
end
|
||||
|
||||
def mute
|
||||
|
||||
44
app/services/contacts/filter_service.rb
Normal file
44
app/services/contacts/filter_service.rb
Normal file
@@ -0,0 +1,44 @@
|
||||
class Contacts::FilterService < FilterService
|
||||
def perform
|
||||
@contacts = contact_query_builder
|
||||
|
||||
{
|
||||
contacts: @contacts,
|
||||
count: {
|
||||
all_count: @contacts.count
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def contact_query_builder
|
||||
contact_filters = @filters['contacts']
|
||||
|
||||
@params[:payload].each_with_index do |query_hash, current_index|
|
||||
current_filter = contact_filters[query_hash['attribute_key']]
|
||||
@query_string += contact_query_string(current_filter, query_hash, current_index)
|
||||
end
|
||||
|
||||
base_relation.where(@query_string, @filter_values.with_indifferent_access)
|
||||
end
|
||||
|
||||
def contact_query_string(current_filter, query_hash, current_index)
|
||||
attribute_key = query_hash[:attribute_key]
|
||||
query_operator = query_hash[:query_operator]
|
||||
filter_operator_value = filter_operation(query_hash, current_index)
|
||||
|
||||
case current_filter['attribute_type']
|
||||
when 'additional_attributes'
|
||||
" contacts.additional_attributes ->> '#{attribute_key}' #{filter_operator_value} #{query_operator} "
|
||||
when 'standard'
|
||||
if attribute_key == 'labels'
|
||||
" tags.id #{filter_operator_value} #{query_operator} "
|
||||
else
|
||||
" contacts.#{attribute_key} #{filter_operator_value} #{query_operator} "
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def base_relation
|
||||
Current.account.contacts.left_outer_joins(:labels)
|
||||
end
|
||||
end
|
||||
59
app/services/conversations/filter_service.rb
Normal file
59
app/services/conversations/filter_service.rb
Normal file
@@ -0,0 +1,59 @@
|
||||
class Conversations::FilterService < FilterService
|
||||
def perform
|
||||
@conversations = conversation_query_builder
|
||||
mine_count, unassigned_count, all_count, = set_count_for_all_conversations
|
||||
assigned_count = all_count - unassigned_count
|
||||
|
||||
{
|
||||
conversations: conversations,
|
||||
count: {
|
||||
mine_count: mine_count,
|
||||
assigned_count: assigned_count,
|
||||
unassigned_count: unassigned_count,
|
||||
all_count: all_count
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def conversation_query_builder
|
||||
conversation_filters = @filters['conversations']
|
||||
@params[:payload].each_with_index do |query_hash, current_index|
|
||||
current_filter = conversation_filters[query_hash['attribute_key']]
|
||||
@query_string += conversation_query_string(current_filter, query_hash, current_index)
|
||||
end
|
||||
|
||||
base_relation.where(@query_string, @filter_values.with_indifferent_access)
|
||||
end
|
||||
|
||||
def conversation_query_string(current_filter, query_hash, current_index)
|
||||
attribute_key = query_hash[:attribute_key]
|
||||
query_operator = query_hash[:query_operator]
|
||||
filter_operator_value = filter_operation(query_hash, current_index)
|
||||
|
||||
case current_filter['attribute_type']
|
||||
when 'additional_attributes'
|
||||
" conversations.additional_attributes ->> '#{attribute_key}' #{filter_operator_value} #{query_operator} "
|
||||
when 'standard'
|
||||
if attribute_key == 'labels'
|
||||
" tags.id #{filter_operator_value} #{query_operator} "
|
||||
else
|
||||
" conversations.#{attribute_key} #{filter_operator_value} #{query_operator} "
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def base_relation
|
||||
Current.account.conversations.left_outer_joins(:labels)
|
||||
end
|
||||
|
||||
def current_page
|
||||
@params[:page] || 1
|
||||
end
|
||||
|
||||
def conversations
|
||||
@conversations = @conversations.includes(
|
||||
:taggings, :inbox, { assignee: { avatar_attachment: [:blob] } }, { contact: { avatar_attachment: [:blob] } }, :team
|
||||
)
|
||||
@conversations.latest.page(current_page)
|
||||
end
|
||||
end
|
||||
50
app/services/filter_service.rb
Normal file
50
app/services/filter_service.rb
Normal file
@@ -0,0 +1,50 @@
|
||||
require 'json'
|
||||
|
||||
class FilterService
|
||||
def initialize(params, user)
|
||||
@params = params
|
||||
@user = user
|
||||
file = File.read('./lib/filters/filter_keys.json')
|
||||
@filters = JSON.parse(file)
|
||||
@query_string = ''
|
||||
@filter_values = {}
|
||||
end
|
||||
|
||||
def perform; end
|
||||
|
||||
def filter_operation(query_hash, current_index)
|
||||
case query_hash[:filter_operator]
|
||||
when 'equal_to'
|
||||
@filter_values["value_#{current_index}"] = filter_values(query_hash)
|
||||
"IN (:value_#{current_index})"
|
||||
when 'not_equal_to'
|
||||
@filter_values["value_#{current_index}"] = filter_values(query_hash)
|
||||
"NOT IN (:value_#{current_index})"
|
||||
when 'contains'
|
||||
@filter_values["value_#{current_index}"] = "%#{filter_values(query_hash)}%"
|
||||
"LIKE :value_#{current_index}"
|
||||
when 'does_not_contain'
|
||||
@filter_values["value_#{current_index}"] = "%#{filter_values(query_hash)}%"
|
||||
"NOT LIKE :value_#{current_index}"
|
||||
else
|
||||
@filter_values["value_#{current_index}"] = filter_values(query_hash).to_s
|
||||
"= :value_#{current_index}"
|
||||
end
|
||||
end
|
||||
|
||||
def filter_values(query_hash)
|
||||
if query_hash['attribute_key'] == 'status'
|
||||
query_hash['values'].map { |x| Conversation.statuses[x.to_sym] }
|
||||
else
|
||||
query_hash['values']
|
||||
end
|
||||
end
|
||||
|
||||
def set_count_for_all_conversations
|
||||
[
|
||||
@conversations.assigned_to(@user).count,
|
||||
@conversations.unassigned.count,
|
||||
@conversations.count
|
||||
]
|
||||
end
|
||||
end
|
||||
@@ -1,3 +1,10 @@
|
||||
json.array! @conversations do |conversation|
|
||||
json.partial! 'api/v1/models/conversation.json.jbuilder', conversation: conversation
|
||||
json.meta do
|
||||
json.mine_count @conversations_count[:mine_count]
|
||||
json.unassigned_count @conversations_count[:unassigned_count]
|
||||
json.all_count @conversations_count[:all_count]
|
||||
end
|
||||
json.payload do
|
||||
json.array! @conversations do |conversation|
|
||||
json.partial! 'api/v1/conversations/partials/conversation.json.jbuilder', conversation: conversation
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user