diff --git a/Gemfile b/Gemfile
index 680a0738b..7533cf3cf 100644
--- a/Gemfile
+++ b/Gemfile
@@ -76,7 +76,7 @@ gem 'faraday_middleware-aws-sigv4'
##--- gems for server & infra configuration ---##
gem 'dotenv-rails', '>= 3.0.0'
gem 'foreman'
-gem 'puma'
+gem 'puma', '~> 7.2', '>= 7.2.1'
gem 'vite_rails'
# metrics on heroku
gem 'barnes'
diff --git a/Gemfile.lock b/Gemfile.lock
index 7151d0ff1..141afc122 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -136,6 +136,8 @@ GEM
audited (5.4.1)
activerecord (>= 5.0, < 7.7)
activesupport (>= 5.0, < 7.7)
+ auth-sanitizer (0.2.1)
+ version_gem (~> 1.1, >= 1.1.10)
aws-actionmailbox-ses (0.1.0)
actionmailbox (>= 7.1.0)
aws-sdk-s3 (~> 1, >= 1.123.0)
@@ -168,7 +170,7 @@ GEM
base64 (0.3.0)
bcrypt (3.1.22)
benchmark (0.4.1)
- bigdecimal (3.2.2)
+ bigdecimal (3.3.1)
bindex (0.8.1)
bootsnap (1.16.0)
msgpack (~> 1.2)
@@ -184,6 +186,7 @@ GEM
bundler (>= 1.2.0, < 3)
thor (~> 1.0)
byebug (11.1.3)
+ cgi (0.5.1)
childprocess (5.1.0)
logger (~> 1.5)
cld3 (3.7.0)
@@ -312,7 +315,7 @@ GEM
hashie
faraday-multipart (1.2.0)
multipart-post (~> 2.0)
- faraday-net_http (3.4.2)
+ faraday-net_http (3.4.4)
net-http (~> 0.5)
faraday-net_http_persistent (2.1.0)
faraday (~> 2.5)
@@ -435,7 +438,8 @@ GEM
hana (1.3.7)
hash_diff (1.1.1)
hashdiff (1.1.0)
- hashie (5.0.0)
+ hashie (5.1.0)
+ logger
html2text (0.4.0)
nokogiri (>= 1.0, < 2.0)
http (5.1.1)
@@ -470,7 +474,7 @@ GEM
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
- json (2.19.5)
+ json (2.19.8)
json_refs (0.1.8)
hana
json_schemer (0.2.24)
@@ -568,7 +572,7 @@ GEM
ruby2_keywords
msgpack (1.8.0)
multi_json (1.15.0)
- multi_xml (0.8.0)
+ multi_xml (0.9.1)
bigdecimal (>= 3.1, < 5)
multipart-post (2.4.1)
mutex_m (0.3.0)
@@ -593,7 +597,7 @@ GEM
sidekiq
newrelic_rpm (9.6.0)
base64
- nio4r (2.7.3)
+ nio4r (2.7.5)
nokogiri (1.19.3)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
@@ -603,19 +607,26 @@ GEM
racc (~> 1.4)
nokogiri (1.19.3-x86_64-linux-gnu)
racc (~> 1.4)
- oauth (1.1.0)
- oauth-tty (~> 1.0, >= 1.0.1)
- snaky_hash (~> 2.0)
- version_gem (~> 1.1)
- oauth-tty (1.0.5)
- version_gem (~> 1.1, >= 1.1.1)
- oauth2 (2.0.9)
- faraday (>= 0.17.3, < 3.0)
- jwt (>= 1.0, < 3.0)
+ oauth (1.1.6)
+ auth-sanitizer (~> 0.2, >= 0.2.1)
+ base64 (~> 0.1)
+ cgi
+ oauth-tty (~> 1.0, >= 1.0.8)
+ snaky_hash (~> 2.0, >= 2.0.5)
+ version_gem (~> 1.1, >= 1.1.11)
+ oauth-tty (1.0.8)
+ auth-sanitizer (~> 0.1, >= 0.1.3)
+ cgi
+ version_gem (~> 1.1, >= 1.1.9)
+ oauth2 (2.0.22)
+ auth-sanitizer (~> 0.2, >= 0.2.1)
+ faraday (>= 0.17.3, < 4.0)
+ jwt (>= 1.0, < 4.0)
+ logger (~> 1.2)
multi_xml (~> 0.5)
rack (>= 1.2, < 4)
- snaky_hash (~> 2.0)
- version_gem (~> 1.1)
+ snaky_hash (~> 2.0, >= 2.0.5)
+ version_gem (~> 1.1, >= 1.1.11)
oj (3.16.10)
bigdecimal (>= 3.0)
ostruct (>= 0.2)
@@ -682,7 +693,7 @@ GEM
pry-rails (0.3.9)
pry (>= 0.10.4)
public_suffix (7.0.5)
- puma (6.4.3)
+ puma (7.2.1)
nio4r (~> 2.0)
pundit (2.3.0)
activesupport (>= 3.0.0)
@@ -935,9 +946,9 @@ GEM
gli
hashie
logger
- snaky_hash (2.0.1)
- hashie
- version_gem (~> 1.1, >= 1.1.1)
+ snaky_hash (2.0.5)
+ hashie (>= 0.1.0, < 6)
+ version_gem (>= 1.1.8, < 3)
sorbet-runtime (0.5.11934)
spring (4.1.1)
spring-watcher-listen (2.1.0)
@@ -995,7 +1006,7 @@ GEM
valid_email2 (5.2.6)
activemodel (>= 3.2)
mail (~> 2.5)
- version_gem (1.1.4)
+ version_gem (1.1.11)
vite_rails (3.10.0)
railties (>= 5.1, < 9)
vite_ruby (~> 3.0, >= 3.2.2)
@@ -1132,7 +1143,7 @@ DEPENDENCIES
pgvector
procore-sift
pry-rails
- puma
+ puma (~> 7.2, >= 7.2.1)
pundit
rack-attack (>= 6.7.0)
rack-cors (= 2.0.0)
diff --git a/VERSION_CW b/VERSION_CW
index d2b9909a9..0fb7a35b6 100644
--- a/VERSION_CW
+++ b/VERSION_CW
@@ -1 +1 @@
-4.14.1
+4.14.2
diff --git a/app/builders/contact_inbox_with_contact_builder.rb b/app/builders/contact_inbox_with_contact_builder.rb
index 2c0e6087e..2ba9179ed 100644
--- a/app/builders/contact_inbox_with_contact_builder.rb
+++ b/app/builders/contact_inbox_with_contact_builder.rb
@@ -50,7 +50,7 @@ class ContactInboxWithContactBuilder
def create_contact
account.contacts.create!(
- name: contact_attributes[:name] || ::Haikunator.haikunate(1000),
+ name: contact_name,
phone_number: contact_attributes[:phone_number],
email: contact_attributes[:email],
identifier: contact_attributes[:identifier],
@@ -59,6 +59,11 @@ class ContactInboxWithContactBuilder
)
end
+ def contact_name
+ name = contact_attributes[:name] || ::Haikunator.haikunate(1000)
+ name.truncate(ApplicationRecord::MAX_STRING_COLUMN_LENGTH, omission: '')
+ end
+
def find_contact
contact = find_contact_by_identifier(contact_attributes[:identifier])
contact ||= find_contact_by_email(contact_attributes[:email])
diff --git a/app/controllers/api/v1/accounts/onboardings_controller.rb b/app/controllers/api/v1/accounts/onboardings_controller.rb
index 77c6245ea..181e4965e 100644
--- a/app/controllers/api/v1/accounts/onboardings_controller.rb
+++ b/app/controllers/api/v1/accounts/onboardings_controller.rb
@@ -16,6 +16,10 @@ class Api::V1::Accounts::OnboardingsController < Api::V1::Accounts::BaseControll
render 'api/v1/accounts/update', format: :json
end
+ def help_center_generation
+ render json: help_center_generation_status
+ end
+
private
def finalizing_account_details?
@@ -33,4 +37,15 @@ class Api::V1::Accounts::OnboardingsController < Api::V1::Accounts::BaseControll
def custom_attributes_params
params.permit(:industry, :company_size, :timezone, :referral_source, :user_role, :website)
end
+
+ def help_center_generation_status
+ {
+ generation_id: nil,
+ state: nil,
+ articles_count: 0,
+ categories_count: 0
+ }
+ end
end
+
+Api::V1::Accounts::OnboardingsController.prepend_mod_with('Api::V1::Accounts::OnboardingsController')
diff --git a/app/finders/conversation_finder.rb b/app/finders/conversation_finder.rb
index fa437327d..1c27d8260 100644
--- a/app/finders/conversation_finder.rb
+++ b/app/finders/conversation_finder.rb
@@ -40,7 +40,7 @@ class ConversationFinder
def perform
set_up
- mine_count, unassigned_count, all_count, = set_count_for_all_conversations
+ mine_count, unassigned_count, all_count = set_count_for_all_conversations
assigned_count = all_count - unassigned_count
filter_by_assignee_type
@@ -184,6 +184,17 @@ class ConversationFinder
end
def set_count_for_all_conversations
+ return legacy_count_for_all_conversations if @conversations.limit_value || @conversations.offset_value || @conversations.eager_loading?
+
+ counts = @conversations.unscope(:order).pick(
+ Arel.sql("COUNT(*) FILTER (WHERE assignee_id = #{current_user.id})"),
+ Arel.sql('COUNT(*) FILTER (WHERE assignee_id IS NULL)'),
+ Arel.sql('COUNT(*)')
+ )
+ counts || [0, 0, 0]
+ end
+
+ def legacy_count_for_all_conversations
[
@conversations.assigned_to(current_user).count,
@conversations.unassigned.count,
diff --git a/app/javascript/dashboard/api/inboxes.js b/app/javascript/dashboard/api/inboxes.js
index 114dbb6f4..3c1d17fc8 100644
--- a/app/javascript/dashboard/api/inboxes.js
+++ b/app/javascript/dashboard/api/inboxes.js
@@ -60,6 +60,12 @@ class Inboxes extends CacheEnabledApiClient {
disableWhatsappCalling(inboxId) {
return axios.post(`${this.url}/${inboxId}/disable_whatsapp_calling`);
}
+
+ setInboundCalls(inboxId, enabled) {
+ return axios.post(`${this.url}/${inboxId}/set_inbound_calls`, {
+ inbound_calls_enabled: enabled,
+ });
+ }
}
export default new Inboxes();
diff --git a/app/javascript/dashboard/api/onboarding.js b/app/javascript/dashboard/api/onboarding.js
index 2bc098eef..e15d16da3 100644
--- a/app/javascript/dashboard/api/onboarding.js
+++ b/app/javascript/dashboard/api/onboarding.js
@@ -9,6 +9,10 @@ class OnboardingAPI extends ApiClient {
update(data) {
return axios.patch(this.url, data);
}
+
+ getHelpCenterGeneration() {
+ return axios.get(`${this.url}/help_center_generation`);
+ }
}
export default new OnboardingAPI();
diff --git a/app/javascript/dashboard/components-next/NewConversation/helpers/composeConversationHelper.js b/app/javascript/dashboard/components-next/NewConversation/helpers/composeConversationHelper.js
index 5c002d9bd..8e933cd84 100644
--- a/app/javascript/dashboard/components-next/NewConversation/helpers/composeConversationHelper.js
+++ b/app/javascript/dashboard/components-next/NewConversation/helpers/composeConversationHelper.js
@@ -182,7 +182,10 @@ const MIN_SEARCH_LENGTH = 2;
export const createContactSearcher = () => {
let controller = null;
- return async (query, { skipMinLength = false } = {}) => {
+ return async (
+ query,
+ { skipMinLength = false, reachableOnly = true } = {}
+ ) => {
const trimmed = typeof query === 'string' ? query.trim() : '';
controller?.abort();
@@ -199,6 +202,8 @@ export const createContactSearcher = () => {
} = await ContactAPI.search(trimmed, 1, 'name', '', { signal });
const camelCasedPayload = camelcaseKeys(payload, { deep: true });
+ if (!reachableOnly) return camelCasedPayload || [];
+
// Filter contacts that have either phone_number or email
const filteredPayload = camelCasedPayload?.filter(
contact => contact.phoneNumber || contact.email
diff --git a/app/javascript/dashboard/components-next/filter/ConditionRow.vue b/app/javascript/dashboard/components-next/filter/ConditionRow.vue
index cc620de32..30709babd 100644
--- a/app/javascript/dashboard/components-next/filter/ConditionRow.vue
+++ b/app/javascript/dashboard/components-next/filter/ConditionRow.vue
@@ -1,6 +1,7 @@
diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Facebook.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Facebook.vue
index 39e0df818..d08c7e607 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Facebook.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Facebook.vue
@@ -1,20 +1,16 @@
diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/VoiceConfigurationPage.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/VoiceConfigurationPage.vue
index b0fe858e5..b5f3183f1 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/VoiceConfigurationPage.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/VoiceConfigurationPage.vue
@@ -1,9 +1,11 @@