Merge branch 'release/2.5.0'
This commit is contained in:
commit
63b1013b45
@ -161,13 +161,15 @@ USE_INBOX_AVATAR_FOR_BOT=true
|
|||||||
## NewRelic
|
## NewRelic
|
||||||
# https://docs.newrelic.com/docs/agents/ruby-agent/configuration/ruby-agent-configuration/
|
# https://docs.newrelic.com/docs/agents/ruby-agent/configuration/ruby-agent-configuration/
|
||||||
# NEW_RELIC_LICENSE_KEY=
|
# NEW_RELIC_LICENSE_KEY=
|
||||||
|
# Set this to true to allow newrelic apm to send logs.
|
||||||
|
# This is turned off by default.
|
||||||
|
# NEW_RELIC_APPLICATION_LOGGING_ENABLED=
|
||||||
|
|
||||||
## Datadog
|
## Datadog
|
||||||
## https://github.com/DataDog/dd-trace-rb/blob/master/docs/GettingStarted.md#environment-variables
|
## https://github.com/DataDog/dd-trace-rb/blob/master/docs/GettingStarted.md#environment-variables
|
||||||
# DD_TRACE_AGENT_URL=
|
# DD_TRACE_AGENT_URL=
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## IP look up configuration
|
## IP look up configuration
|
||||||
## ref https://github.com/alexreisner/geocoder/blob/master/README_API_GUIDE.md
|
## ref https://github.com/alexreisner/geocoder/blob/master/README_API_GUIDE.md
|
||||||
## works only on accounts with ip look up feature enabled
|
## works only on accounts with ip look up feature enabled
|
||||||
|
|||||||
3
.github/workflows/run_foss_spec.yml
vendored
3
.github/workflows/run_foss_spec.yml
vendored
@ -42,7 +42,8 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.head_ref }}
|
ref: ${{ github.event.pull_request.head.ref }}
|
||||||
|
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||||
|
|
||||||
- uses: ruby/setup-ruby@v1
|
- uses: ruby/setup-ruby@v1
|
||||||
with:
|
with:
|
||||||
|
|||||||
8
Gemfile
8
Gemfile
@ -97,14 +97,14 @@ gem 'brakeman'
|
|||||||
gem 'ddtrace'
|
gem 'ddtrace'
|
||||||
gem 'newrelic_rpm'
|
gem 'newrelic_rpm'
|
||||||
gem 'scout_apm'
|
gem 'scout_apm'
|
||||||
gem 'sentry-rails'
|
gem 'sentry-rails', '~> 5.3'
|
||||||
gem 'sentry-ruby'
|
gem 'sentry-ruby', '~> 5.3'
|
||||||
gem 'sentry-sidekiq'
|
gem 'sentry-sidekiq', '~> 5.3'
|
||||||
|
|
||||||
##-- background job processing --##
|
##-- background job processing --##
|
||||||
gem 'sidekiq', '~> 6.4.0'
|
gem 'sidekiq', '~> 6.4.0'
|
||||||
# We want cron jobs
|
# We want cron jobs
|
||||||
gem 'sidekiq-cron'
|
gem 'sidekiq-cron', '~> 1.3'
|
||||||
|
|
||||||
##-- Push notification service --##
|
##-- Push notification service --##
|
||||||
gem 'fcm'
|
gem 'fcm'
|
||||||
|
|||||||
158
Gemfile.lock
158
Gemfile.lock
@ -9,63 +9,63 @@ GIT
|
|||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
actioncable (6.1.4.7)
|
actioncable (6.1.5.1)
|
||||||
actionpack (= 6.1.4.7)
|
actionpack (= 6.1.5.1)
|
||||||
activesupport (= 6.1.4.7)
|
activesupport (= 6.1.5.1)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
websocket-driver (>= 0.6.1)
|
websocket-driver (>= 0.6.1)
|
||||||
actionmailbox (6.1.4.7)
|
actionmailbox (6.1.5.1)
|
||||||
actionpack (= 6.1.4.7)
|
actionpack (= 6.1.5.1)
|
||||||
activejob (= 6.1.4.7)
|
activejob (= 6.1.5.1)
|
||||||
activerecord (= 6.1.4.7)
|
activerecord (= 6.1.5.1)
|
||||||
activestorage (= 6.1.4.7)
|
activestorage (= 6.1.5.1)
|
||||||
activesupport (= 6.1.4.7)
|
activesupport (= 6.1.5.1)
|
||||||
mail (>= 2.7.1)
|
mail (>= 2.7.1)
|
||||||
actionmailer (6.1.4.7)
|
actionmailer (6.1.5.1)
|
||||||
actionpack (= 6.1.4.7)
|
actionpack (= 6.1.5.1)
|
||||||
actionview (= 6.1.4.7)
|
actionview (= 6.1.5.1)
|
||||||
activejob (= 6.1.4.7)
|
activejob (= 6.1.5.1)
|
||||||
activesupport (= 6.1.4.7)
|
activesupport (= 6.1.5.1)
|
||||||
mail (~> 2.5, >= 2.5.4)
|
mail (~> 2.5, >= 2.5.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
actionpack (6.1.4.7)
|
actionpack (6.1.5.1)
|
||||||
actionview (= 6.1.4.7)
|
actionview (= 6.1.5.1)
|
||||||
activesupport (= 6.1.4.7)
|
activesupport (= 6.1.5.1)
|
||||||
rack (~> 2.0, >= 2.0.9)
|
rack (~> 2.0, >= 2.0.9)
|
||||||
rack-test (>= 0.6.3)
|
rack-test (>= 0.6.3)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||||
actiontext (6.1.4.7)
|
actiontext (6.1.5.1)
|
||||||
actionpack (= 6.1.4.7)
|
actionpack (= 6.1.5.1)
|
||||||
activerecord (= 6.1.4.7)
|
activerecord (= 6.1.5.1)
|
||||||
activestorage (= 6.1.4.7)
|
activestorage (= 6.1.5.1)
|
||||||
activesupport (= 6.1.4.7)
|
activesupport (= 6.1.5.1)
|
||||||
nokogiri (>= 1.8.5)
|
nokogiri (>= 1.8.5)
|
||||||
actionview (6.1.4.7)
|
actionview (6.1.5.1)
|
||||||
activesupport (= 6.1.4.7)
|
activesupport (= 6.1.5.1)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
erubi (~> 1.4)
|
erubi (~> 1.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||||
active_record_query_trace (1.8)
|
active_record_query_trace (1.8)
|
||||||
activejob (6.1.4.7)
|
activejob (6.1.5.1)
|
||||||
activesupport (= 6.1.4.7)
|
activesupport (= 6.1.5.1)
|
||||||
globalid (>= 0.3.6)
|
globalid (>= 0.3.6)
|
||||||
activemodel (6.1.4.7)
|
activemodel (6.1.5.1)
|
||||||
activesupport (= 6.1.4.7)
|
activesupport (= 6.1.5.1)
|
||||||
activerecord (6.1.4.7)
|
activerecord (6.1.5.1)
|
||||||
activemodel (= 6.1.4.7)
|
activemodel (= 6.1.5.1)
|
||||||
activesupport (= 6.1.4.7)
|
activesupport (= 6.1.5.1)
|
||||||
activerecord-import (1.3.0)
|
activerecord-import (1.3.0)
|
||||||
activerecord (>= 4.2)
|
activerecord (>= 4.2)
|
||||||
activestorage (6.1.4.7)
|
activestorage (6.1.5.1)
|
||||||
actionpack (= 6.1.4.7)
|
actionpack (= 6.1.5.1)
|
||||||
activejob (= 6.1.4.7)
|
activejob (= 6.1.5.1)
|
||||||
activerecord (= 6.1.4.7)
|
activerecord (= 6.1.5.1)
|
||||||
activesupport (= 6.1.4.7)
|
activesupport (= 6.1.5.1)
|
||||||
marcel (~> 1.0.0)
|
marcel (~> 1.0)
|
||||||
mini_mime (>= 1.1.0)
|
mini_mime (>= 1.1.0)
|
||||||
activesupport (6.1.4.7)
|
activesupport (6.1.5.1)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
i18n (>= 1.6, < 2)
|
i18n (>= 1.6, < 2)
|
||||||
minitest (>= 5.1)
|
minitest (>= 5.1)
|
||||||
@ -136,7 +136,7 @@ GEM
|
|||||||
climate_control (1.0.1)
|
climate_control (1.0.1)
|
||||||
coderay (1.1.3)
|
coderay (1.1.3)
|
||||||
commonmarker (0.23.4)
|
commonmarker (0.23.4)
|
||||||
concurrent-ruby (1.1.9)
|
concurrent-ruby (1.1.10)
|
||||||
connection_pool (2.2.5)
|
connection_pool (2.2.5)
|
||||||
crack (0.4.5)
|
crack (0.4.5)
|
||||||
rexml
|
rexml
|
||||||
@ -183,7 +183,7 @@ GEM
|
|||||||
email_reply_trimmer (0.1.13)
|
email_reply_trimmer (0.1.13)
|
||||||
erubi (1.10.0)
|
erubi (1.10.0)
|
||||||
erubis (2.7.0)
|
erubis (2.7.0)
|
||||||
et-orbi (1.2.6)
|
et-orbi (1.2.7)
|
||||||
tzinfo
|
tzinfo
|
||||||
execjs (2.8.1)
|
execjs (2.8.1)
|
||||||
facebook-messenger (2.0.1)
|
facebook-messenger (2.0.1)
|
||||||
@ -210,8 +210,8 @@ GEM
|
|||||||
ruby_parser (~> 3.0)
|
ruby_parser (~> 3.0)
|
||||||
sexp_processor (~> 4.0)
|
sexp_processor (~> 4.0)
|
||||||
foreman (0.87.2)
|
foreman (0.87.2)
|
||||||
fugit (1.5.2)
|
fugit (1.5.3)
|
||||||
et-orbi (~> 1.1, >= 1.1.8)
|
et-orbi (~> 1, >= 1.2.7)
|
||||||
raabro (~> 1.4)
|
raabro (~> 1.4)
|
||||||
gapic-common (0.3.4)
|
gapic-common (0.3.4)
|
||||||
google-protobuf (~> 3.12, >= 3.12.2)
|
google-protobuf (~> 3.12, >= 3.12.2)
|
||||||
@ -349,7 +349,7 @@ GEM
|
|||||||
listen (3.7.1)
|
listen (3.7.1)
|
||||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||||
rb-inotify (~> 0.9, >= 0.9.10)
|
rb-inotify (~> 0.9, >= 0.9.10)
|
||||||
loofah (2.14.0)
|
loofah (2.17.0)
|
||||||
crass (~> 1.0.2)
|
crass (~> 1.0.2)
|
||||||
nokogiri (>= 1.5.9)
|
nokogiri (>= 1.5.9)
|
||||||
mail (2.7.1)
|
mail (2.7.1)
|
||||||
@ -376,16 +376,16 @@ GEM
|
|||||||
net-http-persistent (4.0.1)
|
net-http-persistent (4.0.1)
|
||||||
connection_pool (~> 2.2)
|
connection_pool (~> 2.2)
|
||||||
netrc (0.11.0)
|
netrc (0.11.0)
|
||||||
newrelic_rpm (8.4.0)
|
newrelic_rpm (8.7.0)
|
||||||
nio4r (2.5.8)
|
nio4r (2.5.8)
|
||||||
nokogiri (1.13.4)
|
nokogiri (1.13.5)
|
||||||
mini_portile2 (~> 2.8.0)
|
mini_portile2 (~> 2.8.0)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.13.4-arm64-darwin)
|
nokogiri (1.13.5-arm64-darwin)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.13.4-x86_64-darwin)
|
nokogiri (1.13.5-x86_64-darwin)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.13.4-x86_64-linux)
|
nokogiri (1.13.5-x86_64-linux)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
oauth (0.5.8)
|
oauth (0.5.8)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
@ -419,31 +419,31 @@ GEM
|
|||||||
rack-test (1.1.0)
|
rack-test (1.1.0)
|
||||||
rack (>= 1.0, < 3)
|
rack (>= 1.0, < 3)
|
||||||
rack-timeout (0.6.0)
|
rack-timeout (0.6.0)
|
||||||
rails (6.1.4.7)
|
rails (6.1.5.1)
|
||||||
actioncable (= 6.1.4.7)
|
actioncable (= 6.1.5.1)
|
||||||
actionmailbox (= 6.1.4.7)
|
actionmailbox (= 6.1.5.1)
|
||||||
actionmailer (= 6.1.4.7)
|
actionmailer (= 6.1.5.1)
|
||||||
actionpack (= 6.1.4.7)
|
actionpack (= 6.1.5.1)
|
||||||
actiontext (= 6.1.4.7)
|
actiontext (= 6.1.5.1)
|
||||||
actionview (= 6.1.4.7)
|
actionview (= 6.1.5.1)
|
||||||
activejob (= 6.1.4.7)
|
activejob (= 6.1.5.1)
|
||||||
activemodel (= 6.1.4.7)
|
activemodel (= 6.1.5.1)
|
||||||
activerecord (= 6.1.4.7)
|
activerecord (= 6.1.5.1)
|
||||||
activestorage (= 6.1.4.7)
|
activestorage (= 6.1.5.1)
|
||||||
activesupport (= 6.1.4.7)
|
activesupport (= 6.1.5.1)
|
||||||
bundler (>= 1.15.0)
|
bundler (>= 1.15.0)
|
||||||
railties (= 6.1.4.7)
|
railties (= 6.1.5.1)
|
||||||
sprockets-rails (>= 2.0.0)
|
sprockets-rails (>= 2.0.0)
|
||||||
rails-dom-testing (2.0.3)
|
rails-dom-testing (2.0.3)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
nokogiri (>= 1.6)
|
nokogiri (>= 1.6)
|
||||||
rails-html-sanitizer (1.4.2)
|
rails-html-sanitizer (1.4.2)
|
||||||
loofah (~> 2.3)
|
loofah (~> 2.3)
|
||||||
railties (6.1.4.7)
|
railties (6.1.5.1)
|
||||||
actionpack (= 6.1.4.7)
|
actionpack (= 6.1.5.1)
|
||||||
activesupport (= 6.1.4.7)
|
activesupport (= 6.1.5.1)
|
||||||
method_source
|
method_source
|
||||||
rake (>= 0.13)
|
rake (>= 12.2)
|
||||||
thor (~> 1.0)
|
thor (~> 1.0)
|
||||||
rainbow (3.1.1)
|
rainbow (3.1.1)
|
||||||
rake (13.0.6)
|
rake (13.0.6)
|
||||||
@ -533,16 +533,16 @@ GEM
|
|||||||
activesupport (>= 4)
|
activesupport (>= 4)
|
||||||
selectize-rails (0.12.6)
|
selectize-rails (0.12.6)
|
||||||
semantic_range (3.0.0)
|
semantic_range (3.0.0)
|
||||||
sentry-rails (5.1.0)
|
sentry-rails (5.3.0)
|
||||||
railties (>= 5.0)
|
railties (>= 5.0)
|
||||||
sentry-ruby-core (~> 5.1.0)
|
sentry-ruby-core (~> 5.3.0)
|
||||||
sentry-ruby (5.1.0)
|
sentry-ruby (5.3.0)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
sentry-ruby-core (= 5.1.0)
|
sentry-ruby-core (= 5.3.0)
|
||||||
sentry-ruby-core (5.1.0)
|
sentry-ruby-core (5.3.0)
|
||||||
concurrent-ruby
|
concurrent-ruby
|
||||||
sentry-sidekiq (5.1.0)
|
sentry-sidekiq (5.3.0)
|
||||||
sentry-ruby-core (~> 5.1.0)
|
sentry-ruby-core (~> 5.3.0)
|
||||||
sidekiq (>= 3.0)
|
sidekiq (>= 3.0)
|
||||||
sexp_processor (4.16.0)
|
sexp_processor (4.16.0)
|
||||||
shoulda-matchers (5.1.0)
|
shoulda-matchers (5.1.0)
|
||||||
@ -551,8 +551,8 @@ GEM
|
|||||||
connection_pool (>= 2.2.2)
|
connection_pool (>= 2.2.2)
|
||||||
rack (~> 2.0)
|
rack (~> 2.0)
|
||||||
redis (>= 4.2.0)
|
redis (>= 4.2.0)
|
||||||
sidekiq-cron (1.2.0)
|
sidekiq-cron (1.4.0)
|
||||||
fugit (~> 1.1)
|
fugit (~> 1)
|
||||||
sidekiq (>= 4.2.1)
|
sidekiq (>= 4.2.1)
|
||||||
signet (0.16.0)
|
signet (0.16.0)
|
||||||
addressable (~> 2.8)
|
addressable (~> 2.8)
|
||||||
@ -726,12 +726,12 @@ DEPENDENCIES
|
|||||||
rubocop-rspec
|
rubocop-rspec
|
||||||
scout_apm
|
scout_apm
|
||||||
seed_dump
|
seed_dump
|
||||||
sentry-rails
|
sentry-rails (~> 5.3)
|
||||||
sentry-ruby
|
sentry-ruby (~> 5.3)
|
||||||
sentry-sidekiq
|
sentry-sidekiq (~> 5.3)
|
||||||
shoulda-matchers
|
shoulda-matchers
|
||||||
sidekiq (~> 6.4.0)
|
sidekiq (~> 6.4.0)
|
||||||
sidekiq-cron
|
sidekiq-cron (~> 1.3)
|
||||||
simplecov (= 0.17.1)
|
simplecov (= 0.17.1)
|
||||||
slack-ruby-client
|
slack-ruby-client
|
||||||
spring
|
spring
|
||||||
@ -755,4 +755,4 @@ RUBY VERSION
|
|||||||
ruby 3.0.2p107
|
ruby 3.0.2p107
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
2.3.8
|
2.3.10
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
class Campaigns::CampaignConversationBuilder
|
class Campaigns::CampaignConversationBuilder
|
||||||
pattr_initialize [:contact_inbox_id!, :campaign_display_id!, :conversation_additional_attributes]
|
pattr_initialize [:contact_inbox_id!, :campaign_display_id!, :conversation_additional_attributes, :custom_attributes]
|
||||||
|
|
||||||
def perform
|
def perform
|
||||||
@contact_inbox = ContactInbox.find(@contact_inbox_id)
|
@contact_inbox = ContactInbox.find(@contact_inbox_id)
|
||||||
@ -21,7 +21,8 @@ class Campaigns::CampaignConversationBuilder
|
|||||||
|
|
||||||
def message_params
|
def message_params
|
||||||
ActionController::Parameters.new({
|
ActionController::Parameters.new({
|
||||||
content: @campaign.message
|
content: @campaign.message,
|
||||||
|
campaign_id: @campaign.id
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -32,7 +33,8 @@ class Campaigns::CampaignConversationBuilder
|
|||||||
contact_id: @contact_inbox.contact_id,
|
contact_id: @contact_inbox.contact_id,
|
||||||
contact_inbox_id: @contact_inbox.id,
|
contact_inbox_id: @contact_inbox.id,
|
||||||
campaign_id: @campaign.id,
|
campaign_id: @campaign.id,
|
||||||
additional_attributes: conversation_additional_attributes
|
additional_attributes: conversation_additional_attributes,
|
||||||
|
custom_attributes: custom_attributes || {}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -15,11 +15,10 @@ class ContactBuilder
|
|||||||
end
|
end
|
||||||
|
|
||||||
def create_contact_inbox(contact)
|
def create_contact_inbox(contact)
|
||||||
::ContactInbox.create!(
|
::ContactInbox.create_with(hmac_verified: hmac_verified || false).find_or_create_by!(
|
||||||
contact_id: contact.id,
|
contact_id: contact.id,
|
||||||
inbox_id: inbox.id,
|
inbox_id: inbox.id,
|
||||||
source_id: source_id,
|
source_id: source_id
|
||||||
hmac_verified: hmac_verified || false
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -29,7 +29,7 @@ class Messages::Facebook::MessageBuilder < Messages::Messenger::MessageBuilder
|
|||||||
rescue Koala::Facebook::AuthenticationError
|
rescue Koala::Facebook::AuthenticationError
|
||||||
Rails.logger.error "Facebook Authorization expired for Inbox #{@inbox.id}"
|
Rails.logger.error "Facebook Authorization expired for Inbox #{@inbox.id}"
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
Sentry.capture_exception(e)
|
ChatwootExceptionTracker.new(e, account: @inbox.account).capture_exception
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ class Messages::Facebook::MessageBuilder < Messages::Messenger::MessageBuilder
|
|||||||
return if contact.present?
|
return if contact.present?
|
||||||
|
|
||||||
@contact = Contact.create!(contact_params.except(:remote_avatar_url))
|
@contact = Contact.create!(contact_params.except(:remote_avatar_url))
|
||||||
@contact_inbox = ContactInbox.create(contact: contact, inbox: @inbox, source_id: @sender_id)
|
@contact_inbox = ContactInbox.find_or_create_by!(contact: contact, inbox: @inbox, source_id: @sender_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_message
|
def build_message
|
||||||
@ -128,10 +128,10 @@ class Messages::Facebook::MessageBuilder < Messages::Messenger::MessageBuilder
|
|||||||
result = {}
|
result = {}
|
||||||
# OAuthException, code: 100, error_subcode: 2018218, message: (#100) No profile available for this user
|
# OAuthException, code: 100, error_subcode: 2018218, message: (#100) No profile available for this user
|
||||||
# We don't need to capture this error as we don't care about contact params in case of echo messages
|
# We don't need to capture this error as we don't care about contact params in case of echo messages
|
||||||
Sentry.capture_exception(e) unless @outgoing_echo
|
ChatwootExceptionTracker.new(e, account: @inbox.account).capture_exception unless @outgoing_echo
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
result = {}
|
result = {}
|
||||||
Sentry.capture_exception(e)
|
ChatwootExceptionTracker.new(e, account: @inbox.account).capture_exception
|
||||||
end
|
end
|
||||||
process_contact_params_result(result)
|
process_contact_params_result(result)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -24,7 +24,7 @@ class Messages::Instagram::MessageBuilder < Messages::Messenger::MessageBuilder
|
|||||||
@inbox.channel.authorization_error!
|
@inbox.channel.authorization_error!
|
||||||
raise
|
raise
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
Sentry.capture_exception(e)
|
ChatwootExceptionTracker.new(e, account: @inbox.account).capture_exception
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ class Messages::MessageBuilder
|
|||||||
@user = user
|
@user = user
|
||||||
@message_type = params[:message_type] || 'outgoing'
|
@message_type = params[:message_type] || 'outgoing'
|
||||||
@attachments = params[:attachments]
|
@attachments = params[:attachments]
|
||||||
|
@automation_rule = @params&.dig(:content_attributes, :automation_rule_id)
|
||||||
return unless params.instance_of?(ActionController::Parameters)
|
return unless params.instance_of?(ActionController::Parameters)
|
||||||
|
|
||||||
@in_reply_to = params.to_unsafe_h&.dig(:content_attributes, :in_reply_to)
|
@in_reply_to = params.to_unsafe_h&.dig(:content_attributes, :in_reply_to)
|
||||||
@ -64,6 +65,14 @@ class Messages::MessageBuilder
|
|||||||
@params[:external_created_at].present? ? { external_created_at: @params[:external_created_at] } : {}
|
@params[:external_created_at].present? ? { external_created_at: @params[:external_created_at] } : {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def automation_rule_id
|
||||||
|
@automation_rule.present? ? { content_attributes: { automation_rule_id: @automation_rule } } : {}
|
||||||
|
end
|
||||||
|
|
||||||
|
def campaign_id
|
||||||
|
@params[:campaign_id].present? ? { additional_attributes: { campaign_id: @params[:campaign_id] } } : {}
|
||||||
|
end
|
||||||
|
|
||||||
def message_sender
|
def message_sender
|
||||||
return if @params[:sender_type] != 'AgentBot'
|
return if @params[:sender_type] != 'AgentBot'
|
||||||
|
|
||||||
@ -82,6 +91,6 @@ class Messages::MessageBuilder
|
|||||||
items: @items,
|
items: @items,
|
||||||
in_reply_to: @in_reply_to,
|
in_reply_to: @in_reply_to,
|
||||||
echo_id: @params[:echo_id]
|
echo_id: @params[:echo_id]
|
||||||
}.merge(external_created_at)
|
}.merge(external_created_at).merge(automation_rule_id).merge(campaign_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -53,16 +53,7 @@ class Messages::Messenger::MessageBuilder
|
|||||||
|
|
||||||
def fetch_story_link(attachment)
|
def fetch_story_link(attachment)
|
||||||
message = attachment.message
|
message = attachment.message
|
||||||
begin
|
result = get_story_object_from_source_id(message.source_id)
|
||||||
k = Koala::Facebook::API.new(@inbox.channel.page_access_token) if @inbox.facebook?
|
|
||||||
result = k.get_object(message.source_id, fields: %w[story from]) || {}
|
|
||||||
rescue Koala::Facebook::AuthenticationError
|
|
||||||
@inbox.channel.authorization_error!
|
|
||||||
raise
|
|
||||||
rescue StandardError => e
|
|
||||||
result = {}
|
|
||||||
Sentry.capture_exception(e)
|
|
||||||
end
|
|
||||||
story_id = result['story']['mention']['id']
|
story_id = result['story']['mention']['id']
|
||||||
story_sender = result['from']['username']
|
story_sender = result['from']['username']
|
||||||
message.content_attributes[:story_sender] = story_sender
|
message.content_attributes[:story_sender] = story_sender
|
||||||
@ -70,4 +61,15 @@ class Messages::Messenger::MessageBuilder
|
|||||||
message.content = I18n.t('conversations.messages.instagram_story_content', story_sender: story_sender)
|
message.content = I18n.t('conversations.messages.instagram_story_content', story_sender: story_sender)
|
||||||
message.save!
|
message.save!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_story_object_from_source_id(source_id)
|
||||||
|
k = Koala::Facebook::API.new(@inbox.channel.page_access_token) if @inbox.facebook?
|
||||||
|
k.get_object(source_id, fields: %w[story from]) || {}
|
||||||
|
rescue Koala::Facebook::AuthenticationError
|
||||||
|
@inbox.channel.authorization_error!
|
||||||
|
raise
|
||||||
|
rescue StandardError => e
|
||||||
|
ChatwootExceptionTracker.new(e, account: @inbox.account).capture_exception
|
||||||
|
{}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -4,6 +4,7 @@ class V2::ReportBuilder
|
|||||||
attr_reader :account, :params
|
attr_reader :account, :params
|
||||||
|
|
||||||
DEFAULT_GROUP_BY = 'day'.freeze
|
DEFAULT_GROUP_BY = 'day'.freeze
|
||||||
|
AGENT_RESULTS_PER_PAGE = 25
|
||||||
|
|
||||||
def initialize(account, params)
|
def initialize(account, params)
|
||||||
@account = account
|
@account = account
|
||||||
@ -45,7 +46,7 @@ class V2::ReportBuilder
|
|||||||
if params[:type].equal?(:account)
|
if params[:type].equal?(:account)
|
||||||
conversations
|
conversations
|
||||||
else
|
else
|
||||||
agent_metrics
|
agent_metrics.sort_by { |hash| hash[:metric][:open] }.reverse
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -79,20 +80,23 @@ class V2::ReportBuilder
|
|||||||
end
|
end
|
||||||
|
|
||||||
def agent_metrics
|
def agent_metrics
|
||||||
users = @account.users
|
account_users = @account.account_users.page(params[:page]).per(AGENT_RESULTS_PER_PAGE)
|
||||||
users = users.where(id: params[:user_id]) if params[:user_id].present?
|
account_users.each_with_object([]) do |account_user, arr|
|
||||||
users.each_with_object([]) do |user, arr|
|
@user = account_user.user
|
||||||
@user = user
|
|
||||||
arr << {
|
arr << {
|
||||||
user: { id: user.id, name: user.name, thumbnail: user.avatar_url },
|
id: @user.id,
|
||||||
|
name: @user.name,
|
||||||
|
email: @user.email,
|
||||||
|
thumbnail: @user.avatar_url,
|
||||||
|
availability: account_user.availability_status,
|
||||||
metric: conversations
|
metric: conversations
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def conversations
|
def conversations
|
||||||
@open_conversations = scope.conversations.open
|
@open_conversations = scope.conversations.where(account_id: @account.id).open
|
||||||
first_response_count = scope.reporting_events.where(name: 'first_response', conversation_id: @open_conversations.pluck('id')).count
|
first_response_count = @account.reporting_events.where(name: 'first_response', conversation_id: @open_conversations.pluck('id')).count
|
||||||
metric = {
|
metric = {
|
||||||
open: @open_conversations.count,
|
open: @open_conversations.count,
|
||||||
unattended: @open_conversations.count - first_response_count
|
unattended: @open_conversations.count - first_response_count
|
||||||
|
|||||||
@ -45,6 +45,8 @@ class RoomChannel < ApplicationCable::Channel
|
|||||||
end
|
end
|
||||||
|
|
||||||
def current_account
|
def current_account
|
||||||
|
return if current_user.blank?
|
||||||
|
|
||||||
@current_account ||= if @current_user.is_a? Contact
|
@current_account ||= if @current_user.is_a? Contact
|
||||||
@current_user.account
|
@current_user.account
|
||||||
else
|
else
|
||||||
|
|||||||
@ -17,6 +17,16 @@ class Api::V1::Accounts::AutomationRulesController < Api::V1::Accounts::BaseCont
|
|||||||
@automation_rule
|
@automation_rule
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def attach_file
|
||||||
|
file_blob = ActiveStorage::Blob.create_and_upload!(
|
||||||
|
key: nil,
|
||||||
|
io: params[:attachment].tempfile,
|
||||||
|
filename: params[:attachment].original_filename,
|
||||||
|
content_type: params[:attachment].content_type
|
||||||
|
)
|
||||||
|
render json: { blob_key: file_blob.key, blob_id: file_blob.id }
|
||||||
|
end
|
||||||
|
|
||||||
def show; end
|
def show; end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@ -25,6 +35,7 @@ class Api::V1::Accounts::AutomationRulesController < Api::V1::Accounts::BaseCont
|
|||||||
@automation_rule.actions = params[:actions] if params[:actions]
|
@automation_rule.actions = params[:actions] if params[:actions]
|
||||||
@automation_rule.save!
|
@automation_rule.save!
|
||||||
process_attachments
|
process_attachments
|
||||||
|
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
Rails.logger.error e
|
Rails.logger.error e
|
||||||
render json: { error: @automation_rule.errors.messages }.to_json, status: :unprocessable_entity
|
render json: { error: @automation_rule.errors.messages }.to_json, status: :unprocessable_entity
|
||||||
@ -43,17 +54,19 @@ class Api::V1::Accounts::AutomationRulesController < Api::V1::Accounts::BaseCont
|
|||||||
@automation_rule = new_rule
|
@automation_rule = new_rule
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def process_attachments
|
def process_attachments
|
||||||
return if params[:attachments].blank?
|
actions = @automation_rule.actions.filter_map { |k, _v| k if k['action_name'] == 'send_attachment' }
|
||||||
|
return if actions.blank?
|
||||||
|
|
||||||
params[:attachments].each do |uploaded_attachment|
|
actions.each do |action|
|
||||||
@automation_rule.files.attach(uploaded_attachment)
|
blob_id = action['action_params']
|
||||||
|
blob = ActiveStorage::Blob.find_by(id: blob_id)
|
||||||
|
@automation_rule.files.attach(blob)
|
||||||
end
|
end
|
||||||
@automation_rule
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
def automation_rules_permit
|
def automation_rules_permit
|
||||||
params.permit(
|
params.permit(
|
||||||
:name, :description, :event_name, :account_id, :active,
|
:name, :description, :event_name, :account_id, :active,
|
||||||
|
|||||||
@ -15,7 +15,7 @@ class Api::V1::Accounts::CallbacksController < Api::V1::Accounts::BaseController
|
|||||||
set_instagram_id(page_access_token, facebook_channel)
|
set_instagram_id(page_access_token, facebook_channel)
|
||||||
set_avatar(@facebook_inbox, page_id)
|
set_avatar(@facebook_inbox, page_id)
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
Sentry.capture_exception(e)
|
ChatwootExceptionTracker.new(e).capture_exception
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ class Api::V1::Accounts::CallbacksController < Api::V1::Accounts::BaseController
|
|||||||
set_instagram_id(access_token, fb_page)
|
set_instagram_id(access_token, fb_page)
|
||||||
fb_page&.reauthorized!
|
fb_page&.reauthorized!
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
Sentry.capture_exception(e)
|
ChatwootExceptionTracker.new(e).capture_exception
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@ class Api::V1::Accounts::Channels::TwilioChannelsController < Api::V1::Accounts:
|
|||||||
build_inbox
|
build_inbox
|
||||||
setup_webhooks if @twilio_channel.sms?
|
setup_webhooks if @twilio_channel.sms?
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
Sentry.capture_exception(e)
|
|
||||||
render_could_not_create_error(e.message)
|
render_could_not_create_error(e.message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -5,7 +5,7 @@ class Api::V1::Accounts::Conversations::BaseController < Api::V1::Accounts::Base
|
|||||||
private
|
private
|
||||||
|
|
||||||
def conversation
|
def conversation
|
||||||
@conversation ||= Current.account.conversations.find_by(display_id: params[:conversation_id])
|
@conversation ||= Current.account.conversations.find_by!(display_id: params[:conversation_id])
|
||||||
authorize @conversation.inbox, :show?
|
authorize @conversation.inbox, :show?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -4,6 +4,6 @@ class Api::V1::Accounts::Kbase::BaseController < Api::V1::Accounts::BaseControll
|
|||||||
private
|
private
|
||||||
|
|
||||||
def portal
|
def portal
|
||||||
@portal ||= Current.account.kbase_portals.find_by(id: params[:portal_id])
|
@portal ||= Current.account.kbase_portals.find_by(slug: params[:portal_id])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
class Api::V1::Accounts::Kbase::PortalsController < Api::V1::Accounts::Kbase::BaseController
|
class Api::V1::Accounts::Kbase::PortalsController < Api::V1::Accounts::BaseController
|
||||||
before_action :fetch_portal, except: [:index, :create]
|
before_action :fetch_portal, except: [:index, :create]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@portals = Current.account.kbase_portals
|
@portals = Current.account.kbase_portals
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def show; end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@portal = Current.account.kbase_portals.create!(portal_params)
|
@portal = Current.account.kbase_portals.create!(portal_params)
|
||||||
end
|
end
|
||||||
@ -21,7 +23,11 @@ class Api::V1::Accounts::Kbase::PortalsController < Api::V1::Accounts::Kbase::Ba
|
|||||||
private
|
private
|
||||||
|
|
||||||
def fetch_portal
|
def fetch_portal
|
||||||
@portal = current_account.kbase_portals.find(params[:id])
|
@portal = Current.account.kbase_portals.find_by(slug: permitted_params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def permitted_params
|
||||||
|
params.permit(:id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def portal_params
|
def portal_params
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class Api::V1::Accounts::WebhooksController < Api::V1::Accounts::BaseController
|
|||||||
private
|
private
|
||||||
|
|
||||||
def webhook_params
|
def webhook_params
|
||||||
params.require(:webhook).permit(:inbox_id, :url)
|
params.require(:webhook).permit(:inbox_id, :url, subscriptions: [])
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch_webhook
|
def fetch_webhook
|
||||||
|
|||||||
@ -10,7 +10,7 @@ class Api::V1::WebhooksController < ApplicationController
|
|||||||
twitter_consumer.consume
|
twitter_consumer.consume
|
||||||
head :ok
|
head :ok
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
Sentry.capture_exception(e)
|
ChatwootExceptionTracker.new(e).capture_exception
|
||||||
head :ok
|
head :ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -71,7 +71,7 @@ class Api::V1::Widget::BaseController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def contact_email
|
def contact_email
|
||||||
permitted_params[:contact][:email].downcase if permitted_params[:contact].present?
|
permitted_params.dig(:contact, :email)&.downcase
|
||||||
end
|
end
|
||||||
|
|
||||||
def contact_name
|
def contact_name
|
||||||
@ -79,7 +79,7 @@ class Api::V1::Widget::BaseController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def contact_phone_number
|
def contact_phone_number
|
||||||
params[:contact][:phone_number]
|
permitted_params.dig(:contact, :phone_number)
|
||||||
end
|
end
|
||||||
|
|
||||||
def browser_params
|
def browser_params
|
||||||
|
|||||||
@ -69,7 +69,8 @@ class Api::V1::Widget::ConversationsController < Api::V1::Widget::BaseController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def permitted_params
|
def permitted_params
|
||||||
params.permit(:id, :typing_status, :website_token, :email, contact: [:name, :email], message: [:content, :referer_url, :timestamp, :echo_id],
|
params.permit(:id, :typing_status, :website_token, :email, contact: [:name, :email, :phone_number],
|
||||||
|
message: [:content, :referer_url, :timestamp, :echo_id],
|
||||||
custom_attributes: {})
|
custom_attributes: {})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -82,7 +82,8 @@ class Api::V2::Accounts::ReportsController < Api::V1::Accounts::BaseController
|
|||||||
def conversation_params
|
def conversation_params
|
||||||
{
|
{
|
||||||
type: params[:type].to_sym,
|
type: params[:type].to_sym,
|
||||||
user_id: params[:user_id]
|
user_id: params[:user_id],
|
||||||
|
page: params[:page].presence || 1
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -9,8 +9,7 @@ module RequestExceptionHandler
|
|||||||
|
|
||||||
def handle_with_exception
|
def handle_with_exception
|
||||||
yield
|
yield
|
||||||
rescue ActiveRecord::RecordNotFound => e
|
rescue ActiveRecord::RecordNotFound
|
||||||
Sentry.capture_exception(e)
|
|
||||||
render_not_found_error('Resource could not be found')
|
render_not_found_error('Resource could not be found')
|
||||||
rescue Pundit::NotAuthorizedError
|
rescue Pundit::NotAuthorizedError
|
||||||
render_unauthorized('You are not authorized to do this action')
|
render_unauthorized('You are not authorized to do this action')
|
||||||
|
|||||||
@ -38,9 +38,12 @@ class DashboardController < ActionController::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def app_config
|
def app_config
|
||||||
{ APP_VERSION: Chatwoot.config[:version],
|
{
|
||||||
|
APP_VERSION: Chatwoot.config[:version],
|
||||||
VAPID_PUBLIC_KEY: VapidService.public_key,
|
VAPID_PUBLIC_KEY: VapidService.public_key,
|
||||||
ENABLE_ACCOUNT_SIGNUP: GlobalConfigService.load('ENABLE_ACCOUNT_SIGNUP', 'false'),
|
ENABLE_ACCOUNT_SIGNUP: GlobalConfigService.load('ENABLE_ACCOUNT_SIGNUP', 'false'),
|
||||||
FB_APP_ID: GlobalConfigService.load('FB_APP_ID', '') }
|
FB_APP_ID: GlobalConfigService.load('FB_APP_ID', ''),
|
||||||
|
FACEBOOK_API_VERSION: 'v13.0'
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -21,6 +21,10 @@ class Platform::Api::V1::UsersController < PlatformController
|
|||||||
|
|
||||||
def update
|
def update
|
||||||
@resource.assign_attributes(user_update_params)
|
@resource.assign_attributes(user_update_params)
|
||||||
|
|
||||||
|
# We are using devise's reconfirmable flow for changing emails
|
||||||
|
# But in case of platform APIs we don't want user to go through this extra step
|
||||||
|
@resource.skip_reconfirmation! if user_update_params[:email].present?
|
||||||
@resource.save!
|
@resource.save!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -43,6 +43,6 @@ class Public::Api::V1::Inboxes::ContactsController < Public::Api::V1::InboxesCon
|
|||||||
end
|
end
|
||||||
|
|
||||||
def permitted_params
|
def permitted_params
|
||||||
params.permit(:identifier, :identifier_hash, :email, :name, :avatar_url, custom_attributes: {})
|
params.permit(:identifier, :identifier_hash, :email, :name, :avatar_url, :phone_number, custom_attributes: {})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -22,7 +22,7 @@ class MessageFinder
|
|||||||
|
|
||||||
def current_messages
|
def current_messages
|
||||||
if @params[:before].present?
|
if @params[:before].present?
|
||||||
messages.reorder('created_at desc').where('id < ?', @params[:before]).limit(20).reverse
|
messages.reorder('created_at desc').where('id < ?', @params[:before].to_i).limit(20).reverse
|
||||||
else
|
else
|
||||||
messages.reorder('created_at desc').limit(20).reverse
|
messages.reorder('created_at desc').limit(20).reverse
|
||||||
end
|
end
|
||||||
|
|||||||
@ -17,30 +17,30 @@ module ReportHelper
|
|||||||
end
|
end
|
||||||
|
|
||||||
def conversations_count
|
def conversations_count
|
||||||
(get_grouped_values scope.conversations).count
|
(get_grouped_values scope.conversations.where(account_id: account.id)).count
|
||||||
end
|
end
|
||||||
|
|
||||||
def incoming_messages_count
|
def incoming_messages_count
|
||||||
(get_grouped_values scope.messages.incoming.unscope(:order)).count
|
(get_grouped_values scope.messages.where(account_id: account.id).incoming.unscope(:order)).count
|
||||||
end
|
end
|
||||||
|
|
||||||
def outgoing_messages_count
|
def outgoing_messages_count
|
||||||
(get_grouped_values scope.messages.outgoing.unscope(:order)).count
|
(get_grouped_values scope.messages.where(account_id: account.id).outgoing.unscope(:order)).count
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolutions_count
|
def resolutions_count
|
||||||
(get_grouped_values scope.conversations.resolved).count
|
(get_grouped_values scope.conversations.where(account_id: account.id).resolved).count
|
||||||
end
|
end
|
||||||
|
|
||||||
def avg_first_response_time
|
def avg_first_response_time
|
||||||
grouped_reporting_events = (get_grouped_values scope.reporting_events.where(name: 'first_response'))
|
grouped_reporting_events = (get_grouped_values scope.reporting_events.where(name: 'first_response', account_id: account.id))
|
||||||
return grouped_reporting_events.average(:value_in_business_hours) if params[:business_hours]
|
return grouped_reporting_events.average(:value_in_business_hours) if params[:business_hours]
|
||||||
|
|
||||||
grouped_reporting_events.average(:value)
|
grouped_reporting_events.average(:value)
|
||||||
end
|
end
|
||||||
|
|
||||||
def avg_resolution_time
|
def avg_resolution_time
|
||||||
grouped_reporting_events = (get_grouped_values scope.reporting_events.where(name: 'conversation_resolved'))
|
grouped_reporting_events = (get_grouped_values scope.reporting_events.where(name: 'conversation_resolved', account_id: account.id))
|
||||||
return grouped_reporting_events.average(:value_in_business_hours) if params[:business_hours]
|
return grouped_reporting_events.average(:value_in_business_hours) if params[:business_hours]
|
||||||
|
|
||||||
grouped_reporting_events.average(:value)
|
grouped_reporting_events.average(:value)
|
||||||
@ -48,7 +48,7 @@ module ReportHelper
|
|||||||
|
|
||||||
def avg_resolution_time_summary
|
def avg_resolution_time_summary
|
||||||
reporting_events = scope.reporting_events
|
reporting_events = scope.reporting_events
|
||||||
.where(name: 'conversation_resolved', created_at: range)
|
.where(name: 'conversation_resolved', account_id: account.id, created_at: range)
|
||||||
avg_rt = params[:business_hours] ? reporting_events.average(:value_in_business_hours) : reporting_events.average(:value)
|
avg_rt = params[:business_hours] ? reporting_events.average(:value_in_business_hours) : reporting_events.average(:value)
|
||||||
|
|
||||||
return 0 if avg_rt.blank?
|
return 0 if avg_rt.blank?
|
||||||
@ -58,7 +58,7 @@ module ReportHelper
|
|||||||
|
|
||||||
def avg_first_response_time_summary
|
def avg_first_response_time_summary
|
||||||
reporting_events = scope.reporting_events
|
reporting_events = scope.reporting_events
|
||||||
.where(name: 'first_response', created_at: range)
|
.where(name: 'first_response', account_id: account.id, created_at: range)
|
||||||
avg_frt = params[:business_hours] ? reporting_events.average(:value_in_business_hours) : reporting_events.average(:value)
|
avg_frt = params[:business_hours] ? reporting_events.average(:value_in_business_hours) : reporting_events.average(:value)
|
||||||
|
|
||||||
return 0 if avg_frt.blank?
|
return 0 if avg_frt.blank?
|
||||||
|
|||||||
@ -9,6 +9,14 @@ class AutomationsAPI extends ApiClient {
|
|||||||
clone(automationId) {
|
clone(automationId) {
|
||||||
return axios.post(`${this.url}/${automationId}/clone`);
|
return axios.post(`${this.url}/${automationId}/clone`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attachment(file) {
|
||||||
|
return axios.post(`${this.url}/attach_file`, file, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new AutomationsAPI();
|
export default new AutomationsAPI();
|
||||||
|
|||||||
@ -44,6 +44,15 @@ class ReportsAPI extends ApiClient {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getConversationMetric(type = 'account', page = 1) {
|
||||||
|
return axios.get(`${this.url}/conversations`, {
|
||||||
|
params: {
|
||||||
|
type,
|
||||||
|
page,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getAgentReports(since, until) {
|
getAgentReports(since, until) {
|
||||||
return axios.get(`${this.url}/agents`, {
|
return axios.get(`${this.url}/agents`, {
|
||||||
params: { since, until },
|
params: { since, until },
|
||||||
|
|||||||
@ -97,5 +97,18 @@ describe('#Reports API', () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('#getConversationMetric', () => {
|
||||||
|
reportsAPI.getConversationMetric('account');
|
||||||
|
expect(context.axiosMock.get).toHaveBeenCalledWith(
|
||||||
|
'/api/v2/reports/conversations',
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
type: 'account',
|
||||||
|
page: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2,6 +2,10 @@
|
|||||||
margin-right: var(--space-small);
|
margin-right: var(--space-small);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.margin-bottom-small {
|
||||||
|
margin-bottom: var(--space-small);
|
||||||
|
}
|
||||||
|
|
||||||
.margin-right-smaller {
|
.margin-right-smaller {
|
||||||
margin-right: var(--space-smaller);
|
margin-right: var(--space-smaller);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,16 @@
|
|||||||
padding: 0 $space-small;
|
padding: 0 $space-small;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.video-js {
|
||||||
|
background: transparent;
|
||||||
|
// Override min-height : 50px in foundation
|
||||||
|
//
|
||||||
|
max-height: $space-mega * 2.4;
|
||||||
|
min-height: 4.8rem;
|
||||||
|
padding: var(--space-normal) 0 0;
|
||||||
|
resize: none;
|
||||||
|
}
|
||||||
|
|
||||||
>textarea {
|
>textarea {
|
||||||
@include ghost-input();
|
@include ghost-input();
|
||||||
@include margin(0);
|
@include margin(0);
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
:menu-config="activeSecondaryMenu"
|
:menu-config="activeSecondaryMenu"
|
||||||
:current-role="currentRole"
|
:current-role="currentRole"
|
||||||
@add-label="showAddLabelPopup"
|
@add-label="showAddLabelPopup"
|
||||||
|
@toggle-accounts="toggleAccountModal"
|
||||||
/>
|
/>
|
||||||
</aside>
|
</aside>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -3,7 +3,8 @@ import { frontendURL } from '../../../../helper/URLHelper';
|
|||||||
const reports = accountId => ({
|
const reports = accountId => ({
|
||||||
parentNav: 'reports',
|
parentNav: 'reports',
|
||||||
routes: [
|
routes: [
|
||||||
'settings_account_reports',
|
'account_overview_reports',
|
||||||
|
'conversation_reports',
|
||||||
'csat_reports',
|
'csat_reports',
|
||||||
'agent_reports',
|
'agent_reports',
|
||||||
'label_reports',
|
'label_reports',
|
||||||
@ -16,7 +17,14 @@ const reports = accountId => ({
|
|||||||
label: 'REPORTS_OVERVIEW',
|
label: 'REPORTS_OVERVIEW',
|
||||||
hasSubMenu: false,
|
hasSubMenu: false,
|
||||||
toState: frontendURL(`accounts/${accountId}/reports/overview`),
|
toState: frontendURL(`accounts/${accountId}/reports/overview`),
|
||||||
toStateName: 'settings_account_reports',
|
toStateName: 'account_overview_reports',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'chat',
|
||||||
|
label: 'REPORTS_CONVERSATION',
|
||||||
|
hasSubMenu: false,
|
||||||
|
toState: frontendURL(`accounts/${accountId}/reports/conversation`),
|
||||||
|
toStateName: 'conversation_reports',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'emoji',
|
icon: 'emoji',
|
||||||
|
|||||||
@ -1,14 +1,34 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="showShowCurrentAccountContext" class="account-context--group">
|
<div
|
||||||
|
v-if="showShowCurrentAccountContext"
|
||||||
|
class="account-context--group"
|
||||||
|
@mouseover="setShowSwitch"
|
||||||
|
@mouseleave="resetShowSwitch"
|
||||||
|
>
|
||||||
{{ $t('SIDEBAR.CURRENTLY_VIEWING_ACCOUNT') }}
|
{{ $t('SIDEBAR.CURRENTLY_VIEWING_ACCOUNT') }}
|
||||||
<p class="account-context--name text-ellipsis">
|
<p class="account-context--name text-ellipsis">
|
||||||
{{ account.name }}
|
{{ account.name }}
|
||||||
</p>
|
</p>
|
||||||
|
<transition name="fade">
|
||||||
|
<div v-if="showSwitchButton" class="account-context--switch-group">
|
||||||
|
<woot-button
|
||||||
|
variant="clear"
|
||||||
|
icon="arrow-swap"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@click="$emit('toggle-accounts')"
|
||||||
|
>
|
||||||
|
{{ $t('SIDEBAR.SWITCH') }}
|
||||||
|
</woot-button>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
export default {
|
export default {
|
||||||
|
data() {
|
||||||
|
return { showSwitchButton: false };
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
account: 'getCurrentAccount',
|
account: 'getCurrentAccount',
|
||||||
@ -18,6 +38,14 @@ export default {
|
|||||||
return this.userAccounts.length > 1 && this.account.name;
|
return this.userAccounts.length > 1 && this.account.name;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
methods: {
|
||||||
|
setShowSwitch() {
|
||||||
|
this.showSwitchButton = true;
|
||||||
|
},
|
||||||
|
resetShowSwitch() {
|
||||||
|
this.showSwitchButton = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@ -27,10 +55,49 @@ export default {
|
|||||||
font-size: var(--font-size-mini);
|
font-size: var(--font-size-mini);
|
||||||
padding: var(--space-small);
|
padding: var(--space-small);
|
||||||
margin-bottom: var(--space-small);
|
margin-bottom: var(--space-small);
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--b-100);
|
||||||
|
}
|
||||||
|
|
||||||
.account-context--name {
|
.account-context--name {
|
||||||
font-weight: var(--font-weight-medium);
|
font-weight: var(--font-weight-medium);
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.account-context--switch-group {
|
||||||
|
--overlay-shadow: linear-gradient(
|
||||||
|
to right,
|
||||||
|
rgba(255, 255, 255, 0) 0%,
|
||||||
|
rgba(255, 255, 255, 1) 50%
|
||||||
|
);
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
background-image: var(--overlay-shadow);
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: var(--border-radius-normal);
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: var(--border-radius-normal);
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
justify-content: end;
|
||||||
|
opacity: 1;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter-active,
|
||||||
|
.fade-leave-active {
|
||||||
|
transition: opacity 300ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter,
|
||||||
|
.fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="hasSecondaryMenu" class="main-nav secondary-menu">
|
<div v-if="hasSecondaryMenu" class="main-nav secondary-menu">
|
||||||
<account-context />
|
<account-context @toggle-accounts="toggleAccountModal" />
|
||||||
<transition-group name="menu-list" tag="ul" class="menu vertical">
|
<transition-group name="menu-list" tag="ul" class="menu vertical">
|
||||||
<secondary-nav-item
|
<secondary-nav-item
|
||||||
v-for="menuItem in accessibleMenuItems"
|
v-for="menuItem in accessibleMenuItems"
|
||||||
@ -224,6 +224,9 @@ export default {
|
|||||||
showAddLabelPopup() {
|
showAddLabelPopup() {
|
||||||
this.$emit('add-label');
|
this.$emit('add-label');
|
||||||
},
|
},
|
||||||
|
toggleAccountModal() {
|
||||||
|
this.$emit('toggle-accounts');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -52,6 +52,11 @@
|
|||||||
class="answer--text-input"
|
class="answer--text-input"
|
||||||
placeholder="Enter url"
|
placeholder="Enter url"
|
||||||
/>
|
/>
|
||||||
|
<automation-action-file-input
|
||||||
|
v-if="inputType === 'attachment'"
|
||||||
|
v-model="action_params"
|
||||||
|
:initial-file-name="initialFileName"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<woot-button
|
<woot-button
|
||||||
@ -84,9 +89,11 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import AutomationActionTeamMessageInput from './AutomationActionTeamMessageInput.vue';
|
import AutomationActionTeamMessageInput from './AutomationActionTeamMessageInput.vue';
|
||||||
|
import AutomationActionFileInput from './AutomationFileInput.vue';
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
AutomationActionTeamMessageInput,
|
AutomationActionTeamMessageInput,
|
||||||
|
AutomationActionFileInput,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
@ -109,6 +116,10 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
|
initialFileName: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
action_name: {
|
action_name: {
|
||||||
@ -187,6 +198,7 @@ export default {
|
|||||||
.filter__answer--wrap {
|
.filter__answer--wrap {
|
||||||
margin-right: var(--space-smaller);
|
margin-right: var(--space-smaller);
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
max-width: 50%;
|
||||||
|
|
||||||
input {
|
input {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|||||||
@ -0,0 +1,117 @@
|
|||||||
|
<template>
|
||||||
|
<label class="input-wrapper" :class="uploadState">
|
||||||
|
<input
|
||||||
|
v-if="uploadState !== 'processing'"
|
||||||
|
type="file"
|
||||||
|
name="attachment"
|
||||||
|
:class="uploadState === 'processing' ? 'disabled' : ''"
|
||||||
|
@change="onChangeFile"
|
||||||
|
/>
|
||||||
|
<spinner v-if="uploadState === 'processing'" />
|
||||||
|
<fluent-icon v-if="uploadState === 'idle'" icon="file-upload" />
|
||||||
|
<fluent-icon
|
||||||
|
v-if="uploadState === 'uploaded'"
|
||||||
|
icon="checkmark-circle"
|
||||||
|
type="outline"
|
||||||
|
class="success-icon"
|
||||||
|
/>
|
||||||
|
<fluent-icon
|
||||||
|
v-if="uploadState === 'failed'"
|
||||||
|
icon="dismiss-circle"
|
||||||
|
type="outline"
|
||||||
|
class="error-icon"
|
||||||
|
/>
|
||||||
|
<p class="file-button">{{ label }}</p>
|
||||||
|
</label>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Spinner from 'shared/components/Spinner';
|
||||||
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Spinner,
|
||||||
|
},
|
||||||
|
mixins: [alertMixin],
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
initialFileName: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
uploadState: 'idle',
|
||||||
|
label: this.$t('AUTOMATION.ATTACHMENT.LABEL_IDLE'),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (this.initialFileName) {
|
||||||
|
this.label = this.initialFileName;
|
||||||
|
this.uploadState = 'uploaded';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async onChangeFile(event) {
|
||||||
|
this.uploadState = 'processing';
|
||||||
|
this.label = this.$t('AUTOMATION.ATTACHMENT.LABEL_UPLOADING');
|
||||||
|
try {
|
||||||
|
const file = event.target.files[0];
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('attachment', file, file.name);
|
||||||
|
const id = await this.$store.dispatch(
|
||||||
|
'automations/uploadAttachment',
|
||||||
|
formData
|
||||||
|
);
|
||||||
|
this.$emit('input', [id]);
|
||||||
|
this.uploadState = 'uploaded';
|
||||||
|
this.label = this.$t('AUTOMATION.ATTACHMENT.LABEL_UPLOADED');
|
||||||
|
} catch (error) {
|
||||||
|
this.uploadState = 'failed';
|
||||||
|
this.label = this.$t('AUTOMATION.ATTACHMENT.LABEL_UPLOAD_FAILED');
|
||||||
|
this.showAlert(this.$t('AUTOMATION.ATTACHMENT.UPLOAD_ERROR'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
input[type='file'] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.input-wrapper {
|
||||||
|
display: flex;
|
||||||
|
height: 39px;
|
||||||
|
background-color: var(--white);
|
||||||
|
border-radius: var(--border-radius-small);
|
||||||
|
border: 1px dashed var(--w-100);
|
||||||
|
padding: var(--space-smaller) var(--space-small);
|
||||||
|
align-items: center;
|
||||||
|
font-size: var(--font-size-mini);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.success-icon {
|
||||||
|
margin-right: var(--space-small);
|
||||||
|
color: var(--g-500);
|
||||||
|
}
|
||||||
|
.error-icon {
|
||||||
|
margin-right: var(--space-small);
|
||||||
|
color: var(--r-500);
|
||||||
|
}
|
||||||
|
|
||||||
|
.processing {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
.file-button {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
50
app/javascript/dashboard/components/widgets/ShowMore.vue
Normal file
50
app/javascript/dashboard/components/widgets/ShowMore.vue
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<template>
|
||||||
|
<span>
|
||||||
|
{{ textToBeDisplayed }}
|
||||||
|
<button class="show-more--button" @click="toggleShowMore">
|
||||||
|
{{ buttonLabel }}
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
text: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
limit: {
|
||||||
|
type: Number,
|
||||||
|
default: 120,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showMore: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
textToBeDisplayed() {
|
||||||
|
if (this.showMore) {
|
||||||
|
return this.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.text.slice(0, this.limit) + '...';
|
||||||
|
},
|
||||||
|
buttonLabel() {
|
||||||
|
const i18nKey = !this.showMore ? 'SHOW_MORE' : 'SHOW_LESS';
|
||||||
|
return this.$t(`COMPONENTS.SHOW_MORE_BLOCK.${i18nKey}`);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleShowMore() {
|
||||||
|
this.showMore = !this.showMore;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.show-more--button {
|
||||||
|
color: var(--w-500);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,16 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="audio-wave-wrapper">
|
<div class="audio-wave-wrapper">
|
||||||
<div id="audio-wave"></div>
|
<audio id="audio-wave" class="video-js vjs-fill vjs-default-skin"></audio>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import WaveSurfer from 'wavesurfer.js';
|
import 'video.js/dist/video-js.css';
|
||||||
import MicrophonePlugin from 'wavesurfer.js/dist/plugin/wavesurfer.microphone.js';
|
import 'videojs-record/dist/css/videojs.record.css';
|
||||||
import RecordRTC from 'recordrtc';
|
|
||||||
|
import videojs from 'video.js';
|
||||||
|
|
||||||
import inboxMixin from '../../../../shared/mixins/inboxMixin';
|
import inboxMixin from '../../../../shared/mixins/inboxMixin';
|
||||||
import alertMixin from '../../../../shared/mixins/alertMixin';
|
import alertMixin from '../../../../shared/mixins/alertMixin';
|
||||||
|
|
||||||
|
import Recorder from 'opus-recorder';
|
||||||
|
import encoderWorker from 'opus-recorder/dist/encoderWorker.min';
|
||||||
|
|
||||||
|
import WaveSurfer from 'wavesurfer.js';
|
||||||
|
import MicrophonePlugin from 'wavesurfer.js/dist/plugin/wavesurfer.microphone.js';
|
||||||
|
import 'videojs-wavesurfer/dist/videojs.wavesurfer.js';
|
||||||
|
|
||||||
|
import 'videojs-record/dist/videojs.record.js';
|
||||||
|
import 'videojs-record/dist/plugins/videojs.record.opus-recorder.js';
|
||||||
|
import { format, addSeconds } from 'date-fns';
|
||||||
|
|
||||||
WaveSurfer.microphone = MicrophonePlugin;
|
WaveSurfer.microphone = MicrophonePlugin;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -18,104 +31,116 @@ export default {
|
|||||||
mixins: [inboxMixin, alertMixin],
|
mixins: [inboxMixin, alertMixin],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
wavesurfer: false,
|
player: false,
|
||||||
recorder: false,
|
recordingDateStarted: new Date(0),
|
||||||
recordingInterval: false,
|
|
||||||
recordingDateStarted: new Date().getTime(),
|
|
||||||
timeDuration: '00:00',
|
|
||||||
initialTimeDuration: '00:00',
|
initialTimeDuration: '00:00',
|
||||||
options: {
|
recorderOptions: {
|
||||||
container: '#audio-wave',
|
debug: true,
|
||||||
backend: 'WebAudio',
|
controls: true,
|
||||||
interact: true,
|
bigPlayButton: false,
|
||||||
cursorWidth: 1,
|
fluid: false,
|
||||||
plugins: [
|
controlBar: {
|
||||||
WaveSurfer.microphone.create({
|
deviceButton: false,
|
||||||
bufferSize: 4096,
|
fullscreenToggle: false,
|
||||||
numberOfInputChannels: 1,
|
cameraButton: false,
|
||||||
numberOfOutputChannels: 1,
|
volumePanel: false,
|
||||||
constraints: {
|
},
|
||||||
video: false,
|
plugins: {
|
||||||
audio: true,
|
wavesurfer: {
|
||||||
},
|
backend: 'WebAudio',
|
||||||
}),
|
waveColor: '#1f93ff',
|
||||||
],
|
progressColor: 'rgb(25, 118, 204)',
|
||||||
},
|
cursorColor: 'rgba(43, 51, 63, 0.7)',
|
||||||
optionsRecorder: {
|
backgroundColor: 'none',
|
||||||
type: 'audio',
|
barWidth: 1,
|
||||||
mimeType: 'audio/wav',
|
cursorWidth: 1,
|
||||||
disableLogs: true,
|
hideScrollbar: true,
|
||||||
recorderType: RecordRTC.StereoAudioRecorder,
|
plugins: [
|
||||||
sampleRate: 44100,
|
WaveSurfer.microphone.create({
|
||||||
numberOfAudioChannels: 2,
|
bufferSize: 4096,
|
||||||
checkForInactiveTracks: true,
|
numberOfInputChannels: 1,
|
||||||
bufferSize: 4096,
|
numberOfOutputChannels: 1,
|
||||||
|
constraints: {
|
||||||
|
video: false,
|
||||||
|
audio: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
record: {
|
||||||
|
audio: true,
|
||||||
|
video: false,
|
||||||
|
displayMilliseconds: false,
|
||||||
|
maxLength: 300,
|
||||||
|
audioEngine: 'opus-recorder',
|
||||||
|
audioWorkerURL: encoderWorker,
|
||||||
|
audioChannels: 1,
|
||||||
|
audioSampleRate: 48000,
|
||||||
|
audioBitRate: 128,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isRecording() {
|
isRecording() {
|
||||||
if (this.recorder) {
|
return this.player && this.player.record().isRecording();
|
||||||
return this.recorder.getState() === 'recording';
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.wavesurfer = WaveSurfer.create(this.options);
|
window.Recorder = Recorder;
|
||||||
this.wavesurfer.on('play', this.playingRecorder);
|
this.fireProgressRecord(this.initialTimeDuration);
|
||||||
this.wavesurfer.on('pause', this.pausedRecorder);
|
this.player = videojs('#audio-wave', this.recorderOptions, () => {
|
||||||
this.wavesurfer.microphone.on('deviceReady', this.startRecording);
|
this.$nextTick(() => {
|
||||||
this.wavesurfer.microphone.on('deviceError', this.deviceError);
|
this.player.record().getDevice();
|
||||||
this.wavesurfer.microphone.start();
|
});
|
||||||
this.fireStateRecorderTimerChanged(this.initialTimeDuration);
|
});
|
||||||
|
this.player.on('deviceReady', this.deviceReady);
|
||||||
|
this.player.on('deviceError', this.deviceError);
|
||||||
|
this.player.on('startRecord', this.startRecord);
|
||||||
|
this.player.on('stopRecord', this.stopRecord);
|
||||||
|
this.player.on('progressRecord', this.progressRecord);
|
||||||
|
this.player.on('finishRecord', this.finishRecord);
|
||||||
|
this.player.on('playbackFinish', this.playbackFinish);
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
if (this.recorder) {
|
if (this.player) {
|
||||||
this.recorder.destroy();
|
this.player.dispose();
|
||||||
}
|
}
|
||||||
if (this.wavesurfer) {
|
if (window.Recorder) {
|
||||||
this.wavesurfer.destroy();
|
window.Recorder = undefined;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
startRecording(stream) {
|
deviceReady() {
|
||||||
this.recorder = RecordRTC(stream, this.optionsRecorder);
|
this.player.record().start();
|
||||||
this.recorder.onStateChanged = this.onStateRecorderChanged;
|
},
|
||||||
this.recorder.startRecording();
|
startRecord() {
|
||||||
|
this.fireStateRecorderChanged('recording');
|
||||||
|
},
|
||||||
|
stopRecord() {
|
||||||
|
this.fireStateRecorderChanged('stopped');
|
||||||
|
},
|
||||||
|
finishRecord() {
|
||||||
|
const file = new File(
|
||||||
|
[this.player.recordedData],
|
||||||
|
this.player.recordedData.name,
|
||||||
|
{ type: this.player.recordedData.type }
|
||||||
|
);
|
||||||
|
this.fireRecorderBlob(file);
|
||||||
|
},
|
||||||
|
progressRecord() {
|
||||||
|
this.fireProgressRecord(this.formatTimeProgress());
|
||||||
},
|
},
|
||||||
stopAudioRecording() {
|
stopAudioRecording() {
|
||||||
if (this.isRecording) {
|
this.player.record().stop();
|
||||||
this.recorder.stopRecording(() => {
|
|
||||||
this.wavesurfer.microphone.stopDevice();
|
|
||||||
this.wavesurfer.loadBlob(this.recorder.getBlob());
|
|
||||||
this.wavesurfer.stop();
|
|
||||||
this.fireRecorderBlob(this.getAudioFile());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
getAudioFile() {
|
deviceError() {
|
||||||
if (this.hasAudio()) {
|
const deviceError = this.player.deviceErrorCode;
|
||||||
return new File([this.recorder.getBlob()], this.getAudioFileName(), {
|
const deviceErrorName = deviceError?.name.toLowerCase();
|
||||||
type: 'audio/wav',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
hasAudio() {
|
|
||||||
return !(this.isRecording || this.wavesurfer.isPlaying());
|
|
||||||
},
|
|
||||||
playingRecorder() {
|
|
||||||
this.fireStateRecorderChanged('playing');
|
|
||||||
},
|
|
||||||
pausedRecorder() {
|
|
||||||
this.fireStateRecorderChanged('paused');
|
|
||||||
},
|
|
||||||
deviceError(err) {
|
|
||||||
if (
|
if (
|
||||||
err?.name &&
|
deviceErrorName?.includes('notallowederror') ||
|
||||||
(err.name.toLowerCase().includes('notallowederror') ||
|
deviceErrorName?.includes('permissiondeniederror')
|
||||||
err.name.toLowerCase().includes('permissiondeniederror'))
|
|
||||||
) {
|
) {
|
||||||
this.showAlert(
|
this.showAlert(
|
||||||
this.$t('CONVERSATION.REPLYBOX.TIP_AUDIORECORDER_PERMISSION')
|
this.$t('CONVERSATION.REPLYBOX.TIP_AUDIORECORDER_PERMISSION')
|
||||||
@ -127,56 +152,37 @@ export default {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onStateRecorderChanged(state) {
|
formatTimeProgress() {
|
||||||
// recording stopped inactive destroyed
|
return format(
|
||||||
switch (state) {
|
addSeconds(
|
||||||
case 'recording':
|
new Date(this.recordingDateStarted.getTimezoneOffset() * 1000 * 60),
|
||||||
this.timerDurationChanged();
|
this.player.record().getDuration()
|
||||||
break;
|
),
|
||||||
case 'stopped':
|
'mm:ss'
|
||||||
this.timerDurationChanged();
|
);
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this.fireStateRecorderChanged(state);
|
|
||||||
},
|
|
||||||
timerDurationChanged() {
|
|
||||||
if (this.isRecording) {
|
|
||||||
this.recordingInterval = setInterval(() => {
|
|
||||||
this.calculateTimeDuration(
|
|
||||||
(new Date().getTime() - this.recordingDateStarted) / 1000
|
|
||||||
);
|
|
||||||
this.fireStateRecorderTimerChanged(this.timeDuration);
|
|
||||||
}, 1000);
|
|
||||||
} else {
|
|
||||||
clearInterval(this.recordingInterval);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
calculateTimeDuration(secs) {
|
|
||||||
let hr = Math.floor(secs / 3600);
|
|
||||||
let min = Math.floor((secs - hr * 3600) / 60);
|
|
||||||
let sec = Math.floor(secs - hr * 3600 - min * 60);
|
|
||||||
if (min < 10) {
|
|
||||||
min = '0' + min;
|
|
||||||
}
|
|
||||||
if (sec < 10) {
|
|
||||||
sec = '0' + sec;
|
|
||||||
}
|
|
||||||
if (hr <= 0) {
|
|
||||||
this.timeDuration = min + ':' + sec;
|
|
||||||
} else {
|
|
||||||
if (hr < 10) {
|
|
||||||
hr = '0' + hr;
|
|
||||||
}
|
|
||||||
this.timeDuration = hr + ':' + min + ':' + sec;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
playPause() {
|
playPause() {
|
||||||
this.wavesurfer.playPause();
|
if (this.player.wavesurfer().surfer.isPlaying()) {
|
||||||
|
this.fireStateRecorderChanged('paused');
|
||||||
|
} else {
|
||||||
|
this.fireStateRecorderChanged('playing');
|
||||||
|
}
|
||||||
|
this.player.wavesurfer().surfer.playPause();
|
||||||
|
},
|
||||||
|
play() {
|
||||||
|
this.fireStateRecorderChanged('playing');
|
||||||
|
this.player.wavesurfer().play();
|
||||||
|
},
|
||||||
|
pause() {
|
||||||
|
this.fireStateRecorderChanged('paused');
|
||||||
|
this.player.wavesurfer().pause();
|
||||||
|
},
|
||||||
|
playbackFinish() {
|
||||||
|
this.fireStateRecorderChanged('paused');
|
||||||
|
this.player.wavesurfer().pause();
|
||||||
},
|
},
|
||||||
fireRecorderBlob(blob) {
|
fireRecorderBlob(blob) {
|
||||||
this.$emit('recorder-blob', {
|
this.$emit('finish-record', {
|
||||||
name: blob.name,
|
name: blob.name,
|
||||||
type: blob.type,
|
type: blob.type,
|
||||||
size: blob.size,
|
size: blob.size,
|
||||||
@ -186,29 +192,8 @@ export default {
|
|||||||
fireStateRecorderChanged(state) {
|
fireStateRecorderChanged(state) {
|
||||||
this.$emit('state-recorder-changed', state);
|
this.$emit('state-recorder-changed', state);
|
||||||
},
|
},
|
||||||
fireStateRecorderTimerChanged(duration) {
|
fireProgressRecord(duration) {
|
||||||
this.$emit('state-recorder-timer-changed', duration);
|
this.$emit('state-recorder-progress-changed', duration);
|
||||||
},
|
|
||||||
getAudioFileName() {
|
|
||||||
const d = new Date();
|
|
||||||
return `audio-${d.getFullYear()}-${d.getMonth()}-${d.getDate()}-${this.getRandomString()}.wav`;
|
|
||||||
},
|
|
||||||
getRandomString() {
|
|
||||||
if (
|
|
||||||
window.crypto &&
|
|
||||||
window.crypto.getRandomValues &&
|
|
||||||
navigator.userAgent.indexOf('Safari') === -1
|
|
||||||
) {
|
|
||||||
let a = window.crypto.getRandomValues(new Uint32Array(3));
|
|
||||||
let token = '';
|
|
||||||
for (let i = 0, l = a.length; i < l; i += 1) {
|
|
||||||
token += a[i].toString(36);
|
|
||||||
}
|
|
||||||
return token.toLowerCase();
|
|
||||||
}
|
|
||||||
return (Math.random() * new Date().getTime())
|
|
||||||
.toString(36)
|
|
||||||
.replace(/\./g, '');
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -217,7 +202,9 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.audio-wave-wrapper {
|
.audio-wave-wrapper {
|
||||||
min-height: 8rem;
|
min-height: 8rem;
|
||||||
max-height: 12rem;
|
height: 8rem;
|
||||||
overflow: hidden;
|
}
|
||||||
|
.video-js .vjs-control-bar {
|
||||||
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -60,6 +60,7 @@
|
|||||||
:readable-time="readableTime"
|
:readable-time="readableTime"
|
||||||
:source-id="data.source_id"
|
:source-id="data.source_id"
|
||||||
:inbox-id="data.inbox_id"
|
:inbox-id="data.inbox_id"
|
||||||
|
:message-read="showReadTicks"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<spinner v-if="isPending" size="tiny" />
|
<spinner v-if="isPending" size="tiny" />
|
||||||
@ -153,6 +154,14 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
hasUserReadMessage: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
isWebWidgetInbox: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -268,6 +277,14 @@ export default {
|
|||||||
isOutgoing() {
|
isOutgoing() {
|
||||||
return this.data.message_type === MESSAGE_TYPE.OUTGOING;
|
return this.data.message_type === MESSAGE_TYPE.OUTGOING;
|
||||||
},
|
},
|
||||||
|
showReadTicks() {
|
||||||
|
return (
|
||||||
|
(this.isOutgoing || this.isTemplate) &&
|
||||||
|
this.hasUserReadMessage &&
|
||||||
|
this.isWebWidgetInbox &&
|
||||||
|
!this.data.private
|
||||||
|
);
|
||||||
|
},
|
||||||
isTemplate() {
|
isTemplate() {
|
||||||
return this.data.message_type === MESSAGE_TYPE.TEMPLATE;
|
return this.data.message_type === MESSAGE_TYPE.TEMPLATE;
|
||||||
},
|
},
|
||||||
|
|||||||
@ -48,6 +48,10 @@
|
|||||||
:data="message"
|
:data="message"
|
||||||
:is-a-tweet="isATweet"
|
:is-a-tweet="isATweet"
|
||||||
:has-instagram-story="hasInstagramStory"
|
:has-instagram-story="hasInstagramStory"
|
||||||
|
:has-user-read-message="
|
||||||
|
hasUserReadMessage(message.created_at, getLastSeenAt)
|
||||||
|
"
|
||||||
|
:is-web-widget-inbox="isAWebWidgetInbox"
|
||||||
/>
|
/>
|
||||||
<li v-show="getUnreadCount != 0" class="unread--toast">
|
<li v-show="getUnreadCount != 0" class="unread--toast">
|
||||||
<span class="text-uppercase">
|
<span class="text-uppercase">
|
||||||
@ -66,6 +70,10 @@
|
|||||||
:data="message"
|
:data="message"
|
||||||
:is-a-tweet="isATweet"
|
:is-a-tweet="isATweet"
|
||||||
:has-instagram-story="hasInstagramStory"
|
:has-instagram-story="hasInstagramStory"
|
||||||
|
:has-user-read-message="
|
||||||
|
hasUserReadMessage(message.created_at, getLastSeenAt)
|
||||||
|
"
|
||||||
|
:is-web-widget-inbox="isAWebWidgetInbox"
|
||||||
/>
|
/>
|
||||||
</ul>
|
</ul>
|
||||||
<div
|
<div
|
||||||
@ -141,6 +149,7 @@ export default {
|
|||||||
listLoadingStatus: 'getAllMessagesLoaded',
|
listLoadingStatus: 'getAllMessagesLoaded',
|
||||||
getUnreadCount: 'getUnreadCount',
|
getUnreadCount: 'getUnreadCount',
|
||||||
loadingChatList: 'getChatListLoadingStatus',
|
loadingChatList: 'getChatListLoadingStatus',
|
||||||
|
conversationLastSeen: 'getConversationLastSeen',
|
||||||
}),
|
}),
|
||||||
inboxId() {
|
inboxId() {
|
||||||
return this.currentChat.inbox_id;
|
return this.currentChat.inbox_id;
|
||||||
@ -241,6 +250,11 @@ export default {
|
|||||||
}
|
}
|
||||||
return 'arrow-chevron-left';
|
return 'arrow-chevron-left';
|
||||||
},
|
},
|
||||||
|
getLastSeenAt() {
|
||||||
|
if (this.conversationLastSeen) return this.conversationLastSeen;
|
||||||
|
const { contact_last_seen_at: contactLastSeenAt } = this.currentChat;
|
||||||
|
return contactLastSeenAt;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
|
|||||||
@ -36,9 +36,9 @@
|
|||||||
<woot-audio-recorder
|
<woot-audio-recorder
|
||||||
v-if="showAudioRecorderEditor"
|
v-if="showAudioRecorderEditor"
|
||||||
ref="audioRecorderInput"
|
ref="audioRecorderInput"
|
||||||
@state-recorder-timer-changed="onStateRecorderTimerChanged"
|
@state-recorder-progress-changed="onStateProgressRecorderChanged"
|
||||||
@state-recorder-changed="onStateRecorderChanged"
|
@state-recorder-changed="onStateRecorderChanged"
|
||||||
@recorder-blob="onRecorderBlob"
|
@finish-record="onFinishRecorder"
|
||||||
/>
|
/>
|
||||||
<resizable-text-area
|
<resizable-text-area
|
||||||
v-else-if="!showRichContentEditor"
|
v-else-if="!showRichContentEditor"
|
||||||
@ -80,8 +80,8 @@
|
|||||||
>
|
>
|
||||||
<p
|
<p
|
||||||
v-if="isSignatureAvailable"
|
v-if="isSignatureAvailable"
|
||||||
|
v-dompurify-html="formatMessage(messageSignature)"
|
||||||
class="message-signature"
|
class="message-signature"
|
||||||
v-html="formatMessage(messageSignature)"
|
|
||||||
/>
|
/>
|
||||||
<p v-else class="message-signature">
|
<p v-else class="message-signature">
|
||||||
{{ $t('CONVERSATION.FOOTER.MESSAGE_SIGNATURE_NOT_CONFIGURED') }}
|
{{ $t('CONVERSATION.FOOTER.MESSAGE_SIGNATURE_NOT_CONFIGURED') }}
|
||||||
@ -103,7 +103,7 @@
|
|||||||
:show-emoji-picker="showEmojiPicker"
|
:show-emoji-picker="showEmojiPicker"
|
||||||
:on-send="sendMessage"
|
:on-send="sendMessage"
|
||||||
:is-send-disabled="isReplyButtonDisabled"
|
:is-send-disabled="isReplyButtonDisabled"
|
||||||
:recording-audio-duration-text="recordingAudioDuration"
|
:recording-audio-duration-text="recordingAudioDurationText"
|
||||||
:recording-audio-state="recordingAudioState"
|
:recording-audio-state="recordingAudioState"
|
||||||
:is-recording-audio="isRecordingAudio"
|
:is-recording-audio="isRecordingAudio"
|
||||||
:set-format-mode="setFormatMode"
|
:set-format-mode="setFormatMode"
|
||||||
@ -193,7 +193,7 @@ export default {
|
|||||||
attachedFiles: [],
|
attachedFiles: [],
|
||||||
isRecordingAudio: false,
|
isRecordingAudio: false,
|
||||||
recordingAudioState: '',
|
recordingAudioState: '',
|
||||||
recordingAudioDuration: '',
|
recordingAudioDurationText: '',
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
replyType: REPLY_EDITOR_MODES.REPLY,
|
replyType: REPLY_EDITOR_MODES.REPLY,
|
||||||
mentionSearchKey: '',
|
mentionSearchKey: '',
|
||||||
@ -585,11 +585,13 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
toggleAudioRecorderPlayPause() {
|
toggleAudioRecorderPlayPause() {
|
||||||
if (this.isRecordingAudio && !this.isRecorderAudioStopped) {
|
if (this.isRecordingAudio) {
|
||||||
this.isRecorderAudioStopped = true;
|
if (!this.isRecorderAudioStopped) {
|
||||||
this.$refs.audioRecorderInput.stopAudioRecording();
|
this.isRecorderAudioStopped = true;
|
||||||
} else if (this.isRecordingAudio && this.isRecorderAudioStopped) {
|
this.$refs.audioRecorderInput.stopAudioRecording();
|
||||||
this.$refs.audioRecorderInput.playPause();
|
} else if (this.isRecorderAudioStopped) {
|
||||||
|
this.$refs.audioRecorderInput.playPause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hideEmojiPicker() {
|
hideEmojiPicker() {
|
||||||
@ -612,19 +614,17 @@ export default {
|
|||||||
onFocus() {
|
onFocus() {
|
||||||
this.isFocused = true;
|
this.isFocused = true;
|
||||||
},
|
},
|
||||||
onStateRecorderTimerChanged(time) {
|
onStateProgressRecorderChanged(duration) {
|
||||||
this.recordingAudioDuration = time;
|
this.recordingAudioDurationText = duration;
|
||||||
},
|
},
|
||||||
onStateRecorderChanged(state) {
|
onStateRecorderChanged(state) {
|
||||||
this.recordingAudioState = state;
|
this.recordingAudioState = state;
|
||||||
if (state.includes('notallowederror')) {
|
if (state && 'notallowederror'.includes(state)) {
|
||||||
this.toggleAudioRecorder();
|
this.toggleAudioRecorder();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onRecorderBlob(file) {
|
onFinishRecorder(file) {
|
||||||
if (file) {
|
return file && this.onFileUpload(file);
|
||||||
this.onFileUpload(file);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
toggleTyping(status) {
|
toggleTyping(status) {
|
||||||
const conversationId = this.currentChat.id;
|
const conversationId = this.currentChat.id;
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="message-text--metadata">
|
<div class="message-text--metadata">
|
||||||
<span class="time">{{ readableTime }}</span>
|
<span class="time" :class="{ delivered: messageRead }">{{
|
||||||
|
readableTime
|
||||||
|
}}</span>
|
||||||
<span v-if="showSentIndicator" class="time">
|
<span v-if="showSentIndicator" class="time">
|
||||||
<fluent-icon
|
<fluent-icon
|
||||||
v-tooltip.top-start="$t('CHAT_LIST.SENT')"
|
v-tooltip.top-start="$t('CHAT_LIST.SENT')"
|
||||||
@ -8,6 +10,13 @@
|
|||||||
size="16"
|
size="16"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
<fluent-icon
|
||||||
|
v-if="messageRead"
|
||||||
|
v-tooltip.top-start="$t('CHAT_LIST.MESSAGE_READ')"
|
||||||
|
icon="checkmark-double"
|
||||||
|
class="action--icon read-tick"
|
||||||
|
size="12"
|
||||||
|
/>
|
||||||
<fluent-icon
|
<fluent-icon
|
||||||
v-if="isEmail"
|
v-if="isEmail"
|
||||||
v-tooltip.top-start="$t('CHAT_LIST.RECEIVED_VIA_EMAIL')"
|
v-tooltip.top-start="$t('CHAT_LIST.RECEIVED_VIA_EMAIL')"
|
||||||
@ -120,6 +129,10 @@ export default {
|
|||||||
type: [String, Number],
|
type: [String, Number],
|
||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
|
messageRead: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
inbox() {
|
inbox() {
|
||||||
@ -173,6 +186,10 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.action--icon {
|
.action--icon {
|
||||||
|
&.read-tick {
|
||||||
|
color: var(--v-100);
|
||||||
|
margin-top: calc(var(--space-micro) + var(--space-micro) / 2);
|
||||||
|
}
|
||||||
color: var(--white);
|
color: var(--white);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,6 +254,15 @@ export default {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
right: var(--space-small);
|
right: var(--space-small);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
&.delivered {
|
||||||
|
right: var(--space-medium);
|
||||||
|
line-height: 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.read-tick {
|
||||||
|
position: absolute;
|
||||||
|
bottom: var(--space-small);
|
||||||
|
right: var(--space-small);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
'hide--quoted': !showQuotedContent,
|
'hide--quoted': !showQuotedContent,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div class="text-content" v-html="message"></div>
|
<div v-dompurify-html="message" class="text-content"></div>
|
||||||
<button
|
<button
|
||||||
v-if="displayQuotedButton"
|
v-if="displayQuotedButton"
|
||||||
class="quoted-text--button"
|
class="quoted-text--button"
|
||||||
|
|||||||
@ -23,6 +23,8 @@ class ActionCableConnector extends BaseActionCableConnector {
|
|||||||
'contact.updated': this.onContactUpdate,
|
'contact.updated': this.onContactUpdate,
|
||||||
'conversation.mentioned': this.onConversationMentioned,
|
'conversation.mentioned': this.onConversationMentioned,
|
||||||
'notification.created': this.onNotificationCreated,
|
'notification.created': this.onNotificationCreated,
|
||||||
|
'first.reply.created': this.onFirstReplyCreated,
|
||||||
|
'conversation.read': this.onConversationRead,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +66,11 @@ class ActionCableConnector extends BaseActionCableConnector {
|
|||||||
this.fetchConversationStats();
|
this.fetchConversationStats();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onConversationRead = data => {
|
||||||
|
const { contact_last_seen_at: lastSeen } = data;
|
||||||
|
this.app.$store.dispatch('updateConversationRead', lastSeen);
|
||||||
|
};
|
||||||
|
|
||||||
onLogout = () => AuthAPI.logout();
|
onLogout = () => AuthAPI.logout();
|
||||||
|
|
||||||
onMessageCreated = data => {
|
onMessageCreated = data => {
|
||||||
@ -122,6 +129,7 @@ class ActionCableConnector extends BaseActionCableConnector {
|
|||||||
|
|
||||||
fetchConversationStats = () => {
|
fetchConversationStats = () => {
|
||||||
bus.$emit('fetch_conversation_stats');
|
bus.$emit('fetch_conversation_stats');
|
||||||
|
bus.$emit('fetch_overview_reports');
|
||||||
};
|
};
|
||||||
|
|
||||||
onContactDelete = data => {
|
onContactDelete = data => {
|
||||||
@ -139,6 +147,10 @@ class ActionCableConnector extends BaseActionCableConnector {
|
|||||||
onNotificationCreated = data => {
|
onNotificationCreated = data => {
|
||||||
this.app.$store.dispatch('notifications/addNotification', data);
|
this.app.$store.dispatch('notifications/addNotification', data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onFirstReplyCreated = () => {
|
||||||
|
bus.$emit('fetch_overview_reports');
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
@ -1,7 +1,15 @@
|
|||||||
|
const allElementsString = arr => {
|
||||||
|
return arr.every(elem => typeof elem === 'string');
|
||||||
|
};
|
||||||
|
|
||||||
|
const allElementsNumbers = arr => {
|
||||||
|
return arr.every(elem => typeof elem === 'number');
|
||||||
|
};
|
||||||
|
|
||||||
const formatArray = params => {
|
const formatArray = params => {
|
||||||
if (params.length <= 0) {
|
if (params.length <= 0) {
|
||||||
params = [];
|
params = [];
|
||||||
} else if (params.every(elem => typeof elem === 'string')) {
|
} else if (allElementsString(params) || allElementsNumbers(params)) {
|
||||||
params = [...params];
|
params = [...params];
|
||||||
} else {
|
} else {
|
||||||
params = params.map(val => val.id);
|
params = params.map(val => val.id);
|
||||||
|
|||||||
100
app/javascript/dashboard/helper/preChat.js
Normal file
100
app/javascript/dashboard/helper/preChat.js
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import i18n from 'widget/i18n/index';
|
||||||
|
const defaultTranslations = Object.fromEntries(
|
||||||
|
Object.entries(i18n).filter(([key]) => key.includes('en'))
|
||||||
|
).en;
|
||||||
|
|
||||||
|
export const standardFieldKeys = {
|
||||||
|
emailAddress: {
|
||||||
|
key: 'EMAIL_ADDRESS',
|
||||||
|
label: 'Email Id',
|
||||||
|
placeholder: 'Please enter your email address',
|
||||||
|
},
|
||||||
|
fullName: {
|
||||||
|
key: 'FULL_NAME',
|
||||||
|
label: 'Full Name',
|
||||||
|
placeholder: 'Please enter your full name',
|
||||||
|
},
|
||||||
|
phoneNumber: {
|
||||||
|
key: 'PHONE_NUMBER',
|
||||||
|
label: 'Phone Number',
|
||||||
|
placeholder: 'Please enter your phone number',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getLabel = ({ key, label }) => {
|
||||||
|
return defaultTranslations.PRE_CHAT_FORM.FIELDS[key]
|
||||||
|
? defaultTranslations.PRE_CHAT_FORM.FIELDS[key].LABEL
|
||||||
|
: label;
|
||||||
|
};
|
||||||
|
export const getPlaceHolder = ({ key, placeholder }) => {
|
||||||
|
return defaultTranslations.PRE_CHAT_FORM.FIELDS[key]
|
||||||
|
? defaultTranslations.PRE_CHAT_FORM.FIELDS[key].PLACEHOLDER
|
||||||
|
: placeholder;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getCustomFields = ({ standardFields, customAttributes }) => {
|
||||||
|
let customFields = [];
|
||||||
|
const { pre_chat_fields: preChatFields } = standardFields;
|
||||||
|
customAttributes.forEach(attribute => {
|
||||||
|
const itemExist = preChatFields.find(
|
||||||
|
item => item.name === attribute.attribute_key
|
||||||
|
);
|
||||||
|
if (!itemExist) {
|
||||||
|
customFields.push({
|
||||||
|
label: attribute.attribute_display_name,
|
||||||
|
placeholder: attribute.attribute_display_name,
|
||||||
|
name: attribute.attribute_key,
|
||||||
|
type: attribute.attribute_display_type,
|
||||||
|
values: attribute.attribute_values,
|
||||||
|
field_type: attribute.attribute_model,
|
||||||
|
required: false,
|
||||||
|
enabled: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return customFields;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getFormattedPreChatFields = ({ preChatFields }) => {
|
||||||
|
return preChatFields.map(item => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
label: getLabel({
|
||||||
|
key: standardFieldKeys[item.name]
|
||||||
|
? standardFieldKeys[item.name].key
|
||||||
|
: item.name,
|
||||||
|
label: item.label ? item.label : item.name,
|
||||||
|
}),
|
||||||
|
placeholder: getPlaceHolder({
|
||||||
|
key: standardFieldKeys[item.name]
|
||||||
|
? standardFieldKeys[item.name].key
|
||||||
|
: item.name,
|
||||||
|
placeholder: item.placeholder ? item.placeholder : item.name,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getPreChatFields = ({
|
||||||
|
preChatFormOptions = {},
|
||||||
|
customAttributes = [],
|
||||||
|
}) => {
|
||||||
|
const { pre_chat_message, pre_chat_fields } = preChatFormOptions;
|
||||||
|
let customFields = {};
|
||||||
|
let preChatFields = {};
|
||||||
|
|
||||||
|
const formattedPreChatFields = getFormattedPreChatFields({
|
||||||
|
preChatFields: pre_chat_fields,
|
||||||
|
});
|
||||||
|
|
||||||
|
customFields = getCustomFields({
|
||||||
|
standardFields: { pre_chat_fields: formattedPreChatFields },
|
||||||
|
customAttributes,
|
||||||
|
});
|
||||||
|
preChatFields = [...formattedPreChatFields, ...customFields];
|
||||||
|
|
||||||
|
return {
|
||||||
|
pre_chat_message,
|
||||||
|
pre_chat_fields: preChatFields,
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -1,25 +0,0 @@
|
|||||||
export const createMessengerScript = pageId => `
|
|
||||||
<script>
|
|
||||||
window.fbAsyncInit = function() {
|
|
||||||
FB.init({
|
|
||||||
appId: "${window.chatwootConfig.fbAppId}",
|
|
||||||
xfbml: true,
|
|
||||||
version: "v4.0"
|
|
||||||
});
|
|
||||||
};
|
|
||||||
(function(d, s, id){
|
|
||||||
var js, fjs = d.getElementsByTagName(s)[0];
|
|
||||||
if (d.getElementById(id)) { return; }
|
|
||||||
js = d.createElement(s); js.id = id;
|
|
||||||
js.src = "//connect.facebook.net/en_US/sdk.js";
|
|
||||||
fjs.parentNode.insertBefore(js, fjs);
|
|
||||||
}(document, 'script', 'facebook-jssdk'));
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<div class="fb-messengermessageus"
|
|
||||||
messenger_app_id="${window.chatwootConfig.fbAppId}"
|
|
||||||
page_id="${pageId}"
|
|
||||||
color="blue"
|
|
||||||
size="standard" >
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
47
app/javascript/dashboard/helper/specs/inboxFixture.js
Normal file
47
app/javascript/dashboard/helper/specs/inboxFixture.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
export default {
|
||||||
|
customFields: {
|
||||||
|
pre_chat_message: 'Share your queries or comments here.',
|
||||||
|
pre_chat_fields: [
|
||||||
|
{
|
||||||
|
label: 'Email Address',
|
||||||
|
name: 'emailAddress',
|
||||||
|
type: 'email',
|
||||||
|
field_type: 'standard',
|
||||||
|
required: false,
|
||||||
|
enabled: false,
|
||||||
|
|
||||||
|
placeholder: 'Please enter your email address',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Full Name',
|
||||||
|
name: 'fullName',
|
||||||
|
type: 'text',
|
||||||
|
field_type: 'standard',
|
||||||
|
required: false,
|
||||||
|
enabled: false,
|
||||||
|
placeholder: 'Please enter your full name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Phone Number',
|
||||||
|
name: 'phoneNumber',
|
||||||
|
type: 'text',
|
||||||
|
field_type: 'standard',
|
||||||
|
required: false,
|
||||||
|
enabled: false,
|
||||||
|
placeholder: 'Please enter your phone number',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
customAttributes: [
|
||||||
|
{
|
||||||
|
id: 101,
|
||||||
|
attribute_description: 'Order Identifier',
|
||||||
|
attribute_display_name: 'Order Id',
|
||||||
|
attribute_display_type: 'number',
|
||||||
|
attribute_key: 'order_id',
|
||||||
|
attribute_model: 'conversation_attribute',
|
||||||
|
attribute_values: Array(0),
|
||||||
|
created_at: '2021-11-29T10:20:04.563Z',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
76
app/javascript/dashboard/helper/specs/preChat.spec.js
Normal file
76
app/javascript/dashboard/helper/specs/preChat.spec.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import {
|
||||||
|
getPreChatFields,
|
||||||
|
getFormattedPreChatFields,
|
||||||
|
getCustomFields,
|
||||||
|
} from '../preChat';
|
||||||
|
import inboxFixture from './inboxFixture';
|
||||||
|
|
||||||
|
const { customFields, customAttributes } = inboxFixture;
|
||||||
|
describe('#Pre chat Helpers', () => {
|
||||||
|
describe('getPreChatFields', () => {
|
||||||
|
it('should return correct pre-chat fields form options passed', () => {
|
||||||
|
expect(getPreChatFields({ preChatFormOptions: customFields })).toEqual(
|
||||||
|
customFields
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('getFormattedPreChatFields', () => {
|
||||||
|
it('should return correct custom fields', () => {
|
||||||
|
expect(
|
||||||
|
getFormattedPreChatFields({
|
||||||
|
preChatFields: customFields.pre_chat_fields,
|
||||||
|
})
|
||||||
|
).toEqual([
|
||||||
|
{
|
||||||
|
label: 'Email Address',
|
||||||
|
name: 'emailAddress',
|
||||||
|
placeholder: 'Please enter your email address',
|
||||||
|
type: 'email',
|
||||||
|
field_type: 'standard',
|
||||||
|
|
||||||
|
required: false,
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Full Name',
|
||||||
|
name: 'fullName',
|
||||||
|
placeholder: 'Please enter your full name',
|
||||||
|
type: 'text',
|
||||||
|
field_type: 'standard',
|
||||||
|
required: false,
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Phone Number',
|
||||||
|
name: 'phoneNumber',
|
||||||
|
placeholder: 'Please enter your phone number',
|
||||||
|
type: 'text',
|
||||||
|
field_type: 'standard',
|
||||||
|
required: false,
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('getCustomFields', () => {
|
||||||
|
it('should return correct custom fields', () => {
|
||||||
|
expect(
|
||||||
|
getCustomFields({
|
||||||
|
standardFields: { pre_chat_fields: customFields.pre_chat_fields },
|
||||||
|
customAttributes,
|
||||||
|
})
|
||||||
|
).toEqual([
|
||||||
|
{
|
||||||
|
enabled: false,
|
||||||
|
label: 'Order Id',
|
||||||
|
placeholder: 'Order Id',
|
||||||
|
name: 'order_id',
|
||||||
|
required: false,
|
||||||
|
field_type: 'conversation_attribute',
|
||||||
|
type: 'number',
|
||||||
|
values: [],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -89,7 +89,9 @@
|
|||||||
"DELETE_MESSAGE": "يجب أن يكون لديك على الأقل شرط واحد للحفظ"
|
"DELETE_MESSAGE": "يجب أن يكون لديك على الأقل شرط واحد للحفظ"
|
||||||
},
|
},
|
||||||
"ACTION": {
|
"ACTION": {
|
||||||
"DELETE_MESSAGE": "يجب أن يكون لديك على الأقل شرط واحد للحفظ"
|
"DELETE_MESSAGE": "يجب أن يكون لديك على الأقل شرط واحد للحفظ",
|
||||||
|
"TEAM_MESSAGE_INPUT_PLACEHOLDER": "اكتب رسالتك هنا",
|
||||||
|
"TEAM_DROPDOWN_PLACEHOLDER": "اختيار فريق"
|
||||||
},
|
},
|
||||||
"TOGGLE": {
|
"TOGGLE": {
|
||||||
"ACTIVATION_TITLE": "تفعيل قاعدة الأتمتة",
|
"ACTIVATION_TITLE": "تفعيل قاعدة الأتمتة",
|
||||||
@ -102,6 +104,13 @@
|
|||||||
"DEACTIVATION_ERROR": "تعذر إلغاء تنشيط قاعدة الأتمتة، الرجاء المحاولة مرة أخرى لاحقاً",
|
"DEACTIVATION_ERROR": "تعذر إلغاء تنشيط قاعدة الأتمتة، الرجاء المحاولة مرة أخرى لاحقاً",
|
||||||
"CONFIRMATION_LABEL": "نعم",
|
"CONFIRMATION_LABEL": "نعم",
|
||||||
"CANCEL_LABEL": "لا"
|
"CANCEL_LABEL": "لا"
|
||||||
|
},
|
||||||
|
"ATTACHMENT": {
|
||||||
|
"UPLOAD_ERROR": "تعذر تحميل المرفق، الرجاء المحاولة مرة أخرى",
|
||||||
|
"LABEL_IDLE": "ارفع المرفق",
|
||||||
|
"LABEL_UPLOADING": "جاري الرفع...",
|
||||||
|
"LABEL_UPLOADED": "تم الرفع بنجاح",
|
||||||
|
"LABEL_UPLOAD_FAILED": "فشل الرفع"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -81,6 +81,7 @@
|
|||||||
"NO_MESSAGES": "لا توجد رسائل",
|
"NO_MESSAGES": "لا توجد رسائل",
|
||||||
"NO_CONTENT": "لم يتم العثور على محتوى",
|
"NO_CONTENT": "لم يتم العثور على محتوى",
|
||||||
"HIDE_QUOTED_TEXT": "Hide Quoted Text",
|
"HIDE_QUOTED_TEXT": "Hide Quoted Text",
|
||||||
"SHOW_QUOTED_TEXT": "Show Quoted Text"
|
"SHOW_QUOTED_TEXT": "Show Quoted Text",
|
||||||
|
"MESSAGE_READ": "قرائة"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,6 +70,14 @@
|
|||||||
"SUCCESS_MESSAGE": "تم حفظ جهة الاتصال بنجاح",
|
"SUCCESS_MESSAGE": "تم حفظ جهة الاتصال بنجاح",
|
||||||
"ERROR_MESSAGE": "حدث خطأ، الرجاء المحاولة مرة أخرى"
|
"ERROR_MESSAGE": "حدث خطأ، الرجاء المحاولة مرة أخرى"
|
||||||
},
|
},
|
||||||
|
"DELETE_NOTE": {
|
||||||
|
"CONFIRM": {
|
||||||
|
"TITLE": "تأكيد الحذف",
|
||||||
|
"MESSAGE": "هل أنت متأكد من حذف هذه الملاحظة؟",
|
||||||
|
"YES": "نعم، احذف",
|
||||||
|
"NO": "لا، احتفظ به"
|
||||||
|
}
|
||||||
|
},
|
||||||
"DELETE_CONTACT": {
|
"DELETE_CONTACT": {
|
||||||
"BUTTON_LABEL": "حذف جهة الاتصال",
|
"BUTTON_LABEL": "حذف جهة الاتصال",
|
||||||
"TITLE": "حذف جهة الاتصال",
|
"TITLE": "حذف جهة الاتصال",
|
||||||
|
|||||||
@ -60,6 +60,13 @@
|
|||||||
"NOTIFICATIONS_PAGE": {
|
"NOTIFICATIONS_PAGE": {
|
||||||
"HEADER": "الإشعارات",
|
"HEADER": "الإشعارات",
|
||||||
"MARK_ALL_DONE": "وضع علامة على جميع المنجز",
|
"MARK_ALL_DONE": "وضع علامة على جميع المنجز",
|
||||||
|
"DELETE_TITLE": "تم الحذف",
|
||||||
|
"UNREAD_NOTIFICATION": {
|
||||||
|
"TITLE": "إشعارات غير مقروءة",
|
||||||
|
"ALL_NOTIFICATIONS": "عرض جميع الإشعارات",
|
||||||
|
"LOADING_UNREAD_MESSAGE": "تحميل الإشعارات الغير مقروءة...",
|
||||||
|
"EMPTY_MESSAGE": "ليس لديك إشعارات غير مقروءة"
|
||||||
|
},
|
||||||
"LIST": {
|
"LIST": {
|
||||||
"LOADING_MESSAGE": "جاري تحميل الإشعارات...",
|
"LOADING_MESSAGE": "جاري تحميل الإشعارات...",
|
||||||
"404": "لا يوجد إشعارات",
|
"404": "لا يوجد إشعارات",
|
||||||
@ -101,6 +108,7 @@
|
|||||||
"GO_TO_CONVERSATION_DASHBOARD": "الذهاب إلى لوحة المحادثة",
|
"GO_TO_CONVERSATION_DASHBOARD": "الذهاب إلى لوحة المحادثة",
|
||||||
"GO_TO_CONTACTS_DASHBOARD": "الذهاب إلى لوحة جهات الاتصال",
|
"GO_TO_CONTACTS_DASHBOARD": "الذهاب إلى لوحة جهات الاتصال",
|
||||||
"GO_TO_REPORTS_OVERVIEW": "الذهاب إلى نظرة التقارير",
|
"GO_TO_REPORTS_OVERVIEW": "الذهاب إلى نظرة التقارير",
|
||||||
|
"GO_TO_CONVERSATION_REPORTS": "الذهاب إلى تقارير المحادثات",
|
||||||
"GO_TO_AGENT_REPORTS": "الذهاب إلى تقارير الوكيل",
|
"GO_TO_AGENT_REPORTS": "الذهاب إلى تقارير الوكيل",
|
||||||
"GO_TO_LABEL_REPORTS": "انتقل إلى تقارير التسمية",
|
"GO_TO_LABEL_REPORTS": "انتقل إلى تقارير التسمية",
|
||||||
"GO_TO_INBOX_REPORTS": "الذهاب إلى تقارير صندوق الوارد",
|
"GO_TO_INBOX_REPORTS": "الذهاب إلى تقارير صندوق الوارد",
|
||||||
|
|||||||
@ -341,10 +341,6 @@
|
|||||||
"AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "تم تحديث إعدادات الإسناد التلقائي بنجاح",
|
"AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "تم تحديث إعدادات الإسناد التلقائي بنجاح",
|
||||||
"ERROR_MESSAGE": "تعذر تحديث لون صندوق الدردشة. الرجاء المحاولة مرة أخرى لاحقاً."
|
"ERROR_MESSAGE": "تعذر تحديث لون صندوق الدردشة. الرجاء المحاولة مرة أخرى لاحقاً."
|
||||||
},
|
},
|
||||||
"AUTO_ASSIGNMENT": {
|
|
||||||
"ENABLED": "مفعل",
|
|
||||||
"DISABLED": "معطّل"
|
|
||||||
},
|
|
||||||
"EMAIL_COLLECT_BOX": {
|
"EMAIL_COLLECT_BOX": {
|
||||||
"ENABLED": "مفعل",
|
"ENABLED": "مفعل",
|
||||||
"DISABLED": "معطّل"
|
"DISABLED": "معطّل"
|
||||||
@ -394,13 +390,16 @@
|
|||||||
"FEATURES": {
|
"FEATURES": {
|
||||||
"LABEL": "الخصائص",
|
"LABEL": "الخصائص",
|
||||||
"DISPLAY_FILE_PICKER": "عرض أداة انتقاء الملفات في الـ widget",
|
"DISPLAY_FILE_PICKER": "عرض أداة انتقاء الملفات في الـ widget",
|
||||||
"DISPLAY_EMOJI_PICKER": "عرض منتقي الرموز التعبيرية على الـ widget"
|
"DISPLAY_EMOJI_PICKER": "عرض منتقي الرموز التعبيرية على الـ widget",
|
||||||
|
"ALLOW_END_CONVERSATION": "السماح للمستخدمين بإنهاء المحادثة من عنصر واجهة المستخدم"
|
||||||
},
|
},
|
||||||
"SETTINGS_POPUP": {
|
"SETTINGS_POPUP": {
|
||||||
"MESSENGER_HEADING": "كود \"الماسنجر\"",
|
"MESSENGER_HEADING": "كود \"الماسنجر\"",
|
||||||
"MESSENGER_SUB_HEAD": "ضع هذا الكود داخل وسم الـ body في موقعك",
|
"MESSENGER_SUB_HEAD": "ضع هذا الكود داخل وسم الـ body في موقعك",
|
||||||
"INBOX_AGENTS": "موظف الدعم",
|
"INBOX_AGENTS": "موظف الدعم",
|
||||||
"INBOX_AGENTS_SUB_TEXT": "إضافة أو إزالة موظفين من قناة التواصل هذه",
|
"INBOX_AGENTS_SUB_TEXT": "إضافة أو إزالة موظفين من قناة التواصل هذه",
|
||||||
|
"AGENT_ASSIGNMENT": "إسناد المحادثات",
|
||||||
|
"AGENT_ASSIGNMENT_SUB_TEXT": "تحديث إعدادات إسناد المحادثات",
|
||||||
"UPDATE": "تحديث",
|
"UPDATE": "تحديث",
|
||||||
"ENABLE_EMAIL_COLLECT_BOX": "تفعيل صندوق جمع البريد الإلكتروني",
|
"ENABLE_EMAIL_COLLECT_BOX": "تفعيل صندوق جمع البريد الإلكتروني",
|
||||||
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "تمكين أو تعطيل مربع جمع البريد الإلكتروني في محادثة جديدة",
|
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "تمكين أو تعطيل مربع جمع البريد الإلكتروني في محادثة جديدة",
|
||||||
@ -431,6 +430,15 @@
|
|||||||
},
|
},
|
||||||
"PRE_CHAT_FORM": {
|
"PRE_CHAT_FORM": {
|
||||||
"DESCRIPTION": "نماذج ما قبل الدردشة تمكنك من التقاط معلومات المستخدم قبل بدء المحادثة معك.",
|
"DESCRIPTION": "نماذج ما قبل الدردشة تمكنك من التقاط معلومات المستخدم قبل بدء المحادثة معك.",
|
||||||
|
"SET_FIELDS": "حقول نموذج الدردشة السابقة",
|
||||||
|
"SET_FIELDS_HEADER": {
|
||||||
|
"FIELDS": "الحقول",
|
||||||
|
"LABEL": "الوسم",
|
||||||
|
"PLACE_HOLDER": "المحتوى",
|
||||||
|
"KEY": "المفتاح",
|
||||||
|
"TYPE": "النوع",
|
||||||
|
"REQUIRED": "مطلوب"
|
||||||
|
},
|
||||||
"ENABLE": {
|
"ENABLE": {
|
||||||
"LABEL": "تمكين نموذج الدردشة السابقة",
|
"LABEL": "تمكين نموذج الدردشة السابقة",
|
||||||
"OPTIONS": {
|
"OPTIONS": {
|
||||||
@ -468,6 +476,7 @@
|
|||||||
"IMAP": {
|
"IMAP": {
|
||||||
"TITLE": "IMAP",
|
"TITLE": "IMAP",
|
||||||
"SUBTITLE": "تعيين تفاصيل IMAP الخاصة بك",
|
"SUBTITLE": "تعيين تفاصيل IMAP الخاصة بك",
|
||||||
|
"NOTE_TEXT": "لتمكين SMTP ، الرجاء تكوين IMAP.",
|
||||||
"UPDATE": "تحديث الإعدادات",
|
"UPDATE": "تحديث الإعدادات",
|
||||||
"TOGGLE_AVAILABILITY": "تمكين تكوين IMAP لهذا البريد الوارد",
|
"TOGGLE_AVAILABILITY": "تمكين تكوين IMAP لهذا البريد الوارد",
|
||||||
"TOGGLE_HELP": "تمكين IMAP سيساعد المستخدم على تلقي البريد الإلكتروني",
|
"TOGGLE_HELP": "تمكين IMAP سيساعد المستخدم على تلقي البريد الإلكتروني",
|
||||||
@ -483,9 +492,9 @@
|
|||||||
"LABEL": "المنفذ",
|
"LABEL": "المنفذ",
|
||||||
"PLACE_HOLDER": "المنفذ"
|
"PLACE_HOLDER": "المنفذ"
|
||||||
},
|
},
|
||||||
"EMAIL": {
|
"LOGIN": {
|
||||||
"LABEL": "البريد الإلكتروني",
|
"LABEL": "تسجيل الدخول",
|
||||||
"PLACE_HOLDER": "البريد الإلكتروني"
|
"PLACE_HOLDER": "تسجيل الدخول"
|
||||||
},
|
},
|
||||||
"PASSWORD": {
|
"PASSWORD": {
|
||||||
"LABEL": "كلمة المرور",
|
"LABEL": "كلمة المرور",
|
||||||
@ -511,9 +520,9 @@
|
|||||||
"LABEL": "المنفذ",
|
"LABEL": "المنفذ",
|
||||||
"PLACE_HOLDER": "المنفذ"
|
"PLACE_HOLDER": "المنفذ"
|
||||||
},
|
},
|
||||||
"EMAIL": {
|
"LOGIN": {
|
||||||
"LABEL": "البريد الإلكتروني",
|
"LABEL": "تسجيل الدخول",
|
||||||
"PLACE_HOLDER": "البريد الإلكتروني"
|
"PLACE_HOLDER": "تسجيل الدخول"
|
||||||
},
|
},
|
||||||
"PASSWORD": {
|
"PASSWORD": {
|
||||||
"LABEL": "كلمة المرور",
|
"LABEL": "كلمة المرور",
|
||||||
@ -526,7 +535,9 @@
|
|||||||
"ENCRYPTION": "التشفير",
|
"ENCRYPTION": "التشفير",
|
||||||
"SSL_TLS": "SSL/TLS",
|
"SSL_TLS": "SSL/TLS",
|
||||||
"START_TLS": "STARTTLS",
|
"START_TLS": "STARTTLS",
|
||||||
"OPEN_SSL_VERIFY_MODE": "فتح وضع التحقق من SSL"
|
"OPEN_SSL_VERIFY_MODE": "فتح وضع التحقق من SSL",
|
||||||
}
|
"AUTH_MECHANISM": "المصادقة"
|
||||||
|
},
|
||||||
|
"NOTE": "ملاحظة: "
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,29 @@
|
|||||||
"INTEGRATION_SETTINGS": {
|
"INTEGRATION_SETTINGS": {
|
||||||
"HEADER": "خيارات الربط",
|
"HEADER": "خيارات الربط",
|
||||||
"WEBHOOK": {
|
"WEBHOOK": {
|
||||||
|
"SUBSCRIBED_EVENTS": "الأحداث المشتركة",
|
||||||
|
"FORM": {
|
||||||
|
"CANCEL": "إلغاء",
|
||||||
|
"DESC": "أحداث Webhook توفر لك معلومات في الوقت الحقيقي حول ما يحدث في حساب Chatwoot الخاص بك. الرجاء إدخال عنوان URL صالح لتكوين callback.",
|
||||||
|
"SUBSCRIPTIONS": {
|
||||||
|
"LABEL": "الأحداث",
|
||||||
|
"EVENTS": {
|
||||||
|
"CONVERSATION_CREATED": "تم إنشاء المحادثة",
|
||||||
|
"CONVERSATION_STATUS_CHANGED": "تم تغيير حالة المحادثة",
|
||||||
|
"CONVERSATION_UPDATED": "تم تحديث المحادثة",
|
||||||
|
"MESSAGE_CREATED": "تم إنشاء رسالة",
|
||||||
|
"MESSAGE_UPDATED": "تم تحديث الرسالة",
|
||||||
|
"WEBWIDGET_TRIGGERED": "أداة الدردشة المباشرة مفتوحة من قبل المستخدم"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"END_POINT": {
|
||||||
|
"LABEL": "رابط Webhook",
|
||||||
|
"PLACEHOLDER": "مثال: https://example/api/webhook",
|
||||||
|
"ERROR": "الرجاء إدخال عنوان URL صالح"
|
||||||
|
},
|
||||||
|
"EDIT_SUBMIT": "تحديث الويبهوك",
|
||||||
|
"ADD_SUBMIT": "إنشاء webhook"
|
||||||
|
},
|
||||||
"TITLE": "Webhook",
|
"TITLE": "Webhook",
|
||||||
"CONFIGURE": "تهيئة",
|
"CONFIGURE": "تهيئة",
|
||||||
"HEADER": "إعدادات الـ Webhook",
|
"HEADER": "إعدادات الـ Webhook",
|
||||||
@ -20,35 +43,16 @@
|
|||||||
"EDIT": {
|
"EDIT": {
|
||||||
"BUTTON_TEXT": "تعديل",
|
"BUTTON_TEXT": "تعديل",
|
||||||
"TITLE": "تعديل webhook",
|
"TITLE": "تعديل webhook",
|
||||||
"CANCEL": "إلغاء",
|
|
||||||
"DESC": "أحداث Webhook توفر لك معلومات في الوقت الحقيقي حول ما يحدث في حساب Chatwoot الخاص بك. الرجاء إدخال عنوان URL صالح لتكوين callback.",
|
|
||||||
"FORM": {
|
|
||||||
"END_POINT": {
|
|
||||||
"LABEL": "رابط Webhook",
|
|
||||||
"PLACEHOLDER": "مثال: https://example/api/webhook",
|
|
||||||
"ERROR": "الرجاء إدخال عنوان URL صالح"
|
|
||||||
},
|
|
||||||
"SUBMIT": "تعديل webhook"
|
|
||||||
},
|
|
||||||
"API": {
|
"API": {
|
||||||
"SUCCESS_MESSAGE": "تم تحديث رابط Webhook بنجاح",
|
"SUCCESS_MESSAGE": "تم تحديث تكوين ويبهوك بنجاح",
|
||||||
"ERROR_MESSAGE": "تعذر الاتصال بالخادم، الرجاء المحاولة مرة أخرى لاحقاً"
|
"ERROR_MESSAGE": "تعذر الاتصال بالخادم، الرجاء المحاولة مرة أخرى لاحقاً"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ADD": {
|
"ADD": {
|
||||||
"CANCEL": "إلغاء",
|
"CANCEL": "إلغاء",
|
||||||
"TITLE": "إضافة webhook جديد",
|
"TITLE": "إضافة webhook جديد",
|
||||||
"DESC": "أحداث Webhook توفر لك معلومات في الوقت الحقيقي حول ما يحدث في حساب Chatwoot الخاص بك. الرجاء إدخال عنوان URL صالح لتكوين callback.",
|
|
||||||
"FORM": {
|
|
||||||
"END_POINT": {
|
|
||||||
"LABEL": "رابط Webhook",
|
|
||||||
"PLACEHOLDER": "مثال: https://example/api/webhook",
|
|
||||||
"ERROR": "الرجاء إدخال عنوان URL صالح"
|
|
||||||
},
|
|
||||||
"SUBMIT": "إنشاء webhook"
|
|
||||||
},
|
|
||||||
"API": {
|
"API": {
|
||||||
"SUCCESS_MESSAGE": "تم إضافة Webhook بنجاح",
|
"SUCCESS_MESSAGE": "تم إضافة إعدادات Webhook بنجاح",
|
||||||
"ERROR_MESSAGE": "تعذر الاتصال بالخادم، الرجاء المحاولة مرة أخرى لاحقاً"
|
"ERROR_MESSAGE": "تعذر الاتصال بالخادم، الرجاء المحاولة مرة أخرى لاحقاً"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -60,7 +64,7 @@
|
|||||||
},
|
},
|
||||||
"CONFIRM": {
|
"CONFIRM": {
|
||||||
"TITLE": "تأكيد الحذف",
|
"TITLE": "تأكيد الحذف",
|
||||||
"MESSAGE": "هل أنت متأكد من الحذف ",
|
"MESSAGE": "هل أنت متأكد من حذف webhook؟ (%{webhookURL})",
|
||||||
"YES": "نعم، احذف ",
|
"YES": "نعم، احذف ",
|
||||||
"NO": "لا، احتفظ به"
|
"NO": "لا، احتفظ به"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"REPORT": {
|
"REPORT": {
|
||||||
"HEADER": "نظرة عامة",
|
"HEADER": "المحادثات",
|
||||||
"LOADING_CHART": "تحميل بيانات الرسم البياني...",
|
"LOADING_CHART": "تحميل بيانات الرسم البياني...",
|
||||||
"NO_ENOUGH_DATA": "لم يتم جمع بيانات بقدر كافي لإنشاء التقرير، الرجاء المحاولة مرة أخرى لاحقاً.",
|
"NO_ENOUGH_DATA": "لم يتم جمع بيانات بقدر كافي لإنشاء التقرير، الرجاء المحاولة مرة أخرى لاحقاً.",
|
||||||
"DOWNLOAD_AGENT_REPORTS": "تنزيل تقارير الوكيل",
|
"DOWNLOAD_AGENT_REPORTS": "تنزيل تقارير الوكيل",
|
||||||
@ -19,11 +19,15 @@
|
|||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "وقت الاستجابة الأولى",
|
"NAME": "وقت الاستجابة الأولى",
|
||||||
"DESC": "(متوسط)"
|
"DESC": "(متوسط)",
|
||||||
|
"INFO_TEXT": "العدد الإجمالي للمحادثات المستخدمة في الحساب:",
|
||||||
|
"TOOLTIP_TEXT": "وقت الرد الأول هو %{metricValue} (على أساس %{conversationCount} محادثات)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "وقت إغلاق المحادثات",
|
"NAME": "وقت إغلاق المحادثات",
|
||||||
"DESC": "(متوسط)"
|
"DESC": "(متوسط)",
|
||||||
|
"INFO_TEXT": "العدد الإجمالي للمحادثات المستخدمة في الحساب:",
|
||||||
|
"TOOLTIP_TEXT": "وقت الحل هو %{metricValue} (على أساس %{conversationCount} محادثات)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "عدد مرات الإغلاق",
|
"NAME": "عدد مرات الإغلاق",
|
||||||
@ -108,7 +112,8 @@
|
|||||||
"id": 4,
|
"id": 4,
|
||||||
"groupBy": "السنة"
|
"groupBy": "السنة"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"BUSINESS_HOURS": "ساعات العمل"
|
||||||
},
|
},
|
||||||
"AGENT_REPORTS": {
|
"AGENT_REPORTS": {
|
||||||
"HEADER": "نظرة عامة للوكلاء",
|
"HEADER": "نظرة عامة للوكلاء",
|
||||||
@ -131,11 +136,15 @@
|
|||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "وقت الاستجابة الأولى",
|
"NAME": "وقت الاستجابة الأولى",
|
||||||
"DESC": "(متوسط)"
|
"DESC": "(متوسط)",
|
||||||
|
"INFO_TEXT": "العدد الإجمالي للمحادثات المستخدمة في الحساب:",
|
||||||
|
"TOOLTIP_TEXT": "وقت الرد الأول هو %{metricValue} (على أساس %{conversationCount} محادثات)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "وقت إغلاق المحادثات",
|
"NAME": "وقت إغلاق المحادثات",
|
||||||
"DESC": "(متوسط)"
|
"DESC": "(متوسط)",
|
||||||
|
"INFO_TEXT": "العدد الإجمالي للمحادثات المستخدمة في الحساب:",
|
||||||
|
"TOOLTIP_TEXT": "وقت الحل هو %{metricValue} (على أساس %{conversationCount} محادثات)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "عدد مرات الإغلاق",
|
"NAME": "عدد مرات الإغلاق",
|
||||||
@ -194,11 +203,15 @@
|
|||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "وقت الاستجابة الأولى",
|
"NAME": "وقت الاستجابة الأولى",
|
||||||
"DESC": "(متوسط)"
|
"DESC": "(متوسط)",
|
||||||
|
"INFO_TEXT": "العدد الإجمالي للمحادثات المستخدمة في الحساب:",
|
||||||
|
"TOOLTIP_TEXT": "وقت الرد الأول هو %{metricValue} (على أساس %{conversationCount} محادثات)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "وقت إغلاق المحادثات",
|
"NAME": "وقت إغلاق المحادثات",
|
||||||
"DESC": "(متوسط)"
|
"DESC": "(متوسط)",
|
||||||
|
"INFO_TEXT": "العدد الإجمالي للمحادثات المستخدمة في الحساب:",
|
||||||
|
"TOOLTIP_TEXT": "وقت الحل هو %{metricValue} (على أساس %{conversationCount} محادثات)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "عدد مرات الإغلاق",
|
"NAME": "عدد مرات الإغلاق",
|
||||||
@ -257,11 +270,15 @@
|
|||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "وقت الاستجابة الأولى",
|
"NAME": "وقت الاستجابة الأولى",
|
||||||
"DESC": "(متوسط)"
|
"DESC": "(متوسط)",
|
||||||
|
"INFO_TEXT": "العدد الإجمالي للمحادثات المستخدمة في الحساب:",
|
||||||
|
"TOOLTIP_TEXT": "وقت الرد الأول هو %{metricValue} (على أساس %{conversationCount} محادثات)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "وقت إغلاق المحادثات",
|
"NAME": "وقت إغلاق المحادثات",
|
||||||
"DESC": "(متوسط)"
|
"DESC": "(متوسط)",
|
||||||
|
"INFO_TEXT": "العدد الإجمالي للمحادثات المستخدمة في الحساب:",
|
||||||
|
"TOOLTIP_TEXT": "وقت الحل هو %{metricValue} (على أساس %{conversationCount} محادثات)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "عدد مرات الإغلاق",
|
"NAME": "عدد مرات الإغلاق",
|
||||||
@ -320,11 +337,15 @@
|
|||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "وقت الاستجابة الأولى",
|
"NAME": "وقت الاستجابة الأولى",
|
||||||
"DESC": "(متوسط)"
|
"DESC": "(متوسط)",
|
||||||
|
"INFO_TEXT": "العدد الإجمالي للمحادثات المستخدمة في الحساب:",
|
||||||
|
"TOOLTIP_TEXT": "وقت الرد الأول هو %{metricValue} (على أساس %{conversationCount} محادثات)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "وقت إغلاق المحادثات",
|
"NAME": "وقت إغلاق المحادثات",
|
||||||
"DESC": "(متوسط)"
|
"DESC": "(متوسط)",
|
||||||
|
"INFO_TEXT": "العدد الإجمالي للمحادثات المستخدمة في الحساب:",
|
||||||
|
"TOOLTIP_TEXT": "وقت الحل هو %{metricValue} (على أساس %{conversationCount} محادثات)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "عدد مرات الإغلاق",
|
"NAME": "عدد مرات الإغلاق",
|
||||||
@ -392,5 +413,33 @@
|
|||||||
"TOOLTIP": "العدد الإجمالي للردود / العدد الإجمالي لرسائل الاستقصاء التي أرسلتها CSAT * 100"
|
"TOOLTIP": "العدد الإجمالي للردود / العدد الإجمالي لرسائل الاستقصاء التي أرسلتها CSAT * 100"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"OVERVIEW_REPORTS": {
|
||||||
|
"HEADER": "نظرة عامة",
|
||||||
|
"LIVE": "مباشر",
|
||||||
|
"ACCOUNT_CONVERSATIONS": {
|
||||||
|
"HEADER": "المحادثات المفتوحة",
|
||||||
|
"LOADING_MESSAGE": "جارٍ تحميل مقاييس المحادثات...",
|
||||||
|
"OPEN": "فتح",
|
||||||
|
"UNATTENDED": "بدون حضور",
|
||||||
|
"UNASSIGNED": "غير مسند"
|
||||||
|
},
|
||||||
|
"AGENT_CONVERSATIONS": {
|
||||||
|
"HEADER": "المحادثات من قبل الوكلاء",
|
||||||
|
"LOADING_MESSAGE": "جاري تحميل مقاييس الوكيل...",
|
||||||
|
"NO_AGENTS": "لا توجد أي محادثات من قبل الوكلاء",
|
||||||
|
"TABLE_HEADER": {
|
||||||
|
"AGENT": "موظف الدعم",
|
||||||
|
"OPEN": "افتتحت",
|
||||||
|
"UNATTENDED": "بدون حضور",
|
||||||
|
"STATUS": "الحالة"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AGENT_STATUS": {
|
||||||
|
"HEADER": "حالة الوكيل",
|
||||||
|
"ONLINE": "متصل",
|
||||||
|
"BUSY": "مشغول",
|
||||||
|
"OFFLINE": "غير متصل"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,9 @@
|
|||||||
"SUCCESS_MESSAGE": "تم تغيير كلمة المرور بنجاح",
|
"SUCCESS_MESSAGE": "تم تغيير كلمة المرور بنجاح",
|
||||||
"ERROR_MESSAGE": "تعذر الاتصال بالخادم، الرجاء المحاولة مرة أخرى لاحقاً"
|
"ERROR_MESSAGE": "تعذر الاتصال بالخادم، الرجاء المحاولة مرة أخرى لاحقاً"
|
||||||
},
|
},
|
||||||
|
"CAPTCHA": {
|
||||||
|
"ERROR": "انتهت صلاحية التحقق. الرجاء حل كلمة التحقق مرة أخرى."
|
||||||
|
},
|
||||||
"SUBMIT": "إرسال"
|
"SUBMIT": "إرسال"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -131,6 +131,10 @@
|
|||||||
"BUTTON_TEXT": "نسخ",
|
"BUTTON_TEXT": "نسخ",
|
||||||
"COPY_SUCCESSFUL": "تم نسخ الكود إلى الحافظة بنجاح"
|
"COPY_SUCCESSFUL": "تم نسخ الكود إلى الحافظة بنجاح"
|
||||||
},
|
},
|
||||||
|
"SHOW_MORE_BLOCK": {
|
||||||
|
"SHOW_MORE": "إظهار المزيد",
|
||||||
|
"SHOW_LESS": "إظهار أقل"
|
||||||
|
},
|
||||||
"FILE_BUBBLE": {
|
"FILE_BUBBLE": {
|
||||||
"DOWNLOAD": "تنزيل",
|
"DOWNLOAD": "تنزيل",
|
||||||
"UPLOADING": "جاري الرفع..."
|
"UPLOADING": "جاري الرفع..."
|
||||||
@ -147,6 +151,7 @@
|
|||||||
},
|
},
|
||||||
"SIDEBAR": {
|
"SIDEBAR": {
|
||||||
"CURRENTLY_VIEWING_ACCOUNT": "مشاهدة حاليا:",
|
"CURRENTLY_VIEWING_ACCOUNT": "مشاهدة حاليا:",
|
||||||
|
"SWITCH": "تبديل",
|
||||||
"CONVERSATIONS": "المحادثات",
|
"CONVERSATIONS": "المحادثات",
|
||||||
"ALL_CONVERSATIONS": "كل المحادثات",
|
"ALL_CONVERSATIONS": "كل المحادثات",
|
||||||
"MENTIONED_CONVERSATIONS": "الإشارات",
|
"MENTIONED_CONVERSATIONS": "الإشارات",
|
||||||
@ -173,8 +178,8 @@
|
|||||||
"NEW_LABEL": "علامة جديدة",
|
"NEW_LABEL": "علامة جديدة",
|
||||||
"NEW_TEAM": "فريق جديد",
|
"NEW_TEAM": "فريق جديد",
|
||||||
"NEW_INBOX": "صندوق الوارد الجديد",
|
"NEW_INBOX": "صندوق الوارد الجديد",
|
||||||
"REPORTS_OVERVIEW": "نظرة عامة",
|
"REPORTS_CONVERSATION": "المحادثات",
|
||||||
"CSAT": "CSAT",
|
"CSAT": "تقييم رضاء العملاء",
|
||||||
"CAMPAIGNS": "الحملات",
|
"CAMPAIGNS": "الحملات",
|
||||||
"ONGOING": "جارية",
|
"ONGOING": "جارية",
|
||||||
"ONE_OFF": "إيقاف واحد",
|
"ONE_OFF": "إيقاف واحد",
|
||||||
@ -183,7 +188,8 @@
|
|||||||
"REPORTS_INBOX": "صندوق الوارد",
|
"REPORTS_INBOX": "صندوق الوارد",
|
||||||
"REPORTS_TEAM": "الفريق",
|
"REPORTS_TEAM": "الفريق",
|
||||||
"SET_AVAILABILITY_TITLE": "تعيين نفسك كـ",
|
"SET_AVAILABILITY_TITLE": "تعيين نفسك كـ",
|
||||||
"BETA": "تجريبي"
|
"BETA": "تجريبي",
|
||||||
|
"REPORTS_OVERVIEW": "نظرة عامة"
|
||||||
},
|
},
|
||||||
"CREATE_ACCOUNT": {
|
"CREATE_ACCOUNT": {
|
||||||
"NO_ACCOUNT_WARNING": "أوه! لم نتمكن من العثور على الحساب. الرجاء إنشاء حساب جديد للمتابعة.",
|
"NO_ACCOUNT_WARNING": "أوه! لم نتمكن من العثور على الحساب. الرجاء إنشاء حساب جديد للمتابعة.",
|
||||||
|
|||||||
@ -21,7 +21,8 @@
|
|||||||
"PASSWORD": {
|
"PASSWORD": {
|
||||||
"LABEL": "كلمة المرور",
|
"LABEL": "كلمة المرور",
|
||||||
"PLACEHOLDER": "كلمة المرور",
|
"PLACEHOLDER": "كلمة المرور",
|
||||||
"ERROR": "كلمة المرور قصيرة جداً"
|
"ERROR": "كلمة المرور قصيرة جداً",
|
||||||
|
"IS_INVALID_PASSWORD": "يجب أن تحتوي كلمة المرور على الأقل على حرف كبير واحد وحرف صغير واحد ورقم واحد وحرف خاص واحد"
|
||||||
},
|
},
|
||||||
"CONFIRM_PASSWORD": {
|
"CONFIRM_PASSWORD": {
|
||||||
"LABEL": "تأكيد كلمة المرور",
|
"LABEL": "تأكيد كلمة المرور",
|
||||||
|
|||||||
@ -89,7 +89,9 @@
|
|||||||
"DELETE_MESSAGE": "You need to have atleast one condition to save"
|
"DELETE_MESSAGE": "You need to have atleast one condition to save"
|
||||||
},
|
},
|
||||||
"ACTION": {
|
"ACTION": {
|
||||||
"DELETE_MESSAGE": "You need to have atleast one action to save"
|
"DELETE_MESSAGE": "You need to have atleast one action to save",
|
||||||
|
"TEAM_MESSAGE_INPUT_PLACEHOLDER": "Enter your message here",
|
||||||
|
"TEAM_DROPDOWN_PLACEHOLDER": "Select teams"
|
||||||
},
|
},
|
||||||
"TOGGLE": {
|
"TOGGLE": {
|
||||||
"ACTIVATION_TITLE": "Activate Automation Rule",
|
"ACTIVATION_TITLE": "Activate Automation Rule",
|
||||||
@ -102,6 +104,13 @@
|
|||||||
"DEACTIVATION_ERROR": "Could not Deactivate Automation, Please try again later",
|
"DEACTIVATION_ERROR": "Could not Deactivate Automation, Please try again later",
|
||||||
"CONFIRMATION_LABEL": "Yes",
|
"CONFIRMATION_LABEL": "Yes",
|
||||||
"CANCEL_LABEL": "No"
|
"CANCEL_LABEL": "No"
|
||||||
|
},
|
||||||
|
"ATTACHMENT": {
|
||||||
|
"UPLOAD_ERROR": "Could not upload attachment, Please try again",
|
||||||
|
"LABEL_IDLE": "Upload Attachment",
|
||||||
|
"LABEL_UPLOADING": "Качване...",
|
||||||
|
"LABEL_UPLOADED": "Succesfully Uploaded",
|
||||||
|
"LABEL_UPLOAD_FAILED": "Upload Failed"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -81,6 +81,7 @@
|
|||||||
"NO_MESSAGES": "Няма съобщения",
|
"NO_MESSAGES": "Няма съобщения",
|
||||||
"NO_CONTENT": "Няма налично съдържание",
|
"NO_CONTENT": "Няма налично съдържание",
|
||||||
"HIDE_QUOTED_TEXT": "Скриване на цитирания текст",
|
"HIDE_QUOTED_TEXT": "Скриване на цитирания текст",
|
||||||
"SHOW_QUOTED_TEXT": "Показване на цитирания текст"
|
"SHOW_QUOTED_TEXT": "Показване на цитирания текст",
|
||||||
|
"MESSAGE_READ": "Read"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,6 +70,14 @@
|
|||||||
"SUCCESS_MESSAGE": "Успешно запазване на контактите",
|
"SUCCESS_MESSAGE": "Успешно запазване на контактите",
|
||||||
"ERROR_MESSAGE": "Възникна грешка, моля опитайте отново"
|
"ERROR_MESSAGE": "Възникна грешка, моля опитайте отново"
|
||||||
},
|
},
|
||||||
|
"DELETE_NOTE": {
|
||||||
|
"CONFIRM": {
|
||||||
|
"TITLE": "Потвърди изтриването",
|
||||||
|
"MESSAGE": "Are you want sure to delete this note?",
|
||||||
|
"YES": "Yes, Delete it",
|
||||||
|
"NO": "No, Keep it"
|
||||||
|
}
|
||||||
|
},
|
||||||
"DELETE_CONTACT": {
|
"DELETE_CONTACT": {
|
||||||
"BUTTON_LABEL": "Изтриване на контакта",
|
"BUTTON_LABEL": "Изтриване на контакта",
|
||||||
"TITLE": "Изтриване на контакта",
|
"TITLE": "Изтриване на контакта",
|
||||||
|
|||||||
@ -60,6 +60,13 @@
|
|||||||
"NOTIFICATIONS_PAGE": {
|
"NOTIFICATIONS_PAGE": {
|
||||||
"HEADER": "Notifications",
|
"HEADER": "Notifications",
|
||||||
"MARK_ALL_DONE": "Mark All Done",
|
"MARK_ALL_DONE": "Mark All Done",
|
||||||
|
"DELETE_TITLE": "deleted",
|
||||||
|
"UNREAD_NOTIFICATION": {
|
||||||
|
"TITLE": "Unread Notifications",
|
||||||
|
"ALL_NOTIFICATIONS": "View all notifications",
|
||||||
|
"LOADING_UNREAD_MESSAGE": "Loading unread notifications...",
|
||||||
|
"EMPTY_MESSAGE": "You have no unread notifications"
|
||||||
|
},
|
||||||
"LIST": {
|
"LIST": {
|
||||||
"LOADING_MESSAGE": "Loading notifications...",
|
"LOADING_MESSAGE": "Loading notifications...",
|
||||||
"404": "No Notifications",
|
"404": "No Notifications",
|
||||||
@ -101,6 +108,7 @@
|
|||||||
"GO_TO_CONVERSATION_DASHBOARD": "Go to Conversation Dashboard",
|
"GO_TO_CONVERSATION_DASHBOARD": "Go to Conversation Dashboard",
|
||||||
"GO_TO_CONTACTS_DASHBOARD": "Go to Contacts Dashboard",
|
"GO_TO_CONTACTS_DASHBOARD": "Go to Contacts Dashboard",
|
||||||
"GO_TO_REPORTS_OVERVIEW": "Go to Reports Overview",
|
"GO_TO_REPORTS_OVERVIEW": "Go to Reports Overview",
|
||||||
|
"GO_TO_CONVERSATION_REPORTS": "Go to Conversation Reports",
|
||||||
"GO_TO_AGENT_REPORTS": "Go to Agent Reports",
|
"GO_TO_AGENT_REPORTS": "Go to Agent Reports",
|
||||||
"GO_TO_LABEL_REPORTS": "Go to Label Reports",
|
"GO_TO_LABEL_REPORTS": "Go to Label Reports",
|
||||||
"GO_TO_INBOX_REPORTS": "Go to Inbox Reports",
|
"GO_TO_INBOX_REPORTS": "Go to Inbox Reports",
|
||||||
|
|||||||
@ -341,10 +341,6 @@
|
|||||||
"AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "Auto assignment updated successfully",
|
"AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "Auto assignment updated successfully",
|
||||||
"ERROR_MESSAGE": "Could not update widget color. Please try again later."
|
"ERROR_MESSAGE": "Could not update widget color. Please try again later."
|
||||||
},
|
},
|
||||||
"AUTO_ASSIGNMENT": {
|
|
||||||
"ENABLED": "Enabled",
|
|
||||||
"DISABLED": "Disabled"
|
|
||||||
},
|
|
||||||
"EMAIL_COLLECT_BOX": {
|
"EMAIL_COLLECT_BOX": {
|
||||||
"ENABLED": "Enabled",
|
"ENABLED": "Enabled",
|
||||||
"DISABLED": "Disabled"
|
"DISABLED": "Disabled"
|
||||||
@ -394,13 +390,16 @@
|
|||||||
"FEATURES": {
|
"FEATURES": {
|
||||||
"LABEL": "Features",
|
"LABEL": "Features",
|
||||||
"DISPLAY_FILE_PICKER": "Display file picker on the widget",
|
"DISPLAY_FILE_PICKER": "Display file picker on the widget",
|
||||||
"DISPLAY_EMOJI_PICKER": "Display emoji picker on the widget"
|
"DISPLAY_EMOJI_PICKER": "Display emoji picker on the widget",
|
||||||
|
"ALLOW_END_CONVERSATION": "Allow users to end conversation from the widget"
|
||||||
},
|
},
|
||||||
"SETTINGS_POPUP": {
|
"SETTINGS_POPUP": {
|
||||||
"MESSENGER_HEADING": "Messenger Script",
|
"MESSENGER_HEADING": "Messenger Script",
|
||||||
"MESSENGER_SUB_HEAD": "Place this button inside your body tag",
|
"MESSENGER_SUB_HEAD": "Place this button inside your body tag",
|
||||||
"INBOX_AGENTS": "Агенти",
|
"INBOX_AGENTS": "Агенти",
|
||||||
"INBOX_AGENTS_SUB_TEXT": "Add or remove agents from this inbox",
|
"INBOX_AGENTS_SUB_TEXT": "Add or remove agents from this inbox",
|
||||||
|
"AGENT_ASSIGNMENT": "Conversation Assignment",
|
||||||
|
"AGENT_ASSIGNMENT_SUB_TEXT": "Update conversation assignment settings",
|
||||||
"UPDATE": "Update",
|
"UPDATE": "Update",
|
||||||
"ENABLE_EMAIL_COLLECT_BOX": "Enable email collect box",
|
"ENABLE_EMAIL_COLLECT_BOX": "Enable email collect box",
|
||||||
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Enable or disable email collect box on new conversation",
|
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Enable or disable email collect box on new conversation",
|
||||||
@ -431,6 +430,15 @@
|
|||||||
},
|
},
|
||||||
"PRE_CHAT_FORM": {
|
"PRE_CHAT_FORM": {
|
||||||
"DESCRIPTION": "Pre chat forms enable you to capture user information before they start conversation with you.",
|
"DESCRIPTION": "Pre chat forms enable you to capture user information before they start conversation with you.",
|
||||||
|
"SET_FIELDS": "Pre chat form fields",
|
||||||
|
"SET_FIELDS_HEADER": {
|
||||||
|
"FIELDS": "Fields",
|
||||||
|
"LABEL": "Label",
|
||||||
|
"PLACE_HOLDER": "Placeholder",
|
||||||
|
"KEY": "Ключ",
|
||||||
|
"TYPE": "Тип",
|
||||||
|
"REQUIRED": "Required"
|
||||||
|
},
|
||||||
"ENABLE": {
|
"ENABLE": {
|
||||||
"LABEL": "Enable pre chat form",
|
"LABEL": "Enable pre chat form",
|
||||||
"OPTIONS": {
|
"OPTIONS": {
|
||||||
@ -439,7 +447,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"PRE_CHAT_MESSAGE": {
|
"PRE_CHAT_MESSAGE": {
|
||||||
"LABEL": "Pre Chat Message",
|
"LABEL": "Pre chat message",
|
||||||
"PLACEHOLDER": "This message would be visible to the users along with the form"
|
"PLACEHOLDER": "This message would be visible to the users along with the form"
|
||||||
},
|
},
|
||||||
"REQUIRE_EMAIL": {
|
"REQUIRE_EMAIL": {
|
||||||
@ -468,6 +476,7 @@
|
|||||||
"IMAP": {
|
"IMAP": {
|
||||||
"TITLE": "IMAP",
|
"TITLE": "IMAP",
|
||||||
"SUBTITLE": "Set your IMAP details",
|
"SUBTITLE": "Set your IMAP details",
|
||||||
|
"NOTE_TEXT": "To enable SMTP, please configure IMAP.",
|
||||||
"UPDATE": "Update IMAP settings",
|
"UPDATE": "Update IMAP settings",
|
||||||
"TOGGLE_AVAILABILITY": "Enable IMAP configuration for this inbox",
|
"TOGGLE_AVAILABILITY": "Enable IMAP configuration for this inbox",
|
||||||
"TOGGLE_HELP": "Enabling IMAP will help the user to recieve email",
|
"TOGGLE_HELP": "Enabling IMAP will help the user to recieve email",
|
||||||
@ -483,9 +492,9 @@
|
|||||||
"LABEL": "Port",
|
"LABEL": "Port",
|
||||||
"PLACE_HOLDER": "Port"
|
"PLACE_HOLDER": "Port"
|
||||||
},
|
},
|
||||||
"EMAIL": {
|
"LOGIN": {
|
||||||
"LABEL": "Email",
|
"LABEL": "Login",
|
||||||
"PLACE_HOLDER": "Email"
|
"PLACE_HOLDER": "Login"
|
||||||
},
|
},
|
||||||
"PASSWORD": {
|
"PASSWORD": {
|
||||||
"LABEL": "Password",
|
"LABEL": "Password",
|
||||||
@ -511,9 +520,9 @@
|
|||||||
"LABEL": "Port",
|
"LABEL": "Port",
|
||||||
"PLACE_HOLDER": "Port"
|
"PLACE_HOLDER": "Port"
|
||||||
},
|
},
|
||||||
"EMAIL": {
|
"LOGIN": {
|
||||||
"LABEL": "Email",
|
"LABEL": "Login",
|
||||||
"PLACE_HOLDER": "Email"
|
"PLACE_HOLDER": "Login"
|
||||||
},
|
},
|
||||||
"PASSWORD": {
|
"PASSWORD": {
|
||||||
"LABEL": "Password",
|
"LABEL": "Password",
|
||||||
@ -526,7 +535,9 @@
|
|||||||
"ENCRYPTION": "Encryption",
|
"ENCRYPTION": "Encryption",
|
||||||
"SSL_TLS": "SSL/TLS",
|
"SSL_TLS": "SSL/TLS",
|
||||||
"START_TLS": "STARTTLS",
|
"START_TLS": "STARTTLS",
|
||||||
"OPEN_SSL_VERIFY_MODE": "Open SSL Verify Mode"
|
"OPEN_SSL_VERIFY_MODE": "Open SSL Verify Mode",
|
||||||
}
|
"AUTH_MECHANISM": "Authentication"
|
||||||
|
},
|
||||||
|
"NOTE": "Note: "
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,29 @@
|
|||||||
"INTEGRATION_SETTINGS": {
|
"INTEGRATION_SETTINGS": {
|
||||||
"HEADER": "Integrations",
|
"HEADER": "Integrations",
|
||||||
"WEBHOOK": {
|
"WEBHOOK": {
|
||||||
|
"SUBSCRIBED_EVENTS": "Subscribed Events",
|
||||||
|
"FORM": {
|
||||||
|
"CANCEL": "Отмени",
|
||||||
|
"DESC": "Webhook events provide you the realtime information about what's happening in your Chatwoot account. Please enter a valid URL to configure a callback.",
|
||||||
|
"SUBSCRIPTIONS": {
|
||||||
|
"LABEL": "Events",
|
||||||
|
"EVENTS": {
|
||||||
|
"CONVERSATION_CREATED": "Conversation Created",
|
||||||
|
"CONVERSATION_STATUS_CHANGED": "Conversation Status Changed",
|
||||||
|
"CONVERSATION_UPDATED": "Conversation Updated",
|
||||||
|
"MESSAGE_CREATED": "Message created",
|
||||||
|
"MESSAGE_UPDATED": "Message updated",
|
||||||
|
"WEBWIDGET_TRIGGERED": "Live chat widget opened by the user"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"END_POINT": {
|
||||||
|
"LABEL": "Webhook URL",
|
||||||
|
"PLACEHOLDER": "Example: https://example/api/webhook",
|
||||||
|
"ERROR": "Please enter a valid URL"
|
||||||
|
},
|
||||||
|
"EDIT_SUBMIT": "Update webhook",
|
||||||
|
"ADD_SUBMIT": "Create webhook"
|
||||||
|
},
|
||||||
"TITLE": "Webhook",
|
"TITLE": "Webhook",
|
||||||
"CONFIGURE": "Configure",
|
"CONFIGURE": "Configure",
|
||||||
"HEADER": "Webhook settings",
|
"HEADER": "Webhook settings",
|
||||||
@ -20,35 +43,16 @@
|
|||||||
"EDIT": {
|
"EDIT": {
|
||||||
"BUTTON_TEXT": "Редактирай",
|
"BUTTON_TEXT": "Редактирай",
|
||||||
"TITLE": "Edit webhook",
|
"TITLE": "Edit webhook",
|
||||||
"CANCEL": "Отмени",
|
|
||||||
"DESC": "Webhook events provide you the realtime information about what's happening in your Chatwoot account. Please enter a valid URL to configure a callback.",
|
|
||||||
"FORM": {
|
|
||||||
"END_POINT": {
|
|
||||||
"LABEL": "Webhook URL",
|
|
||||||
"PLACEHOLDER": "Example: https://example/api/webhook",
|
|
||||||
"ERROR": "Please enter a valid URL"
|
|
||||||
},
|
|
||||||
"SUBMIT": "Edit webhook"
|
|
||||||
},
|
|
||||||
"API": {
|
"API": {
|
||||||
"SUCCESS_MESSAGE": "Webhook URL updated successfully",
|
"SUCCESS_MESSAGE": "Webhook configuration updated successfully",
|
||||||
"ERROR_MESSAGE": "Не можа да се свърже с Woot сървър. Моля, опитайте отново по-късно"
|
"ERROR_MESSAGE": "Не можа да се свърже с Woot сървър. Моля, опитайте отново по-късно"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ADD": {
|
"ADD": {
|
||||||
"CANCEL": "Отмени",
|
"CANCEL": "Отмени",
|
||||||
"TITLE": "Add new webhook",
|
"TITLE": "Add new webhook",
|
||||||
"DESC": "Webhook events provide you the realtime information about what's happening in your Chatwoot account. Please enter a valid URL to configure a callback.",
|
|
||||||
"FORM": {
|
|
||||||
"END_POINT": {
|
|
||||||
"LABEL": "Webhook URL",
|
|
||||||
"PLACEHOLDER": "Example: https://example/api/webhook",
|
|
||||||
"ERROR": "Please enter a valid URL"
|
|
||||||
},
|
|
||||||
"SUBMIT": "Create webhook"
|
|
||||||
},
|
|
||||||
"API": {
|
"API": {
|
||||||
"SUCCESS_MESSAGE": "Webhook added successfully",
|
"SUCCESS_MESSAGE": "Webhook configuration added successfully",
|
||||||
"ERROR_MESSAGE": "Не можа да се свърже с Woot сървър. Моля, опитайте отново по-късно"
|
"ERROR_MESSAGE": "Не можа да се свърже с Woot сървър. Моля, опитайте отново по-късно"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -60,7 +64,7 @@
|
|||||||
},
|
},
|
||||||
"CONFIRM": {
|
"CONFIRM": {
|
||||||
"TITLE": "Потвърди изтриването",
|
"TITLE": "Потвърди изтриването",
|
||||||
"MESSAGE": "Сигурни ли сте за изтриването ",
|
"MESSAGE": "Are you sure to delete the webhook? (%{webhookURL})",
|
||||||
"YES": "Да, изтрий ",
|
"YES": "Да, изтрий ",
|
||||||
"NO": "No, Keep it"
|
"NO": "No, Keep it"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"REPORT": {
|
"REPORT": {
|
||||||
"HEADER": "Overview",
|
"HEADER": "Разговори",
|
||||||
"LOADING_CHART": "Loading chart data...",
|
"LOADING_CHART": "Loading chart data...",
|
||||||
"NO_ENOUGH_DATA": "We've not received enough data points to generate report, Please try again later.",
|
"NO_ENOUGH_DATA": "We've not received enough data points to generate report, Please try again later.",
|
||||||
"DOWNLOAD_AGENT_REPORTS": "Download agent reports",
|
"DOWNLOAD_AGENT_REPORTS": "Download agent reports",
|
||||||
@ -18,12 +18,16 @@
|
|||||||
"DESC": "( Total )"
|
"DESC": "( Total )"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "First response time",
|
"NAME": "First Response Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Resolution Time",
|
"NAME": "Resolution Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Resolution Count",
|
"NAME": "Resolution Count",
|
||||||
@ -108,7 +112,8 @@
|
|||||||
"id": 4,
|
"id": 4,
|
||||||
"groupBy": "Year"
|
"groupBy": "Year"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"BUSINESS_HOURS": "Business Hours"
|
||||||
},
|
},
|
||||||
"AGENT_REPORTS": {
|
"AGENT_REPORTS": {
|
||||||
"HEADER": "Agents Overview",
|
"HEADER": "Agents Overview",
|
||||||
@ -130,12 +135,16 @@
|
|||||||
"DESC": "( Total )"
|
"DESC": "( Total )"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "First response time",
|
"NAME": "First Response Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Resolution Time",
|
"NAME": "Resolution Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Resolution Count",
|
"NAME": "Resolution Count",
|
||||||
@ -193,12 +202,16 @@
|
|||||||
"DESC": "( Total )"
|
"DESC": "( Total )"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "First response time",
|
"NAME": "First Response Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Resolution Time",
|
"NAME": "Resolution Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Resolution Count",
|
"NAME": "Resolution Count",
|
||||||
@ -256,12 +269,16 @@
|
|||||||
"DESC": "( Total )"
|
"DESC": "( Total )"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "First response time",
|
"NAME": "First Response Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Resolution Time",
|
"NAME": "Resolution Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Resolution Count",
|
"NAME": "Resolution Count",
|
||||||
@ -319,12 +336,16 @@
|
|||||||
"DESC": "( Total )"
|
"DESC": "( Total )"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "First response time",
|
"NAME": "First Response Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Resolution Time",
|
"NAME": "Resolution Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Resolution Count",
|
"NAME": "Resolution Count",
|
||||||
@ -392,5 +413,33 @@
|
|||||||
"TOOLTIP": "Total number of responses / Total number of CSAT survey messages sent * 100"
|
"TOOLTIP": "Total number of responses / Total number of CSAT survey messages sent * 100"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"OVERVIEW_REPORTS": {
|
||||||
|
"HEADER": "Overview",
|
||||||
|
"LIVE": "Live",
|
||||||
|
"ACCOUNT_CONVERSATIONS": {
|
||||||
|
"HEADER": "Open Conversations",
|
||||||
|
"LOADING_MESSAGE": "Loading conversation metrics...",
|
||||||
|
"OPEN": "Отворен",
|
||||||
|
"UNATTENDED": "Unattended",
|
||||||
|
"UNASSIGNED": "Неназначен"
|
||||||
|
},
|
||||||
|
"AGENT_CONVERSATIONS": {
|
||||||
|
"HEADER": "Conversations by agents",
|
||||||
|
"LOADING_MESSAGE": "Loading agent metrics...",
|
||||||
|
"NO_AGENTS": "There are no conversations by agents",
|
||||||
|
"TABLE_HEADER": {
|
||||||
|
"AGENT": "Агент",
|
||||||
|
"OPEN": "OPEN",
|
||||||
|
"UNATTENDED": "Unattended",
|
||||||
|
"STATUS": "Статус"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AGENT_STATUS": {
|
||||||
|
"HEADER": "Agent status",
|
||||||
|
"ONLINE": "Online",
|
||||||
|
"BUSY": "Busy",
|
||||||
|
"OFFLINE": "Offline"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,9 @@
|
|||||||
"SUCCESS_MESSAGE": "Successfully changed the password",
|
"SUCCESS_MESSAGE": "Successfully changed the password",
|
||||||
"ERROR_MESSAGE": "Не можа да се свърже с Woot сървър. Моля, опитайте отново по-късно"
|
"ERROR_MESSAGE": "Не можа да се свърже с Woot сървър. Моля, опитайте отново по-късно"
|
||||||
},
|
},
|
||||||
|
"CAPTCHA": {
|
||||||
|
"ERROR": "Verification expired. Please solve captcha again."
|
||||||
|
},
|
||||||
"SUBMIT": "Изпращане"
|
"SUBMIT": "Изпращане"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
},
|
},
|
||||||
"MESSAGE_SIGNATURE_SECTION": {
|
"MESSAGE_SIGNATURE_SECTION": {
|
||||||
"TITLE": "Personal message signature",
|
"TITLE": "Personal message signature",
|
||||||
"NOTE": "Create a personal message signature that would be added to all the messages you send from the platform. Use the rich content editor to create a highly personalised signature.",
|
"NOTE": "Create a personal message signature that would be added to all the messages you send from your email inbox. Use the rich content editor to create a highly personalised signature.",
|
||||||
"BTN_TEXT": "Save message signature",
|
"BTN_TEXT": "Save message signature",
|
||||||
"API_ERROR": "Couldn't save signature! Try again",
|
"API_ERROR": "Couldn't save signature! Try again",
|
||||||
"API_SUCCESS": "Signature saved successfully"
|
"API_SUCCESS": "Signature saved successfully"
|
||||||
@ -131,6 +131,10 @@
|
|||||||
"BUTTON_TEXT": "Copy",
|
"BUTTON_TEXT": "Copy",
|
||||||
"COPY_SUCCESSFUL": "Code copied to clipboard successfully"
|
"COPY_SUCCESSFUL": "Code copied to clipboard successfully"
|
||||||
},
|
},
|
||||||
|
"SHOW_MORE_BLOCK": {
|
||||||
|
"SHOW_MORE": "Show More",
|
||||||
|
"SHOW_LESS": "Show Less"
|
||||||
|
},
|
||||||
"FILE_BUBBLE": {
|
"FILE_BUBBLE": {
|
||||||
"DOWNLOAD": "Download",
|
"DOWNLOAD": "Download",
|
||||||
"UPLOADING": "Качване..."
|
"UPLOADING": "Качване..."
|
||||||
@ -147,6 +151,7 @@
|
|||||||
},
|
},
|
||||||
"SIDEBAR": {
|
"SIDEBAR": {
|
||||||
"CURRENTLY_VIEWING_ACCOUNT": "Currently viewing:",
|
"CURRENTLY_VIEWING_ACCOUNT": "Currently viewing:",
|
||||||
|
"SWITCH": "Switch",
|
||||||
"CONVERSATIONS": "Разговори",
|
"CONVERSATIONS": "Разговори",
|
||||||
"ALL_CONVERSATIONS": "All Conversations",
|
"ALL_CONVERSATIONS": "All Conversations",
|
||||||
"MENTIONED_CONVERSATIONS": "Споменавания",
|
"MENTIONED_CONVERSATIONS": "Споменавания",
|
||||||
@ -173,7 +178,7 @@
|
|||||||
"NEW_LABEL": "New label",
|
"NEW_LABEL": "New label",
|
||||||
"NEW_TEAM": "New team",
|
"NEW_TEAM": "New team",
|
||||||
"NEW_INBOX": "New inbox",
|
"NEW_INBOX": "New inbox",
|
||||||
"REPORTS_OVERVIEW": "Overview",
|
"REPORTS_CONVERSATION": "Разговори",
|
||||||
"CSAT": "CSAT",
|
"CSAT": "CSAT",
|
||||||
"CAMPAIGNS": "Campaigns",
|
"CAMPAIGNS": "Campaigns",
|
||||||
"ONGOING": "Ongoing",
|
"ONGOING": "Ongoing",
|
||||||
@ -183,7 +188,8 @@
|
|||||||
"REPORTS_INBOX": "Входяща кутия",
|
"REPORTS_INBOX": "Входяща кутия",
|
||||||
"REPORTS_TEAM": "Team",
|
"REPORTS_TEAM": "Team",
|
||||||
"SET_AVAILABILITY_TITLE": "Set yourself as",
|
"SET_AVAILABILITY_TITLE": "Set yourself as",
|
||||||
"BETA": "Beta"
|
"BETA": "Beta",
|
||||||
|
"REPORTS_OVERVIEW": "Overview"
|
||||||
},
|
},
|
||||||
"CREATE_ACCOUNT": {
|
"CREATE_ACCOUNT": {
|
||||||
"NO_ACCOUNT_WARNING": "Uh oh! We could not find any Chatwoot accounts. Please create a new account to continue.",
|
"NO_ACCOUNT_WARNING": "Uh oh! We could not find any Chatwoot accounts. Please create a new account to continue.",
|
||||||
|
|||||||
@ -21,7 +21,8 @@
|
|||||||
"PASSWORD": {
|
"PASSWORD": {
|
||||||
"LABEL": "Password",
|
"LABEL": "Password",
|
||||||
"PLACEHOLDER": "Password",
|
"PLACEHOLDER": "Password",
|
||||||
"ERROR": "Password is too short"
|
"ERROR": "Password is too short",
|
||||||
|
"IS_INVALID_PASSWORD": "Password should contain atleast 1 uppercase letter, 1 lowercase letter, 1 number and 1 special character"
|
||||||
},
|
},
|
||||||
"CONFIRM_PASSWORD": {
|
"CONFIRM_PASSWORD": {
|
||||||
"LABEL": "Confirm Password",
|
"LABEL": "Confirm Password",
|
||||||
|
|||||||
@ -83,7 +83,7 @@
|
|||||||
"SELECT_ALL": "select all agents",
|
"SELECT_ALL": "select all agents",
|
||||||
"SELECTED_COUNT": "%{selected} out of %{total} agents selected.",
|
"SELECTED_COUNT": "%{selected} out of %{total} agents selected.",
|
||||||
"BUTTON_TEXT": "Add agents",
|
"BUTTON_TEXT": "Add agents",
|
||||||
"AGENT_VALIDATION_ERROR": "Select atleaset one agent."
|
"AGENT_VALIDATION_ERROR": "Select at least one agent."
|
||||||
},
|
},
|
||||||
"FINISH": {
|
"FINISH": {
|
||||||
"TITLE": "Your team is ready!",
|
"TITLE": "Your team is ready!",
|
||||||
|
|||||||
@ -89,7 +89,9 @@
|
|||||||
"DELETE_MESSAGE": "You need to have atleast one condition to save"
|
"DELETE_MESSAGE": "You need to have atleast one condition to save"
|
||||||
},
|
},
|
||||||
"ACTION": {
|
"ACTION": {
|
||||||
"DELETE_MESSAGE": "You need to have atleast one action to save"
|
"DELETE_MESSAGE": "You need to have atleast one action to save",
|
||||||
|
"TEAM_MESSAGE_INPUT_PLACEHOLDER": "Enter your message here",
|
||||||
|
"TEAM_DROPDOWN_PLACEHOLDER": "Select teams"
|
||||||
},
|
},
|
||||||
"TOGGLE": {
|
"TOGGLE": {
|
||||||
"ACTIVATION_TITLE": "Activate Automation Rule",
|
"ACTIVATION_TITLE": "Activate Automation Rule",
|
||||||
@ -102,6 +104,13 @@
|
|||||||
"DEACTIVATION_ERROR": "Could not Deactivate Automation, Please try again later",
|
"DEACTIVATION_ERROR": "Could not Deactivate Automation, Please try again later",
|
||||||
"CONFIRMATION_LABEL": "Si",
|
"CONFIRMATION_LABEL": "Si",
|
||||||
"CANCEL_LABEL": "No"
|
"CANCEL_LABEL": "No"
|
||||||
|
},
|
||||||
|
"ATTACHMENT": {
|
||||||
|
"UPLOAD_ERROR": "Could not upload attachment, Please try again",
|
||||||
|
"LABEL_IDLE": "Upload Attachment",
|
||||||
|
"LABEL_UPLOADING": "S'està carregant...",
|
||||||
|
"LABEL_UPLOADED": "Succesfully Uploaded",
|
||||||
|
"LABEL_UPLOAD_FAILED": "Upload Failed"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -81,6 +81,7 @@
|
|||||||
"NO_MESSAGES": "Cap Missatge",
|
"NO_MESSAGES": "Cap Missatge",
|
||||||
"NO_CONTENT": "No content available",
|
"NO_CONTENT": "No content available",
|
||||||
"HIDE_QUOTED_TEXT": "Hide Quoted Text",
|
"HIDE_QUOTED_TEXT": "Hide Quoted Text",
|
||||||
"SHOW_QUOTED_TEXT": "Show Quoted Text"
|
"SHOW_QUOTED_TEXT": "Show Quoted Text",
|
||||||
|
"MESSAGE_READ": "Read"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,6 +70,14 @@
|
|||||||
"SUCCESS_MESSAGE": "Contacts saved successfully",
|
"SUCCESS_MESSAGE": "Contacts saved successfully",
|
||||||
"ERROR_MESSAGE": "S'ha produït un error; tornau-ho a provar"
|
"ERROR_MESSAGE": "S'ha produït un error; tornau-ho a provar"
|
||||||
},
|
},
|
||||||
|
"DELETE_NOTE": {
|
||||||
|
"CONFIRM": {
|
||||||
|
"TITLE": "Confirma l'esborrat",
|
||||||
|
"MESSAGE": "Are you want sure to delete this note?",
|
||||||
|
"YES": "Yes, Delete it",
|
||||||
|
"NO": "No, manten-la"
|
||||||
|
}
|
||||||
|
},
|
||||||
"DELETE_CONTACT": {
|
"DELETE_CONTACT": {
|
||||||
"BUTTON_LABEL": "Delete Contact",
|
"BUTTON_LABEL": "Delete Contact",
|
||||||
"TITLE": "Delete contact",
|
"TITLE": "Delete contact",
|
||||||
|
|||||||
@ -60,6 +60,13 @@
|
|||||||
"NOTIFICATIONS_PAGE": {
|
"NOTIFICATIONS_PAGE": {
|
||||||
"HEADER": "Notificacions",
|
"HEADER": "Notificacions",
|
||||||
"MARK_ALL_DONE": "Marca Tot Fet",
|
"MARK_ALL_DONE": "Marca Tot Fet",
|
||||||
|
"DELETE_TITLE": "deleted",
|
||||||
|
"UNREAD_NOTIFICATION": {
|
||||||
|
"TITLE": "Unread Notifications",
|
||||||
|
"ALL_NOTIFICATIONS": "View all notifications",
|
||||||
|
"LOADING_UNREAD_MESSAGE": "Loading unread notifications...",
|
||||||
|
"EMPTY_MESSAGE": "You have no unread notifications"
|
||||||
|
},
|
||||||
"LIST": {
|
"LIST": {
|
||||||
"LOADING_MESSAGE": "Carregant notificacions...",
|
"LOADING_MESSAGE": "Carregant notificacions...",
|
||||||
"404": "Cap Notificació",
|
"404": "Cap Notificació",
|
||||||
@ -101,6 +108,7 @@
|
|||||||
"GO_TO_CONVERSATION_DASHBOARD": "Go to Conversation Dashboard",
|
"GO_TO_CONVERSATION_DASHBOARD": "Go to Conversation Dashboard",
|
||||||
"GO_TO_CONTACTS_DASHBOARD": "Go to Contacts Dashboard",
|
"GO_TO_CONTACTS_DASHBOARD": "Go to Contacts Dashboard",
|
||||||
"GO_TO_REPORTS_OVERVIEW": "Go to Reports Overview",
|
"GO_TO_REPORTS_OVERVIEW": "Go to Reports Overview",
|
||||||
|
"GO_TO_CONVERSATION_REPORTS": "Go to Conversation Reports",
|
||||||
"GO_TO_AGENT_REPORTS": "Go to Agent Reports",
|
"GO_TO_AGENT_REPORTS": "Go to Agent Reports",
|
||||||
"GO_TO_LABEL_REPORTS": "Go to Label Reports",
|
"GO_TO_LABEL_REPORTS": "Go to Label Reports",
|
||||||
"GO_TO_INBOX_REPORTS": "Go to Inbox Reports",
|
"GO_TO_INBOX_REPORTS": "Go to Inbox Reports",
|
||||||
|
|||||||
@ -341,10 +341,6 @@
|
|||||||
"AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "Assignació automàtica actualitzada correctament",
|
"AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "Assignació automàtica actualitzada correctament",
|
||||||
"ERROR_MESSAGE": "No s'ha pogut actualitzar el color del widget. Torneu-ho a provar més endavant."
|
"ERROR_MESSAGE": "No s'ha pogut actualitzar el color del widget. Torneu-ho a provar més endavant."
|
||||||
},
|
},
|
||||||
"AUTO_ASSIGNMENT": {
|
|
||||||
"ENABLED": "Habilita",
|
|
||||||
"DISABLED": "Inhabilita"
|
|
||||||
},
|
|
||||||
"EMAIL_COLLECT_BOX": {
|
"EMAIL_COLLECT_BOX": {
|
||||||
"ENABLED": "Habilita",
|
"ENABLED": "Habilita",
|
||||||
"DISABLED": "Inhabilita"
|
"DISABLED": "Inhabilita"
|
||||||
@ -394,13 +390,16 @@
|
|||||||
"FEATURES": {
|
"FEATURES": {
|
||||||
"LABEL": "Característiques",
|
"LABEL": "Característiques",
|
||||||
"DISPLAY_FILE_PICKER": "Mostra el selector de fitxers al widget",
|
"DISPLAY_FILE_PICKER": "Mostra el selector de fitxers al widget",
|
||||||
"DISPLAY_EMOJI_PICKER": "Mostra el selector d'emoji al widget"
|
"DISPLAY_EMOJI_PICKER": "Mostra el selector d'emoji al widget",
|
||||||
|
"ALLOW_END_CONVERSATION": "Allow users to end conversation from the widget"
|
||||||
},
|
},
|
||||||
"SETTINGS_POPUP": {
|
"SETTINGS_POPUP": {
|
||||||
"MESSENGER_HEADING": "Script del missatger",
|
"MESSENGER_HEADING": "Script del missatger",
|
||||||
"MESSENGER_SUB_HEAD": "Col·loca aquest botó dins de l'etiqueta body",
|
"MESSENGER_SUB_HEAD": "Col·loca aquest botó dins de l'etiqueta body",
|
||||||
"INBOX_AGENTS": "Agents",
|
"INBOX_AGENTS": "Agents",
|
||||||
"INBOX_AGENTS_SUB_TEXT": "Afegir o eliminar agents d'aquesta safata d'entrada",
|
"INBOX_AGENTS_SUB_TEXT": "Afegir o eliminar agents d'aquesta safata d'entrada",
|
||||||
|
"AGENT_ASSIGNMENT": "Conversation Assignment",
|
||||||
|
"AGENT_ASSIGNMENT_SUB_TEXT": "Update conversation assignment settings",
|
||||||
"UPDATE": "Actualitza",
|
"UPDATE": "Actualitza",
|
||||||
"ENABLE_EMAIL_COLLECT_BOX": "Enable email collect box",
|
"ENABLE_EMAIL_COLLECT_BOX": "Enable email collect box",
|
||||||
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Enable or disable email collect box on new conversation",
|
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Enable or disable email collect box on new conversation",
|
||||||
@ -431,6 +430,15 @@
|
|||||||
},
|
},
|
||||||
"PRE_CHAT_FORM": {
|
"PRE_CHAT_FORM": {
|
||||||
"DESCRIPTION": "Pre chat forms enable you to capture user information before they start conversation with you.",
|
"DESCRIPTION": "Pre chat forms enable you to capture user information before they start conversation with you.",
|
||||||
|
"SET_FIELDS": "Pre chat form fields",
|
||||||
|
"SET_FIELDS_HEADER": {
|
||||||
|
"FIELDS": "Fields",
|
||||||
|
"LABEL": "Label",
|
||||||
|
"PLACE_HOLDER": "Placeholder",
|
||||||
|
"KEY": "Key",
|
||||||
|
"TYPE": "Type",
|
||||||
|
"REQUIRED": "Required"
|
||||||
|
},
|
||||||
"ENABLE": {
|
"ENABLE": {
|
||||||
"LABEL": "Enable pre chat form",
|
"LABEL": "Enable pre chat form",
|
||||||
"OPTIONS": {
|
"OPTIONS": {
|
||||||
@ -439,7 +447,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"PRE_CHAT_MESSAGE": {
|
"PRE_CHAT_MESSAGE": {
|
||||||
"LABEL": "Pre Chat Message",
|
"LABEL": "Pre chat message",
|
||||||
"PLACEHOLDER": "This message would be visible to the users along with the form"
|
"PLACEHOLDER": "This message would be visible to the users along with the form"
|
||||||
},
|
},
|
||||||
"REQUIRE_EMAIL": {
|
"REQUIRE_EMAIL": {
|
||||||
@ -468,6 +476,7 @@
|
|||||||
"IMAP": {
|
"IMAP": {
|
||||||
"TITLE": "IMAP",
|
"TITLE": "IMAP",
|
||||||
"SUBTITLE": "Set your IMAP details",
|
"SUBTITLE": "Set your IMAP details",
|
||||||
|
"NOTE_TEXT": "To enable SMTP, please configure IMAP.",
|
||||||
"UPDATE": "Update IMAP settings",
|
"UPDATE": "Update IMAP settings",
|
||||||
"TOGGLE_AVAILABILITY": "Enable IMAP configuration for this inbox",
|
"TOGGLE_AVAILABILITY": "Enable IMAP configuration for this inbox",
|
||||||
"TOGGLE_HELP": "Enabling IMAP will help the user to recieve email",
|
"TOGGLE_HELP": "Enabling IMAP will help the user to recieve email",
|
||||||
@ -483,9 +492,9 @@
|
|||||||
"LABEL": "Port",
|
"LABEL": "Port",
|
||||||
"PLACE_HOLDER": "Port"
|
"PLACE_HOLDER": "Port"
|
||||||
},
|
},
|
||||||
"EMAIL": {
|
"LOGIN": {
|
||||||
"LABEL": "Correu electrònic",
|
"LABEL": "Inicia la sessió",
|
||||||
"PLACE_HOLDER": "Correu electrònic"
|
"PLACE_HOLDER": "Inicia la sessió"
|
||||||
},
|
},
|
||||||
"PASSWORD": {
|
"PASSWORD": {
|
||||||
"LABEL": "Contrasenya",
|
"LABEL": "Contrasenya",
|
||||||
@ -511,9 +520,9 @@
|
|||||||
"LABEL": "Port",
|
"LABEL": "Port",
|
||||||
"PLACE_HOLDER": "Port"
|
"PLACE_HOLDER": "Port"
|
||||||
},
|
},
|
||||||
"EMAIL": {
|
"LOGIN": {
|
||||||
"LABEL": "Correu electrònic",
|
"LABEL": "Inicia la sessió",
|
||||||
"PLACE_HOLDER": "Correu electrònic"
|
"PLACE_HOLDER": "Inicia la sessió"
|
||||||
},
|
},
|
||||||
"PASSWORD": {
|
"PASSWORD": {
|
||||||
"LABEL": "Contrasenya",
|
"LABEL": "Contrasenya",
|
||||||
@ -526,7 +535,9 @@
|
|||||||
"ENCRYPTION": "Encryption",
|
"ENCRYPTION": "Encryption",
|
||||||
"SSL_TLS": "SSL/TLS",
|
"SSL_TLS": "SSL/TLS",
|
||||||
"START_TLS": "STARTTLS",
|
"START_TLS": "STARTTLS",
|
||||||
"OPEN_SSL_VERIFY_MODE": "Open SSL Verify Mode"
|
"OPEN_SSL_VERIFY_MODE": "Open SSL Verify Mode",
|
||||||
}
|
"AUTH_MECHANISM": "Authentication"
|
||||||
|
},
|
||||||
|
"NOTE": "Note: "
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,29 @@
|
|||||||
"INTEGRATION_SETTINGS": {
|
"INTEGRATION_SETTINGS": {
|
||||||
"HEADER": "Integracions",
|
"HEADER": "Integracions",
|
||||||
"WEBHOOK": {
|
"WEBHOOK": {
|
||||||
|
"SUBSCRIBED_EVENTS": "Subscribed Events",
|
||||||
|
"FORM": {
|
||||||
|
"CANCEL": "Cancel·la",
|
||||||
|
"DESC": "Els esdeveniments de Webhook us proporcionen informació en temps real sobre el que passa al vostre compte de Chatwoot. Introduïu una URL vàlid per configurar un callback.",
|
||||||
|
"SUBSCRIPTIONS": {
|
||||||
|
"LABEL": "Events",
|
||||||
|
"EVENTS": {
|
||||||
|
"CONVERSATION_CREATED": "Conversation Created",
|
||||||
|
"CONVERSATION_STATUS_CHANGED": "Conversation Status Changed",
|
||||||
|
"CONVERSATION_UPDATED": "Conversation Updated",
|
||||||
|
"MESSAGE_CREATED": "Message created",
|
||||||
|
"MESSAGE_UPDATED": "Message updated",
|
||||||
|
"WEBWIDGET_TRIGGERED": "Live chat widget opened by the user"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"END_POINT": {
|
||||||
|
"LABEL": "URL del webhook",
|
||||||
|
"PLACEHOLDER": "Exemple: https://example/api/webhook",
|
||||||
|
"ERROR": "Introduïu una URL vàlid"
|
||||||
|
},
|
||||||
|
"EDIT_SUBMIT": "Update webhook",
|
||||||
|
"ADD_SUBMIT": "Crear webhook"
|
||||||
|
},
|
||||||
"TITLE": "Webhook",
|
"TITLE": "Webhook",
|
||||||
"CONFIGURE": "Configura",
|
"CONFIGURE": "Configura",
|
||||||
"HEADER": "Configuració Webhook",
|
"HEADER": "Configuració Webhook",
|
||||||
@ -20,35 +43,16 @@
|
|||||||
"EDIT": {
|
"EDIT": {
|
||||||
"BUTTON_TEXT": "Edita",
|
"BUTTON_TEXT": "Edita",
|
||||||
"TITLE": "Edit webhook",
|
"TITLE": "Edit webhook",
|
||||||
"CANCEL": "Cancel·la",
|
|
||||||
"DESC": "Els esdeveniments de Webhook us proporcionen informació en temps real sobre el que passa al vostre compte de Chatwoot. Introduïu una URL vàlid per configurar un callback.",
|
|
||||||
"FORM": {
|
|
||||||
"END_POINT": {
|
|
||||||
"LABEL": "URL del webhook",
|
|
||||||
"PLACEHOLDER": "Exemple: https://example/api/webhook",
|
|
||||||
"ERROR": "Introduïu una URL vàlid"
|
|
||||||
},
|
|
||||||
"SUBMIT": "Edit webhook"
|
|
||||||
},
|
|
||||||
"API": {
|
"API": {
|
||||||
"SUCCESS_MESSAGE": "Webhook URL updated successfully",
|
"SUCCESS_MESSAGE": "Webhook configuration updated successfully",
|
||||||
"ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
|
"ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ADD": {
|
"ADD": {
|
||||||
"CANCEL": "Cancel·la",
|
"CANCEL": "Cancel·la",
|
||||||
"TITLE": "Afegir un nou webhook",
|
"TITLE": "Afegir un nou webhook",
|
||||||
"DESC": "Els esdeveniments de Webhook us proporcionen informació en temps real sobre el que passa al vostre compte de Chatwoot. Introduïu una URL vàlid per configurar un callback.",
|
|
||||||
"FORM": {
|
|
||||||
"END_POINT": {
|
|
||||||
"LABEL": "URL del webhook",
|
|
||||||
"PLACEHOLDER": "Exemple: https://example/api/webhook",
|
|
||||||
"ERROR": "Introduïu una URL vàlid"
|
|
||||||
},
|
|
||||||
"SUBMIT": "Crear webhook"
|
|
||||||
},
|
|
||||||
"API": {
|
"API": {
|
||||||
"SUCCESS_MESSAGE": "S'ha afegit el Webhook correctament",
|
"SUCCESS_MESSAGE": "Webhook configuration added successfully",
|
||||||
"ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
|
"ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -60,7 +64,7 @@
|
|||||||
},
|
},
|
||||||
"CONFIRM": {
|
"CONFIRM": {
|
||||||
"TITLE": "Confirma l'esborrat",
|
"TITLE": "Confirma l'esborrat",
|
||||||
"MESSAGE": "N'estàs segur ",
|
"MESSAGE": "Are you sure to delete the webhook? (%{webhookURL})",
|
||||||
"YES": "Si, esborra ",
|
"YES": "Si, esborra ",
|
||||||
"NO": "No, manten-la"
|
"NO": "No, manten-la"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"REPORT": {
|
"REPORT": {
|
||||||
"HEADER": "Overview",
|
"HEADER": "Converses",
|
||||||
"LOADING_CHART": "S'estan carregant dades del gràfic...",
|
"LOADING_CHART": "S'estan carregant dades del gràfic...",
|
||||||
"NO_ENOUGH_DATA": "No hem rebut suficients punts de dades per generar l'informe. Torneu-ho a provar més endavant.",
|
"NO_ENOUGH_DATA": "No hem rebut suficients punts de dades per generar l'informe. Torneu-ho a provar més endavant.",
|
||||||
"DOWNLOAD_AGENT_REPORTS": "Descarregar Informes d'Agent",
|
"DOWNLOAD_AGENT_REPORTS": "Descarregar Informes d'Agent",
|
||||||
@ -18,12 +18,16 @@
|
|||||||
"DESC": "( Total )"
|
"DESC": "( Total )"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "Primer temps de resposta",
|
"NAME": "First Response Time",
|
||||||
"DESC": "( Promig )"
|
"DESC": "( Promig )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Temps de resolució",
|
"NAME": "Temps de resolució",
|
||||||
"DESC": "( Promig )"
|
"DESC": "( Promig )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Total de resolucions",
|
"NAME": "Total de resolucions",
|
||||||
@ -108,7 +112,8 @@
|
|||||||
"id": 4,
|
"id": 4,
|
||||||
"groupBy": "Year"
|
"groupBy": "Year"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"BUSINESS_HOURS": "Business Hours"
|
||||||
},
|
},
|
||||||
"AGENT_REPORTS": {
|
"AGENT_REPORTS": {
|
||||||
"HEADER": "Agents Overview",
|
"HEADER": "Agents Overview",
|
||||||
@ -130,12 +135,16 @@
|
|||||||
"DESC": "( Total )"
|
"DESC": "( Total )"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "Primer temps de resposta",
|
"NAME": "First Response Time",
|
||||||
"DESC": "( Promig )"
|
"DESC": "( Promig )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Temps de resolució",
|
"NAME": "Temps de resolució",
|
||||||
"DESC": "( Promig )"
|
"DESC": "( Promig )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Total de resolucions",
|
"NAME": "Total de resolucions",
|
||||||
@ -193,12 +202,16 @@
|
|||||||
"DESC": "( Total )"
|
"DESC": "( Total )"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "Primer temps de resposta",
|
"NAME": "First Response Time",
|
||||||
"DESC": "( Promig )"
|
"DESC": "( Promig )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Temps de resolució",
|
"NAME": "Temps de resolució",
|
||||||
"DESC": "( Promig )"
|
"DESC": "( Promig )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Total de resolucions",
|
"NAME": "Total de resolucions",
|
||||||
@ -256,12 +269,16 @@
|
|||||||
"DESC": "( Total )"
|
"DESC": "( Total )"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "Primer temps de resposta",
|
"NAME": "First Response Time",
|
||||||
"DESC": "( Promig )"
|
"DESC": "( Promig )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Temps de resolució",
|
"NAME": "Temps de resolució",
|
||||||
"DESC": "( Promig )"
|
"DESC": "( Promig )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Total de resolucions",
|
"NAME": "Total de resolucions",
|
||||||
@ -319,12 +336,16 @@
|
|||||||
"DESC": "( Total )"
|
"DESC": "( Total )"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "Primer temps de resposta",
|
"NAME": "First Response Time",
|
||||||
"DESC": "( Promig )"
|
"DESC": "( Promig )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Temps de resolució",
|
"NAME": "Temps de resolució",
|
||||||
"DESC": "( Promig )"
|
"DESC": "( Promig )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Total de resolucions",
|
"NAME": "Total de resolucions",
|
||||||
@ -392,5 +413,33 @@
|
|||||||
"TOOLTIP": "Total number of responses / Total number of CSAT survey messages sent * 100"
|
"TOOLTIP": "Total number of responses / Total number of CSAT survey messages sent * 100"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"OVERVIEW_REPORTS": {
|
||||||
|
"HEADER": "Overview",
|
||||||
|
"LIVE": "Live",
|
||||||
|
"ACCOUNT_CONVERSATIONS": {
|
||||||
|
"HEADER": "Open Conversations",
|
||||||
|
"LOADING_MESSAGE": "Loading conversation metrics...",
|
||||||
|
"OPEN": "Obrir",
|
||||||
|
"UNATTENDED": "Unattended",
|
||||||
|
"UNASSIGNED": "Sense assignar"
|
||||||
|
},
|
||||||
|
"AGENT_CONVERSATIONS": {
|
||||||
|
"HEADER": "Conversations by agents",
|
||||||
|
"LOADING_MESSAGE": "Loading agent metrics...",
|
||||||
|
"NO_AGENTS": "There are no conversations by agents",
|
||||||
|
"TABLE_HEADER": {
|
||||||
|
"AGENT": "Agent",
|
||||||
|
"OPEN": "OPEN",
|
||||||
|
"UNATTENDED": "Unattended",
|
||||||
|
"STATUS": "Estat"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AGENT_STATUS": {
|
||||||
|
"HEADER": "Agent status",
|
||||||
|
"ONLINE": "En línia",
|
||||||
|
"BUSY": "Ocupat",
|
||||||
|
"OFFLINE": "Fora de línia"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,9 @@
|
|||||||
"SUCCESS_MESSAGE": "S'ha canviat la contrasenya correctament",
|
"SUCCESS_MESSAGE": "S'ha canviat la contrasenya correctament",
|
||||||
"ERROR_MESSAGE": "No s'ha pogut connectar amb Woot Server. Torneu-ho a provar més endavant"
|
"ERROR_MESSAGE": "No s'ha pogut connectar amb Woot Server. Torneu-ho a provar més endavant"
|
||||||
},
|
},
|
||||||
|
"CAPTCHA": {
|
||||||
|
"ERROR": "Verification expired. Please solve captcha again."
|
||||||
|
},
|
||||||
"SUBMIT": "Envia"
|
"SUBMIT": "Envia"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -131,6 +131,10 @@
|
|||||||
"BUTTON_TEXT": "Copia",
|
"BUTTON_TEXT": "Copia",
|
||||||
"COPY_SUCCESSFUL": "El codi s'ha copiat al porta-retalls amb èxit"
|
"COPY_SUCCESSFUL": "El codi s'ha copiat al porta-retalls amb èxit"
|
||||||
},
|
},
|
||||||
|
"SHOW_MORE_BLOCK": {
|
||||||
|
"SHOW_MORE": "Show More",
|
||||||
|
"SHOW_LESS": "Show Less"
|
||||||
|
},
|
||||||
"FILE_BUBBLE": {
|
"FILE_BUBBLE": {
|
||||||
"DOWNLOAD": "Descarrega",
|
"DOWNLOAD": "Descarrega",
|
||||||
"UPLOADING": "S'està carregant..."
|
"UPLOADING": "S'està carregant..."
|
||||||
@ -147,6 +151,7 @@
|
|||||||
},
|
},
|
||||||
"SIDEBAR": {
|
"SIDEBAR": {
|
||||||
"CURRENTLY_VIEWING_ACCOUNT": "Currently viewing:",
|
"CURRENTLY_VIEWING_ACCOUNT": "Currently viewing:",
|
||||||
|
"SWITCH": "Switch",
|
||||||
"CONVERSATIONS": "Converses",
|
"CONVERSATIONS": "Converses",
|
||||||
"ALL_CONVERSATIONS": "All Conversations",
|
"ALL_CONVERSATIONS": "All Conversations",
|
||||||
"MENTIONED_CONVERSATIONS": "Mentions",
|
"MENTIONED_CONVERSATIONS": "Mentions",
|
||||||
@ -173,7 +178,7 @@
|
|||||||
"NEW_LABEL": "New label",
|
"NEW_LABEL": "New label",
|
||||||
"NEW_TEAM": "New team",
|
"NEW_TEAM": "New team",
|
||||||
"NEW_INBOX": "New inbox",
|
"NEW_INBOX": "New inbox",
|
||||||
"REPORTS_OVERVIEW": "Overview",
|
"REPORTS_CONVERSATION": "Converses",
|
||||||
"CSAT": "CSAT",
|
"CSAT": "CSAT",
|
||||||
"CAMPAIGNS": "Campaigns",
|
"CAMPAIGNS": "Campaigns",
|
||||||
"ONGOING": "Ongoing",
|
"ONGOING": "Ongoing",
|
||||||
@ -183,7 +188,8 @@
|
|||||||
"REPORTS_INBOX": "Inbox",
|
"REPORTS_INBOX": "Inbox",
|
||||||
"REPORTS_TEAM": "Team",
|
"REPORTS_TEAM": "Team",
|
||||||
"SET_AVAILABILITY_TITLE": "Set yourself as",
|
"SET_AVAILABILITY_TITLE": "Set yourself as",
|
||||||
"BETA": "Beta"
|
"BETA": "Beta",
|
||||||
|
"REPORTS_OVERVIEW": "Overview"
|
||||||
},
|
},
|
||||||
"CREATE_ACCOUNT": {
|
"CREATE_ACCOUNT": {
|
||||||
"NO_ACCOUNT_WARNING": "Uh oh! We could not find any Chatwoot accounts. Please create a new account to continue.",
|
"NO_ACCOUNT_WARNING": "Uh oh! We could not find any Chatwoot accounts. Please create a new account to continue.",
|
||||||
|
|||||||
@ -21,7 +21,8 @@
|
|||||||
"PASSWORD": {
|
"PASSWORD": {
|
||||||
"LABEL": "Contrasenya",
|
"LABEL": "Contrasenya",
|
||||||
"PLACEHOLDER": "Contrasenya",
|
"PLACEHOLDER": "Contrasenya",
|
||||||
"ERROR": "La contrasenya és massa curta"
|
"ERROR": "La contrasenya és massa curta",
|
||||||
|
"IS_INVALID_PASSWORD": "Password should contain atleast 1 uppercase letter, 1 lowercase letter, 1 number and 1 special character"
|
||||||
},
|
},
|
||||||
"CONFIRM_PASSWORD": {
|
"CONFIRM_PASSWORD": {
|
||||||
"LABEL": "Confirma la contrasenya",
|
"LABEL": "Confirma la contrasenya",
|
||||||
|
|||||||
@ -83,7 +83,7 @@
|
|||||||
"SELECT_ALL": "select all agents",
|
"SELECT_ALL": "select all agents",
|
||||||
"SELECTED_COUNT": "%{selected} out of %{total} agents selected.",
|
"SELECTED_COUNT": "%{selected} out of %{total} agents selected.",
|
||||||
"BUTTON_TEXT": "Afegir agents",
|
"BUTTON_TEXT": "Afegir agents",
|
||||||
"AGENT_VALIDATION_ERROR": "Select atleaset one agent."
|
"AGENT_VALIDATION_ERROR": "Select at least one agent."
|
||||||
},
|
},
|
||||||
"FINISH": {
|
"FINISH": {
|
||||||
"TITLE": "Your team is ready!",
|
"TITLE": "Your team is ready!",
|
||||||
|
|||||||
@ -89,7 +89,9 @@
|
|||||||
"DELETE_MESSAGE": "You need to have atleast one condition to save"
|
"DELETE_MESSAGE": "You need to have atleast one condition to save"
|
||||||
},
|
},
|
||||||
"ACTION": {
|
"ACTION": {
|
||||||
"DELETE_MESSAGE": "You need to have atleast one action to save"
|
"DELETE_MESSAGE": "You need to have atleast one action to save",
|
||||||
|
"TEAM_MESSAGE_INPUT_PLACEHOLDER": "Enter your message here",
|
||||||
|
"TEAM_DROPDOWN_PLACEHOLDER": "Select teams"
|
||||||
},
|
},
|
||||||
"TOGGLE": {
|
"TOGGLE": {
|
||||||
"ACTIVATION_TITLE": "Activate Automation Rule",
|
"ACTIVATION_TITLE": "Activate Automation Rule",
|
||||||
@ -102,6 +104,13 @@
|
|||||||
"DEACTIVATION_ERROR": "Could not Deactivate Automation, Please try again later",
|
"DEACTIVATION_ERROR": "Could not Deactivate Automation, Please try again later",
|
||||||
"CONFIRMATION_LABEL": "Ano",
|
"CONFIRMATION_LABEL": "Ano",
|
||||||
"CANCEL_LABEL": "Ne"
|
"CANCEL_LABEL": "Ne"
|
||||||
|
},
|
||||||
|
"ATTACHMENT": {
|
||||||
|
"UPLOAD_ERROR": "Could not upload attachment, Please try again",
|
||||||
|
"LABEL_IDLE": "Upload Attachment",
|
||||||
|
"LABEL_UPLOADING": "Nahrávání...",
|
||||||
|
"LABEL_UPLOADED": "Succesfully Uploaded",
|
||||||
|
"LABEL_UPLOAD_FAILED": "Upload Failed"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -81,6 +81,7 @@
|
|||||||
"NO_MESSAGES": "Žádné zprávy",
|
"NO_MESSAGES": "Žádné zprávy",
|
||||||
"NO_CONTENT": "Žádný obsah k dispozici",
|
"NO_CONTENT": "Žádný obsah k dispozici",
|
||||||
"HIDE_QUOTED_TEXT": "Hide Quoted Text",
|
"HIDE_QUOTED_TEXT": "Hide Quoted Text",
|
||||||
"SHOW_QUOTED_TEXT": "Show Quoted Text"
|
"SHOW_QUOTED_TEXT": "Show Quoted Text",
|
||||||
|
"MESSAGE_READ": "Read"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,6 +70,14 @@
|
|||||||
"SUCCESS_MESSAGE": "Contacts saved successfully",
|
"SUCCESS_MESSAGE": "Contacts saved successfully",
|
||||||
"ERROR_MESSAGE": "Došlo k chybě, zkuste to prosím znovu"
|
"ERROR_MESSAGE": "Došlo k chybě, zkuste to prosím znovu"
|
||||||
},
|
},
|
||||||
|
"DELETE_NOTE": {
|
||||||
|
"CONFIRM": {
|
||||||
|
"TITLE": "Potvrdit odstranění",
|
||||||
|
"MESSAGE": "Are you want sure to delete this note?",
|
||||||
|
"YES": "Yes, Delete it",
|
||||||
|
"NO": "No, Keep it"
|
||||||
|
}
|
||||||
|
},
|
||||||
"DELETE_CONTACT": {
|
"DELETE_CONTACT": {
|
||||||
"BUTTON_LABEL": "Delete Contact",
|
"BUTTON_LABEL": "Delete Contact",
|
||||||
"TITLE": "Delete contact",
|
"TITLE": "Delete contact",
|
||||||
|
|||||||
@ -60,6 +60,13 @@
|
|||||||
"NOTIFICATIONS_PAGE": {
|
"NOTIFICATIONS_PAGE": {
|
||||||
"HEADER": "Oznámení",
|
"HEADER": "Oznámení",
|
||||||
"MARK_ALL_DONE": "Označit vše dokončeno",
|
"MARK_ALL_DONE": "Označit vše dokončeno",
|
||||||
|
"DELETE_TITLE": "deleted",
|
||||||
|
"UNREAD_NOTIFICATION": {
|
||||||
|
"TITLE": "Unread Notifications",
|
||||||
|
"ALL_NOTIFICATIONS": "View all notifications",
|
||||||
|
"LOADING_UNREAD_MESSAGE": "Loading unread notifications...",
|
||||||
|
"EMPTY_MESSAGE": "You have no unread notifications"
|
||||||
|
},
|
||||||
"LIST": {
|
"LIST": {
|
||||||
"LOADING_MESSAGE": "Načítání upozornění...",
|
"LOADING_MESSAGE": "Načítání upozornění...",
|
||||||
"404": "Žádná upozornění",
|
"404": "Žádná upozornění",
|
||||||
@ -101,6 +108,7 @@
|
|||||||
"GO_TO_CONVERSATION_DASHBOARD": "Go to Conversation Dashboard",
|
"GO_TO_CONVERSATION_DASHBOARD": "Go to Conversation Dashboard",
|
||||||
"GO_TO_CONTACTS_DASHBOARD": "Go to Contacts Dashboard",
|
"GO_TO_CONTACTS_DASHBOARD": "Go to Contacts Dashboard",
|
||||||
"GO_TO_REPORTS_OVERVIEW": "Go to Reports Overview",
|
"GO_TO_REPORTS_OVERVIEW": "Go to Reports Overview",
|
||||||
|
"GO_TO_CONVERSATION_REPORTS": "Go to Conversation Reports",
|
||||||
"GO_TO_AGENT_REPORTS": "Go to Agent Reports",
|
"GO_TO_AGENT_REPORTS": "Go to Agent Reports",
|
||||||
"GO_TO_LABEL_REPORTS": "Go to Label Reports",
|
"GO_TO_LABEL_REPORTS": "Go to Label Reports",
|
||||||
"GO_TO_INBOX_REPORTS": "Go to Inbox Reports",
|
"GO_TO_INBOX_REPORTS": "Go to Inbox Reports",
|
||||||
|
|||||||
@ -341,10 +341,6 @@
|
|||||||
"AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "Automatické přiřazení bylo úspěšně aktualizováno",
|
"AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "Automatické přiřazení bylo úspěšně aktualizováno",
|
||||||
"ERROR_MESSAGE": "Nelze aktualizovat barvu widgetu. Opakujte akci později."
|
"ERROR_MESSAGE": "Nelze aktualizovat barvu widgetu. Opakujte akci později."
|
||||||
},
|
},
|
||||||
"AUTO_ASSIGNMENT": {
|
|
||||||
"ENABLED": "Povoleno",
|
|
||||||
"DISABLED": "Zakázáno"
|
|
||||||
},
|
|
||||||
"EMAIL_COLLECT_BOX": {
|
"EMAIL_COLLECT_BOX": {
|
||||||
"ENABLED": "Povoleno",
|
"ENABLED": "Povoleno",
|
||||||
"DISABLED": "Zakázáno"
|
"DISABLED": "Zakázáno"
|
||||||
@ -394,13 +390,16 @@
|
|||||||
"FEATURES": {
|
"FEATURES": {
|
||||||
"LABEL": "Funkce",
|
"LABEL": "Funkce",
|
||||||
"DISPLAY_FILE_PICKER": "Display file picker on the widget",
|
"DISPLAY_FILE_PICKER": "Display file picker on the widget",
|
||||||
"DISPLAY_EMOJI_PICKER": "Display emoji picker on the widget"
|
"DISPLAY_EMOJI_PICKER": "Display emoji picker on the widget",
|
||||||
|
"ALLOW_END_CONVERSATION": "Allow users to end conversation from the widget"
|
||||||
},
|
},
|
||||||
"SETTINGS_POPUP": {
|
"SETTINGS_POPUP": {
|
||||||
"MESSENGER_HEADING": "Messenger skript",
|
"MESSENGER_HEADING": "Messenger skript",
|
||||||
"MESSENGER_SUB_HEAD": "Umístěte toto tlačítko dovnitř vašeho tělesného štítku",
|
"MESSENGER_SUB_HEAD": "Umístěte toto tlačítko dovnitř vašeho tělesného štítku",
|
||||||
"INBOX_AGENTS": "Agenti",
|
"INBOX_AGENTS": "Agenti",
|
||||||
"INBOX_AGENTS_SUB_TEXT": "Přidat nebo odebrat agenty z této složky doručené pošty",
|
"INBOX_AGENTS_SUB_TEXT": "Přidat nebo odebrat agenty z této složky doručené pošty",
|
||||||
|
"AGENT_ASSIGNMENT": "Conversation Assignment",
|
||||||
|
"AGENT_ASSIGNMENT_SUB_TEXT": "Update conversation assignment settings",
|
||||||
"UPDATE": "Aktualizovat",
|
"UPDATE": "Aktualizovat",
|
||||||
"ENABLE_EMAIL_COLLECT_BOX": "Enable email collect box",
|
"ENABLE_EMAIL_COLLECT_BOX": "Enable email collect box",
|
||||||
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Enable or disable email collect box on new conversation",
|
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Enable or disable email collect box on new conversation",
|
||||||
@ -431,6 +430,15 @@
|
|||||||
},
|
},
|
||||||
"PRE_CHAT_FORM": {
|
"PRE_CHAT_FORM": {
|
||||||
"DESCRIPTION": "Pre chat forms enable you to capture user information before they start conversation with you.",
|
"DESCRIPTION": "Pre chat forms enable you to capture user information before they start conversation with you.",
|
||||||
|
"SET_FIELDS": "Pre chat form fields",
|
||||||
|
"SET_FIELDS_HEADER": {
|
||||||
|
"FIELDS": "Fields",
|
||||||
|
"LABEL": "Label",
|
||||||
|
"PLACE_HOLDER": "Placeholder",
|
||||||
|
"KEY": "Key",
|
||||||
|
"TYPE": "Type",
|
||||||
|
"REQUIRED": "Required"
|
||||||
|
},
|
||||||
"ENABLE": {
|
"ENABLE": {
|
||||||
"LABEL": "Enable pre chat form",
|
"LABEL": "Enable pre chat form",
|
||||||
"OPTIONS": {
|
"OPTIONS": {
|
||||||
@ -439,7 +447,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"PRE_CHAT_MESSAGE": {
|
"PRE_CHAT_MESSAGE": {
|
||||||
"LABEL": "Zpráva před chatem",
|
"LABEL": "Pre chat message",
|
||||||
"PLACEHOLDER": "This message would be visible to the users along with the form"
|
"PLACEHOLDER": "This message would be visible to the users along with the form"
|
||||||
},
|
},
|
||||||
"REQUIRE_EMAIL": {
|
"REQUIRE_EMAIL": {
|
||||||
@ -468,6 +476,7 @@
|
|||||||
"IMAP": {
|
"IMAP": {
|
||||||
"TITLE": "IMAP",
|
"TITLE": "IMAP",
|
||||||
"SUBTITLE": "Set your IMAP details",
|
"SUBTITLE": "Set your IMAP details",
|
||||||
|
"NOTE_TEXT": "To enable SMTP, please configure IMAP.",
|
||||||
"UPDATE": "Update IMAP settings",
|
"UPDATE": "Update IMAP settings",
|
||||||
"TOGGLE_AVAILABILITY": "Enable IMAP configuration for this inbox",
|
"TOGGLE_AVAILABILITY": "Enable IMAP configuration for this inbox",
|
||||||
"TOGGLE_HELP": "Enabling IMAP will help the user to recieve email",
|
"TOGGLE_HELP": "Enabling IMAP will help the user to recieve email",
|
||||||
@ -483,9 +492,9 @@
|
|||||||
"LABEL": "Port",
|
"LABEL": "Port",
|
||||||
"PLACE_HOLDER": "Port"
|
"PLACE_HOLDER": "Port"
|
||||||
},
|
},
|
||||||
"EMAIL": {
|
"LOGIN": {
|
||||||
"LABEL": "E-mailová adresa",
|
"LABEL": "Přihlásit se",
|
||||||
"PLACE_HOLDER": "E-mailová adresa"
|
"PLACE_HOLDER": "Přihlásit se"
|
||||||
},
|
},
|
||||||
"PASSWORD": {
|
"PASSWORD": {
|
||||||
"LABEL": "Heslo",
|
"LABEL": "Heslo",
|
||||||
@ -511,9 +520,9 @@
|
|||||||
"LABEL": "Port",
|
"LABEL": "Port",
|
||||||
"PLACE_HOLDER": "Port"
|
"PLACE_HOLDER": "Port"
|
||||||
},
|
},
|
||||||
"EMAIL": {
|
"LOGIN": {
|
||||||
"LABEL": "E-mailová adresa",
|
"LABEL": "Přihlásit se",
|
||||||
"PLACE_HOLDER": "E-mailová adresa"
|
"PLACE_HOLDER": "Přihlásit se"
|
||||||
},
|
},
|
||||||
"PASSWORD": {
|
"PASSWORD": {
|
||||||
"LABEL": "Heslo",
|
"LABEL": "Heslo",
|
||||||
@ -526,7 +535,9 @@
|
|||||||
"ENCRYPTION": "Encryption",
|
"ENCRYPTION": "Encryption",
|
||||||
"SSL_TLS": "SSL/TLS",
|
"SSL_TLS": "SSL/TLS",
|
||||||
"START_TLS": "STARTTLS",
|
"START_TLS": "STARTTLS",
|
||||||
"OPEN_SSL_VERIFY_MODE": "Open SSL Verify Mode"
|
"OPEN_SSL_VERIFY_MODE": "Open SSL Verify Mode",
|
||||||
}
|
"AUTH_MECHANISM": "Authentication"
|
||||||
|
},
|
||||||
|
"NOTE": "Note: "
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,29 @@
|
|||||||
"INTEGRATION_SETTINGS": {
|
"INTEGRATION_SETTINGS": {
|
||||||
"HEADER": "Integrace",
|
"HEADER": "Integrace",
|
||||||
"WEBHOOK": {
|
"WEBHOOK": {
|
||||||
|
"SUBSCRIBED_EVENTS": "Subscribed Events",
|
||||||
|
"FORM": {
|
||||||
|
"CANCEL": "Zrušit",
|
||||||
|
"DESC": "Události webhooku vám poskytují reálné informace o tom, co se děje ve vašem Chatwoot účtu. Zadejte prosím platnou URL pro nastavení hovoru.",
|
||||||
|
"SUBSCRIPTIONS": {
|
||||||
|
"LABEL": "Events",
|
||||||
|
"EVENTS": {
|
||||||
|
"CONVERSATION_CREATED": "Conversation Created",
|
||||||
|
"CONVERSATION_STATUS_CHANGED": "Conversation Status Changed",
|
||||||
|
"CONVERSATION_UPDATED": "Conversation Updated",
|
||||||
|
"MESSAGE_CREATED": "Message created",
|
||||||
|
"MESSAGE_UPDATED": "Message updated",
|
||||||
|
"WEBWIDGET_TRIGGERED": "Live chat widget opened by the user"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"END_POINT": {
|
||||||
|
"LABEL": "URL webového háčku",
|
||||||
|
"PLACEHOLDER": "Příklad: https://example/api/webhook",
|
||||||
|
"ERROR": "Zadejte prosím platnou URL"
|
||||||
|
},
|
||||||
|
"EDIT_SUBMIT": "Update webhook",
|
||||||
|
"ADD_SUBMIT": "Create webhook"
|
||||||
|
},
|
||||||
"TITLE": "Webový háček",
|
"TITLE": "Webový háček",
|
||||||
"CONFIGURE": "Konfigurace",
|
"CONFIGURE": "Konfigurace",
|
||||||
"HEADER": "Nastavení webhooku",
|
"HEADER": "Nastavení webhooku",
|
||||||
@ -20,35 +43,16 @@
|
|||||||
"EDIT": {
|
"EDIT": {
|
||||||
"BUTTON_TEXT": "Upravit",
|
"BUTTON_TEXT": "Upravit",
|
||||||
"TITLE": "Edit webhook",
|
"TITLE": "Edit webhook",
|
||||||
"CANCEL": "Zrušit",
|
|
||||||
"DESC": "Události webhooku vám poskytují reálné informace o tom, co se děje ve vašem Chatwoot účtu. Zadejte prosím platnou URL pro nastavení hovoru.",
|
|
||||||
"FORM": {
|
|
||||||
"END_POINT": {
|
|
||||||
"LABEL": "URL webového háčku",
|
|
||||||
"PLACEHOLDER": "Příklad: https://example/api/webhook",
|
|
||||||
"ERROR": "Zadejte prosím platnou URL"
|
|
||||||
},
|
|
||||||
"SUBMIT": "Edit webhook"
|
|
||||||
},
|
|
||||||
"API": {
|
"API": {
|
||||||
"SUCCESS_MESSAGE": "Webhook URL updated successfully",
|
"SUCCESS_MESSAGE": "Webhook configuration updated successfully",
|
||||||
"ERROR_MESSAGE": "Nelze se připojit k Woot serveru, opakujte akci později"
|
"ERROR_MESSAGE": "Nelze se připojit k Woot serveru, opakujte akci později"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ADD": {
|
"ADD": {
|
||||||
"CANCEL": "Zrušit",
|
"CANCEL": "Zrušit",
|
||||||
"TITLE": "Přidat nový webový háček",
|
"TITLE": "Přidat nový webový háček",
|
||||||
"DESC": "Události webhooku vám poskytují reálné informace o tom, co se děje ve vašem Chatwoot účtu. Zadejte prosím platnou URL pro nastavení hovoru.",
|
|
||||||
"FORM": {
|
|
||||||
"END_POINT": {
|
|
||||||
"LABEL": "URL webového háčku",
|
|
||||||
"PLACEHOLDER": "Příklad: https://example/api/webhook",
|
|
||||||
"ERROR": "Zadejte prosím platnou URL"
|
|
||||||
},
|
|
||||||
"SUBMIT": "Vytvořit webový háček"
|
|
||||||
},
|
|
||||||
"API": {
|
"API": {
|
||||||
"SUCCESS_MESSAGE": "Webový háček byl úspěšně přidán",
|
"SUCCESS_MESSAGE": "Webhook configuration added successfully",
|
||||||
"ERROR_MESSAGE": "Nelze se připojit k Woot serveru, opakujte akci později"
|
"ERROR_MESSAGE": "Nelze se připojit k Woot serveru, opakujte akci později"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -60,7 +64,7 @@
|
|||||||
},
|
},
|
||||||
"CONFIRM": {
|
"CONFIRM": {
|
||||||
"TITLE": "Potvrdit odstranění",
|
"TITLE": "Potvrdit odstranění",
|
||||||
"MESSAGE": "Opravdu chcete odstranit ",
|
"MESSAGE": "Are you sure to delete the webhook? (%{webhookURL})",
|
||||||
"YES": "Ano, odstranit ",
|
"YES": "Ano, odstranit ",
|
||||||
"NO": "No, Keep it"
|
"NO": "No, Keep it"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"REPORT": {
|
"REPORT": {
|
||||||
"HEADER": "Overview",
|
"HEADER": "Konverzace",
|
||||||
"LOADING_CHART": "Načítání dat mapy...",
|
"LOADING_CHART": "Načítání dat mapy...",
|
||||||
"NO_ENOUGH_DATA": "Pro vytvoření hlášení jsme neobdrželi dostatek dat, zkuste to prosím později.",
|
"NO_ENOUGH_DATA": "Pro vytvoření hlášení jsme neobdrželi dostatek dat, zkuste to prosím později.",
|
||||||
"DOWNLOAD_AGENT_REPORTS": "Stáhnout reporty agentů",
|
"DOWNLOAD_AGENT_REPORTS": "Stáhnout reporty agentů",
|
||||||
@ -18,12 +18,16 @@
|
|||||||
"DESC": "( celkem)"
|
"DESC": "( celkem)"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "Čas první odpovědi",
|
"NAME": "First Response Time",
|
||||||
"DESC": "(Průměrný)"
|
"DESC": "(Průměrný)",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Čas rozlišení",
|
"NAME": "Čas rozlišení",
|
||||||
"DESC": "(Průměrný)"
|
"DESC": "(Průměrný)",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Počet rozlišení",
|
"NAME": "Počet rozlišení",
|
||||||
@ -108,7 +112,8 @@
|
|||||||
"id": 4,
|
"id": 4,
|
||||||
"groupBy": "Year"
|
"groupBy": "Year"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"BUSINESS_HOURS": "Pracovní doba"
|
||||||
},
|
},
|
||||||
"AGENT_REPORTS": {
|
"AGENT_REPORTS": {
|
||||||
"HEADER": "Agents Overview",
|
"HEADER": "Agents Overview",
|
||||||
@ -130,12 +135,16 @@
|
|||||||
"DESC": "( celkem)"
|
"DESC": "( celkem)"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "Čas první odpovědi",
|
"NAME": "First Response Time",
|
||||||
"DESC": "(Průměrný)"
|
"DESC": "(Průměrný)",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Čas rozlišení",
|
"NAME": "Čas rozlišení",
|
||||||
"DESC": "(Průměrný)"
|
"DESC": "(Průměrný)",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Počet rozlišení",
|
"NAME": "Počet rozlišení",
|
||||||
@ -193,12 +202,16 @@
|
|||||||
"DESC": "( celkem)"
|
"DESC": "( celkem)"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "Čas první odpovědi",
|
"NAME": "First Response Time",
|
||||||
"DESC": "(Průměrný)"
|
"DESC": "(Průměrný)",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Čas rozlišení",
|
"NAME": "Čas rozlišení",
|
||||||
"DESC": "(Průměrný)"
|
"DESC": "(Průměrný)",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Počet rozlišení",
|
"NAME": "Počet rozlišení",
|
||||||
@ -256,12 +269,16 @@
|
|||||||
"DESC": "( celkem)"
|
"DESC": "( celkem)"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "Čas první odpovědi",
|
"NAME": "First Response Time",
|
||||||
"DESC": "(Průměrný)"
|
"DESC": "(Průměrný)",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Čas rozlišení",
|
"NAME": "Čas rozlišení",
|
||||||
"DESC": "(Průměrný)"
|
"DESC": "(Průměrný)",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Počet rozlišení",
|
"NAME": "Počet rozlišení",
|
||||||
@ -319,12 +336,16 @@
|
|||||||
"DESC": "( celkem)"
|
"DESC": "( celkem)"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "Čas první odpovědi",
|
"NAME": "First Response Time",
|
||||||
"DESC": "(Průměrný)"
|
"DESC": "(Průměrný)",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Čas rozlišení",
|
"NAME": "Čas rozlišení",
|
||||||
"DESC": "(Průměrný)"
|
"DESC": "(Průměrný)",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Počet rozlišení",
|
"NAME": "Počet rozlišení",
|
||||||
@ -392,5 +413,33 @@
|
|||||||
"TOOLTIP": "Total number of responses / Total number of CSAT survey messages sent * 100"
|
"TOOLTIP": "Total number of responses / Total number of CSAT survey messages sent * 100"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"OVERVIEW_REPORTS": {
|
||||||
|
"HEADER": "Overview",
|
||||||
|
"LIVE": "Live",
|
||||||
|
"ACCOUNT_CONVERSATIONS": {
|
||||||
|
"HEADER": "Open Conversations",
|
||||||
|
"LOADING_MESSAGE": "Loading conversation metrics...",
|
||||||
|
"OPEN": "Otevřít",
|
||||||
|
"UNATTENDED": "Unattended",
|
||||||
|
"UNASSIGNED": "Nepřiřazeno"
|
||||||
|
},
|
||||||
|
"AGENT_CONVERSATIONS": {
|
||||||
|
"HEADER": "Conversations by agents",
|
||||||
|
"LOADING_MESSAGE": "Loading agent metrics...",
|
||||||
|
"NO_AGENTS": "There are no conversations by agents",
|
||||||
|
"TABLE_HEADER": {
|
||||||
|
"AGENT": "Agent",
|
||||||
|
"OPEN": "OPEN",
|
||||||
|
"UNATTENDED": "Unattended",
|
||||||
|
"STATUS": "Stav"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AGENT_STATUS": {
|
||||||
|
"HEADER": "Agent status",
|
||||||
|
"ONLINE": "Online",
|
||||||
|
"BUSY": "Zaneprázdněn",
|
||||||
|
"OFFLINE": "Offline"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,9 @@
|
|||||||
"SUCCESS_MESSAGE": "Heslo bylo úspěšně změněno",
|
"SUCCESS_MESSAGE": "Heslo bylo úspěšně změněno",
|
||||||
"ERROR_MESSAGE": "Nelze se připojit k Woot serveru, opakujte akci později"
|
"ERROR_MESSAGE": "Nelze se připojit k Woot serveru, opakujte akci později"
|
||||||
},
|
},
|
||||||
|
"CAPTCHA": {
|
||||||
|
"ERROR": "Verification expired. Please solve captcha again."
|
||||||
|
},
|
||||||
"SUBMIT": "Odeslat"
|
"SUBMIT": "Odeslat"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -131,6 +131,10 @@
|
|||||||
"BUTTON_TEXT": "Kopírovat",
|
"BUTTON_TEXT": "Kopírovat",
|
||||||
"COPY_SUCCESSFUL": "Kód byl úspěšně zkopírován do schránky"
|
"COPY_SUCCESSFUL": "Kód byl úspěšně zkopírován do schránky"
|
||||||
},
|
},
|
||||||
|
"SHOW_MORE_BLOCK": {
|
||||||
|
"SHOW_MORE": "Show More",
|
||||||
|
"SHOW_LESS": "Show Less"
|
||||||
|
},
|
||||||
"FILE_BUBBLE": {
|
"FILE_BUBBLE": {
|
||||||
"DOWNLOAD": "Stáhnout",
|
"DOWNLOAD": "Stáhnout",
|
||||||
"UPLOADING": "Nahrávání..."
|
"UPLOADING": "Nahrávání..."
|
||||||
@ -147,6 +151,7 @@
|
|||||||
},
|
},
|
||||||
"SIDEBAR": {
|
"SIDEBAR": {
|
||||||
"CURRENTLY_VIEWING_ACCOUNT": "Currently viewing:",
|
"CURRENTLY_VIEWING_ACCOUNT": "Currently viewing:",
|
||||||
|
"SWITCH": "Switch",
|
||||||
"CONVERSATIONS": "Konverzace",
|
"CONVERSATIONS": "Konverzace",
|
||||||
"ALL_CONVERSATIONS": "All Conversations",
|
"ALL_CONVERSATIONS": "All Conversations",
|
||||||
"MENTIONED_CONVERSATIONS": "Mentions",
|
"MENTIONED_CONVERSATIONS": "Mentions",
|
||||||
@ -173,7 +178,7 @@
|
|||||||
"NEW_LABEL": "New label",
|
"NEW_LABEL": "New label",
|
||||||
"NEW_TEAM": "New team",
|
"NEW_TEAM": "New team",
|
||||||
"NEW_INBOX": "New inbox",
|
"NEW_INBOX": "New inbox",
|
||||||
"REPORTS_OVERVIEW": "Overview",
|
"REPORTS_CONVERSATION": "Konverzace",
|
||||||
"CSAT": "CSAT",
|
"CSAT": "CSAT",
|
||||||
"CAMPAIGNS": "Kampaně",
|
"CAMPAIGNS": "Kampaně",
|
||||||
"ONGOING": "Ongoing",
|
"ONGOING": "Ongoing",
|
||||||
@ -183,7 +188,8 @@
|
|||||||
"REPORTS_INBOX": "Inbox",
|
"REPORTS_INBOX": "Inbox",
|
||||||
"REPORTS_TEAM": "Team",
|
"REPORTS_TEAM": "Team",
|
||||||
"SET_AVAILABILITY_TITLE": "Set yourself as",
|
"SET_AVAILABILITY_TITLE": "Set yourself as",
|
||||||
"BETA": "Beta"
|
"BETA": "Beta",
|
||||||
|
"REPORTS_OVERVIEW": "Overview"
|
||||||
},
|
},
|
||||||
"CREATE_ACCOUNT": {
|
"CREATE_ACCOUNT": {
|
||||||
"NO_ACCOUNT_WARNING": "Uh oh! We could not find any Chatwoot accounts. Please create a new account to continue.",
|
"NO_ACCOUNT_WARNING": "Uh oh! We could not find any Chatwoot accounts. Please create a new account to continue.",
|
||||||
|
|||||||
@ -21,7 +21,8 @@
|
|||||||
"PASSWORD": {
|
"PASSWORD": {
|
||||||
"LABEL": "Heslo",
|
"LABEL": "Heslo",
|
||||||
"PLACEHOLDER": "Heslo",
|
"PLACEHOLDER": "Heslo",
|
||||||
"ERROR": "Heslo je příliš krátké"
|
"ERROR": "Heslo je příliš krátké",
|
||||||
|
"IS_INVALID_PASSWORD": "Password should contain atleast 1 uppercase letter, 1 lowercase letter, 1 number and 1 special character"
|
||||||
},
|
},
|
||||||
"CONFIRM_PASSWORD": {
|
"CONFIRM_PASSWORD": {
|
||||||
"LABEL": "Potvrzení hesla",
|
"LABEL": "Potvrzení hesla",
|
||||||
|
|||||||
@ -83,7 +83,7 @@
|
|||||||
"SELECT_ALL": "select all agents",
|
"SELECT_ALL": "select all agents",
|
||||||
"SELECTED_COUNT": "%{selected} out of %{total} agents selected.",
|
"SELECTED_COUNT": "%{selected} out of %{total} agents selected.",
|
||||||
"BUTTON_TEXT": "Přidat agenty",
|
"BUTTON_TEXT": "Přidat agenty",
|
||||||
"AGENT_VALIDATION_ERROR": "Select atleaset one agent."
|
"AGENT_VALIDATION_ERROR": "Select at least one agent."
|
||||||
},
|
},
|
||||||
"FINISH": {
|
"FINISH": {
|
||||||
"TITLE": "Your team is ready!",
|
"TITLE": "Your team is ready!",
|
||||||
|
|||||||
@ -89,7 +89,9 @@
|
|||||||
"DELETE_MESSAGE": "You need to have atleast one condition to save"
|
"DELETE_MESSAGE": "You need to have atleast one condition to save"
|
||||||
},
|
},
|
||||||
"ACTION": {
|
"ACTION": {
|
||||||
"DELETE_MESSAGE": "You need to have atleast one action to save"
|
"DELETE_MESSAGE": "You need to have atleast one action to save",
|
||||||
|
"TEAM_MESSAGE_INPUT_PLACEHOLDER": "Enter your message here",
|
||||||
|
"TEAM_DROPDOWN_PLACEHOLDER": "Select teams"
|
||||||
},
|
},
|
||||||
"TOGGLE": {
|
"TOGGLE": {
|
||||||
"ACTIVATION_TITLE": "Activate Automation Rule",
|
"ACTIVATION_TITLE": "Activate Automation Rule",
|
||||||
@ -102,6 +104,13 @@
|
|||||||
"DEACTIVATION_ERROR": "Could not Deactivate Automation, Please try again later",
|
"DEACTIVATION_ERROR": "Could not Deactivate Automation, Please try again later",
|
||||||
"CONFIRMATION_LABEL": "Yes",
|
"CONFIRMATION_LABEL": "Yes",
|
||||||
"CANCEL_LABEL": "No"
|
"CANCEL_LABEL": "No"
|
||||||
|
},
|
||||||
|
"ATTACHMENT": {
|
||||||
|
"UPLOAD_ERROR": "Could not upload attachment, Please try again",
|
||||||
|
"LABEL_IDLE": "Upload Attachment",
|
||||||
|
"LABEL_UPLOADING": "Uploader...",
|
||||||
|
"LABEL_UPLOADED": "Succesfully Uploaded",
|
||||||
|
"LABEL_UPLOAD_FAILED": "Upload Failed"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -81,6 +81,7 @@
|
|||||||
"NO_MESSAGES": "No Messages",
|
"NO_MESSAGES": "No Messages",
|
||||||
"NO_CONTENT": "No content available",
|
"NO_CONTENT": "No content available",
|
||||||
"HIDE_QUOTED_TEXT": "Hide Quoted Text",
|
"HIDE_QUOTED_TEXT": "Hide Quoted Text",
|
||||||
"SHOW_QUOTED_TEXT": "Show Quoted Text"
|
"SHOW_QUOTED_TEXT": "Show Quoted Text",
|
||||||
|
"MESSAGE_READ": "Read"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,6 +70,14 @@
|
|||||||
"SUCCESS_MESSAGE": "Contacts saved successfully",
|
"SUCCESS_MESSAGE": "Contacts saved successfully",
|
||||||
"ERROR_MESSAGE": "Der opstod en fejl. Prøv venligst igen"
|
"ERROR_MESSAGE": "Der opstod en fejl. Prøv venligst igen"
|
||||||
},
|
},
|
||||||
|
"DELETE_NOTE": {
|
||||||
|
"CONFIRM": {
|
||||||
|
"TITLE": "Bekræft Sletning",
|
||||||
|
"MESSAGE": "Are you want sure to delete this note?",
|
||||||
|
"YES": "Yes, Delete it",
|
||||||
|
"NO": "Nej, behold det"
|
||||||
|
}
|
||||||
|
},
|
||||||
"DELETE_CONTACT": {
|
"DELETE_CONTACT": {
|
||||||
"BUTTON_LABEL": "Delete Contact",
|
"BUTTON_LABEL": "Delete Contact",
|
||||||
"TITLE": "Delete contact",
|
"TITLE": "Delete contact",
|
||||||
|
|||||||
@ -60,6 +60,13 @@
|
|||||||
"NOTIFICATIONS_PAGE": {
|
"NOTIFICATIONS_PAGE": {
|
||||||
"HEADER": "Notifications",
|
"HEADER": "Notifications",
|
||||||
"MARK_ALL_DONE": "Mark All Done",
|
"MARK_ALL_DONE": "Mark All Done",
|
||||||
|
"DELETE_TITLE": "deleted",
|
||||||
|
"UNREAD_NOTIFICATION": {
|
||||||
|
"TITLE": "Unread Notifications",
|
||||||
|
"ALL_NOTIFICATIONS": "View all notifications",
|
||||||
|
"LOADING_UNREAD_MESSAGE": "Loading unread notifications...",
|
||||||
|
"EMPTY_MESSAGE": "You have no unread notifications"
|
||||||
|
},
|
||||||
"LIST": {
|
"LIST": {
|
||||||
"LOADING_MESSAGE": "Loading notifications...",
|
"LOADING_MESSAGE": "Loading notifications...",
|
||||||
"404": "No Notifications",
|
"404": "No Notifications",
|
||||||
@ -101,6 +108,7 @@
|
|||||||
"GO_TO_CONVERSATION_DASHBOARD": "Go to Conversation Dashboard",
|
"GO_TO_CONVERSATION_DASHBOARD": "Go to Conversation Dashboard",
|
||||||
"GO_TO_CONTACTS_DASHBOARD": "Go to Contacts Dashboard",
|
"GO_TO_CONTACTS_DASHBOARD": "Go to Contacts Dashboard",
|
||||||
"GO_TO_REPORTS_OVERVIEW": "Go to Reports Overview",
|
"GO_TO_REPORTS_OVERVIEW": "Go to Reports Overview",
|
||||||
|
"GO_TO_CONVERSATION_REPORTS": "Go to Conversation Reports",
|
||||||
"GO_TO_AGENT_REPORTS": "Go to Agent Reports",
|
"GO_TO_AGENT_REPORTS": "Go to Agent Reports",
|
||||||
"GO_TO_LABEL_REPORTS": "Go to Label Reports",
|
"GO_TO_LABEL_REPORTS": "Go to Label Reports",
|
||||||
"GO_TO_INBOX_REPORTS": "Go to Inbox Reports",
|
"GO_TO_INBOX_REPORTS": "Go to Inbox Reports",
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user