Skip to content

Commit

Permalink
Merge branch 'release/3.10.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
sojan-official committed Jun 27, 2024
2 parents 9a1d551 + 7ed7c1b commit 862ef37
Show file tree
Hide file tree
Showing 13 changed files with 157 additions and 63 deletions.
4 changes: 2 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ gem 'elastic-apm', require: false
gem 'newrelic_rpm', require: false
gem 'newrelic-sidekiq-metrics', '>= 1.6.2', require: false
gem 'scout_apm', require: false
gem 'sentry-rails', '>= 5.14.0', require: false
gem 'sentry-rails', '>= 5.18.0', require: false
gem 'sentry-ruby', require: false
gem 'sentry-sidekiq', '>= 5.15.0', require: false
gem 'sentry-sidekiq', '>= 5.18.0', require: false

##-- background job processing --##
gem 'sidekiq', '>= 7.2.4'
Expand Down
18 changes: 9 additions & 9 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ GEM
statsd-ruby (~> 1.1)
base64 (0.2.0)
bcrypt (3.1.20)
bigdecimal (3.1.7)
bigdecimal (3.1.8)
bindex (0.8.1)
bootsnap (1.16.0)
msgpack (~> 1.2)
Expand Down Expand Up @@ -603,7 +603,7 @@ GEM
ffi (~> 1.0)
redis (5.0.6)
redis-client (>= 0.9.0)
redis-client (0.22.1)
redis-client (0.22.2)
connection_pool
redis-namespace (1.10.0)
redis (>= 4)
Expand Down Expand Up @@ -703,14 +703,14 @@ GEM
activesupport (>= 4)
selectize-rails (0.12.6)
semantic_range (3.0.0)
sentry-rails (5.17.3)
sentry-rails (5.18.0)
railties (>= 5.0)
sentry-ruby (~> 5.17.3)
sentry-ruby (5.17.3)
sentry-ruby (~> 5.18.0)
sentry-ruby (5.18.0)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
sentry-sidekiq (5.17.3)
sentry-ruby (~> 5.17.3)
sentry-sidekiq (5.18.0)
sentry-ruby (~> 5.18.0)
sidekiq (>= 3.0)
sexp_processor (4.17.0)
shoulda-matchers (5.3.0)
Expand Down Expand Up @@ -931,9 +931,9 @@ DEPENDENCIES
scout_apm
scss_lint
seed_dump
sentry-rails (>= 5.14.0)
sentry-rails (>= 5.18.0)
sentry-ruby
sentry-sidekiq (>= 5.15.0)
sentry-sidekiq (>= 5.18.0)
shoulda-matchers
sidekiq (>= 7.2.4)
sidekiq-cron (>= 1.12.0)
Expand Down
6 changes: 3 additions & 3 deletions app/javascript/dashboard/helper/automationHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export const generateConditionOptions = (options, key = 'id') => {
};

