Compare commits

...
Author SHA1 Message Date
Shivam Mishra 5761120fa8 feat: add unread count calculation in meta 2023-06-29 19:08:43 +05:30
Shivam Mishra 7066f66fa7 feat: set count from store on action cable event 2023-06-29 17:57:19 +05:30
Sivin VargheseandGitHub 191b8a64fe chore: Remove URLs from translations (#7414) 2023-06-29 15:09:02 +05:30
ea78020f2f fix: Translation issues (#7416)
Co-authored-by: Hricha Shandily <103104754+Hricha-Shandily@users.noreply.github.com>
2023-06-29 14:41:23 +05:30
Muhsin KelothandGitHub dc1a41b136 fix: Set date hours to 9 in snooze time (#7426) 2023-06-29 14:38:03 +05:30
Shivam MishraandGitHub 28e7a5d228 fix: CC conditions when the last email is from someone else (#7010) 2023-06-28 20:28:44 -07:00
40830046e8 feat: Audit Logs for Account User Changes (#7405)
- Audit log for user invitations: https://linear.app/chatwoot/issue/CW-1768/invited-a-user-to-the-account
- Audit log for change role: https://linear.app/chatwoot/issue/CW-1767/name-or-email-changed-the-role-of-the-user-email-to-agent-or-admin
- Audit log for status change: https://linear.app/chatwoot/issue/CW-1766/availability-status-as-events-for-audit-logs


Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
2023-06-28 22:42:06 +05:30
Tejaswini ChileandGitHub d05c953eef feat: Support Azure single-tenant application using the Graph API (#6728) (#6878) 2023-06-28 08:13:08 +05:30
4a770fdea7 feat: Add Plus Jakarta Font to dashboard (#7421)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
2023-06-27 17:39:37 -07:00
Tejaswini ChileandGitHub 239b1e2bf1 feat: Include email in the searched result (#7397) 2023-06-27 21:05:36 +05:30
f963e00731 fix: capture user and ip details on Inbox delete (#7395)
Fixes: https://linear.app/chatwoot/issue/CW-1772/ip-address-and-user-details-are-missing-in-some-of-the-logs

Co-authored-by: Sojan <sojan@pepalo.com>
2023-06-27 19:49:24 +05:30
TOMMYandGitHub 155a5b9947 fix: Remove free space (#7411) 2023-06-27 19:28:38 +05:30
TOMMYandGitHub 26a75b250d Merge pull request from GHSA-2472-ggjh-43h2 2023-06-27 17:22:54 +05:30
Pranav Raj SandGitHub 20b84ee6a1 chore: Fix darkMode styles in widget (#7408) 2023-06-26 14:43:22 -07:00
Pranav Raj SandGitHub f1f14312fe chore: Upgrade Tailwind CSS to 3.3.2 (#7380) 2023-06-26 11:27:16 -07:00
Tejaswini ChileandGitHub 212d7caab1 fix: log User is authenticated but not connected (#7394) 2023-06-26 16:07:40 +05:30
9cda16d0e8 fix: Remove overflow string in label delete confirm button (#7386)
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
2023-06-26 13:26:47 +05:30
Sivin VargheseandGitHub a8acbb7427 fix: Issue with i18n in update banner (#7392) 2023-06-26 11:32:40 +05:30
1176e5eb8a feat: Custom phone input in pre-chat form (#7275)
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2023-06-26 10:26:06 +05:30
996325f35b feat: multiple UX improvements to labels (#7358)
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Nithin David Thomas <1277421+nithindavid@users.noreply.github.com>
2023-06-25 18:49:49 +05:30
Pranav Raj SandGitHub 4f8ce7b597 chore: Add support for dark mode logo (#7378) 2023-06-23 12:06:01 -07:00
Sojan JoseandGitHub f8e631a00c chore: Update Crowdin Config (#7375)
- add pull request titles
- skip ci for crowdin commits
2023-06-23 23:02:55 +05:30
54bf33083e chore: Update translations (#7372)
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2023-06-23 16:01:14 +05:30
533f9f7fe4 fix: Email collect overriding existing contact name (#7355)
Currently, if Enable email collect box is enabled, and the user starting the chat already has an account with the same email, it will override the current account with {name} from the email name@email.com , this fixes it.

Co-authored-by: Sojan <sojan@pepalo.com>
2023-06-22 19:09:12 +05:30
82e5fc413e fix: Label Duplication in Bulk Actions (#7341)
When looping the conversations in bulk action to assign them to new labels, the existing labels in other conversations were also getting duplicated across all conversations. This PR fixes the issue. 

> In the previous implementation, new_labels is appended to the existing labels using the << operator. This operator modifies the original array instead of creating a new one, causing unwanted side effects. More specifically, new_labels is a reference to the original argument array of the method.

Co-authored-by: Sojan <sojan@pepalo.com>
Co-authored-by: Peter Salib <74493166+Peteraymansalib@users.noreply.github.com>
2023-06-22 18:36:58 +05:30
Pranav Raj SandGitHub 93daaea19b feat: Add a sort option for conversations waiting for a reply from an agent (#7364) 2023-06-21 13:20:39 -07:00
e6a49b5800 feat: Shows Youtube and Vimeo links as embeds [cw-1393] (#7330)
This change will render the youbtube, vimeo and .mp4 urls as embedded in the article page in the help centre.

Fixes: https://linear.app/chatwoot/issue/CW-1393/help-center-support-video-upload-in-articles

Co-authored-by: Sojan <sojan@pepalo.com>
2023-06-21 20:28:28 +05:30
292 changed files with 6675 additions and 1612 deletions
+11 -1
View File
@@ -222,10 +222,20 @@ STRIPE_WEBHOOK_SECRET=
# Make sure to follow https://edgeguides.rubyonrails.org/active_storage_overview.html#cross-origin-resource-sharing-cors-configuration on the cloud storage after setting this to true.
DIRECT_UPLOADS_ENABLED=
#MS OAUTH creds
# MS OAUTH creds
AZURE_APP_ID=
AZURE_APP_SECRET=
## MS Azure Tenant ID
# Set the following id to the id of your Azure 'tenant'.
# This will enable single tenant applications to work.
# If the following id is set, Chatwoot will use the Microsoft Graph API
# to send and receive emails, as that seems to be required for single
# tenant applications.
#
# https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-how-to-find-tenant
AZURE_TENANT_ID=
## Advanced configurations
## Change these values to fine tune performance
# control the concurrency setting of sidekiq
+2
View File
@@ -74,3 +74,5 @@ yalc.lock
/yarn-error.log
yarn-debug.log*
.yarn-integrity
/storybook-static
+1 -1
View File
@@ -4,7 +4,7 @@ ruby '3.2.2'
##-- base gems for rails --##
gem 'rack-cors', require: 'rack/cors'
gem 'rails', '~> 7'
gem 'rails', '~> 7.0.5.1'
# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', require: false
+54 -54
View File
@@ -33,70 +33,70 @@ GIT
GEM
remote: https://rubygems.org/
specs:
actioncable (7.0.5)
actionpack (= 7.0.5)
activesupport (= 7.0.5)
actioncable (7.0.5.1)
actionpack (= 7.0.5.1)
activesupport (= 7.0.5.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (7.0.5)
actionpack (= 7.0.5)
activejob (= 7.0.5)
activerecord (= 7.0.5)
activestorage (= 7.0.5)
activesupport (= 7.0.5)
actionmailbox (7.0.5.1)
actionpack (= 7.0.5.1)
activejob (= 7.0.5.1)
activerecord (= 7.0.5.1)
activestorage (= 7.0.5.1)
activesupport (= 7.0.5.1)
mail (>= 2.7.1)
net-imap
net-pop
net-smtp
actionmailer (7.0.5)
actionpack (= 7.0.5)
actionview (= 7.0.5)
activejob (= 7.0.5)
activesupport (= 7.0.5)
actionmailer (7.0.5.1)
actionpack (= 7.0.5.1)
actionview (= 7.0.5.1)
activejob (= 7.0.5.1)
activesupport (= 7.0.5.1)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
rails-dom-testing (~> 2.0)
actionpack (7.0.5)
actionview (= 7.0.5)
activesupport (= 7.0.5)
actionpack (7.0.5.1)
actionview (= 7.0.5.1)
activesupport (= 7.0.5.1)
rack (~> 2.0, >= 2.2.4)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (7.0.5)
actionpack (= 7.0.5)
activerecord (= 7.0.5)
activestorage (= 7.0.5)
activesupport (= 7.0.5)
actiontext (7.0.5.1)
actionpack (= 7.0.5.1)
activerecord (= 7.0.5.1)
activestorage (= 7.0.5.1)
activesupport (= 7.0.5.1)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.0.5)
activesupport (= 7.0.5)
actionview (7.0.5.1)
activesupport (= 7.0.5.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
active_record_query_trace (1.8)
activejob (7.0.5)
activesupport (= 7.0.5)
activejob (7.0.5.1)
activesupport (= 7.0.5.1)
globalid (>= 0.3.6)
activemodel (7.0.5)
activesupport (= 7.0.5)
activerecord (7.0.5)
activemodel (= 7.0.5)
activesupport (= 7.0.5)
activemodel (7.0.5.1)
activesupport (= 7.0.5.1)
activerecord (7.0.5.1)
activemodel (= 7.0.5.1)
activesupport (= 7.0.5.1)
activerecord-import (1.4.1)
activerecord (>= 4.2)
activestorage (7.0.5)
actionpack (= 7.0.5)
activejob (= 7.0.5)
activerecord (= 7.0.5)
activesupport (= 7.0.5)
activestorage (7.0.5.1)
actionpack (= 7.0.5.1)
activejob (= 7.0.5.1)
activerecord (= 7.0.5.1)
activesupport (= 7.0.5.1)
marcel (~> 1.0)
mini_mime (>= 1.1.0)
activesupport (7.0.5)
activesupport (7.0.5.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
@@ -540,29 +540,29 @@ GEM
rack-test (2.1.0)
rack (>= 1.3)
rack-timeout (0.6.3)
rails (7.0.5)
actioncable (= 7.0.5)
actionmailbox (= 7.0.5)
actionmailer (= 7.0.5)
actionpack (= 7.0.5)
actiontext (= 7.0.5)
actionview (= 7.0.5)
activejob (= 7.0.5)
activemodel (= 7.0.5)
activerecord (= 7.0.5)
activestorage (= 7.0.5)
activesupport (= 7.0.5)
rails (7.0.5.1)
actioncable (= 7.0.5.1)
actionmailbox (= 7.0.5.1)
actionmailer (= 7.0.5.1)
actionpack (= 7.0.5.1)
actiontext (= 7.0.5.1)
actionview (= 7.0.5.1)
activejob (= 7.0.5.1)
activemodel (= 7.0.5.1)
activerecord (= 7.0.5.1)
activestorage (= 7.0.5.1)
activesupport (= 7.0.5.1)
bundler (>= 1.15.0)
railties (= 7.0.5)
railties (= 7.0.5.1)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.0)
loofah (~> 2.21)
nokogiri (~> 1.14)
railties (7.0.5)
actionpack (= 7.0.5)
activesupport (= 7.0.5)
railties (7.0.5.1)
actionpack (= 7.0.5.1)
activesupport (= 7.0.5.1)
method_source
rake (>= 12.2)
thor (~> 1.0)
@@ -875,7 +875,7 @@ DEPENDENCIES
rack-cors
rack-mini-profiler
rack-timeout
rails (~> 7)
rails (~> 7.0.5.1)
redis
redis-namespace
responders
+1 -1
View File
@@ -11,7 +11,7 @@ function prepareData(data) {
function getChartOptions() {
var fontFamily =
'Inter,-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
'PlusJakarta,-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
return {
responsive: true,
legend: { labels: { fontFamily } },
@@ -1,5 +1,5 @@
// Typography
$base-font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
$base-font-family: PlusJakarta, Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
"Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif !default;
$heading-font-family: $base-font-family !default;
+11 -6
View File
@@ -48,17 +48,22 @@ class Messages::MessageBuilder
def process_emails
return unless @conversation.inbox&.inbox_type == 'Email'
cc_emails = []
cc_emails = @params[:cc_emails].gsub(/\s+/, '').split(',') if @params[:cc_emails].present?
cc_emails = process_email_string(@params[:cc_emails])
bcc_emails = process_email_string(@params[:bcc_emails])
to_emails = process_email_string(@params[:to_emails])
bcc_emails = []
bcc_emails = @params[:bcc_emails].gsub(/\s+/, '').split(',') if @params[:bcc_emails].present?
all_email_addresses = cc_emails + bcc_emails
all_email_addresses = cc_emails + bcc_emails + to_emails
validate_email_addresses(all_email_addresses)
@message.content_attributes[:cc_emails] = cc_emails
@message.content_attributes[:bcc_emails] = bcc_emails
@message.content_attributes[:to_emails] = to_emails
end
def process_email_string(email_string)
return [] if email_string.blank?
email_string.gsub(/\s+/, '').split(',')
end
def validate_email_addresses(all_emails)
@@ -63,7 +63,7 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController
end
def destroy
::DeleteObjectJob.perform_later(@inbox) if @inbox.present?
::DeleteObjectJob.perform_later(@inbox, Current.user, request.ip) if @inbox.present?
render status: :ok, json: { message: I18n.t('messages.inbox_deletetion_response') }
end
@@ -4,13 +4,7 @@ class Api::V1::Accounts::Microsoft::AuthorizationsController < Api::V1::Accounts
def create
email = params[:authorization][:email]
redirect_url = microsoft_client.auth_code.authorize_url(
{
redirect_uri: "#{base_url}/microsoft/callback",
scope: 'offline_access https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send openid profile',
prompt: 'consent'
}
)
redirect_url = microsoft_client.auth_code.authorize_url(auth_params)
if redirect_url
email = email.downcase
::Redis::Alfred.setex(email, Current.account.id, 5.minutes)
@@ -25,4 +19,31 @@ class Api::V1::Accounts::Microsoft::AuthorizationsController < Api::V1::Accounts
def check_authorization
raise Pundit::NotAuthorizedError unless Current.account_user.administrator?
end
# SMTP, Pop and IMAP are being deprecated by Outlook.
# https://learn.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/deprecation-of-basic-authentication-exchange-online
#
# As such, Microsoft has made it a real pain to use them.
# If AZURE_TENANT_ID is set, we will use the MS Graph API instead.
def auth_params
return graph_auth_params if ENV.fetch('AZURE_TENANT_ID', false)
standard_auth_params
end
def standard_auth_params
{
redirect_uri: "#{base_url}/microsoft/callback",
scope: 'offline_access https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send openid profile',
prompt: 'consent'
}
end
def graph_auth_params
{
redirect_uri: "#{base_url}/microsoft/callback",
scope: 'offline_access https://graph.microsoft.com/Mail.Read https://graph.microsoft.com/Mail.Send openid profile',
prompt: 'consent'
}
end
end
@@ -17,7 +17,8 @@ class Api::V1::Widget::MessagesController < Api::V1::Widget::BaseController
@message.update!(submitted_email: contact_email)
ContactIdentifyAction.new(
contact: @contact,
params: { email: contact_email, name: contact_name }
params: { email: contact_email, name: contact_name },
retain_original_contact_name: true
).perform
else
@message.update!(message_update_params[:message])
@@ -5,8 +5,8 @@ module MicrosoftConcern
::OAuth2::Client.new(ENV.fetch('AZURE_APP_ID', nil), ENV.fetch('AZURE_APP_SECRET', nil),
{
site: 'https://login.microsoftonline.com',
authorize_url: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',
token_url: 'https://login.microsoftonline.com/common/oauth2/v2.0/token'
authorize_url: "https://login.microsoftonline.com/#{azure_tenant_id}/oauth2/v2.0/authorize",
token_url: "https://login.microsoftonline.com/#{azure_tenant_id}/oauth2/v2.0/token"
})
end
@@ -19,4 +19,8 @@ module MicrosoftConcern
def base_url
ENV.fetch('FRONTEND_URL', 'http://localhost:3000')
end
def azure_tenant_id
MicrosoftGraphAuth.azure_tenant_id
end
end
+1 -1
View File
@@ -14,7 +14,7 @@ class DashboardController < ActionController::Base
def set_global_config
@global_config = GlobalConfig.get(
'LOGO', 'LOGO_THUMBNAIL',
'LOGO', 'LOGO_DARK', 'LOGO_THUMBNAIL',
'INSTALLATION_NAME',
'WIDGET_BRAND_URL', 'TERMS_URL',
'PRIVACY_URL',
+9 -4
View File
@@ -6,7 +6,8 @@ class ConversationFinder
latest: 'latest',
sort_on_created_at: 'sort_on_created_at',
last_user_message_at: 'last_user_message_at',
sort_on_priority: 'sort_on_priority'
sort_on_priority: 'sort_on_priority',
sort_on_waiting_since: 'sort_on_waiting_since'
}.with_indifferent_access
# assumptions
@@ -29,7 +30,7 @@ class ConversationFinder
def perform
set_up
mine_count, unassigned_count, all_count, = set_count_for_all_conversations
mine_count, unassigned_count, all_count, unread_count = set_count_for_all_conversations
assigned_count = all_count - unassigned_count
filter_by_assignee_type
@@ -40,7 +41,8 @@ class ConversationFinder
mine_count: mine_count,
assigned_count: assigned_count,
unassigned_count: unassigned_count,
all_count: all_count
all_count: all_count,
unread_count: unread_count
}
}
end
@@ -146,7 +148,10 @@ class ConversationFinder
[
@conversations.assigned_to(current_user).count,
@conversations.unassigned.count,
@conversations.count
@conversations.count,
@conversations.joins(:messages)
.where('conversations.agent_last_seen_at IS NULL OR messages.created_at > conversations.agent_last_seen_at')
.distinct.count
]
end
@@ -10,6 +10,7 @@ export const buildCreatePayload = ({
files,
ccEmails = '',
bccEmails = '',
toEmails = '',
templateParams,
}) => {
let payload;
@@ -25,6 +26,9 @@ export const buildCreatePayload = ({
payload.append('echo_id', echoId);
payload.append('cc_emails', ccEmails);
payload.append('bcc_emails', bccEmails);
if (toEmails) {
payload.append('to_emails', toEmails);
}
} else {
payload = {
content: message,
@@ -33,6 +37,7 @@ export const buildCreatePayload = ({
content_attributes: contentAttributes,
cc_emails: ccEmails,
bcc_emails: bccEmails,
to_emails: toEmails,
template_params: templateParams,
};
}
@@ -53,6 +58,7 @@ class MessageApi extends ApiClient {
files,
ccEmails = '',
bccEmails = '',
toEmails = '',
templateParams,
}) {
return axios({
@@ -66,6 +72,7 @@ class MessageApi extends ApiClient {
files,
ccEmails,
bccEmails,
toEmails,
templateParams,
}),
});
@@ -63,7 +63,7 @@ $black: #000;
$white: #fff;
$body-background: $white;
$body-font-color: $color-body;
$body-font-family: 'Inter',
$body-font-family: 'PlusJakarta',
-apple-system,
system-ui,
BlinkMacSystemFont,
@@ -133,7 +133,7 @@ $header-styles: (small: ("h1": ("font-size": 24),
$header-text-rendering: optimizeLegibility;
$small-font-size: 80%;
$header-small-font-color: $medium-gray;
$paragraph-lineheight: 1.45;
$paragraph-lineheight: 1.65;
$paragraph-margin-bottom: var(--space-small);
$paragraph-text-rendering: optimizeLegibility;
$code-color: $black;
@@ -29,4 +29,5 @@ a {
p {
font-size: $font-size-small;
word-spacing: .12em;
}
@@ -1,4 +1,4 @@
@import 'shared/assets/fonts/inter';
@import 'shared/assets/fonts/plus-jakarta';
@import 'shared/assets/stylesheets/animations';
@import 'shared/assets/stylesheets/colors';
@import 'shared/assets/stylesheets/spacing';
@@ -1,4 +1,5 @@
@import 'shared/assets/fonts/inter';
@import 'shared/assets/fonts/plus-jakarta';
@import 'shared/assets/stylesheets/animations';
@import 'shared/assets/stylesheets/colors';
@import 'shared/assets/stylesheets/spacing';
@@ -1,3 +1,3 @@
@import 'shared/assets/fonts/inter';
@import 'shared/assets/fonts/plus-jakarta';
@import '../variables';
@import '~shared/assets/stylesheets/ionicons';
@@ -0,0 +1,25 @@
<template>
<kbd class="hotkey">
<slot />
</kbd>
</template>
<style lang="scss">
kbd.hotkey {
display: inline-flex;
flex-shrink: 0;
align-items: center;
user-select: none;
justify-content: center;
padding: var(--space-micro);
min-width: var(--space-normal);
font-size: var(--font-size-micro);
border-radius: var(--space-smaller);
background-color: var(--color-background);
border: 1px solid var(--color-border);
text-transform: uppercase;
color: var(--color-body);
letter-spacing: var(--space-micro);
line-height: var(--font-size-micro);
}
</style>
@@ -20,6 +20,7 @@
v-if="showSearchDropdownLabel"
:account-labels="allLabels"
:selected-labels="selectedLabels"
:allow-creation="isAdmin"
@add="addItem"
@remove="removeItem"
/>
@@ -30,8 +31,15 @@
<script>
import AddLabel from 'shared/components/ui/dropdown/AddLabel';
import eventListenerMixins from 'shared/mixins/eventListenerMixins';
import LabelDropdown from 'shared/components/ui/label/LabelDropdown';
import { mixin as clickaway } from 'vue-clickaway';
import adminMixin from 'dashboard/mixins/isAdmin';
import {
buildHotKeys,
isEscape,
isActiveElementTypeable,
} from 'shared/helpers/KeyboardHelpers';
export default {
components: {
@@ -39,7 +47,7 @@ export default {
LabelDropdown,
},
mixins: [clickaway],
mixins: [clickaway, adminMixin, eventListenerMixins],
props: {
allLabels: {
@@ -80,6 +88,18 @@ export default {
closeDropdownLabel() {
this.showSearchDropdownLabel = false;
},
handleKeyEvents(e) {
const keyPattern = buildHotKeys(e);
if (keyPattern === 'l' && !isActiveElementTypeable(e)) {
this.toggleLabels();
e.preventDefault();
} else if (isEscape(e) && this.showSearchDropdownLabel) {
this.closeDropdownLabel();
e.preventDefault();
}
},
},
};
</script>
@@ -35,6 +35,7 @@
v-if="showReplyHead"
:cc-emails.sync="ccEmails"
:bcc-emails.sync="bccEmails"
:to-emails.sync="toEmails"
/>
<woot-audio-recorder
v-if="showAudioRecorderEditor"
@@ -238,6 +239,7 @@ export default {
hasSlashCommand: false,
bccEmails: '',
ccEmails: '',
toEmails: '',
doAutoSaveDraft: () => {},
showWhatsAppTemplatesModal: false,
updateEditorSelectionWith: '',
@@ -528,7 +530,7 @@ export default {
this.replyType = REPLY_EDITOR_MODES.NOTE;
}
this.setCCEmailFromLastChat();
this.setCCAndToEmailsFromLastChat();
},
conversationIdByRoute(conversationId, oldConversationId) {
if (conversationId !== oldConversationId) {
@@ -562,7 +564,7 @@ export default {
// working even if input/textarea is focussed.
document.addEventListener('paste', this.onPaste);
document.addEventListener('keydown', this.handleKeyEvents);
this.setCCEmailFromLastChat();
this.setCCAndToEmailsFromLastChat();
this.doAutoSaveDraft = debounce(
() => {
this.saveDraft(this.conversationIdByRoute, this.replyType);
@@ -844,6 +846,7 @@ export default {
clearEmailField() {
this.ccEmails = '';
this.bccEmails = '';
this.toEmails = '';
},
toggleEmojiPicker() {
this.showEmojiPicker = !this.showEmojiPicker;
@@ -1054,22 +1057,56 @@ export default {
messagePayload.bccEmails = this.bccEmails;
}
if (this.toEmails && !this.isOnPrivateNote) {
messagePayload.toEmails = this.toEmails;
}
return messagePayload;
},
setCcEmails(value) {
this.bccEmails = value.bccEmails;
this.ccEmails = value.ccEmails;
},
setCCEmailFromLastChat() {
if (this.lastEmail) {
const {
content_attributes: { email: emailAttributes = {} },
} = this.lastEmail;
const cc = emailAttributes.cc || [];
const bcc = emailAttributes.bcc || [];
this.ccEmails = cc.join(', ');
this.bccEmails = bcc.join(', ');
setCCAndToEmailsFromLastChat() {
if (!this.lastEmail) return;
const {
content_attributes: { email: emailAttributes = {} },
} = this.lastEmail;
// Retrieve the email of the current conversation's sender
const conversationContact = this.currentChat?.meta?.sender?.email || '';
let cc = [...emailAttributes.cc] || [];
let to = [];
// there might be a situation where the current conversation will include a message from a third person,
// and the current conversation contact is in CC.
// This is an edge-case, reported here: CW-1511 [ONLY FOR INTERNAL REFERENCE]
// So we remove the current conversation contact's email from the CC list if present
if (cc.includes(conversationContact)) {
cc = cc.filter(email => email !== conversationContact);
}
// If the last incoming message sender is different from the conversation contact, add them to the "to"
// and add the conversation contact to the CC
if (!emailAttributes.from.includes(conversationContact)) {
to.push(...emailAttributes.from);
cc.push(conversationContact);
}
// Remove the conversation contact's email from the BCC list if present
let bcc = (emailAttributes.bcc || []).filter(
email => email !== conversationContact
);
// Ensure only unique email addresses are in the CC list
bcc = [...new Set(bcc)];
cc = [...new Set(cc)];
to = [...new Set(to)];
this.ccEmails = cc.join(', ');
this.bccEmails = bcc.join(', ');
this.toEmails = to.join(', ');
},
},
};
@@ -1,5 +1,21 @@
<template>
<div>
<div v-if="toEmails">
<div class="input-group small" :class="{ error: $v.toEmailsVal.$error }">
<label class="input-group-label">
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.TO') }}
</label>
<div class="input-group-field">
<woot-input
v-model.trim="$v.toEmailsVal.$model"
type="text"
:class="{ error: $v.toEmailsVal.$error }"
:placeholder="$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.PLACEHOLDER')"
@blur="onBlur"
/>
</div>
</div>
</div>
<div class="input-group-wrap">
<div class="input-group small" :class="{ error: $v.ccEmailsVal.$error }">
<label class="input-group-label">
@@ -53,6 +69,7 @@
<script>
import { validEmailsByComma } from './helpers/emailHeadHelper';
export default {
props: {
ccEmails: {
@@ -63,12 +80,17 @@ export default {
type: String,
default: '',
},
toEmails: {
type: String,
default: '',
},
},
data() {
return {
showBcc: false,
ccEmailsVal: '',
bccEmailsVal: '',
toEmailsVal: '',
};
},
watch: {
@@ -82,10 +104,16 @@ export default {
this.ccEmailsVal = newVal;
}
},
toEmails(newVal) {
if (newVal !== this.toEmailsVal) {
this.toEmailsVal = newVal;
}
},
},
mounted() {
this.ccEmailsVal = this.ccEmails;
this.bccEmailsVal = this.bccEmails;
this.toEmailsVal = this.toEmails;
},
validations: {
ccEmailsVal: {
@@ -98,6 +126,11 @@ export default {
return validEmailsByComma(value);
},
},
toEmailsVal: {
hasValidEmails(value) {
return validEmailsByComma(value);
},
},
},
methods: {
handleAddBcc() {
@@ -107,6 +140,7 @@ export default {
this.$v.$touch();
this.$emit('update:bccEmails', this.bccEmailsVal);
this.$emit('update:ccEmails', this.ccEmailsVal);
this.$emit('update:toEmails', this.toEmailsVal);
},
},
};
@@ -16,6 +16,7 @@ export default {
LATEST: 'latest',
CREATED_AT: 'sort_on_created_at',
PRIORITY: 'sort_on_priority',
WATIING_SINCE: 'waiting_since',
},
ARTICLE_STATUS_TYPES: {
DRAFT: 0,
@@ -38,5 +39,7 @@ export default {
UNTIL_NEXT_MONTH: 'until_next_month',
UNTIL_CUSTOM_TIME: 'until_custom_time',
},
EXAMPLE_URL: 'https://example.com',
EXAMPLE_WEBHOOK_URL: 'https://example/api/webhook',
};
export const DEFAULT_REDIRECT_URL = '/app/';
@@ -111,6 +111,7 @@ class ActionCableConnector extends BaseActionCableConnector {
} = data;
DashboardAudioNotificationHelper.onNewMessage(data);
this.app.$store.dispatch('addMessage', data);
this.app.$store.dispatch('updateUnreadCount');
this.app.$store.dispatch('updateConversationLastActivity', {
lastActivityAt,
conversationId,
@@ -0,0 +1,147 @@
const roleMapping = {
0: 'agent',
1: 'administrator',
};
const availabilityMapping = {
0: 'online',
1: 'offline',
2: 'busy',
};
const translationKeys = {
'automationrule:create': `AUDIT_LOGS.AUTOMATION_RULE.ADD`,
'automationrule:update': `AUDIT_LOGS.AUTOMATION_RULE.EDIT`,
'automationrule:destroy': `AUDIT_LOGS.AUTOMATION_RULE.DELETE`,
'webhook:create': `AUDIT_LOGS.WEBHOOK.ADD`,
'webhook:update': `AUDIT_LOGS.WEBHOOK.EDIT`,
'webhook:destroy': `AUDIT_LOGS.WEBHOOK.DELETE`,
'inbox:create': `AUDIT_LOGS.INBOX.ADD`,
'inbox:update': `AUDIT_LOGS.INBOX.EDIT`,
'inbox:destroy': `AUDIT_LOGS.INBOX.DELETE`,
'user:sign_in': `AUDIT_LOGS.USER_ACTION.SIGN_IN`,
'user:sign_out': `AUDIT_LOGS.USER_ACTION.SIGN_OUT`,
'team:create': `AUDIT_LOGS.TEAM.ADD`,
'team:update': `AUDIT_LOGS.TEAM.EDIT`,
'team:destroy': `AUDIT_LOGS.TEAM.DELETE`,
'macro:create': `AUDIT_LOGS.MACRO.ADD`,
'macro:update': `AUDIT_LOGS.MACRO.EDIT`,
'macro:destroy': `AUDIT_LOGS.MACRO.DELETE`,
'accountuser:create': `AUDIT_LOGS.ACCOUNT_USER.ADD`,
'accountuser:update:self': `AUDIT_LOGS.ACCOUNT_USER.EDIT.SELF`,
'accountuser:update:other': `AUDIT_LOGS.ACCOUNT_USER.EDIT.OTHER`,
};
function extractAttrChange(attrChange) {
if (Array.isArray(attrChange)) {
return attrChange[attrChange.length - 1];
}
return attrChange;
}
export function extractChangedAccountUserValues(auditedChanges) {
let changes = [];
let values = [];
// Check roles
if (auditedChanges.role && auditedChanges.role.length) {
changes.push('role');
values.push(roleMapping[extractAttrChange(auditedChanges.role)]);
}
// Check availability
if (auditedChanges.availability && auditedChanges.availability.length) {
changes.push('availability');
values.push(
availabilityMapping[extractAttrChange(auditedChanges.availability)]
);
}
return { changes, values };
}
function getAgentName(userId, agentList) {
if (userId === null) {
return 'System';
}
const agentName = agentList.find(agent => agent.id === userId)?.name;
// If agent does not exist(removed/deleted), return userId
return agentName || userId;
}
function handleAccountUserCreate(auditLogItem, translationPayload, agentList) {
translationPayload.invitee = getAgentName(
auditLogItem.audited_changes.user_id,
agentList
);
const roleKey = auditLogItem.audited_changes.role;
translationPayload.role = roleMapping[roleKey] || 'unknown'; // 'unknown' as a fallback in case an unrecognized key is provided
return translationPayload;
}
function handleAccountUserUpdate(auditLogItem, translationPayload, agentList) {
if (auditLogItem.user_id !== auditLogItem.auditable.user_id) {
translationPayload.user = getAgentName(
auditLogItem.auditable.user_id,
agentList
);
}
const accountUserChanges = extractChangedAccountUserValues(
auditLogItem.audited_changes
);
if (accountUserChanges) {
translationPayload.attributes = accountUserChanges.changes;
translationPayload.values = accountUserChanges.values;
}
return translationPayload;
}
export function generateTranslationPayload(auditLogItem, agentList) {
let translationPayload = {
agentName: getAgentName(auditLogItem.user_id, agentList),
id: auditLogItem.auditable_id,
};
const auditableType = auditLogItem.auditable_type.toLowerCase();
const action = auditLogItem.action.toLowerCase();
if (auditableType === 'accountuser') {
if (action === 'create') {
translationPayload = handleAccountUserCreate(
auditLogItem,
translationPayload,
agentList
);
}
if (action === 'update') {
translationPayload = handleAccountUserUpdate(
auditLogItem,
translationPayload,
agentList
);
}
}
return translationPayload;
}
export const generateLogActionKey = auditLogItem => {
const auditableType = auditLogItem.auditable_type.toLowerCase();
const action = auditLogItem.action.toLowerCase();
let logActionKey = `${auditableType}:${action}`;
if (auditableType === 'accountuser' && action === 'update') {
logActionKey +=
auditLogItem.user_id === auditLogItem.auditable.user_id
? ':self'
: ':other';
}
return translationKeys[logActionKey] || '';
};
@@ -8,6 +8,8 @@ import {
isMonday,
isToday,
setHours,
setMinutes,
setSeconds,
} from 'date-fns';
import wootConstants from 'dashboard/constants/globals';
@@ -36,7 +38,7 @@ export const findNextDay = currentDate => {
};
export const setHoursToNine = date => {
return setHours(date, 9, 0, 0);
return setSeconds(setMinutes(setHours(date, 9), 0), 0);
};
export const findSnoozeTime = (snoozeType, currentDate = new Date()) => {
@@ -0,0 +1,146 @@
import {
extractChangedAccountUserValues,
generateTranslationPayload,
generateLogActionKey,
} from '../auditlogHelper'; // import the functions
describe('Helper functions', () => {
const agentList = [
{ id: 1, name: 'Agent 1' },
{ id: 2, name: 'Agent 2' },
{ id: 3, name: 'Agent 3' },
];
describe('extractChangedAccountUserValues', () => {
it('should correctly extract values when role is changed', () => {
const changes = {
role: [0, 1],
};
const {
changes: extractedChanges,
values,
} = extractChangedAccountUserValues(changes);
expect(extractedChanges).toEqual(['role']);
expect(values).toEqual(['administrator']);
});
it('should correctly extract values when availability is changed', () => {
const changes = {
availability: [0, 2],
};
const {
changes: extractedChanges,
values,
} = extractChangedAccountUserValues(changes);
expect(extractedChanges).toEqual(['availability']);
expect(values).toEqual(['busy']);
});
it('should correctly extract values when both are changed', () => {
const changes = {
role: [1, 0],
availability: [1, 2],
};
const {
changes: extractedChanges,
values,
} = extractChangedAccountUserValues(changes);
expect(extractedChanges).toEqual(['role', 'availability']);
expect(values).toEqual(['agent', 'busy']);
});
});
describe('generateTranslationPayload', () => {
it('should handle AccountUser create', () => {
const auditLogItem = {
auditable_type: 'AccountUser',
action: 'create',
user_id: 1,
auditable_id: 123,
audited_changes: {
user_id: 2,
role: 1,
},
};
const payload = generateTranslationPayload(auditLogItem, agentList);
expect(payload).toEqual({
agentName: 'Agent 1',
id: 123,
invitee: 'Agent 2',
role: 'administrator',
});
});
it('should handle AccountUser update', () => {
const auditLogItem = {
auditable_type: 'AccountUser',
action: 'update',
user_id: 1,
auditable_id: 123,
audited_changes: {
user_id: 2,
role: [1, 0],
availability: [0, 2],
},
auditable: {
user_id: 3,
},
};
const payload = generateTranslationPayload(auditLogItem, agentList);
expect(payload).toEqual({
agentName: 'Agent 1',
id: 123,
user: 'Agent 3',
attributes: ['role', 'availability'],
values: ['agent', 'busy'],
});
});
it('should handle generic case like Team create', () => {
const auditLogItem = {
auditable_type: 'Team',
action: 'create',
user_id: 1,
auditable_id: 456,
};
const payload = generateTranslationPayload(auditLogItem, agentList);
expect(payload).toEqual({
agentName: 'Agent 1',
id: 456,
});
});
});
describe('generateLogActionKey', () => {
it('should generate correct action key when user updates self', () => {
const auditLogItem = {
auditable_type: 'AccountUser',
action: 'update',
user_id: 1,
auditable: {
user_id: 1,
},
};
const logActionKey = generateLogActionKey(auditLogItem);
expect(logActionKey).toEqual('AUDIT_LOGS.ACCOUNT_USER.EDIT.SELF');
});
it('should generate correct action key when user updates other agent', () => {
const auditLogItem = {
auditable_type: 'AccountUser',
action: 'update',
user_id: 1,
auditable: {
user_id: 2,
},
};
const logActionKey = generateLogActionKey(auditLogItem);
expect(logActionKey).toEqual('AUDIT_LOGS.ACCOUNT_USER.EDIT.OTHER');
});
});
});
@@ -40,6 +40,11 @@ describe('#Snooze Helpers', () => {
nextDay.setHours(9, 0, 0, 0);
expect(setHoursToNine(nextDay)).toEqual(nextDay);
});
it('should return date with 9.00AM time if date with 10am is passes', () => {
const nextDay = new Date('06/17/2023 10:00:00');
nextDay.setHours(9, 0, 0, 0);
expect(setHoursToNine(nextDay)).toEqual(nextDay);
});
});
describe('findSnoozeTime', () => {
@@ -19,7 +19,6 @@
"SUCCESS_MESSAGE": "AuditLogs retrieved successfully",
"ERROR_MESSAGE": "تعذر الاتصال بالخادم، الرجاء المحاولة مرة أخرى لاحقاً"
},
"DEFAULT_USER": "System",
"AUTOMATION_RULE": {
"ADD": "%{agentName} created a new automation rule (#%{id})",
"EDIT": "%{agentName} updated an automation rule (#%{id})",
@@ -43,6 +42,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "الأولوية"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "تغيير المحال إليه",
"CHANGE_PRIORITY": "Change Priority",
"CHANGE_TEAM": "تغيير الفريق",
"SNOOZE_CONVERSATION": "تأجيل المحادثة",
"ADD_LABEL": "إضافة تسمية إلى المحادثة",
"REMOVE_LABEL": "إزالة التسمية من المحادثة",
"SETTINGS": "الإعدادات"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "تأجيل المحادثة",
"UNTIL_NEXT_REPLY": "حتى الرد القادم",
"UNTIL_NEXT_WEEK": "حتى الأسبوع القادم",
"UNTIL_TOMORROW": "حتى الغد"
"UNTIL_TOMORROW": "حتى الغد",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Priority"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "Change Assignee",
"CHANGE_PRIORITY": "Change Priority",
"CHANGE_TEAM": "Change Team",
"SNOOZE_CONVERSATION": "Snooze Conversation",
"ADD_LABEL": "Add label to the conversation",
"REMOVE_LABEL": "Remove label from the conversation",
"SETTINGS": "Settings"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "Snooze Conversation",
"UNTIL_NEXT_REPLY": "Until next reply",
"UNTIL_NEXT_WEEK": "Until next week",
"UNTIL_TOMORROW": "Until tomorrow"
"UNTIL_TOMORROW": "Until tomorrow",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Priority"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "Change Assignee",
"CHANGE_PRIORITY": "Change Priority",
"CHANGE_TEAM": "Change Team",
"SNOOZE_CONVERSATION": "Snooze Conversation",
"ADD_LABEL": "Add label to the conversation",
"REMOVE_LABEL": "Remove label from the conversation",
"SETTINGS": "Configuracions"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "Snooze Conversation",
"UNTIL_NEXT_REPLY": "Until next reply",
"UNTIL_NEXT_WEEK": "Until next week",
"UNTIL_TOMORROW": "Until tomorrow"
"UNTIL_TOMORROW": "Until tomorrow",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Priority"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "Change Assignee",
"CHANGE_PRIORITY": "Change Priority",
"CHANGE_TEAM": "Change Team",
"SNOOZE_CONVERSATION": "Snooze Conversation",
"ADD_LABEL": "Add label to the conversation",
"REMOVE_LABEL": "Remove label from the conversation",
"SETTINGS": "Nastavení"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "Snooze Conversation",
"UNTIL_NEXT_REPLY": "Until next reply",
"UNTIL_NEXT_WEEK": "Until next week",
"UNTIL_TOMORROW": "Until tomorrow"
"UNTIL_TOMORROW": "Until tomorrow",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Priority"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "Skift Modtager",
"CHANGE_PRIORITY": "Change Priority",
"CHANGE_TEAM": "Skift Team",
"SNOOZE_CONVERSATION": "Udsæt Samtale",
"ADD_LABEL": "Tilføj etiket til samtalen",
"REMOVE_LABEL": "Fjern etiket fra samtalen",
"SETTINGS": "Indstillinger"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "Udsæt Samtale",
"UNTIL_NEXT_REPLY": "Indtil næste svar",
"UNTIL_NEXT_WEEK": "Indtil næste uge",
"UNTIL_TOMORROW": "Indtil i morgen"
"UNTIL_TOMORROW": "Indtil i morgen",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Priorität"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "Beauftragten ändern",
"CHANGE_PRIORITY": "Priorität ändern",
"CHANGE_TEAM": "Team wechseln",
"SNOOZE_CONVERSATION": "Snooze-Konversation",
"ADD_LABEL": "Label zur Konversation hinzufügen",
"REMOVE_LABEL": "Label aus der Konversation entfernen",
"SETTINGS": "Einstellungen"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "Snooze-Konversation",
"UNTIL_NEXT_REPLY": "Bis zur nächsten Antwort",
"UNTIL_NEXT_WEEK": "Bis nächste Woche",
"UNTIL_TOMORROW": "Bis morgen"
"UNTIL_TOMORROW": "Bis morgen",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Priority"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "Αλλαγή Αναδόχου",
"CHANGE_PRIORITY": "Change Priority",
"CHANGE_TEAM": "Αλλαγή Ομάδας",
"SNOOZE_CONVERSATION": "Αναβολή Συνομιλίας",
"ADD_LABEL": "Προσθήκη ετικέτας στη συνομιλία",
"REMOVE_LABEL": "Αφαίρεση ετικέτας από την συνομιλία",
"SETTINGS": "Ρυθμίσεις"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "Αναβολή Συνομιλίας",
"UNTIL_NEXT_REPLY": "Μέχρι την επόμενη απάντηση",
"UNTIL_NEXT_WEEK": "Έως την επόμενη εβδομάδα",
"UNTIL_TOMORROW": "Μέχρι αύριο"
"UNTIL_TOMORROW": "Μέχρι αύριο",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {
@@ -25,6 +25,13 @@
"EDIT": "%{agentName} updated an automation rule (#%{id})",
"DELETE": "%{agentName} deleted an automation rule (#%{id})"
},
"ACCOUNT_USER": {
"ADD": "%{agentName} invited %{invitee} to the account as an %{role}",
"EDIT": {
"SELF": "%{agentName} changed their %{attributes} to %{values}",
"OTHER": "%{agentName} changed %{attributes} of %{user} to %{values}"
}
},
"INBOX": {
"ADD": "%{agentName} created a new inbox (#%{id})",
"EDIT": "%{agentName} updated an inbox (#%{id})",
@@ -9,11 +9,7 @@
"404": "There are no canned responses available in this account.",
"TITLE": "Manage canned responses",
"DESC": "Canned Responses are predefined reply templates which can be used to quickly send out replies to tickets.",
"TABLE_HEADER": [
"Short Code",
"Content",
"Actions"
]
"TABLE_HEADER": ["Short Code", "Content", "Actions"]
},
"ADD": {
"TITLE": "Add Canned Response",
@@ -34,7 +30,7 @@
},
"API": {
"SUCCESS_MESSAGE": "Canned Response added successfully",
"ERROR_MESSAGE": "Could not create canned response, Please try again later"
"ERROR_MESSAGE": "Could not create canned response. Please try again later."
}
},
"EDIT": {
@@ -56,14 +52,14 @@
"BUTTON_TEXT": "Edit",
"API": {
"SUCCESS_MESSAGE": "Canned Response updated successfully",
"ERROR_MESSAGE": "Could not update canned response, Please try again later"
"ERROR_MESSAGE": "Could not update canned response. Please try again later."
}
},
"DELETE": {
"BUTTON_TEXT": "Delete",
"API": {
"SUCCESS_MESSAGE": "Canned response deleted successfully",
"ERROR_MESSAGE": "Could not delete canned response, Please try again later"
"ERROR_MESSAGE": "Could not delete canned response. Please try again later."
},
"CONFIRM": {
"TITLE": "Confirm Deletion",
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Priority"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -33,7 +33,8 @@
"LABEL_SELECT": {
"TITLE": "Add Labels",
"PLACEHOLDER": "Search labels",
"NO_RESULT": "No labels found"
"NO_RESULT": "No labels found",
"CREATE_LABEL": "Create new label"
}
},
"MERGE_CONTACT": "Merge contact",
@@ -77,7 +78,7 @@
"BUTTON_LABEL": "Export",
"TITLE": "Export Contacts",
"DESC": "Export contacts to a CSV file.",
"SUCCESS_MESSAGE": "Export is in progress, You will be notified via email when export file is ready to dowanlod.",
"SUCCESS_MESSAGE": "Export is in progress. You will be notified on email when the export file is ready to download.",
"ERROR_MESSAGE": "There was an error, please try again"
},
"DELETE_NOTE": {
@@ -147,6 +147,7 @@
"STOP_AUDIO_RECORDING": "Stop audio recording",
"": "",
"EMAIL_HEAD": {
"TO": "TO",
"ADD_BCC": "Add bcc",
"CC": {
"LABEL": "CC",
@@ -3,6 +3,7 @@
"TITLE": "Account settings",
"SUBMIT": "Update settings",
"BACK": "Back",
"DISMISS": "Dismiss",
"UPDATE": {
"ERROR": "Could not update settings, try again!",
"SUCCESS": "Successfully updated account settings"
@@ -179,7 +179,8 @@
}
},
"ADD": {
"CREATE_FLOW": [{
"CREATE_FLOW": [
{
"title": "Help center information",
"route": "new_portal_information",
"body": "Basic information about portal",
@@ -235,13 +236,13 @@
"DOMAIN": {
"LABEL": "Custom Domain",
"PLACEHOLDER": "Portal custom domain",
"HELP_TEXT": "Add only If you want to use a custom domain for your portals. Eg: https://example.com",
"HELP_TEXT": "Add only If you want to use a custom domain for your portals. Eg: %{exampleURL}",
"ERROR": "Enter a valid domain URL"
},
"HOME_PAGE_LINK": {
"LABEL": "Home Page Link",
"PLACEHOLDER": "Portal home page link",
"HELP_TEXT": "The link used to return from the portal to the home page. Eg: https://example.com",
"HELP_TEXT": "The link used to return from the portal to the home page. Eg: %{exampleURL}",
"ERROR": "Enter a valid home page URL"
},
"THEME_COLOR": {
@@ -21,7 +21,7 @@
},
"END_POINT": {
"LABEL": "Webhook URL",
"PLACEHOLDER": "Example: https://example/api/webhook",
"PLACEHOLDER": "Example: %{webhookExampleURL}",
"ERROR": "Please enter a valid URL"
},
"EDIT_SUBMIT": "Update webhook",
@@ -18,6 +18,8 @@
"EMPTY_STATE_DEFAULT": "Search by conversation id, email, phone number, messages for better search results. ",
"BOT_LABEL": "Bot",
"READ_MORE": "Read more",
"WROTE": "wrote:"
"WROTE": "wrote:",
"FROM": "from",
"EMAIL": "email"
}
}
@@ -1,18 +1,18 @@
{
"FILTER": {
"TITLE": "Filtrar Conversaciones",
"SUBTITLE": "Añada filtros a continuación y pulse 'Enviar' para filtrar conversaciones.",
"EDIT_CUSTOM_FILTER": "Edit Folder",
"CUSTOM_VIEWS_SUBTITLE": "Add or remove filters and update your folder.",
"TITLE": "Filtrar conversaciones",
"SUBTITLE": "Agregue filtros a continuación y presione 'Aplicar filtros' para filtrar conversaciones.",
"EDIT_CUSTOM_FILTER": "Editar carpeta",
"CUSTOM_VIEWS_SUBTITLE": "Agregar o eliminar filtros y actualizar la carpeta.",
"ADD_NEW_FILTER": "Añadir Filtro",
"FILTER_DELETE_ERROR": "Debes tener al menos un filtro para guardar",
"SUBMIT_BUTTON_LABEL": "Aplicar filtros",
"UPDATE_BUTTON_LABEL": "Update folder",
"UPDATE_BUTTON_LABEL": "Actualizar carpeta",
"CANCEL_BUTTON_LABEL": "Cancelar",
"CLEAR_BUTTON_LABEL": "Limpiar filtros",
"EMPTY_VALUE_ERROR": "El valor es requerido",
"FOLDER_LABEL": "Folder Name",
"FOLDER_QUERY_LABEL": "Folder Query",
"FOLDER_LABEL": "Nombre de la carpeta",
"FOLDER_QUERY_LABEL": "Consulta de carpetas",
"TOOLTIP_LABEL": "Filtrar conversaciones",
"QUERY_DROPDOWN_LABELS": {
"AND": "Y",
@@ -77,7 +77,7 @@
}
},
"EDIT": {
"EDIT_BUTTON": "Edit folder"
"EDIT_BUTTON": "Editar carpeta"
},
"DELETE": {
"DELETE_BUTTON": "Eliminar filtro",
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Prioridad"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -74,10 +74,10 @@
"ERROR_MESSAGE": "Hubo un error, por favor inténtelo de nuevo"
},
"EXPORT_CONTACTS": {
"BUTTON_LABEL": "Export",
"TITLE": "Export Contacts",
"DESC": "Export contacts to a CSV file.",
"SUCCESS_MESSAGE": "Export is in progress, You will be notified via email when export file is ready to dowanlod.",
"BUTTON_LABEL": "Exportar",
"TITLE": "Exportar contactos",
"DESC": "Exportar contactos a un archivo CSV.",
"SUCCESS_MESSAGE": "El proceso de exportar esta en proceso. Será notificado por correo cuando el archivo esté listo para descargar.",
"ERROR_MESSAGE": "Hubo un error, por favor inténtelo de nuevo"
},
"DELETE_NOTE": {
@@ -218,7 +218,7 @@
"FILTER_CONTACTS": "Filtro",
"FILTER_CONTACTS_SAVE": "Guardar filtro",
"FILTER_CONTACTS_DELETE": "Eliminar filtro",
"FILTER_CONTACTS_EDIT": "Edit segment",
"FILTER_CONTACTS_EDIT": "Editar segmento",
"LIST": {
"LOADING_MESSAGE": "Cargando contactos...",
"404": "No hay contactos que coincidan con tu búsqueda 🔍",
@@ -2,18 +2,18 @@
"CONTACTS_FILTER": {
"TITLE": "Filtrar contactos",
"SUBTITLE": "Añada filtros a continuación y pulse 'Enviar' para filtrar contactos.",
"EDIT_CUSTOM_SEGMENT": "Edit Segment",
"CUSTOM_VIEWS_SUBTITLE": "Add or remove filters and update your segment.",
"EDIT_CUSTOM_SEGMENT": "Editar segmento",
"CUSTOM_VIEWS_SUBTITLE": "Agregar o quitar filtros y actualiza tu segmento.",
"ADD_NEW_FILTER": "Añadir Filtro",
"CLEAR_ALL_FILTERS": "Limpiar todos los filtros",
"FILTER_DELETE_ERROR": "Debes tener al menos un filtro para guardar",
"SUBMIT_BUTTON_LABEL": "Enviar",
"UPDATE_BUTTON_LABEL": "Update Segment",
"UPDATE_BUTTON_LABEL": "Actualizar segmento",
"CANCEL_BUTTON_LABEL": "Cancelar",
"CLEAR_BUTTON_LABEL": "Limpiar filtros",
"EMPTY_VALUE_ERROR": "El valor es requerido",
"SEGMENT_LABEL": "Segment Name",
"SEGMENT_QUERY_LABEL": "Segment Query",
"SEGMENT_LABEL": "Nombre del segmento",
"SEGMENT_QUERY_LABEL": "Consulta de segmentos",
"TOOLTIP_LABEL": "Filtrar contactos",
"QUERY_DROPDOWN_LABELS": {
"AND": "Y",
@@ -49,9 +49,9 @@
},
"UPDATE_CHATWOOT": "Hay una actualización %{latestChatwootVersion} para Chatwoot disponible. Por favor, actualiza tu instancia.",
"LEARN_MORE": "Más información",
"PAYMENT_PENDING": "Your payment is pending. Please update your payment information to continue using Chatwoot",
"LIMITS_UPGRADE": "Your account has exceeded the usage limits, please upgrade your plan to continue using Chatwoot",
"OPEN_BILLING": "Open billing"
"PAYMENT_PENDING": "Tu pago está pendiente. Por favor actualiza tu información de pago para seguir usando Chatwoot",
"LIMITS_UPGRADE": "Su cuenta ha excedido los límites de uso, por favor actualice su plan para seguir usando Chatwoot",
"OPEN_BILLING": "Abrir facturación"
},
"FORMS": {
"MULTISELECT": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "Cambiar Asignado",
"CHANGE_PRIORITY": "Cambiar prioridad",
"CHANGE_TEAM": "Cambiar equipo",
"SNOOZE_CONVERSATION": "Posponer conversación",
"ADD_LABEL": "Añadir etiqueta a la conversación",
"REMOVE_LABEL": "Eliminar etiqueta de la conversación",
"SETTINGS": "Ajustes"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "Posponer conversación",
"UNTIL_NEXT_REPLY": "Hasta la siguiente respuesta",
"UNTIL_NEXT_WEEK": "Hasta la próxima semana",
"UNTIL_TOMORROW": "Hasta mañana"
"UNTIL_TOMORROW": "Hasta mañana",
"UNTIL_NEXT_MONTH": "Hasta el mes próximo",
"AN_HOUR_FROM_NOW": "Hasta una hora a partir de ahora",
"CUSTOM": "Personalizar..."
}
},
"DASHBOARD_APPS": {
@@ -75,12 +75,12 @@
}
},
"ARTICLE_SEARCH_RESULT": {
"UNCATEGORIZED": "Uncategorized",
"INSERT_ARTICLE": "Insert",
"NO_RESULT": "No articles found",
"COPY_LINK": "Copy article link to clipboard",
"OPEN_LINK": "Open article in new tab",
"PREVIEW_LINK": "Preview article"
"UNCATEGORIZED": "Sin categoría",
"INSERT_ARTICLE": "Insertar",
"NO_RESULT": "No se encontraron articulos",
"COPY_LINK": "Copiar enlace del artículo al portapapeles",
"OPEN_LINK": "Abrir artículo en nueva pestaña",
"PREVIEW_LINK": "Previsualizar artículo"
},
"PORTAL": {
"HEADER": "Portales",
@@ -4,7 +4,7 @@
"LOADING_CHART": "Cargando datos del gráfico...",
"NO_ENOUGH_DATA": "No hemos recibido suficientes puntos de datos para generar el informe. Inténtalo de nuevo más tarde.",
"DOWNLOAD_AGENT_REPORTS": "Descargar reportes de agente",
"DATA_FETCHING_FAILED": "Failed to fetch data, please try again later.",
"DATA_FETCHING_FAILED": "Error al obtener datos, por favor intente nuevamente.",
"SUMMARY_FETCHING_FAILED": "Failed to fetch summary, please try again later.",
"METRICS": {
"CONVERSATIONS": {
@@ -404,7 +404,7 @@
"HEADER": "Reporte de encuestas de satisfacción",
"NO_RECORDS": "No hay respuestas de encuestas de satisfacción disponibles.",
"DOWNLOAD": "Descargar reportes CSAT",
"DOWNLOAD_FAILED": "Failed to download CSAT Reports",
"DOWNLOAD_FAILED": "Error al descargar los informes CSAT",
"FILTERS": {
"AGENTS": {
"PLACEHOLDER": "Elegir agentes"
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "اولویت"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "نماینده را تغییر دهید",
"CHANGE_PRIORITY": "Change Priority",
"CHANGE_TEAM": "تیم را تغییر دهید",
"SNOOZE_CONVERSATION": "به تعویق انداختن مکالمه",
"ADD_LABEL": "برچسب را به مکالمه اضافه کنید",
"REMOVE_LABEL": "برچسب را از مکالمه حذف کنید",
"SETTINGS": "تنظیمات"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "به تعویق انداختن مکالمه",
"UNTIL_NEXT_REPLY": "تا پاسخ بعدی",
"UNTIL_NEXT_WEEK": "تا هفته بعد",
"UNTIL_TOMORROW": "تا فردا"
"UNTIL_TOMORROW": "تا فردا",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Priority"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "Change Assignee",
"CHANGE_PRIORITY": "Change Priority",
"CHANGE_TEAM": "Change Team",
"SNOOZE_CONVERSATION": "Snooze Conversation",
"ADD_LABEL": "Add label to the conversation",
"REMOVE_LABEL": "Remove label from the conversation",
"SETTINGS": "Asetukset"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "Snooze Conversation",
"UNTIL_NEXT_REPLY": "Until next reply",
"UNTIL_NEXT_WEEK": "Until next week",
"UNTIL_TOMORROW": "Until tomorrow"
"UNTIL_TOMORROW": "Until tomorrow",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Priority"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "Change Assignee",
"CHANGE_PRIORITY": "Change Priority",
"CHANGE_TEAM": "Changer d’équipe",
"SNOOZE_CONVERSATION": "Snooze Conversation",
"ADD_LABEL": "Add label to the conversation",
"REMOVE_LABEL": "Remove label from the conversation",
"SETTINGS": "Paramètres"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "Snooze Conversation",
"UNTIL_NEXT_REPLY": "Until next reply",
"UNTIL_NEXT_WEEK": "Until next week",
"UNTIL_TOMORROW": "Until tomorrow"
"UNTIL_TOMORROW": "Until tomorrow",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Priority"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "שנה מוקצה",
"CHANGE_PRIORITY": "Change Priority",
"CHANGE_TEAM": "להחליף קבוצה",
"SNOOZE_CONVERSATION": "נודניק שיחה",
"ADD_LABEL": "הוסף תווית לשיחה",
"REMOVE_LABEL": "הסר תווית מהשיחה",
"SETTINGS": "הגדרות"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "נודניק שיחה",
"UNTIL_NEXT_REPLY": "עד לתשובה הבאה",
"UNTIL_NEXT_WEEK": "עד שבוע הבא",
"UNTIL_TOMORROW": "עד מחר"
"UNTIL_TOMORROW": "עד מחר",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Priority"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "Change Assignee",
"CHANGE_PRIORITY": "Change Priority",
"CHANGE_TEAM": "Change Team",
"SNOOZE_CONVERSATION": "Snooze Conversation",
"ADD_LABEL": "Add label to the conversation",
"REMOVE_LABEL": "Remove label from the conversation",
"SETTINGS": "Settings"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "Snooze Conversation",
"UNTIL_NEXT_REPLY": "Until next reply",
"UNTIL_NEXT_WEEK": "Until next week",
"UNTIL_TOMORROW": "Until tomorrow"
"UNTIL_TOMORROW": "Until tomorrow",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Prioritet"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "Change Assignee",
"CHANGE_PRIORITY": "Promjena prioriteta",
"CHANGE_TEAM": "Change Team",
"SNOOZE_CONVERSATION": "Snooze Conversation",
"ADD_LABEL": "Add label to the conversation",
"REMOVE_LABEL": "Remove label from the conversation",
"SETTINGS": "Settings"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "Snooze Conversation",
"UNTIL_NEXT_REPLY": "Until next reply",
"UNTIL_NEXT_WEEK": "Until next week",
"UNTIL_TOMORROW": "Until tomorrow"
"UNTIL_TOMORROW": "Until tomorrow",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Priority"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "Change Assignee",
"CHANGE_PRIORITY": "Change Priority",
"CHANGE_TEAM": "Change Team",
"SNOOZE_CONVERSATION": "Snooze Conversation",
"ADD_LABEL": "Add label to the conversation",
"REMOVE_LABEL": "Remove label from the conversation",
"SETTINGS": "Beállítások"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "Snooze Conversation",
"UNTIL_NEXT_REPLY": "Until next reply",
"UNTIL_NEXT_WEEK": "Until next week",
"UNTIL_TOMORROW": "Until tomorrow"
"UNTIL_TOMORROW": "Until tomorrow",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Priority"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "Change Assignee",
"CHANGE_PRIORITY": "Change Priority",
"CHANGE_TEAM": "Change Team",
"SNOOZE_CONVERSATION": "Snooze Conversation",
"ADD_LABEL": "Add label to the conversation",
"REMOVE_LABEL": "Remove label from the conversation",
"SETTINGS": "Settings"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "Snooze Conversation",
"UNTIL_NEXT_REPLY": "Until next reply",
"UNTIL_NEXT_WEEK": "Until next week",
"UNTIL_TOMORROW": "Until tomorrow"
"UNTIL_TOMORROW": "Until tomorrow",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Priority"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "Change Assignee",
"CHANGE_PRIORITY": "Change Priority",
"CHANGE_TEAM": "Change Team",
"SNOOZE_CONVERSATION": "Snooze Conversation",
"ADD_LABEL": "Add label to the conversation",
"REMOVE_LABEL": "Remove label from the conversation",
"SETTINGS": "Pengaturan"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "Snooze Conversation",
"UNTIL_NEXT_REPLY": "Until next reply",
"UNTIL_NEXT_WEEK": "Until next week",
"UNTIL_TOMORROW": "Until tomorrow"
"UNTIL_TOMORROW": "Until tomorrow",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Priority"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "Breyta úthlutun",
"CHANGE_PRIORITY": "Change Priority",
"CHANGE_TEAM": "Breyta Teymi",
"SNOOZE_CONVERSATION": "Fresta Samtali",
"ADD_LABEL": "Merkja samtalið",
"REMOVE_LABEL": "Fjarlægja merki af samtali",
"SETTINGS": "Stillingar"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "Fresta Samtali",
"UNTIL_NEXT_REPLY": "Þar til að næsta svar berst",
"UNTIL_NEXT_WEEK": "Þar til í næstu viku",
"UNTIL_TOMORROW": "Þar til á morgun"
"UNTIL_TOMORROW": "Þar til á morgun",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {
@@ -43,6 +43,11 @@
"ADD": "%{agentName} created a new team (#%{id})",
"EDIT": "%{agentName} updated a team (#%{id})",
"DELETE": "%{agentName} deleted a team (#%{id})"
},
"MACRO": {
"ADD": "%{agentName} created a new macro (#%{id})",
"EDIT": "%{agentName} updated a macro (#%{id})",
"DELETE": "%{agentName} deleted a macro (#%{id})"
}
}
}
@@ -50,6 +50,9 @@
},
"sort_on_priority": {
"TEXT": "Priorità"
},
"sort_on_waiting_since": {
"TEXT": "Pending Response"
}
},
"ATTACHMENTS": {
@@ -106,6 +106,7 @@
"CHANGE_ASSIGNEE": "Cambia assegnatario",
"CHANGE_PRIORITY": "Change Priority",
"CHANGE_TEAM": "Cambia Team",
"SNOOZE_CONVERSATION": "Posticipa conversazione",
"ADD_LABEL": "Aggiungi etichetta alla conversazione",
"REMOVE_LABEL": "Rimuovi etichetta dalla conversazione",
"SETTINGS": "Impostazioni"
@@ -141,7 +142,10 @@
"SNOOZE_CONVERSATION": "Posticipa conversazione",
"UNTIL_NEXT_REPLY": "Fino alla prossima risposta",
"UNTIL_NEXT_WEEK": "Fino alla prossima settimana",
"UNTIL_TOMORROW": "Fino a domani"
"UNTIL_TOMORROW": "Fino a domani",
"UNTIL_NEXT_MONTH": "Until next month",
"AN_HOUR_FROM_NOW": "Until an hour from now",
"CUSTOM": "Custom..."
}
},
"DASHBOARD_APPS": {

Some files were not shown because too many files have changed in this diff Show More