// Add the "None" option to the agent list
export const agentList = agents => [
export const addNoneToList = agents => [
{
id: 'nil',
name: 'None',
Expand All @@ -137,8 +137,8 @@ export const getActionOptions = ({
type,
}) => {
const actionsMap = {
assign_agent: agentList(agents),
assign_team: teams,
assign_agent: addNoneToList(agents),
assign_team: addNoneToList(teams),
send_email_to_team: teams,
add_label: generateConditionOptions(labels, 'title'),
remove_label: generateConditionOptions(labels, 'title'),
Expand Down
16 changes: 16 additions & 0 deletions app/javascript/widget/components/UserMessage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@
:readable-time="readableTime"
@error="onImageLoadError"
/>

<video-bubble
v-if="attachment.file_type === 'video' && !hasVideoError"
:url="attachment.data_url"
:readable-time="readableTime"
@error="onVideoLoadError"
/>

<file-bubble
v-else
:url="attachment.data_url"
Expand Down Expand Up @@ -72,6 +80,7 @@
import UserMessageBubble from 'widget/components/UserMessageBubble.vue';
import MessageReplyButton from 'widget/components/MessageReplyButton.vue';
import ImageBubble from 'widget/components/ImageBubble.vue';
import VideoBubble from 'widget/components/VideoBubble.vue';
import FluentIcon from 'shared/components/FluentIcon/Index.vue';
import FileBubble from 'widget/components/FileBubble.vue';
import timeMixin from 'dashboard/mixins/time';
Expand All @@ -88,6 +97,7 @@ export default {
UserMessageBubble,
MessageReplyButton,
ImageBubble,
VideoBubble,
FileBubble,
FluentIcon,
ReplyToChip,
Expand All @@ -107,6 +117,7 @@ export default {
data() {
return {
hasImageError: false,
hasVideoError: false,
};
},
computed: {
Expand Down Expand Up @@ -143,10 +154,12 @@ export default {
watch: {
message() {
this.hasImageError = false;
this.hasVideoError = false;
},
},
mounted() {
this.hasImageError = false;
this.hasVideoError = false;
},
methods: {
async retrySendMessage() {
Expand All @@ -158,6 +171,9 @@ export default {
onImageLoadError() {
this.hasImageError = true;
},
onVideoLoadError() {
this.hasVideoError = true;
},
toggleReply() {
this.$emitter.emit(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.message);
},
Expand Down
27 changes: 27 additions & 0 deletions app/javascript/widget/components/VideoBubble.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script setup>
defineProps({
url: { type: String, default: '' },
readableTime: { type: String, default: '' },
});
const emits = defineEmits(['error']);
const onVideoError = () => {
emits('error');
};
</script>
<template>
<div class="block relative max-w-full">
<video
class="w-full max-w-[250px] h-auto"
:src="url"
controls
@error="onVideoError"
/>
<span
class="text-xs absolute text-white dark:text-white right-3 bottom-1 whitespace-nowrap"
>
{{ readableTime }}
</span>
</div>
</template>
1 change: 0 additions & 1 deletion app/models/concerns/json_schema_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ def validate(record)

# Add validation errors to the record with a formatted statement
validation_errors.each do |error|
# byebug
format_and_append_error(error, record)
end
end
Expand Down
6 changes: 5 additions & 1 deletion app/services/action_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ def remove_label(labels)
end

def assign_team(team_ids = [])
return unassign_team if team_ids[0]&.zero?
# FIXME: The explicit checks for zero or nil (string) is bad. Move
# this to a separate unassign action.
should_unassign = team_ids.blank? || %w[nil 0].include?(team_ids[0].to_s)
return @conversation.update!(team_id: nil) if should_unassign

# check if team belongs to account only if team_id is present
# if team_id is nil, then it means that the team is being unassigned
return unless !team_ids[0].nil? && team_belongs_to_account?(team_ids)
Expand Down
2 changes: 1 addition & 1 deletion app/services/notification/push_notification_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def browser_push_payload(subscription)
def send_browser_push(subscription)
return unless can_send_browser_push?(subscription)

WebPush.payload_send(browser_push_payload(subscription))
WebPush.payload_send(**browser_push_payload(subscription))
Rails.logger.info("Browser push sent to #{user.email} with title #{push_message[:title]}")
rescue WebPush::ExpiredSubscription, WebPush::InvalidSubscription, WebPush::Unauthorized => e
Rails.logger.info "WebPush subscription expired: #{e.message}"
Expand Down
2 changes: 1 addition & 1 deletion config/app.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
shared: &shared
version: '3.10.1'
version: '3.10.2'

development:
<<: *shared
Expand Down
80 changes: 40 additions & 40 deletions config/locales/vi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ vi:
disposable_email: Chúng tôi không cho phép các email dùng một lần
invalid_email: Bạn đã nhập một email không hợp lệ
email_already_exists: "Bạn đã đăng ký một tài khoản với %{email}"
invalid_params: 'Invalid, please check the signup paramters and try again'
invalid_params: 'Không hợp lệ, vui lòng kiểm tra thông số đăng ký và thử lại'
failed: Đăng ký thât bại
data_import:
data_type:
Expand All @@ -51,7 +51,7 @@ vi:
dyte:
invalid_message_type: "Loại tin nhắn không hợp lệ. Hành động không được phép"
slack:
invalid_channel_id: "Invalid slack channel. Please try again"
invalid_channel_id: "Kênh chùng không hợp lệ. Vui lòng thử lại"
inboxes:
imap:
socket_error: Vui lòng kiểm tra kết nối mạng, địa chỉ IMAP và thử lại.
Expand All @@ -63,43 +63,43 @@ vi:
name: không nên bắt đầu hoặc kết thúc bằng các ký hiệu và không nên có kí tự < > / \ @.
custom_filters:
number_of_records: Đã đạt giới hạn. Số lượng tuỳ chọn lọc tối đa cho mỗi mỗi người dùng mỗi tài khoản là 50.
invalid_attribute: Invalid attribute key - [%{key}]. The key should be one of [%{allowed_keys}] or a custom attribute defined in the account.
invalid_operator: Invalid operator. The allowed operators for %{attribute_name} are [%{allowed_keys}].
invalid_value: Invalid value. The values provided for %{attribute_name} are invalid
invalid_attribute: Khóa thuộc tính không hợp lệ - [%{key}]. Chìa khóa phải là một trong [%{allowed_keys}] hoặc thuộc tính tùy chỉnh được xác định trong tài khoản.
invalid_operator: Toán tử không hợp lệ. Các toán tử được phép cho %{attribute_name} [%{allowed_keys}].
invalid_value: Giá trị không hợp lệ. Các giá trị được cung cấp cho %{attribute_name} không hợp lệ
reports:
period: Thời gian báo cáo từ %{since} đến %{until}
utc_warning: Báo cáo đã được tạo với múi giờ UTC
agent_csv:
agent_name: Tên tổng đài viên
conversations_count: Assigned conversations
avg_first_response_time: Avg first response time
conversations_count: Cuộc trò chuyện được chỉ định
avg_first_response_time: Thời gian phản hồi đầu tiên trung bình
avg_resolution_time: Avg resolution time
resolution_count: Số lượng giải quyết
avg_customer_waiting_time: Avg customer waiting time
avg_customer_waiting_time: Thời gian chờ đợi trung bình của khách hàng
inbox_csv:
inbox_name: Tên kênh
inbox_type: Kiểu kênh
conversations_count: Số hội thoại
avg_first_response_time: Avg first response time
avg_resolution_time: Avg resolution time
avg_first_response_time: Thời gian phản hồi đầu tiên trung bình
avg_resolution_time: Thời gian giải quyết trung bình
label_csv:
label_title: Nhãn
conversations_count: Số hội thoại
avg_first_response_time: Avg first response time
avg_resolution_time: Avg resolution time
avg_first_response_time: Thời gian phản hồi đầu tiên trung bình
avg_resolution_time: Thời gian giải quyết trung bình
team_csv:
team_name: Tên nhóm
conversations_count: Số hội thoại
avg_first_response_time: Avg first response time
avg_resolution_time: Avg resolution time
avg_first_response_time: Thời gian phản hồi đầu tiên trung bình
avg_resolution_time: Thời gian giải quyết trung bình
resolution_count: Số lượng giải quyết
avg_customer_waiting_time: Avg customer waiting time
avg_customer_waiting_time: Thời gian chờ đợi trung bình của khách hàng
conversation_traffic_csv:
timezone: Múi giờ
sla_csv:
conversation_id: Conversation ID
conversation_id: ID hội thoại
sla_policy_breached: SLA Policy
assignee: Assignee
assignee: Đại lý được chỉ định
team: Nhóm
inbox: Hộp thư đến
labels: Nhãn
Expand All @@ -118,22 +118,22 @@ vi:
recorded_at: Ngày nghi
notifications:
notification_title:
conversation_creation: "A conversation (#%{display_id}) has been created in %{inbox_name}"
conversation_assignment: "A conversation (#%{display_id}) has been assigned to you"
assigned_conversation_new_message: "A new message is created in conversation (#%{display_id})"
conversation_mention: "You have been mentioned in conversation (#%{display_id})"
sla_missed_first_response: "SLA target first response missed for conversation (#%{display_id})"
sla_missed_next_response: "SLA target next response missed for conversation (#%{display_id})"
sla_missed_resolution: "SLA target resolution missed for conversation (#%{display_id})"
attachment: "Attachment"
no_content: "No content"
conversation_creation: "Một cuộc trò chuyện (#%{display_id}) đã được tạo trong %{inbox_name}"
conversation_assignment: "Một cuộc trò chuyện (#%{display_id}) đã được chỉ định cho bạn"
assigned_conversation_new_message: "Một tin nhắn mới được tạo trong cuộc trò chuyện (#%{display_id})"
conversation_mention: "Bạn đã được nhắc đến trong cuộc trò chuyện (#%{display_id})"
sla_missed_first_response: "Mục tiêu SLA phản hồi đầu tiên bị bỏ lỡ cho cuộc trò chuyện (#%{display_id})"
sla_missed_next_response: "Mục tiêu SLA phản hồi tiếp theo bị bỏ lỡ cho cuộc trò chuyện (#%{display_id})"
sla_missed_resolution: "Độ phân giải mục tiêu SLA bị bỏ lỡ cho cuộc trò chuyện (#%{display_id})"
attachment: "Tập tin đính kèm"
no_content: "Không có nội dung"
conversations:
messages:
instagram_story_content: "%{story_sender} đã đề cập đến bạn trong hội thoại: "
instagram_deleted_story_content: Hội thoại này không còn nữa.
deleted: Tin nhắn đã bị xoá
delivery_status:
error_code: "Error code: %{error_code}"
error_code: "Mã lỗi: %{error_code}"
activity:
status:
resolved: "Cuộc trò chuyện được đánh dấu là đã giải quyết bởi %{user_name}"
Expand Down Expand Up @@ -221,7 +221,7 @@ vi:
common:
home: Trang Chủ
last_updated_on: 'Cập nhật lần cuối: %{last_updated_on}'
view_all_articles: View all
view_all_articles: Xem tất cả
article: bài viết
articles: bài viết
author: tác giả
Expand All @@ -233,17 +233,17 @@ vi:
footer:
made_with: Tạo bởi
header:
go_to_homepage: Website
go_to_homepage: Trang web
appearance:
system: System
light: Light
dark: Dark
featured_articles: Featured Articles
system: Hệ thống
light: Sáng
dark: Tối
featured_articles: Bài viết nổi bật
uncategorized: Chưa được phân loại
404:
title: Page not found
description: We couldn't find the page you were looking for.
back_to_home: Go to home page
title: Không tìm thấy trang
description: Chúng tôi không thể tìm thấy trang bạn đang tìm kiếm.
back_to_home: Tới trang chủ
slack_unfurl:
fields:
name: Tên
Expand All @@ -255,10 +255,10 @@ vi:
button: Mở cuộc trò chuyện
time_units:
days:
other: "%{count} days"
other: "%{count} ngày"
hours:
other: "%{count} hours"
other: "%{count} giờ"
minutes:
other: "%{count} minutes"
other: "%{count} phút"
seconds:
other: "%{count} seconds"
other: "%{count} giây"
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@chatwoot/chatwoot",
"version": "3.10.1",
"version": "3.10.2",
"license": "MIT",
"scripts": {
"eslint": "eslint app/**/*.{js,vue}",
Expand Down
12 changes: 12 additions & 0 deletions spec/factories/conversations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,17 @@
conversation.contact ||= create(:contact, :with_email, account: conversation.account)
conversation.contact_inbox ||= create(:contact_inbox, contact: conversation.contact, inbox: conversation.inbox)
end

trait :with_team do
after(:build) do |conversation|
conversation.team ||= create(:team, account: conversation.account)
end
end

trait :with_assignee do
after(:build) do |conversation|
conversation.assignee ||= create(:user, account: conversation.account, role: :agent)
end
end
end
end
Loading

0 comments on commit 862ef37

Please sign in to comment.