Compare commits

..
Author SHA1 Message Date
Tanmay Deep Sharma 78b03a1651 validate swagger api specification 2025-05-20 17:00:52 +07:00
Tanmay Deep Sharma 22b2280337 update the commit id in docs.json 2025-05-20 16:55:50 +07:00
Tanmay Deep Sharma 3b42191705 add tags to swagger 2025-05-20 16:43:22 +07:00
Tanmay Deep Sharma 019a596a3e add tags to swagger 2025-05-20 16:09:44 +07:00
Tanmay Deep Sharma 285b79d488 add tags to swagger 2025-05-20 15:49:16 +07:00
Tanmay Deep Sharma b3c17cc81e add tags to swagger 2025-05-20 15:41:50 +07:00
Tanmay Deep Sharma 90c600acd9 add tags to swagger 2025-05-20 15:35:41 +07:00
Tanmay Deep Sharma 2187a3e566 update user profile payload for developer docs 2025-05-20 00:49:24 +07:00
Tanmay Deep Sharma 2b043e5460 update contact payload for developer docs 2025-05-20 00:34:42 +07:00
Tanmay Deep Sharma ac94e34c72 update message payload for developer docs 2025-05-15 15:36:55 +07:00
Tanmay Deep Sharma dc9e19a122 update portal payload for developer docs 2025-05-15 15:30:40 +07:00
Tanmay Deep Sharma 073e32770f update portal payload for developer docs 2025-05-15 15:22:16 +07:00
Tanmay Deep Sharma a1bddd53f1 update automation rules payload for developer docs 2025-05-15 15:10:04 +07:00
Tanmay Deep Sharma fa74cac1d6 update automation rules payload for developer docs 2025-05-15 15:03:51 +07:00
Tanmay Deep Sharma 7d863d3e29 update automation rules payload for developer docs 2025-05-15 14:56:38 +07:00
Tanmay Deep Sharma 97c3da6f93 update automation rules payload for developer docs 2025-05-15 14:49:26 +07:00
Tanmay Deep Sharma c56c1489d5 update contact payload for developer docs 2025-05-15 14:28:29 +07:00
Tanmay Deep Sharma f0a43e3ba6 update contact payload for developer docs 2025-05-15 14:01:36 +07:00
Tanmay Deep Sharma 97b6624d9d update message payload for developer docs 2025-05-15 13:43:35 +07:00
Tanmay Deep Sharma fd3426a984 update conversation payload for developer docs 2025-05-15 13:11:10 +07:00
Tanmay Deep Sharma 9181a57df2 fix developer docs request data 2025-05-15 12:39:48 +07:00
Tanmay Deep Sharma c738b3cfaa define tags in openapi documentation 2025-05-13 17:28:56 +07:00
Tanmay Deep Sharma f20a1e96e4 Merge remote-tracking branch 'daniel/develop' into developer-docs 2025-05-13 14:58:46 +07:00
Daniel Jimenez aedec95e37 fix: Test all endpoints, ensuring payloads work correctly 2025-05-13 17:24:36 +12:00
Daniel Jimenez 2c3a3bbbd2 feat: Finish adding all request payload examples 2025-05-13 14:29:02 +12:00
Daniel Jimenez c3f741bdda fix: Update swagger.json spec 2025-05-13 14:29:02 +12:00
Daniel Jimenez 62e9c613df fix: Add more examples to api endpoints 2025-05-13 14:29:02 +12:00
Daniel Jimenez 9eefec31b3 feat: Add examples to request payloads 2025-05-13 14:29:02 +12:00
Daniel Jimenez 470d51c913 fix: Security definitions for endpoints 2025-05-13 14:29:02 +12:00
Daniel JimenezandDaniel Jimenez 444668c646 feat: Update swagger to openapi 3.0.4 2025-05-13 14:29:02 +12:00
Tanmay Deep Sharma f4a77dabd9 add Open API v3 developer docs 2025-05-08 12:47:22 +07:00
337 changed files with 2416 additions and 8148 deletions
+3 -3
View File
@@ -73,15 +73,15 @@ jobs:
libvips libvips
- run: - run:
name: Install RVM and Ruby 3.4.4 name: Install RVM and Ruby 3.3.3
command: | command: |
sudo apt-get install -y gpg sudo apt-get install -y gpg
gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
\curl -sSL https://get.rvm.io | bash -s stable \curl -sSL https://get.rvm.io | bash -s stable
echo 'source ~/.rvm/scripts/rvm' >> $BASH_ENV echo 'source ~/.rvm/scripts/rvm' >> $BASH_ENV
source ~/.rvm/scripts/rvm source ~/.rvm/scripts/rvm
rvm install "3.4.4" rvm install "3.3.3"
rvm use 3.4.4 --default rvm use 3.3.3 --default
gem install bundler -v 2.5.16 gem install bundler -v 2.5.16
- run: - run:
+2 -2
View File
@@ -12,7 +12,7 @@ services:
args: args:
VARIANT: 'ubuntu-22.04' VARIANT: 'ubuntu-22.04'
NODE_VERSION: '23.7.0' NODE_VERSION: '23.7.0'
RUBY_VERSION: '3.4.4' RUBY_VERSION: '3.3.3'
# On Linux, you may need to update USER_UID and USER_GID below if not your local UID is not 1000. # On Linux, you may need to update USER_UID and USER_GID below if not your local UID is not 1000.
USER_UID: '1000' USER_UID: '1000'
USER_GID: '1000' USER_GID: '1000'
@@ -25,7 +25,7 @@ services:
args: args:
VARIANT: 'ubuntu-22.04' VARIANT: 'ubuntu-22.04'
NODE_VERSION: '23.7.0' NODE_VERSION: '23.7.0'
RUBY_VERSION: '3.4.4' RUBY_VERSION: '3.3.3'
# On Linux, you may need to update USER_UID and USER_GID below if not your local UID is not 1000. # On Linux, you may need to update USER_UID and USER_GID below if not your local UID is not 1000.
USER_UID: '1000' USER_UID: '1000'
USER_GID: '1000' USER_GID: '1000'
+5 -5
View File
@@ -71,6 +71,9 @@ test/cypress/videos/*
/config/master.key /config/master.key
/config/*.enc /config/*.enc
#ignore files under .vscode directory
.vscode
.cursor
# yalc for local testing # yalc for local testing
.yalc .yalc
@@ -89,8 +92,5 @@ yarn-debug.log*
# https://vitejs.dev/guide/env-and-mode.html#env-files # https://vitejs.dev/guide/env-and-mode.html#env-files
*.local *.local
# Claude.ai config file
# TextEditors & AI Agents config files CLAUDE.md
.vscode
.claude/settings.local.json
.cursor
+8 -179
View File
@@ -1,10 +1,7 @@
plugins: require:
- rubocop-performance - rubocop-performance
- rubocop-rails - rubocop-rails
- rubocop-rspec - rubocop-rspec
- rubocop-factory_bot
require:
- ./rubocop/use_from_email.rb - ./rubocop/use_from_email.rb
- ./rubocop/custom_cop_location.rb - ./rubocop/custom_cop_location.rb
@@ -16,61 +13,44 @@ Metrics/ClassLength:
Exclude: Exclude:
- 'app/models/message.rb' - 'app/models/message.rb'
- 'app/models/conversation.rb' - 'app/models/conversation.rb'
Metrics/MethodLength: Metrics/MethodLength:
Max: 19 Max: 19
Exclude:
- 'enterprise/lib/captain/agent.rb'
RSpec/ExampleLength: RSpec/ExampleLength:
Max: 25 Max: 25
Style/Documentation: Style/Documentation:
Enabled: false Enabled: false
Style/ExponentialNotation: Style/ExponentialNotation:
Enabled: false Enabled: false
Style/FrozenStringLiteralComment: Style/FrozenStringLiteralComment:
Enabled: false Enabled: false
Style/SymbolArray: Style/SymbolArray:
Enabled: false Enabled: false
Style/OpenStructUse: Style/OpenStructUse:
Enabled: false Enabled: false
Style/OptionalBooleanParameter: Style/OptionalBooleanParameter:
Exclude: Exclude:
- 'app/services/email_templates/db_resolver_service.rb' - 'app/services/email_templates/db_resolver_service.rb'
- 'app/dispatchers/dispatcher.rb' - 'app/dispatchers/dispatcher.rb'
Style/GlobalVars: Style/GlobalVars:
Exclude: Exclude:
- 'config/initializers/01_redis.rb' - 'config/initializers/01_redis.rb'
- 'config/initializers/rack_attack.rb' - 'config/initializers/rack_attack.rb'
- 'lib/redis/alfred.rb' - 'lib/redis/alfred.rb'
- 'lib/global_config.rb' - 'lib/global_config.rb'
Style/ClassVars: Style/ClassVars:
Exclude: Exclude:
- 'app/services/email_templates/db_resolver_service.rb' - 'app/services/email_templates/db_resolver_service.rb'
Lint/MissingSuper: Lint/MissingSuper:
Exclude: Exclude:
- 'app/drops/base_drop.rb' - 'app/drops/base_drop.rb'
Lint/SymbolConversion: Lint/SymbolConversion:
Enabled: false Enabled: false
Lint/EmptyBlock: Lint/EmptyBlock:
Exclude: Exclude:
- 'app/views/api/v1/accounts/conversations/toggle_status.json.jbuilder' - 'app/views/api/v1/accounts/conversations/toggle_status.json.jbuilder'
Lint/OrAssignmentToConstant: Lint/OrAssignmentToConstant:
Exclude: Exclude:
- 'lib/redis/config.rb' - 'lib/redis/config.rb'
Metrics/BlockLength: Metrics/BlockLength:
Max: 30 Max: 30
Exclude: Exclude:
@@ -78,16 +58,10 @@ Metrics/BlockLength:
- '**/routes.rb' - '**/routes.rb'
- 'config/environments/*' - 'config/environments/*'
- db/schema.rb - db/schema.rb
Metrics/ModuleLength: Metrics/ModuleLength:
Exclude: Exclude:
- lib/seeders/message_seeder.rb - lib/seeders/message_seeder.rb
- spec/support/slack_stubs.rb - spec/support/slack_stubs.rb
Rails/HelperInstanceVariable:
Exclude:
- enterprise/app/helpers/captain/chat_helper.rb
Rails/ApplicationController: Rails/ApplicationController:
Exclude: Exclude:
- 'app/controllers/api/v1/widget/messages_controller.rb' - 'app/controllers/api/v1/widget/messages_controller.rb'
@@ -97,101 +71,74 @@ Rails/ApplicationController:
- 'app/controllers/platform_controller.rb' - 'app/controllers/platform_controller.rb'
- 'app/controllers/public_controller.rb' - 'app/controllers/public_controller.rb'
- 'app/controllers/survey/responses_controller.rb' - 'app/controllers/survey/responses_controller.rb'
Rails/FindEach: Rails/FindEach:
Enabled: true Enabled: true
Include: Include:
- 'app/**/*.rb' - 'app/**/*.rb'
Rails/CompactBlank: Rails/CompactBlank:
Enabled: false Enabled: false
Rails/EnvironmentVariableAccess: Rails/EnvironmentVariableAccess:
Enabled: false Enabled: false
Rails/TimeZoneAssignment: Rails/TimeZoneAssignment:
Enabled: false Enabled: false
Rails/RedundantPresenceValidationOnBelongsTo: Rails/RedundantPresenceValidationOnBelongsTo:
Enabled: false Enabled: false
Rails/InverseOf:
Exclude:
- enterprise/app/models/captain/assistant.rb
Rails/UniqueValidationWithoutIndex:
Exclude:
- app/models/canned_response.rb
- app/models/telegram_bot.rb
- enterprise/app/models/captain_inbox.rb
- 'app/models/channel/twitter_profile.rb'
- 'app/models/webhook.rb'
- 'app/models/contact.rb'
Style/ClassAndModuleChildren: Style/ClassAndModuleChildren:
EnforcedStyle: compact EnforcedStyle: compact
Exclude: Exclude:
- 'config/application.rb' - 'config/application.rb'
- 'config/initializers/monkey_patches/*' - 'config/initializers/monkey_patches/*'
Style/MapToHash: Style/MapToHash:
Enabled: false Enabled: false
Style/HashSyntax: Style/HashSyntax:
Enabled: true Enabled: true
EnforcedStyle: no_mixed_keys EnforcedStyle: no_mixed_keys
EnforcedShorthandSyntax: never EnforcedShorthandSyntax: never
RSpec/NestedGroups: RSpec/NestedGroups:
Enabled: true Enabled: true
Max: 4 Max: 4
RSpec/MessageSpies: RSpec/MessageSpies:
Enabled: false Enabled: false
RSpec/StubbedMock: RSpec/StubbedMock:
Enabled: false Enabled: false
RSpec/FactoryBot/SyntaxMethods:
Enabled: false
Naming/VariableNumber: Naming/VariableNumber:
Enabled: false Enabled: false
Naming/MemoizedInstanceVariableName: Naming/MemoizedInstanceVariableName:
Exclude: Exclude:
- 'app/models/message.rb' - 'app/models/message.rb'
Style/GuardClause: Style/GuardClause:
Exclude: Exclude:
- 'app/builders/account_builder.rb' - 'app/builders/account_builder.rb'
- 'app/models/attachment.rb' - 'app/models/attachment.rb'
- 'app/models/message.rb' - 'app/models/message.rb'
Metrics/AbcSize: Metrics/AbcSize:
Max: 26 Max: 26
Exclude: Exclude:
- 'app/controllers/concerns/auth_helper.rb' - 'app/controllers/concerns/auth_helper.rb'
Rails/UniqueValidationWithoutIndex:
Exclude:
- 'app/models/channel/twitter_profile.rb'
- 'app/models/webhook.rb'
- 'app/models/contact.rb'
- 'app/models/integrations/hook.rb' - 'app/models/integrations/hook.rb'
- 'app/models/canned_response.rb' - 'app/models/canned_response.rb'
- 'app/models/telegram_bot.rb' - 'app/models/telegram_bot.rb'
Rails/RenderInline: Rails/RenderInline:
Exclude: Exclude:
- 'app/controllers/swagger_controller.rb' - 'app/controllers/swagger_controller.rb'
Rails/ThreeStateBooleanColumn: Rails/ThreeStateBooleanColumn:
Exclude: Exclude:
- 'db/migrate/20230503101201_create_sla_policies.rb' - 'db/migrate/20230503101201_create_sla_policies.rb'
RSpec/IndexedLet: RSpec/IndexedLet:
Enabled: false Enabled: false
RSpec/NamedSubject: RSpec/NamedSubject:
Enabled: false Enabled: false
# we should bring this down # we should bring this down
RSpec/MultipleExpectations: RSpec/MultipleExpectations:
Max: 7 Max: 7
RSpec/MultipleMemoizedHelpers: RSpec/MultipleMemoizedHelpers:
Max: 14 Max: 14
@@ -219,121 +166,3 @@ AllCops:
- 'tmp/**/*' - 'tmp/**/*'
- 'storage/**/*' - 'storage/**/*'
- 'db/migrate/20230426130150_init_schema.rb' - 'db/migrate/20230426130150_init_schema.rb'
FactoryBot/SyntaxMethods:
Enabled: false
# Disable new rules causing errors
Layout/LeadingCommentSpace:
Enabled: false
Style/ReturnNilInPredicateMethodDefinition:
Enabled: false
Style/RedundantParentheses:
Enabled: false
Performance/StringIdentifierArgument:
Enabled: false
Layout/EmptyLinesAroundExceptionHandlingKeywords:
Enabled: false
Lint/LiteralAsCondition:
Enabled: false
Style/RedundantReturn:
Enabled: false
Layout/SpaceAroundOperators:
Enabled: false
Rails/EnvLocal:
Enabled: false
Rails/WhereRange:
Enabled: false
Lint/UselessConstantScoping:
Enabled: false
Style/MultipleComparison:
Enabled: false
Bundler/OrderedGems:
Enabled: false
RSpec/ExampleWording:
Enabled: false
RSpec/ReceiveMessages:
Enabled: false
FactoryBot/AssociationStyle:
Enabled: false
Rails/EnumSyntax:
Enabled: false
Lint/RedundantTypeConversion:
Enabled: false
# Additional rules to disable
Rails/RedundantActiveRecordAllMethod:
Enabled: false
Layout/TrailingEmptyLines:
Enabled: false
Style/SafeNavigationChainLength:
Enabled: false
Lint/SafeNavigationConsistency:
Enabled: false
Lint/CopDirectiveSyntax:
Enabled: false
# Final set of rules to disable
FactoryBot/ExcessiveCreateList:
Enabled: false
RSpec/MissingExpectationTargetMethod:
Enabled: false
Performance/InefficientHashSearch:
Enabled: false
Style/RedundantSelfAssignmentBranch:
Enabled: false
Style/YAMLFileRead:
Enabled: false
Layout/ExtraSpacing:
Enabled: false
Style/RedundantFilterChain:
Enabled: false
Performance/MapMethodChain:
Enabled: false
Rails/RootPathnameMethods:
Enabled: false
Style/SuperArguments:
Enabled: false
# Final remaining rules to disable
Rails/Delegate:
Enabled: false
Style/CaseLikeIf:
Enabled: false
FactoryBot/RedundantFactoryOption:
Enabled: false
FactoryBot/FactoryAssociationWithStrategy:
Enabled: false
+1 -1
View File
@@ -1 +1 @@
3.4.4 3.3.3
-1
View File
@@ -1 +0,0 @@
../../AGENTS.md
-58
View File
@@ -1,58 +0,0 @@
# Chatwoot Development Guidelines
## Build / Test / Lint
- **Setup**: `bundle install && pnpm install`
- **Run Dev**: `pnpm dev` or `overmind start -f ./Procfile.dev`
- **Lint JS/Vue**: `pnpm eslint` / `pnpm eslint:fix`
- **Lint Ruby**: `bundle exec rubocop -a`
- **Test JS**: `pnpm test` or `pnpm test:watch`
- **Test Ruby**: `bundle exec rspec spec/path/to/file_spec.rb`
- **Single Test**: `bundle exec rspec spec/path/to/file_spec.rb:LINE_NUMBER`
- **Run Project**: `overmind start -f Procfile.dev`
## Code Style
- **Ruby**: Follow RuboCop rules (150 character max line length)
- **Vue/JS**: Use ESLint (Airbnb base + Vue 3 recommended)
- **Vue Components**: Use PascalCase
- **Events**: Use camelCase
- **I18n**: No bare strings in templates; use i18n
- **Error Handling**: Use custom exceptions (`lib/custom_exceptions/`)
- **Models**: Validate presence/uniqueness, add proper indexes
- **Type Safety**: Use PropTypes in Vue, strong params in Rails
- **Naming**: Use clear, descriptive names with consistent casing
- **Vue API**: Always use Composition API with `<script setup>` at the top
## Styling
- **Tailwind Only**:
- Do not write custom CSS
- Do not use scoped CSS
- Do not use inline styles
- Always use Tailwind utility classes
- **Colors**: Refer to `tailwind.config.js` for color definitions
## General Guidelines
- MVP focus: Least code change, happy-path only
- No unnecessary defensive programming
- Break down complex tasks into small, testable units
- Iterate after confirmation
- Avoid writing specs unless explicitly asked
- Remove dead/unreachable/unused code
- Don’t write multiple versions or backups for the same logic — pick the best approach and implement it
- Don't reference Claude in commit messages
## Project-Specific
- **Translations**:
- Only update `en.yml` and `en.json`
- Other languages are handled by the community
- Backend i18n → `en.yml`, Frontend i18n → `en.json`
- **Frontend**:
- Use `components-next/` for message bubbles (the rest is being deprecated)
## Ruby Best Practices
- Use compact `module/class` definitions; avoid nested styles
-1
View File
@@ -1 +0,0 @@
AGENTS.md
+5 -5
View File
@@ -1,10 +1,10 @@
source 'https://rubygems.org' source 'https://rubygems.org'
ruby '3.4.4' ruby '3.3.3'
##-- base gems for rails --## ##-- base gems for rails --##
gem 'rack-cors', '2.0.0', require: 'rack/cors' gem 'rack-cors', '2.0.0', require: 'rack/cors'
gem 'rails', '~> 7.1' gem 'rails', '~> 7.0.8.4'
# Reduces boot times through caching; required in config/boot.rb # Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', require: false gem 'bootsnap', require: false
@@ -33,8 +33,6 @@ gem 'liquid'
gem 'commonmarker' gem 'commonmarker'
# Validate Data against JSON Schema # Validate Data against JSON Schema
gem 'json_schemer' gem 'json_schemer'
# used in swagger build
gem 'json_refs'
# Rack middleware for blocking & throttling abusive requests # Rack middleware for blocking & throttling abusive requests
gem 'rack-attack', '>= 6.7.0' gem 'rack-attack', '>= 6.7.0'
# a utility tool for streaming, flexible and safe downloading of remote files # a utility tool for streaming, flexible and safe downloading of remote files
@@ -198,6 +196,9 @@ group :development do
gem 'scss_lint', require: false gem 'scss_lint', require: false
gem 'web-console', '>= 4.2.1' gem 'web-console', '>= 4.2.1'
# used in swagger build
gem 'json_refs'
# When we want to squash migrations # When we want to squash migrations
gem 'squasher' gem 'squasher'
@@ -236,7 +237,6 @@ group :development, :test do
gem 'rubocop-performance', require: false gem 'rubocop-performance', require: false
gem 'rubocop-rails', require: false gem 'rubocop-rails', require: false
gem 'rubocop-rspec', require: false gem 'rubocop-rspec', require: false
gem 'rubocop-factory_bot', require: false
gem 'seed_dump' gem 'seed_dump'
gem 'shoulda-matchers' gem 'shoulda-matchers'
gem 'simplecov', '0.17.1', require: false gem 'simplecov', '0.17.1', require: false
+141 -161
View File
@@ -25,89 +25,76 @@ GIT
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
actioncable (7.1.5.1) actioncable (7.0.8.7)
actionpack (= 7.1.5.1) actionpack (= 7.0.8.7)
activesupport (= 7.1.5.1) activesupport (= 7.0.8.7)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (>= 0.6.1) websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6) actionmailbox (7.0.8.7)
actionmailbox (7.1.5.1) actionpack (= 7.0.8.7)
actionpack (= 7.1.5.1) activejob (= 7.0.8.7)
activejob (= 7.1.5.1) activerecord (= 7.0.8.7)
activerecord (= 7.1.5.1) activestorage (= 7.0.8.7)
activestorage (= 7.1.5.1) activesupport (= 7.0.8.7)
activesupport (= 7.1.5.1)
mail (>= 2.7.1) mail (>= 2.7.1)
net-imap net-imap
net-pop net-pop
net-smtp net-smtp
actionmailer (7.1.5.1) actionmailer (7.0.8.7)
actionpack (= 7.1.5.1) actionpack (= 7.0.8.7)
actionview (= 7.1.5.1) actionview (= 7.0.8.7)
activejob (= 7.1.5.1) activejob (= 7.0.8.7)
activesupport (= 7.1.5.1) activesupport (= 7.0.8.7)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
net-imap net-imap
net-pop net-pop
net-smtp net-smtp
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.0)
actionpack (7.1.5.1) actionpack (7.0.8.7)
actionview (= 7.1.5.1) actionview (= 7.0.8.7)
activesupport (= 7.1.5.1) activesupport (= 7.0.8.7)
nokogiri (>= 1.8.5) rack (~> 2.0, >= 2.2.4)
racc
rack (>= 2.2.4)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.6) rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (7.1.5.1) actiontext (7.0.8.7)
actionpack (= 7.1.5.1) actionpack (= 7.0.8.7)
activerecord (= 7.1.5.1) activerecord (= 7.0.8.7)
activestorage (= 7.1.5.1) activestorage (= 7.0.8.7)
activesupport (= 7.1.5.1) activesupport (= 7.0.8.7)
globalid (>= 0.6.0) globalid (>= 0.6.0)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
actionview (7.1.5.1) actionview (7.0.8.7)
activesupport (= 7.1.5.1) activesupport (= 7.0.8.7)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.11) erubi (~> 1.4)
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.6) rails-html-sanitizer (~> 1.1, >= 1.2.0)
active_record_query_trace (1.8) active_record_query_trace (1.8)
activejob (7.1.5.1) activejob (7.0.8.7)
activesupport (= 7.1.5.1) activesupport (= 7.0.8.7)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (7.1.5.1) activemodel (7.0.8.7)
activesupport (= 7.1.5.1) activesupport (= 7.0.8.7)
activerecord (7.1.5.1) activerecord (7.0.8.7)
activemodel (= 7.1.5.1) activemodel (= 7.0.8.7)
activesupport (= 7.1.5.1) activesupport (= 7.0.8.7)
timeout (>= 0.4.0) activerecord-import (1.4.1)
activerecord-import (2.1.0)
activerecord (>= 4.2) activerecord (>= 4.2)
activestorage (7.1.5.1) activestorage (7.0.8.7)
actionpack (= 7.1.5.1) actionpack (= 7.0.8.7)
activejob (= 7.1.5.1) activejob (= 7.0.8.7)
activerecord (= 7.1.5.1) activerecord (= 7.0.8.7)
activesupport (= 7.1.5.1) activesupport (= 7.0.8.7)
marcel (~> 1.0) marcel (~> 1.0)
activesupport (7.1.5.1) mini_mime (>= 1.1.0)
base64 activesupport (7.0.8.7)
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2) i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1) minitest (>= 5.1)
mutex_m
securerandom (>= 0.3)
tzinfo (~> 2.0) tzinfo (~> 2.0)
acts-as-taggable-on (12.0.0) acts-as-taggable-on (9.0.1)
activerecord (>= 7.1, < 8.1) activerecord (>= 6.0, < 7.1)
zeitwerk (>= 2.4, < 3.0)
addressable (2.8.7) addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0) public_suffix (>= 2.0.2, < 7.0)
administrate (0.20.1) administrate (0.20.1)
@@ -129,7 +116,7 @@ GEM
annotate (3.2.0) annotate (3.2.0)
activerecord (>= 3.2, < 8.0) activerecord (>= 3.2, < 8.0)
rake (>= 10.4, < 14.0) rake (>= 10.4, < 14.0)
ast (2.4.3) ast (2.4.2)
attr_extras (7.1.0) attr_extras (7.1.0)
audited (5.4.1) audited (5.4.1)
activerecord (>= 5.0, < 7.7) activerecord (>= 5.0, < 7.7)
@@ -155,15 +142,14 @@ GEM
statsd-ruby (~> 1.1) statsd-ruby (~> 1.1)
base64 (0.2.0) base64 (0.2.0)
bcrypt (3.1.20) bcrypt (3.1.20)
benchmark (0.4.0) bigdecimal (3.1.8)
bigdecimal (3.1.9)
bindex (0.8.1) bindex (0.8.1)
bootsnap (1.16.0) bootsnap (1.16.0)
msgpack (~> 1.2) msgpack (~> 1.2)
brakeman (5.4.1) brakeman (5.4.1)
browser (5.3.1) browser (5.3.1)
builder (3.3.0) builder (3.3.0)
bullet (8.0.7) bullet (7.0.7)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
uniform_notifier (~> 1.11) uniform_notifier (~> 1.11)
bundle-audit (0.1.0) bundle-audit (0.1.0)
@@ -175,8 +161,8 @@ GEM
climate_control (1.2.0) climate_control (1.2.0)
coderay (1.1.3) coderay (1.1.3)
commonmarker (0.23.10) commonmarker (0.23.10)
concurrent-ruby (1.3.5) concurrent-ruby (1.3.4)
connection_pool (2.5.3) connection_pool (2.4.1)
crack (1.0.0) crack (1.0.0)
bigdecimal bigdecimal
rexml rexml
@@ -190,10 +176,16 @@ GEM
activerecord (>= 5.a) activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0) database_cleaner-core (~> 2.0.0)
database_cleaner-core (2.0.1) database_cleaner-core (2.0.1)
date (3.4.1) datadog-ci (0.8.3)
ddtrace (0.48.0)
ffi (~> 1.0)
msgpack msgpack
date (3.4.1)
ddtrace (1.23.2)
datadog-ci (~> 0.8.1)
debase-ruby_core_source (= 3.3.1)
libdatadog (~> 7.0.0.1.0)
libddwaf (~> 1.14.0.0.0)
msgpack
debase-ruby_core_source (3.3.1)
debug (1.8.0) debug (1.8.0)
irb (>= 1.5.0) irb (>= 1.5.0)
reline (>= 0.3.1) reline (>= 0.3.1)
@@ -204,10 +196,10 @@ GEM
railties (>= 4.1.0) railties (>= 4.1.0)
responders responders
warden (~> 1.2.3) warden (~> 1.2.3)
devise_token_auth (1.2.5) devise_token_auth (1.2.3)
bcrypt (~> 3.0) bcrypt (~> 3.0)
devise (> 3.5.2, < 5) devise (> 3.5.2, < 5)
rails (>= 4.2.0, < 8.1) rails (>= 4.2.0, < 7.2)
diff-lcs (1.5.1) diff-lcs (1.5.1)
digest-crc (0.6.5) digest-crc (0.6.5)
rake (>= 12.0.0, < 14.0.0) rake (>= 12.0.0, < 14.0.0)
@@ -220,7 +212,6 @@ GEM
railties (>= 6.1) railties (>= 6.1)
down (5.4.0) down (5.4.0)
addressable (~> 2.8) addressable (~> 2.8)
drb (2.2.3)
dry-cli (1.1.0) dry-cli (1.1.0)
ecma-re-validator (0.4.0) ecma-re-validator (0.4.0)
regexp_parser (~> 2.2) regexp_parser (~> 2.2)
@@ -263,10 +254,7 @@ GEM
fcm (1.0.8) fcm (1.0.8)
faraday (>= 1.0.0, < 3.0) faraday (>= 1.0.0, < 3.0)
googleauth (~> 1) googleauth (~> 1)
ffi (1.17.2) ffi (1.16.3)
ffi (1.17.2-arm64-darwin)
ffi (1.17.2-x86_64-darwin)
ffi (1.17.2-x86_64-linux-gnu)
ffi-compiler (1.0.1) ffi-compiler (1.0.1)
ffi (>= 1.0.0) ffi (>= 1.0.0)
rake rake
@@ -327,13 +315,16 @@ GEM
google-cloud-translate-v3 (0.10.0) google-cloud-translate-v3 (0.10.0)
gapic-common (>= 0.20.0, < 2.a) gapic-common (>= 0.20.0, < 2.a)
google-cloud-errors (~> 1.0) google-cloud-errors (~> 1.0)
google-protobuf (3.25.7) google-protobuf (3.25.5)
google-protobuf (3.25.5-arm64-darwin)
google-protobuf (3.25.5-x86_64-darwin)
google-protobuf (3.25.5-x86_64-linux)
googleapis-common-protos (1.6.0) googleapis-common-protos (1.6.0)
google-protobuf (>= 3.18, < 5.a) google-protobuf (>= 3.18, < 5.a)
googleapis-common-protos-types (~> 1.7) googleapis-common-protos-types (~> 1.7)
grpc (~> 1.41) grpc (~> 1.41)
googleapis-common-protos-types (1.20.0) googleapis-common-protos-types (1.14.0)
google-protobuf (>= 3.18, < 5.a) google-protobuf (~> 3.18)
googleauth (1.11.2) googleauth (1.11.2)
faraday (>= 1.0, < 3.a) faraday (>= 1.0, < 3.a)
google-cloud-env (~> 2.1) google-cloud-env (~> 2.1)
@@ -343,17 +334,17 @@ GEM
signet (>= 0.16, < 2.a) signet (>= 0.16, < 2.a)
groupdate (6.2.1) groupdate (6.2.1)
activesupport (>= 5.2) activesupport (>= 5.2)
grpc (1.72.0) grpc (1.62.0)
google-protobuf (>= 3.25, < 5.0) google-protobuf (~> 3.25)
googleapis-common-protos-types (~> 1.0) googleapis-common-protos-types (~> 1.0)
grpc (1.72.0-arm64-darwin) grpc (1.62.0-arm64-darwin)
google-protobuf (>= 3.25, < 5.0) google-protobuf (~> 3.25)
googleapis-common-protos-types (~> 1.0) googleapis-common-protos-types (~> 1.0)
grpc (1.72.0-x86_64-darwin) grpc (1.62.0-x86_64-darwin)
google-protobuf (>= 3.25, < 5.0) google-protobuf (~> 3.25)
googleapis-common-protos-types (~> 1.0) googleapis-common-protos-types (~> 1.0)
grpc (1.72.0-x86_64-linux) grpc (1.62.0-x86_64-linux)
google-protobuf (>= 3.25, < 5.0) google-protobuf (~> 3.25)
googleapis-common-protos-types (~> 1.0) googleapis-common-protos-types (~> 1.0)
haikunator (1.1.1) haikunator (1.1.1)
hairtrigger (1.0.0) hairtrigger (1.0.0)
@@ -379,7 +370,7 @@ GEM
mini_mime (>= 1.0.0) mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2) multi_xml (>= 0.5.2)
httpclient (2.8.3) httpclient (2.8.3)
i18n (1.14.7) i18n (1.14.6)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
image_processing (1.12.2) image_processing (1.12.2)
mini_magick (>= 4.9.5, < 5) mini_magick (>= 4.9.5, < 5)
@@ -397,7 +388,7 @@ GEM
rails-dom-testing (>= 1, < 3) rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0) railties (>= 4.2.0)
thor (>= 0.14, < 2.0) thor (>= 0.14, < 2.0)
json (2.12.0) json (2.6.3)
json_refs (0.1.8) json_refs (0.1.8)
hana hana
json_schemer (0.2.24) json_schemer (0.2.24)
@@ -432,13 +423,21 @@ GEM
faraday-multipart faraday-multipart
json (>= 1.8) json (>= 1.8)
rexml rexml
language_server-protocol (3.17.0.5)
launchy (2.5.2) launchy (2.5.2)
addressable (~> 2.8) addressable (~> 2.8)
letter_opener (1.8.1) letter_opener (1.8.1)
launchy (>= 2.2, < 3) launchy (>= 2.2, < 3)
libdatadog (7.0.0.1.0)
libdatadog (7.0.0.1.0-x86_64-linux)
libddwaf (1.14.0.0.0)
ffi (~> 1.0)
libddwaf (1.14.0.0.0-arm64-darwin)
ffi (~> 1.0)
libddwaf (1.14.0.0.0-x86_64-darwin)
ffi (~> 1.0)
libddwaf (1.14.0.0.0-x86_64-linux)
ffi (~> 1.0)
line-bot-api (1.28.0) line-bot-api (1.28.0)
lint_roller (1.1.0)
liquid (5.4.0) liquid (5.4.0)
listen (3.8.0) listen (3.8.0)
rb-fsevent (~> 0.10, >= 0.10.3) rb-fsevent (~> 0.10, >= 0.10.3)
@@ -446,7 +445,7 @@ GEM
llhttp-ffi (0.4.0) llhttp-ffi (0.4.0)
ffi-compiler (~> 1.0) ffi-compiler (~> 1.0)
rake (~> 13.0) rake (~> 13.0)
logger (1.7.0) logger (1.6.0)
lograge (0.14.0) lograge (0.14.0)
actionpack (>= 4) actionpack (>= 4)
activesupport (>= 4) activesupport (>= 4)
@@ -472,10 +471,10 @@ GEM
mini_magick (4.12.0) mini_magick (4.12.0)
mini_mime (1.1.5) mini_mime (1.1.5)
mini_portile2 (2.8.8) mini_portile2 (2.8.8)
minitest (5.25.5) minitest (5.25.4)
mock_redis (0.36.0) mock_redis (0.36.0)
ruby2_keywords ruby2_keywords
msgpack (1.8.0) msgpack (1.7.0)
multi_json (1.15.0) multi_json (1.15.0)
multi_xml (0.6.0) multi_xml (0.6.0)
multipart-post (2.3.0) multipart-post (2.3.0)
@@ -546,16 +545,14 @@ GEM
orm_adapter (0.5.0) orm_adapter (0.5.0)
os (1.1.4) os (1.1.4)
ostruct (0.6.1) ostruct (0.6.1)
parallel (1.27.0) parallel (1.23.0)
parser (3.3.8.0) parser (3.2.2.1)
ast (~> 2.4.1) ast (~> 2.4.1)
racc
pg (1.5.3) pg (1.5.3)
pg_search (2.3.6) pg_search (2.3.6)
activerecord (>= 5.2) activerecord (>= 5.2)
activesupport (>= 5.2) activesupport (>= 5.2)
pgvector (0.1.1) pgvector (0.1.1)
prism (1.4.0)
procore-sift (1.0.0) procore-sift (1.0.0)
activerecord (>= 6.1) activerecord (>= 6.1)
pry (0.14.2) pry (0.14.2)
@@ -570,7 +567,7 @@ GEM
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
raabro (1.4.0) raabro (1.4.0)
racc (1.8.1) racc (1.8.1)
rack (2.2.15) rack (2.2.14)
rack-attack (6.7.0) rack-attack (6.7.0)
rack (>= 1.0, < 4) rack (>= 1.0, < 4)
rack-contrib (2.5.0) rack-contrib (2.5.0)
@@ -584,28 +581,23 @@ GEM
rack (~> 2.2, >= 2.2.4) rack (~> 2.2, >= 2.2.4)
rack-proxy (0.7.7) rack-proxy (0.7.7)
rack rack
rack-session (1.0.2)
rack (< 3)
rack-test (2.1.0) rack-test (2.1.0)
rack (>= 1.3) rack (>= 1.3)
rack-timeout (0.6.3) rack-timeout (0.6.3)
rackup (1.0.1) rails (7.0.8.7)
rack (< 3) actioncable (= 7.0.8.7)
webrick actionmailbox (= 7.0.8.7)
rails (7.1.5.1) actionmailer (= 7.0.8.7)
actioncable (= 7.1.5.1) actionpack (= 7.0.8.7)
actionmailbox (= 7.1.5.1) actiontext (= 7.0.8.7)
actionmailer (= 7.1.5.1) actionview (= 7.0.8.7)
actionpack (= 7.1.5.1) activejob (= 7.0.8.7)
actiontext (= 7.1.5.1) activemodel (= 7.0.8.7)
actionview (= 7.1.5.1) activerecord (= 7.0.8.7)
activejob (= 7.1.5.1) activestorage (= 7.0.8.7)
activemodel (= 7.1.5.1) activesupport (= 7.0.8.7)
activerecord (= 7.1.5.1)
activestorage (= 7.1.5.1)
activesupport (= 7.1.5.1)
bundler (>= 1.15.0) bundler (>= 1.15.0)
railties (= 7.1.5.1) railties (= 7.0.8.7)
rails-dom-testing (2.2.0) rails-dom-testing (2.2.0)
activesupport (>= 5.0.0) activesupport (>= 5.0.0)
minitest minitest
@@ -613,14 +605,13 @@ GEM
rails-html-sanitizer (1.6.1) rails-html-sanitizer (1.6.1)
loofah (~> 2.21) loofah (~> 2.21)
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
railties (7.1.5.1) railties (7.0.8.7)
actionpack (= 7.1.5.1) actionpack (= 7.0.8.7)
activesupport (= 7.1.5.1) activesupport (= 7.0.8.7)
irb method_source
rackup (>= 1.0.0)
rake (>= 12.2) rake (>= 12.2)
thor (~> 1.0, >= 1.2.2) thor (~> 1.0)
zeitwerk (~> 2.6) zeitwerk (~> 2.5)
rainbow (3.1.1) rainbow (3.1.1)
rake (13.2.1) rake (13.2.1)
rb-fsevent (0.11.2) rb-fsevent (0.11.2)
@@ -632,7 +623,7 @@ GEM
connection_pool connection_pool
redis-namespace (1.10.0) redis-namespace (1.10.0)
redis (>= 4) redis (>= 4)
regexp_parser (2.10.0) regexp_parser (2.8.0)
reline (0.3.6) reline (0.3.6)
io-console (~> 0.5) io-console (~> 0.5)
representable (3.2.0) representable (3.2.0)
@@ -652,7 +643,7 @@ GEM
retriable (3.1.2) retriable (3.1.2)
reverse_markdown (2.1.1) reverse_markdown (2.1.1)
nokogiri nokogiri
rexml (3.4.1) rexml (3.3.9)
rspec-core (3.13.0) rspec-core (3.13.0)
rspec-support (~> 3.13.0) rspec-support (~> 3.13.0)
rspec-expectations (3.13.2) rspec-expectations (3.13.2)
@@ -672,36 +663,30 @@ GEM
rspec-support (3.13.1) rspec-support (3.13.1)
rspec_junit_formatter (0.6.0) rspec_junit_formatter (0.6.0)
rspec-core (>= 2, < 4, != 2.12.0) rspec-core (>= 2, < 4, != 2.12.0)
rubocop (1.75.6) rubocop (1.50.2)
json (~> 2.3) json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 3.3.0.2) parser (>= 3.2.0.0)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0) regexp_parser (>= 1.8, < 3.0)
rubocop-ast (>= 1.44.0, < 2.0) rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.28.0, < 2.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0) unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.44.1) rubocop-ast (1.28.1)
parser (>= 3.3.7.2) parser (>= 3.2.1.0)
prism (~> 1.4) rubocop-capybara (2.18.0)
rubocop-factory_bot (2.27.1) rubocop (~> 1.41)
lint_roller (~> 1.1) rubocop-performance (1.17.1)
rubocop (~> 1.72, >= 1.72.1) rubocop (>= 1.7.0, < 2.0)
rubocop-performance (1.25.0) rubocop-ast (>= 0.4.0)
lint_roller (~> 1.1) rubocop-rails (2.19.1)
rubocop (>= 1.75.0, < 2.0)
rubocop-ast (>= 1.38.0, < 2.0)
rubocop-rails (2.32.0)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
lint_roller (~> 1.1)
rack (>= 1.1) rack (>= 1.1)
rubocop (>= 1.75.0, < 2.0) rubocop (>= 1.33.0, < 2.0)
rubocop-ast (>= 1.44.0, < 2.0) rubocop-rspec (2.21.0)
rubocop-rspec (3.6.0) rubocop (~> 1.33)
lint_roller (~> 1.1) rubocop-capybara (~> 2.17)
rubocop (~> 1.72, >= 1.72.1)
ruby-openai (7.3.1) ruby-openai (7.3.1)
event_stream_parser (>= 0.3.0, < 2.0.0) event_stream_parser (>= 0.3.0, < 2.0.0)
faraday (>= 1) faraday (>= 1)
@@ -831,10 +816,8 @@ GEM
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
unf_ext (0.0.8.2) unf_ext (0.0.8.2)
unicode-display_width (3.1.4) unicode-display_width (2.4.2)
unicode-emoji (~> 4.0, >= 4.0.4) uniform_notifier (1.16.0)
unicode-emoji (4.0.4)
uniform_notifier (1.17.0)
uri (1.0.3) uri (1.0.3)
uri_template (0.7.0) uri_template (0.7.0)
valid_email2 (5.2.6) valid_email2 (5.2.6)
@@ -862,9 +845,7 @@ GEM
addressable (>= 2.8.0) addressable (>= 2.8.0)
crack (>= 0.3.2) crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0) hashdiff (>= 0.4.0, < 2.0.0)
webrick (1.9.1) websocket-driver (0.7.6)
websocket-driver (0.7.7)
base64
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5) websocket-extensions (0.1.5)
wisper (2.0.0) wisper (2.0.0)
@@ -970,7 +951,7 @@ DEPENDENCIES
rack-cors (= 2.0.0) rack-cors (= 2.0.0)
rack-mini-profiler (>= 3.2.0) rack-mini-profiler (>= 3.2.0)
rack-timeout rack-timeout
rails (~> 7.1) rails (~> 7.0.8.4)
redis redis
redis-namespace redis-namespace
responders (>= 3.1.1) responders (>= 3.1.1)
@@ -979,7 +960,6 @@ DEPENDENCIES
rspec-rails (>= 6.1.5) rspec-rails (>= 6.1.5)
rspec_junit_formatter rspec_junit_formatter
rubocop rubocop
rubocop-factory_bot
rubocop-performance rubocop-performance
rubocop-rails rubocop-rails
rubocop-rspec rubocop-rspec
@@ -1017,7 +997,7 @@ DEPENDENCIES
working_hours working_hours
RUBY VERSION RUBY VERSION
ruby 3.4.4p34 ruby 3.3.3p89
BUNDLED WITH BUNDLED WITH
2.5.16 2.5.16
+25 -1
View File
@@ -32,7 +32,14 @@ class AccountBuilder
end end
def validate_email def validate_email
Account::SignUpEmailValidationService.new(@email).perform raise InvalidEmail.new({ domain_blocked: domain_blocked }) if domain_blocked?
address = ValidEmail2::Address.new(@email)
if address.valid? && !address.disposable?
true
else
raise InvalidEmail.new({ valid: address.valid?, disposable: address.disposable? })
end
end end
def validate_user def validate_user
@@ -74,4 +81,21 @@ class AccountBuilder
@user.confirm if @confirmed @user.confirm if @confirmed
@user.save! @user.save!
end end
def domain_blocked?
domain = @email.split('@').last
blocked_domains.each do |blocked_domain|
return true if domain.match?(blocked_domain)
end
false
end
def blocked_domains
domains = GlobalConfigService.load('BLOCKED_EMAIL_DOMAINS', '')
return [] if domains.blank?
domains.split("\n").map(&:strip)
end
end end
+2 -4
View File
@@ -59,13 +59,11 @@ class ContactInboxBuilder
end end
def create_contact_inbox def create_contact_inbox
attrs = { ::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
} )
::ContactInbox.where(attrs).first_or_create!(hmac_verified: hmac_verified || false)
rescue ActiveRecord::RecordNotUnique rescue ActiveRecord::RecordNotUnique
Rails.logger.info("[ContactInboxBuilder] RecordNotUnique #{@source_id} #{@contact.id} #{@inbox.id}") Rails.logger.info("[ContactInboxBuilder] RecordNotUnique #{@source_id} #{@contact.id} #{@inbox.id}")
update_old_contact_inbox update_old_contact_inbox
@@ -152,13 +152,11 @@ class Messages::Instagram::BaseMessageBuilder < Messages::Messenger::MessageBuil
end end
def message_already_exists? def message_already_exists?
find_message_by_source_id(@messaging[:message][:mid]).present? cw_message = conversation.messages.where(
end source_id: @messaging[:message][:mid]
).first
def find_message_by_source_id(source_id) cw_message.present?
return unless source_id
@message = Message.find_by(source_id: source_id)
end end
def all_unsupported_files? def all_unsupported_files?
@@ -1,6 +1,3 @@
# TODO : Move this to inboxes controller and deprecate this controller
# No need to retain this controller as we could handle everything centrally in inboxes controller
class Api::V1::Accounts::Channels::TwilioChannelsController < Api::V1::Accounts::BaseController class Api::V1::Accounts::Channels::TwilioChannelsController < Api::V1::Accounts::BaseController
before_action :authorize_request before_action :authorize_request
@@ -12,6 +12,10 @@ class Api::V1::Accounts::Contacts::ConversationsController < Api::V1::Accounts::
Current.account Current.account
).perform ).perform
# Only allow conversations from inboxes the user has access to
inbox_ids = Current.user.assigned_inboxes.pluck(:id)
conversations = conversations.where(inbox_id: inbox_ids)
@conversations = conversations.order(last_activity_at: :desc).limit(20) @conversations = conversations.order(last_activity_at: :desc).limit(20)
end end
end end
@@ -42,9 +42,7 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController
end end
def update def update
inbox_params = permitted_params.except(:channel, :csat_config) @inbox.update!(permitted_params.except(:channel))
inbox_params[:csat_config] = format_csat_config(permitted_params[:csat_config]) if permitted_params[:csat_config].present?
@inbox.update!(inbox_params)
update_inbox_working_hours update_inbox_working_hours
update_channel if channel_update_required? update_channel if channel_update_required?
end end
@@ -123,22 +121,10 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController
@inbox.channel.save! @inbox.channel.save!
end end
def format_csat_config(config)
{
display_type: config['display_type'] || 'emoji',
message: config['message'] || '',
survey_rules: {
operator: config.dig('survey_rules', 'operator') || 'contains',
values: config.dig('survey_rules', 'values') || []
}
}
end
def inbox_attributes def inbox_attributes
[:name, :avatar, :greeting_enabled, :greeting_message, :enable_email_collect, :csat_survey_enabled, [:name, :avatar, :greeting_enabled, :greeting_message, :enable_email_collect, :csat_survey_enabled,
:enable_auto_assignment, :working_hours_enabled, :out_of_office_message, :timezone, :allow_messages_after_resolved, :enable_auto_assignment, :working_hours_enabled, :out_of_office_message, :timezone, :allow_messages_after_resolved,
:lock_to_single_conversation, :portal_id, :sender_name_type, :business_name, :lock_to_single_conversation, :portal_id, :sender_name_type, :business_name]
{ csat_config: [:display_type, :message, { survey_rules: [:operator, { values: [] }] }] }]
end end
def permitted_params(channel_attributes = []) def permitted_params(channel_attributes = [])
@@ -94,8 +94,7 @@ class Api::V1::Accounts::Integrations::LinearController < Api::V1::Accounts::Bas
end end
def permitted_params def permitted_params
params.permit(:team_id, :project_id, :conversation_id, :issue_id, :link_id, :title, :description, :assignee_id, :priority, :state_id, params.permit(:team_id, :project_id, :conversation_id, :issue_id, :link_id, :title, :description, :assignee_id, :priority, label_ids: [])
label_ids: [])
end end
def fetch_hook def fetch_hook
@@ -21,7 +21,7 @@ class DeviseOverrides::OmniauthCallbacksController < DeviseTokenAuth::OmniauthCa
def sign_up_user def sign_up_user
return redirect_to login_page_url(error: 'no-account-found') unless account_signup_allowed? return redirect_to login_page_url(error: 'no-account-found') unless account_signup_allowed?
return redirect_to login_page_url(error: 'business-account-only') unless validate_signup_email_is_business_domain? return redirect_to login_page_url(error: 'business-account-only') unless validate_business_account?
create_account_for_user create_account_for_user
token = @resource.send(:set_reset_password_token) token = @resource.send(:set_reset_password_token)
@@ -53,11 +53,9 @@ class DeviseOverrides::OmniauthCallbacksController < DeviseTokenAuth::OmniauthCa
).first ).first
end end
def validate_signup_email_is_business_domain? def validate_business_account?
# return true if the user is a business account, false if it is a blocked domain account # return true if the user is a business account, false if it is a gmail account
Account::SignUpEmailValidationService.new(auth_hash['info']['email']).perform auth_hash['info']['email'].downcase.exclude?('@gmail.com')
rescue CustomExceptions::Account::InvalidEmail
false
end end
def create_account_for_user def create_account_for_user
@@ -1,9 +1,9 @@
class Platform::Api::V1::UsersController < PlatformController class Platform::Api::V1::UsersController < PlatformController
# ref: https://stackoverflow.com/a/45190318/939299 # ref: https://stackoverflow.com/a/45190318/939299
# set resource is called for other actions already in platform controller # set resource is called for other actions already in platform controller
# we want to add login and token to that chain as well # we want to add login to that chain as well
before_action(only: [:login, :token]) { set_resource } before_action(only: [:login]) { set_resource }
before_action(only: [:login, :token]) { validate_platform_app_permissible } before_action(only: [:login]) { validate_platform_app_permissible }
def show; end def show; end
@@ -18,8 +18,6 @@ class Platform::Api::V1::UsersController < PlatformController
render json: { url: @resource.generate_sso_link } render json: { url: @resource.generate_sso_link }
end end
def token; end
def update def update
@resource.assign_attributes(user_update_params) @resource.assign_attributes(user_update_params)
@@ -24,10 +24,9 @@ class Twilio::CallbackController < ApplicationController
:Body, :Body,
:ToCountry, :ToCountry,
:FromState, :FromState,
*Array.new(10) { |i| :"MediaUrl#{i}" }, :MediaUrl0,
*Array.new(10) { |i| :"MediaContentType#{i}" }, :MediaContentType0,
:MessagingServiceSid, :MessagingServiceSid
:NumMedia
) )
end end
end end
+1 -4
View File
@@ -88,10 +88,7 @@ class ConversationFinder
def find_conversation_by_inbox def find_conversation_by_inbox
@conversations = current_account.conversations @conversations = current_account.conversations
@conversations = @conversations.where(inbox_id: @inbox_ids) unless params[:inbox_id].blank? && @is_admin
return unless params[:inbox_id]
@conversations = @conversations.where(inbox_id: @inbox_ids)
end end
def find_all_conversations def find_all_conversations
@@ -134,6 +134,10 @@ class ConversationApi extends ApiClient {
return axios.get(`${this.url}/${conversationId}/attachments`); return axios.get(`${this.url}/${conversationId}/attachments`);
} }
requestCopilot(conversationId, body) {
return axios.post(`${this.url}/${conversationId}/copilot`, body);
}
getInboxAssistant(conversationId) { getInboxAssistant(conversationId) {
return axios.get(`${this.url}/${conversationId}/inbox_assistant`); return axios.get(`${this.url}/${conversationId}/inbox_assistant`);
} }
@@ -3,7 +3,7 @@
} }
.tabs--container--with-border { .tabs--container--with-border {
@apply border-b border-b-n-weak; @apply border-b border-n-weak;
} }
.tabs--container--compact.tab--chat-type { .tabs--container--compact.tab--chat-type {
@@ -1,65 +0,0 @@
<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useToggle } from '@vueuse/core';
import Button from 'dashboard/components-next/button/Button.vue';
import ConfirmContactDeleteDialog from 'dashboard/components-next/Contacts/ContactsForm/ConfirmContactDeleteDialog.vue';
defineProps({
selectedContact: {
type: Object,
required: true,
},
});
const { t } = useI18n();
const [showDeleteSection, toggleDeleteSection] = useToggle();
const confirmDeleteContactDialogRef = ref(null);
const openConfirmDeleteContactDialog = () => {
confirmDeleteContactDialogRef.value?.dialogRef.open();
};
</script>
<template>
<div class="flex flex-col items-start border-t border-n-strong px-6 py-5">
<Button
:label="t('CONTACTS_LAYOUT.DETAILS.DELETE_CONTACT')"
sm
link
slate
class="hover:!no-underline text-n-slate-12"
icon="i-lucide-chevron-down"
trailing-icon
@click="toggleDeleteSection()"
/>
<div
class="transition-all duration-300 ease-in-out grid w-full overflow-hidden"
:class="
showDeleteSection
? 'grid-rows-[1fr] opacity-100 mt-2'
: 'grid-rows-[0fr] opacity-0 mt-0'
"
>
<div class="overflow-hidden min-h-0">
<span class="inline-flex text-n-slate-11 text-sm items-center gap-1">
{{ t('CONTACTS_LAYOUT.CARD.DELETE_CONTACT.MESSAGE') }}
<Button
:label="t('CONTACTS_LAYOUT.CARD.DELETE_CONTACT.BUTTON')"
sm
ruby
link
@click="openConfirmDeleteContactDialog()"
/>
</span>
</div>
</div>
</div>
<ConfirmContactDeleteDialog
ref="confirmDeleteContactDialogRef"
:selected-contact="selectedContact"
/>
</template>
@@ -7,7 +7,6 @@ import ContactsForm from 'dashboard/components-next/Contacts/ContactsForm/Contac
import Button from 'dashboard/components-next/button/Button.vue'; import Button from 'dashboard/components-next/button/Button.vue';
import Avatar from 'dashboard/components-next/avatar/Avatar.vue'; import Avatar from 'dashboard/components-next/avatar/Avatar.vue';
import Flag from 'dashboard/components-next/flag/Flag.vue'; import Flag from 'dashboard/components-next/flag/Flag.vue';
import ContactDeleteSection from 'dashboard/components-next/Contacts/ContactsCard/ContactDeleteSection.vue';
import countries from 'shared/constants/countries'; import countries from 'shared/constants/countries';
const props = defineProps({ const props = defineProps({
@@ -150,15 +149,15 @@ const onClickViewDetails = () => emit('showContact', props.id);
/> />
<template #after> <template #after>
<div <transition
class="transition-all duration-500 ease-in-out grid overflow-hidden" enter-active-class="overflow-hidden transition-all duration-300 ease-out"
:class=" leave-active-class="overflow-hidden transition-all duration-300 ease-in"
isExpanded enter-from-class="overflow-hidden opacity-0 max-h-0"
? 'grid-rows-[1fr] opacity-100' enter-to-class="opacity-100 max-h-[690px] sm:max-h-[470px] md:max-h-[410px]"
: 'grid-rows-[0fr] opacity-0' leave-from-class="opacity-100 max-h-[690px] sm:max-h-[470px] md:max-h-[410px]"
" leave-to-class="overflow-hidden opacity-0 max-h-0"
> >
<div class="overflow-hidden"> <div v-show="isExpanded" class="w-full">
<div class="flex flex-col gap-6 p-6 border-t border-n-strong"> <div class="flex flex-col gap-6 p-6 border-t border-n-strong">
<ContactsForm <ContactsForm
ref="contactsFormRef" ref="contactsFormRef"
@@ -177,14 +176,8 @@ const onClickViewDetails = () => emit('showContact', props.id);
/> />
</div> </div>
</div> </div>
<ContactDeleteSection
:selected-contact="{
id: props.id,
name: props.name,
}"
/>
</div> </div>
</div> </transition>
</template> </template>
</CardLayout> </CardLayout>
</template> </template>
@@ -47,7 +47,11 @@ defineExpose({ dialogRef });
ref="dialogRef" ref="dialogRef"
type="alert" type="alert"
:title="t('CONTACTS_LAYOUT.DETAILS.DELETE_DIALOG.TITLE')" :title="t('CONTACTS_LAYOUT.DETAILS.DELETE_DIALOG.TITLE')"
:description="t('CONTACTS_LAYOUT.DETAILS.DELETE_DIALOG.DESCRIPTION')" :description="
t('CONTACTS_LAYOUT.DETAILS.DELETE_DIALOG.DESCRIPTION', {
contactName: props.selectedContact.name,
})
"
:confirm-button-label="t('CONTACTS_LAYOUT.DETAILS.DELETE_DIALOG.CONFIRM')" :confirm-button-label="t('CONTACTS_LAYOUT.DETAILS.DELETE_DIALOG.CONFIRM')"
@confirm="handleDialogConfirm" @confirm="handleDialogConfirm"
/> />
@@ -200,7 +200,6 @@ defineExpose({ state, isSubmitDisabled });
:label="state.icon" :label="state.icon"
color="slate" color="slate"
size="sm" size="sm"
type="button"
:icon="!state.icon ? 'i-lucide-smile-plus' : ''" :icon="!state.icon ? 'i-lucide-smile-plus' : ''"
class="!h-[2.4rem] !w-[2.375rem] absolute top-[1.94rem] !outline-none !rounded-[0.438rem] border-0 ltr:left-px rtl:right-px ltr:!rounded-r-none rtl:!rounded-l-none" class="!h-[2.4rem] !w-[2.375rem] absolute top-[1.94rem] !outline-none !rounded-[0.438rem] border-0 ltr:left-px rtl:right-px ltr:!rounded-r-none rtl:!rounded-l-none"
@click="isEmojiPickerOpen = !isEmojiPickerOpen" @click="isEmojiPickerOpen = !isEmojiPickerOpen"
@@ -117,7 +117,7 @@ const STYLE_CONFIG = {
'text-n-ruby-11 hover:enabled:bg-n-ruby-9/10 focus-visible:bg-n-ruby-9/10 outline-n-ruby-8', 'text-n-ruby-11 hover:enabled:bg-n-ruby-9/10 focus-visible:bg-n-ruby-9/10 outline-n-ruby-8',
ghost: ghost:
'text-n-ruby-11 hover:enabled:bg-n-alpha-2 focus-visible:bg-n-alpha-2 outline-transparent', 'text-n-ruby-11 hover:enabled:bg-n-alpha-2 focus-visible:bg-n-alpha-2 outline-transparent',
link: 'text-n-ruby-9 dark:text-n-ruby-11 hover:enabled:underline focus-visible:underline outline-transparent', link: 'text-n-ruby-9 hover:enabled:underline focus-visible:underline outline-transparent',
}, },
amber: { amber: {
solid: solid:
@@ -100,10 +100,7 @@ const handleBasicInfoUpdate = async () => {
const payload = { const payload = {
name: state.name, name: state.name,
description: state.description, description: state.description,
config: { product_name: state.productName,
...props.assistant.config,
product_name: state.productName,
},
}; };
emit('submit', payload); emit('submit', payload);
@@ -1,5 +1,6 @@
<script setup> <script setup>
import { nextTick, ref, watch, computed } from 'vue'; import { nextTick, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useTrack } from 'dashboard/composables'; import { useTrack } from 'dashboard/composables';
import { COPILOT_EVENTS } from 'dashboard/helper/AnalyticsHelper/events'; import { COPILOT_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
@@ -7,10 +8,8 @@ import CopilotInput from './CopilotInput.vue';
import CopilotLoader from './CopilotLoader.vue'; import CopilotLoader from './CopilotLoader.vue';
import CopilotAgentMessage from './CopilotAgentMessage.vue'; import CopilotAgentMessage from './CopilotAgentMessage.vue';
import CopilotAssistantMessage from './CopilotAssistantMessage.vue'; import CopilotAssistantMessage from './CopilotAssistantMessage.vue';
import CopilotThinkingGroup from './CopilotThinkingGroup.vue';
import ToggleCopilotAssistant from './ToggleCopilotAssistant.vue'; import ToggleCopilotAssistant from './ToggleCopilotAssistant.vue';
import CopilotHeader from './CopilotHeader.vue'; import Icon from '../icon/Icon.vue';
import CopilotEmptyState from './CopilotEmptyState.vue';
const props = defineProps({ const props = defineProps({
supportAgent: { supportAgent: {
@@ -27,7 +26,7 @@ const props = defineProps({
}, },
conversationInboxType: { conversationInboxType: {
type: String, type: String,
default: '', required: true,
}, },
assistants: { assistants: {
type: Array, type: Array,
@@ -39,13 +38,22 @@ const props = defineProps({
}, },
}); });
const emit = defineEmits(['sendMessage', 'reset', 'setAssistant', 'close']); const emit = defineEmits(['sendMessage', 'reset', 'setAssistant']);
const { t } = useI18n();
const COPILOT_USER_ROLES = ['assistant', 'system'];
const sendMessage = message => { const sendMessage = message => {
emit('sendMessage', message); emit('sendMessage', message);
useTrack(COPILOT_EVENTS.SEND_MESSAGE); useTrack(COPILOT_EVENTS.SEND_MESSAGE);
}; };
const useSuggestion = opt => {
emit('sendMessage', t(opt.prompt));
useTrack(COPILOT_EVENTS.SEND_SUGGESTED);
};
const handleReset = () => { const handleReset = () => {
emit('reset'); emit('reset');
}; };
@@ -59,28 +67,20 @@ const scrollToBottom = async () => {
} }
}; };
const groupedMessages = computed(() => { const promptOptions = [
const result = []; {
let thinkingGroup = []; label: 'CAPTAIN.COPILOT.PROMPTS.SUMMARIZE.LABEL',
prompt: 'CAPTAIN.COPILOT.PROMPTS.SUMMARIZE.CONTENT',
props.messages.forEach(message => { },
if (message.role === 'assistant_thinking') { {
thinkingGroup.push(message); label: 'CAPTAIN.COPILOT.PROMPTS.SUGGEST.LABEL',
} else { prompt: 'CAPTAIN.COPILOT.PROMPTS.SUGGEST.CONTENT',
if (thinkingGroup.length > 0) { },
result.push({ type: 'thinking_group', messages: thinkingGroup }); {
thinkingGroup = []; label: 'CAPTAIN.COPILOT.PROMPTS.RATE.LABEL',
} prompt: 'CAPTAIN.COPILOT.PROMPTS.RATE.CONTENT',
result.push({ type: 'message', message }); },
} ];
});
if (thinkingGroup.length > 0) {
result.push({ type: 'thinking_group', messages: thinkingGroup });
}
return result;
});
watch( watch(
[() => props.messages, () => props.isCaptainTyping], [() => props.messages, () => props.isCaptainTyping],
@@ -93,62 +93,60 @@ watch(
<template> <template>
<div class="flex flex-col h-full text-sm leading-6 tracking-tight w-full"> <div class="flex flex-col h-full text-sm leading-6 tracking-tight w-full">
<CopilotHeader <div ref="chatContainer" class="flex-1 px-4 py-4 space-y-6 overflow-y-auto">
:has-messages="messages.length > 0" <template v-for="message in messages" :key="message.id">
@reset="handleReset" <CopilotAgentMessage
@close="$emit('close')" v-if="message.role === 'user'"
/> :support-agent="supportAgent"
<div :message="message"
ref="chatContainer" />
class="flex-1 flex px-4 py-4 overflow-y-auto items-start" <CopilotAssistantMessage
> v-else-if="COPILOT_USER_ROLES.includes(message.role)"
<div v-if="messages.length" class="space-y-6 flex-1 flex flex-col w-full"> :message="message"
<template :conversation-inbox-type="conversationInboxType"
v-for="item in groupedMessages" />
:key="item.type === 'message' ? item.message.id : 'thinking-group'" </template>
>
<template v-if="item.type === 'message'">
<CopilotAgentMessage
v-if="item.message.role === 'user'"
:support-agent="supportAgent"
:message="item.message"
/>
<CopilotAssistantMessage
v-else-if="
item.message.role === 'assistant' ||
item.message.role === 'system'
"
:message="item.message"
:conversation-inbox-type="conversationInboxType"
/>
</template>
<CopilotThinkingGroup
v-else
:messages="item.messages"
:has-assistant-message-after="
groupedMessages[groupedMessages.indexOf(item) + 1]?.message
?.role === 'assistant'
"
/>
</template>
<CopilotLoader v-if="isCaptainTyping" /> <CopilotLoader v-if="isCaptainTyping" />
</div>
<div
v-if="!messages.length"
class="h-full w-full flex items-center justify-center"
>
<div class="h-fit px-3 py-3 space-y-1">
<span class="text-xs text-n-slate-10">
{{ $t('COPILOT.TRY_THESE_PROMPTS') }}
</span>
<button
v-for="prompt in promptOptions"
:key="prompt.label"
class="px-2 py-1 rounded-md border border-n-weak bg-n-slate-2 text-n-slate-11 flex items-center gap-1"
@click="() => useSuggestion(prompt)"
>
<span>{{ t(prompt.label) }}</span>
<Icon icon="i-lucide-chevron-right" />
</button>
</div> </div>
<CopilotEmptyState
v-if="!messages.length"
@use-suggestion="sendMessage"
/>
</div> </div>
<div class="mx-3 mt-px mb-2"> <div class="mx-3 mt-px mb-2">
<div class="flex items-center gap-2 justify-between w-full mb-1"> <div class="flex items-center gap-2 justify-between w-full mb-1">
<ToggleCopilotAssistant <ToggleCopilotAssistant
v-if="assistants.length > 1" v-if="assistants.length"
:assistants="assistants" :assistants="assistants"
:active-assistant="activeAssistant" :active-assistant="activeAssistant"
@set-assistant="$event => emit('setAssistant', $event)" @set-assistant="$event => emit('setAssistant', $event)"
/> />
<div v-else /> <div v-else />
<button
v-if="messages.length"
class="text-xs flex items-center gap-1 hover:underline"
@click="handleReset"
>
<i class="i-lucide-refresh-ccw" />
<span>{{ $t('CAPTAIN.COPILOT.RESET') }}</span>
</button>
</div> </div>
<CopilotInput class="mb-1 w-full" @send="sendMessage" /> <CopilotInput class="mb-1 w-full" @send="sendMessage" />
</div> </div>
@@ -1,17 +1,31 @@
<script setup> <script setup>
import Avatar from '../avatar/Avatar.vue';
defineProps({ defineProps({
message: { message: {
type: Object, type: Object,
required: true, required: true,
}, },
supportAgent: {
type: Object,
required: true,
},
}); });
</script> </script>
<template> <template>
<div class="space-y-1 text-n-slate-12"> <div class="flex flex-row gap-2">
<div class="font-medium">{{ $t('CAPTAIN.COPILOT.YOU') }}</div> <Avatar
<div class="break-words"> :name="supportAgent.available_name"
{{ message.content }} :src="supportAgent.avatar_url"
:size="24"
rounded-full
/>
<div class="space-y-1 text-n-slate-12">
<div class="font-medium">{{ $t('CAPTAIN.COPILOT.YOU') }}</div>
<div class="break-words">
{{ message.content }}
</div>
</div> </div>
</div> </div>
</template> </template>
@@ -9,6 +9,7 @@ import { COPILOT_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
import MessageFormatter from 'shared/helpers/MessageFormatter.js'; import MessageFormatter from 'shared/helpers/MessageFormatter.js';
import Button from 'dashboard/components-next/button/Button.vue'; import Button from 'dashboard/components-next/button/Button.vue';
import Avatar from '../avatar/Avatar.vue';
const props = defineProps({ const props = defineProps({
message: { message: {
@@ -17,7 +18,7 @@ const props = defineProps({
}, },
conversationInboxType: { conversationInboxType: {
type: String, type: String,
default: '', required: true,
}, },
}); });
@@ -45,25 +46,33 @@ const useCopilotResponse = () => {
</script> </script>
<template> <template>
<div class="flex flex-col gap-1 text-n-slate-12"> <div class="flex flex-row gap-2">
<div class="font-medium">{{ $t('CAPTAIN.NAME') }}</div> <Avatar
<span v-if="hasEmptyMessageContent" class="text-n-ruby-11"> name="Captain Copilot"
{{ $t('CAPTAIN.COPILOT.EMPTY_MESSAGE') }} icon-name="i-woot-captain"
</span> :size="24"
<div rounded-full
v-else
v-dompurify-html="messageContent"
class="prose-sm break-words"
/> />
<div class="flex flex-row mt-1"> <div class="flex flex-col gap-1 text-n-slate-12">
<Button <div class="font-medium">{{ $t('CAPTAIN.NAME') }}</div>
v-if="!hasEmptyMessageContent" <span v-if="hasEmptyMessageContent" class="text-n-ruby-11">
:label="$t('CAPTAIN.COPILOT.USE')" {{ $t('CAPTAIN.COPILOT.EMPTY_MESSAGE') }}
faded </span>
sm <div
slate v-else
@click="useCopilotResponse" v-dompurify-html="messageContent"
class="prose-sm break-words"
/> />
<div class="flex flex-row mt-1">
<Button
v-if="!hasEmptyMessageContent"
:label="$t('CAPTAIN.COPILOT.USE')"
faded
sm
slate
@click="useCopilotResponse"
/>
</div>
</div> </div>
</div> </div>
</template> </template>
@@ -1,91 +0,0 @@
<script setup>
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import Icon from '../icon/Icon.vue';
const emit = defineEmits(['useSuggestion']);
const { t } = useI18n();
const route = useRoute();
const routePromptMap = {
conversations: [
{
label: 'CAPTAIN.COPILOT.PROMPTS.SUMMARIZE.LABEL',
prompt: 'CAPTAIN.COPILOT.PROMPTS.SUMMARIZE.CONTENT',
},
{
label: 'CAPTAIN.COPILOT.PROMPTS.SUGGEST.LABEL',
prompt: 'CAPTAIN.COPILOT.PROMPTS.SUGGEST.CONTENT',
},
{
label: 'CAPTAIN.COPILOT.PROMPTS.RATE.LABEL',
prompt: 'CAPTAIN.COPILOT.PROMPTS.RATE.CONTENT',
},
],
dashboard: [
{
label: 'High priority conversations',
prompt: 'Get me a summary of all high priority open conversations',
},
{
label: 'List contacts',
prompt: 'Show me the list of contacts',
},
{
label: 'Summarize articles',
prompt: 'List articles that are in draft',
},
],
};
const getCurrentRoute = () => {
const path = route.path;
if (path.includes('/conversations')) return 'conversations';
if (path.includes('/dashboard')) return 'dashboard';
if (path.includes('/contacts')) return 'contacts';
if (path.includes('/articles')) return 'articles';
return 'dashboard';
};
const promptOptions = computed(() => {
const currentRoute = getCurrentRoute();
return routePromptMap[currentRoute] || routePromptMap.conversations;
});
const handleSuggestion = opt => {
emit('useSuggestion', t(opt.prompt));
};
</script>
<template>
<div class="flex-1 flex flex-col gap-6 px-2">
<div class="flex flex-col space-y-4 py-4">
<Icon icon="i-woot-captain" class="text-n-slate-9 text-4xl" />
<div class="space-y-1">
<h3 class="text-base font-medium text-n-slate-12 leading-8">
{{ $t('CAPTAIN.COPILOT.PANEL_TITLE') }}
</h3>
<p class="text-sm text-n-slate-11 leading-6">
{{ $t('CAPTAIN.COPILOT.KICK_OFF_MESSAGE') }}
</p>
</div>
</div>
<div class="w-full space-y-2">
<span class="text-xs text-n-slate-10 block">
{{ $t('CAPTAIN.COPILOT.TRY_THESE_PROMPTS') }}
</span>
<div class="space-y-1">
<button
v-for="prompt in promptOptions"
:key="prompt.label"
class="w-full px-3 py-2 rounded-md border border-n-weak bg-n-slate-2 text-n-slate-11 flex items-center justify-between hover:bg-n-slate-3 transition-colors"
@click="handleSuggestion(prompt)"
>
<span>{{ t(prompt.label) }}</span>
<Icon icon="i-lucide-chevron-right" />
</button>
</div>
</div>
</div>
</template>
@@ -1,21 +0,0 @@
<script setup>
import CopilotHeader from './CopilotHeader.vue';
</script>
<template>
<Story
title="Captain/Copilot/CopilotHeader"
:layout="{ type: 'grid', width: '800px' }"
>
<!-- Default State -->
<Variant title="Default State">
<CopilotHeader />
</Variant>
<!-- With New Conversation Button -->
<Variant title="With New Conversation Button">
<!-- eslint-disable-next-line vue/prefer-true-attribute-shorthand -->
<CopilotHeader :has-messages="true" />
</Variant>
</Story>
</template>
@@ -1,32 +0,0 @@
<script setup>
import Button from '../button/Button.vue';
defineProps({
hasMessages: {
type: Boolean,
default: false,
},
});
defineEmits(['reset', 'close']);
</script>
<template>
<div
class="flex items-center justify-between px-4 py-2 border-b border-n-weak h-12"
>
<div class="flex items-center justify-between gap-2 flex-1">
<span class="font-medium text-sm text-n-slate-12">
{{ $t('CAPTAIN.COPILOT.TITLE') }}
</span>
<div class="flex items-center">
<Button
v-if="hasMessages"
icon="i-lucide-plus"
ghost
sm
@click="$emit('reset')"
/>
<Button icon="i-lucide-x" ghost sm @click="$emit('close')" />
</div>
</div>
</div>
</template>
@@ -13,16 +13,19 @@ const sendMessage = () => {
</script> </script>
<template> <template>
<form class="relative" @submit.prevent="sendMessage"> <form
class="border border-n-weak bg-n-alpha-3 rounded-lg h-12 flex"
@submit.prevent="sendMessage"
>
<input <input
v-model="message" v-model="message"
type="text" type="text"
:placeholder="$t('CAPTAIN.COPILOT.SEND_MESSAGE')" :placeholder="$t('CAPTAIN.COPILOT.SEND_MESSAGE')"
class="w-full reset-base bg-n-alpha-3 ltr:pl-4 ltr:pr-12 rtl:pl-12 rtl:pr-4 py-3 text-n-slate-11 text-sm border border-n-weak rounded-lg focus:outline-none focus:ring-1 focus:ring-n-blue-11 focus:border-n-blue-11" class="w-full reset-base bg-transparent px-4 py-3 text-n-slate-11 text-sm"
@keyup.enter="sendMessage" @keyup.enter="sendMessage"
/> />
<button <button
class="absolute ltr:right-1 rtl:left-1 top-1/2 -translate-y-1/2 h-9 w-10 flex items-center justify-center text-n-slate-11 hover:text-n-blue-11" class="h-auto w-12 flex items-center justify-center text-n-slate-11"
type="submit" type="submit"
> >
<i class="i-ph-arrow-up" /> <i class="i-ph-arrow-up" />
@@ -1,47 +0,0 @@
<script setup>
import { computed } from 'vue';
import { useStore } from 'vuex';
import { useRoute } from 'vue-router';
import Button from 'dashboard/components-next/button/Button.vue';
import { useMapGetter } from 'dashboard/composables/store';
const store = useStore();
const route = useRoute();
const getUIState = useMapGetter('uiState/getUIState');
const isSidebarOpen = computed(() => getUIState.value('isCopilotSidebarOpen'));
const isConversationRoute = computed(() => {
const CONVERSATION_ROUTES = [
'inbox_conversation',
'conversation_through_inbox',
'conversations_through_label',
'team_conversations_through_label',
'conversations_through_folders',
'conversation_through_mentions',
'conversation_through_unattended',
'conversation_through_participating',
];
return CONVERSATION_ROUTES.includes(route.name);
});
const toggleSidebar = () => {
store.dispatch('uiState/toggle', 'isCopilotSidebarOpen');
};
</script>
<template>
<div class="fixed bottom-4 right-4 z-50">
<div
v-if="!isSidebarOpen && !isConversationRoute"
class="rounded-full bg-n-solid-2 p-2 hover:bg-n-solid-3"
>
<Button
icon="i-woot-captain"
class="!rounded-full !bg-n-alpha-2 text-n-slate-12 text-xl"
lg
@click="toggleSidebar"
/>
</div>
</div>
</template>
@@ -1,25 +0,0 @@
<script setup>
import Icon from '../../components-next/icon/Icon.vue';
defineProps({
content: {
type: String,
required: true,
},
});
</script>
<template>
<div
class="flex flex-col gap-2 p-3 rounded-lg bg-n-background/50 border border-n-weak hover:bg-n-background/80 transition-colors duration-200"
>
<div class="flex items-start gap-2">
<Icon
icon="i-lucide-sparkles"
class="w-4 h-4 mt-0.5 flex-shrink-0 text-n-slate-9"
/>
<div class="text-sm text-n-slate-11">
{{ content }}
</div>
</div>
</div>
</template>
@@ -1,34 +0,0 @@
<script setup>
import CopilotThinkingGroup from './CopilotThinkingGroup.vue';
const messages = [
{
id: 1,
content: 'Analyzing the user query',
reasoning: 'Breaking down the request into actionable steps',
},
{
id: 2,
content: 'Searching codebase',
reasoning: 'Looking for relevant files and functions',
},
{
id: 3,
content: 'Generating response',
reasoning: 'Composing a helpful and accurate answer',
},
];
</script>
<template>
<Story title="Captain/Copilot/CopilotThinkingGroup" group="components">
<Variant title="Default">
<CopilotThinkingGroup :messages="messages" />
</Variant>
<Variant title="With Default Collapsed">
<!-- eslint-disable-next-line -->
<CopilotThinkingGroup :messages="messages" :default-collapsed="true" />
</Variant>
</Story>
</template>
@@ -1,61 +0,0 @@
<script setup>
import { ref, watch, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import Icon from '../icon/Icon.vue';
import CopilotThinkingBlock from './CopilotThinkingBlock.vue';
const props = defineProps({
messages: { type: Array, required: true },
defaultCollapsed: { type: Boolean, default: false },
});
const { t } = useI18n();
const isExpanded = ref(!props.defaultCollapsed);
const thinkingCount = computed(() => props.messages.length);
watch(
() => props.defaultCollapsed,
newValue => {
if (newValue) {
isExpanded.value = false;
}
}
);
</script>
<template>
<div class="flex flex-col gap-2">
<button
class="group flex items-center gap-2 text-xs text-n-slate-10 hover:text-n-slate-11 transition-colors duration-200 -ml-3"
@click="isExpanded = !isExpanded"
>
<Icon
:icon="isExpanded ? 'i-lucide-chevron-down' : 'i-lucide-chevron-right'"
class="w-4 h-4 transition-transform duration-200 group-hover:scale-110"
/>
<span class="flex items-center gap-2">
{{ t('CAPTAIN.COPILOT.SHOW_STEPS') }}
<span
class="inline-flex items-center justify-center h-4 min-w-4 px-1 text-xs font-medium rounded-full bg-n-solid-3 text-n-slate-11"
>
{{ thinkingCount }}
</span>
</span>
</button>
<div
v-show="isExpanded"
class="space-y-3 transition-all duration-200"
:class="{
'opacity-100': isExpanded,
'opacity-0 max-h-0 overflow-hidden': !isExpanded,
}"
>
<CopilotThinkingBlock
v-for="message in messages"
:key="message.id"
:content="message.content"
:reasoning="message.reasoning"
/>
</div>
</div>
</template>
@@ -81,7 +81,6 @@ onMounted(() => {
<button <button
v-for="(item, index) in filteredMenuItems" v-for="(item, index) in filteredMenuItems"
:key="index" :key="index"
type="button"
class="inline-flex items-center justify-start w-full h-8 min-w-0 gap-2 px-2 py-1.5 transition-all duration-200 ease-in-out border-0 rounded-lg z-60 hover:bg-n-alpha-1 dark:hover:bg-n-alpha-2 disabled:cursor-not-allowed disabled:pointer-events-none disabled:opacity-50" class="inline-flex items-center justify-start w-full h-8 min-w-0 gap-2 px-2 py-1.5 transition-all duration-200 ease-in-out border-0 rounded-lg z-60 hover:bg-n-alpha-1 dark:hover:bg-n-alpha-2 disabled:cursor-not-allowed disabled:pointer-events-none disabled:opacity-50"
:class="{ :class="{
'bg-n-alpha-1 dark:bg-n-solid-active': item.isSelected, 'bg-n-alpha-1 dark:bg-n-solid-active': item.isSelected,
@@ -1,6 +1,5 @@
<script setup> <script setup>
import { computed, ref } from 'vue'; import { computed } from 'vue';
import { useElementBounding, useWindowSize } from '@vueuse/core';
import DropdownContainer from 'next/dropdown-menu/base/DropdownContainer.vue'; import DropdownContainer from 'next/dropdown-menu/base/DropdownContainer.vue';
import DropdownSection from 'next/dropdown-menu/base/DropdownSection.vue'; import DropdownSection from 'next/dropdown-menu/base/DropdownSection.vue';
import DropdownBody from 'next/dropdown-menu/base/DropdownBody.vue'; import DropdownBody from 'next/dropdown-menu/base/DropdownBody.vue';
@@ -26,10 +25,6 @@ const props = defineProps({
type: String, type: String,
default: 'faded', default: 'faded',
}, },
label: {
type: String,
default: null,
},
}); });
const selected = defineModel({ const selected = defineModel({
@@ -37,13 +32,6 @@ const selected = defineModel({
required: true, required: true,
}); });
const triggerRef = ref(null);
const dropdownRef = ref(null);
const { top } = useElementBounding(triggerRef);
const { height } = useWindowSize();
const { height: dropdownHeight } = useElementBounding(dropdownRef);
const selectedOption = computed(() => { const selectedOption = computed(() => {
return props.options.find(o => o.value === selected.value) || {}; return props.options.find(o => o.value === selected.value) || {};
}); });
@@ -53,16 +41,6 @@ const iconToRender = computed(() => {
return selectedOption.value.icon || 'i-lucide-chevron-down'; return selectedOption.value.icon || 'i-lucide-chevron-down';
}); });
const dropdownPosition = computed(() => {
const DROPDOWN_MAX_HEIGHT = 340;
// Get actual height if available or use default
const menuHeight = dropdownHeight.value
? dropdownHeight.value + 20
: DROPDOWN_MAX_HEIGHT;
const spaceBelow = height.value - top.value;
return spaceBelow < menuHeight ? 'bottom-0' : 'top-0';
});
const updateSelected = newValue => { const updateSelected = newValue => {
selected.value = newValue; selected.value = newValue;
}; };
@@ -73,23 +51,17 @@ const updateSelected = newValue => {
<template #trigger="{ toggle }"> <template #trigger="{ toggle }">
<slot name="trigger" :toggle="toggle"> <slot name="trigger" :toggle="toggle">
<Button <Button
ref="triggerRef"
sm sm
slate slate
:variant :variant
:icon="iconToRender" :icon="iconToRender"
:trailing-icon="selectedOption.icon ? false : true" :trailing-icon="selectedOption.icon ? false : true"
:label="label || (hideLabel ? null : selectedOption.label)" :label="hideLabel ? null : selectedOption.label"
@click="toggle" @click="toggle"
/> />
</slot> </slot>
</template> </template>
<DropdownBody <DropdownBody class="top-0 min-w-48 z-50" strong>
ref="dropdownRef"
class="min-w-48 z-50"
:class="dropdownPosition"
strong
>
<DropdownSection class="max-h-80 overflow-scroll"> <DropdownSection class="max-h-80 overflow-scroll">
<DropdownItem <DropdownItem
v-for="option in options" v-for="option in options"
@@ -186,20 +186,12 @@ const isBotOrAgentMessage = computed(() => {
return true; return true;
} }
const senderId = props.senderId ?? props.sender?.id; const senderId = props.senderId ?? props.sender?.id;
const senderType = props.sender?.type ?? props.senderType; const senderType = props.senderType ?? props.sender?.type;
if (!senderType || !senderId) { if (!senderType || !senderId) {
return true; return true;
} }
if (
[SENDER_TYPES.AGENT_BOT, SENDER_TYPES.CAPTAIN_ASSISTANT].includes(
senderType
)
) {
return true;
}
return senderType.toLowerCase() === SENDER_TYPES.USER.toLowerCase(); return senderType.toLowerCase() === SENDER_TYPES.USER.toLowerCase();
}); });
@@ -414,7 +406,7 @@ const avatarInfo = computed(() => {
const { name, type, avatarUrl, thumbnail } = sender || {}; const { name, type, avatarUrl, thumbnail } = sender || {};
// If sender type is agent bot, use avatarUrl // If sender type is agent bot, use avatarUrl
if ([SENDER_TYPES.AGENT_BOT, SENDER_TYPES.CAPTAIN_ASSISTANT].includes(type)) { if (type === SENDER_TYPES.AGENT_BOT) {
return { return {
name: name ?? '', name: name ?? '',
src: avatarUrl ?? '', src: avatarUrl ?? '',
@@ -2,10 +2,10 @@
import { computed } from 'vue'; import { computed } from 'vue';
import BaseBubble from './Base.vue'; import BaseBubble from './Base.vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { CSAT_RATINGS, CSAT_DISPLAY_TYPES } from 'shared/constants/messages'; import { CSAT_RATINGS } from 'shared/constants/messages';
import { useMessageContext } from '../provider.js'; import { useMessageContext } from '../provider.js';
const { contentAttributes, content } = useMessageContext(); const { contentAttributes } = useMessageContext();
const { t } = useI18n(); const { t } = useI18n();
const response = computed(() => { const response = computed(() => {
@@ -16,14 +16,6 @@ const isRatingSubmitted = computed(() => {
return !!response.value.rating; return !!response.value.rating;
}); });
const displayType = computed(() => {
return contentAttributes.value?.displayType || CSAT_DISPLAY_TYPES.EMOJI;
});
const isStarRating = computed(() => {
return displayType.value === CSAT_DISPLAY_TYPES.STAR;
});
const rating = computed(() => { const rating = computed(() => {
if (isRatingSubmitted.value) { if (isRatingSubmitted.value) {
return CSAT_RATINGS.find( return CSAT_RATINGS.find(
@@ -33,33 +25,16 @@ const rating = computed(() => {
return null; return null;
}); });
const starRatingValue = computed(() => {
return response.value.rating || 0;
});
</script> </script>
<template> <template>
<BaseBubble class="px-4 py-3" data-bubble-name="csat"> <BaseBubble class="px-4 py-3" data-bubble-name="csat">
<h4>{{ content || t('CONVERSATION.CSAT_REPLY_MESSAGE') }}</h4> <h4>{{ t('CONVERSATION.CSAT_REPLY_MESSAGE') }}</h4>
<dl v-if="isRatingSubmitted" class="mt-4"> <dl v-if="isRatingSubmitted" class="mt-4">
<dt class="text-n-slate-11 italic"> <dt class="text-n-slate-11 italic">
{{ t('CONVERSATION.RATING_TITLE') }} {{ t('CONVERSATION.RATING_TITLE') }}
</dt> </dt>
<dd v-if="!isStarRating"> <dd>{{ t(rating.translationKey) }}</dd>
{{ t(rating.translationKey) }}
</dd>
<dd v-else class="flex mt-1">
<span v-for="n in 5" :key="n" class="text-2xl mr-1">
<i
:class="[
n <= starRatingValue
? 'i-ri-star-fill text-n-amber-9'
: 'i-ri-star-line text-n-slate-10',
]"
/>
</span>
</dd>
<dt v-if="response.feedbackMessage" class="text-n-slate-11 italic mt-2"> <dt v-if="response.feedbackMessage" class="text-n-slate-11 italic mt-2">
{{ t('CONVERSATION.FEEDBACK_TITLE') }} {{ t('CONVERSATION.FEEDBACK_TITLE') }}
@@ -21,7 +21,6 @@ export const SENDER_TYPES = {
CONTACT: 'Contact', CONTACT: 'Contact',
USER: 'User', USER: 'User',
AGENT_BOT: 'agent_bot', AGENT_BOT: 'agent_bot',
CAPTAIN_ASSISTANT: 'captain_assistant',
}; };
export const ORIENTATION = { export const ORIENTATION = {
@@ -185,7 +185,6 @@ watch(
" "
trailing-icon trailing-icon
:disabled="disabled" :disabled="disabled"
type="button"
class="!h-[1.875rem] top-1 ltr:ml-px rtl:mr-px !px-2 outline-0 !outline-none !rounded-lg border-0 ltr:!rounded-r-none rtl:!rounded-l-none" class="!h-[1.875rem] top-1 ltr:ml-px rtl:mr-px !px-2 outline-0 !outline-none !rounded-lg border-0 ltr:!rounded-r-none rtl:!rounded-l-none"
@click="toggleCountryDropdown" @click="toggleCountryDropdown"
> >
@@ -519,7 +519,7 @@ const menuItems = computed(() => {
</div> </div>
</section> </section>
<nav class="grid flex-grow gap-2 px-2 pb-5 overflow-y-scroll no-scrollbar"> <nav class="grid flex-grow gap-2 px-2 pb-5 overflow-y-scroll no-scrollbar">
<ul class="flex flex-col gap-1.5 m-0 list-none"> <ul class="flex flex-col gap-2 m-0 list-none">
<SidebarGroup <SidebarGroup
v-for="item in menuItems" v-for="item in menuItems"
:key="item.name" :key="item.name"
@@ -4,7 +4,6 @@ import { useMapGetter, useStore } from 'dashboard/composables/store';
import wootConstants from 'dashboard/constants/globals'; import wootConstants from 'dashboard/constants/globals';
import { useAlert } from 'dashboard/composables'; import { useAlert } from 'dashboard/composables';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useImpersonation } from 'dashboard/composables/useImpersonation';
import { import {
DropdownContainer, DropdownContainer,
@@ -21,8 +20,6 @@ const currentUserAvailability = useMapGetter('getCurrentUserAvailability');
const currentAccountId = useMapGetter('getCurrentAccountId'); const currentAccountId = useMapGetter('getCurrentAccountId');
const currentUserAutoOffline = useMapGetter('getCurrentUserAutoOffline'); const currentUserAutoOffline = useMapGetter('getCurrentUserAutoOffline');
const { isImpersonating } = useImpersonation();
const { AVAILABILITY_STATUS_KEYS } = wootConstants; const { AVAILABILITY_STATUS_KEYS } = wootConstants;
const statusList = computed(() => { const statusList = computed(() => {
return [ return [
@@ -49,10 +46,6 @@ const activeStatus = computed(() => {
}); });
function changeAvailabilityStatus(availability) { function changeAvailabilityStatus(availability) {
if (isImpersonating.value) {
useAlert(t('PROFILE_SETTINGS.FORM.AVAILABILITY.IMPERSONATING_ERROR'));
return;
}
try { try {
store.dispatch('updateAvailability', { store.dispatch('updateAvailability', {
availability, availability,
@@ -824,7 +824,7 @@ watch(conversationFilters, (newVal, oldVal) => {
class="flex flex-col flex-shrink-0 bg-n-solid-1 conversations-list-wrap" class="flex flex-col flex-shrink-0 bg-n-solid-1 conversations-list-wrap"
:class="[ :class="[
{ hidden: !showConversationList }, { hidden: !showConversationList },
isOnExpandedLayout ? 'basis-full' : 'w-[21rem] 2xl:w-[26rem]', isOnExpandedLayout ? 'basis-full' : 'w-[360px] 2xl:w-[420px]',
]" ]"
> >
<slot /> <slot />
@@ -80,14 +80,16 @@ const toggleConversationLayout = () => {
<template> <template>
<div <div
class="flex items-center justify-between gap-2 px-3 h-12 pt-3 pb-3" class="flex items-center justify-between gap-2 px-4"
:class="{ :class="{
'border-b border-n-strong': hasAppliedFiltersOrActiveFolders, 'pb-3 border-b border-n-strong': hasAppliedFiltersOrActiveFolders,
'pt-3 pb-2': showV4View,
'mb-2 pb-0': !showV4View,
}" }"
> >
<div class="flex items-center justify-center min-w-0"> <div class="flex items-center justify-center min-w-0">
<h1 <h1
class="text-base font-medium truncate text-n-slate-12" class="text-lg font-medium truncate text-n-slate-12"
:title="pageTitle" :title="pageTitle"
> >
{{ pageTitle }} {{ pageTitle }}
@@ -49,12 +49,12 @@ export default {
if (this.isAttributeTypeDate) { if (this.isAttributeTypeDate) {
return this.value return this.value
? new Date(this.value || new Date()).toLocaleDateString() ? new Date(this.value || new Date()).toLocaleDateString()
: '---'; : '';
} }
if (this.isAttributeTypeCheckbox) { if (this.isAttributeTypeCheckbox) {
return this.value === 'false' ? false : this.value; return this.value === 'false' ? false : this.value;
} }
return this.hasValue ? this.value : '---'; return this.value;
}, },
formattedValue() { formattedValue() {
return this.isAttributeTypeDate return this.isAttributeTypeDate
@@ -83,9 +83,6 @@ export default {
isAttributeTypeDate() { isAttributeTypeDate() {
return this.attributeType === 'date'; return this.attributeType === 'date';
}, },
hasValue() {
return this.value !== null && this.value !== '';
},
urlValue() { urlValue() {
return isValidURL(this.value) ? this.value : '---'; return isValidURL(this.value) ? this.value : '---';
}, },
@@ -226,7 +223,7 @@ export default {
/> />
</span> </span>
<NextButton <NextButton
v-if="showActions && hasValue" v-if="showActions && value"
v-tooltip.left="$t('CUSTOM_ATTRIBUTES.ACTIONS.DELETE')" v-tooltip.left="$t('CUSTOM_ATTRIBUTES.ACTIONS.DELETE')"
slate slate
sm sm
@@ -284,13 +281,13 @@ export default {
v-else v-else
class="group-hover:bg-n-slate-3 group-hover:dark:bg-n-solid-3 inline-block rounded-sm mb-0 break-all py-0.5 px-1" class="group-hover:bg-n-slate-3 group-hover:dark:bg-n-solid-3 inline-block rounded-sm mb-0 break-all py-0.5 px-1"
> >
{{ displayValue }} {{ displayValue || '---' }}
</p> </p>
<div <div
class="flex items-center max-w-[2rem] gap-1 ml-1 rtl:mr-1 rtl:ml-0" class="flex items-center max-w-[2rem] gap-1 ml-1 rtl:mr-1 rtl:ml-0"
> >
<NextButton <NextButton
v-if="showActions && hasValue" v-if="showActions && value"
v-tooltip="$t('CUSTOM_ATTRIBUTES.ACTIONS.COPY')" v-tooltip="$t('CUSTOM_ATTRIBUTES.ACTIONS.COPY')"
xs xs
slate slate
@@ -1,24 +1,31 @@
<script setup> <script setup>
import { ref, computed, onMounted } from 'vue'; import { ref, computed, onMounted, watchEffect } from 'vue';
import { useStore } from 'dashboard/composables/store'; import { useStore } from 'dashboard/composables/store';
import Copilot from 'dashboard/components-next/copilot/Copilot.vue'; import Copilot from 'dashboard/components-next/copilot/Copilot.vue';
import ConversationAPI from 'dashboard/api/inbox/conversation';
import { useMapGetter } from 'dashboard/composables/store'; import { useMapGetter } from 'dashboard/composables/store';
import { useUISettings } from 'dashboard/composables/useUISettings'; import { useUISettings } from 'dashboard/composables/useUISettings';
const props = defineProps({
conversationId: {
type: [Number, String],
required: true,
},
conversationInboxType: {
type: String,
required: true,
},
});
const store = useStore(); const store = useStore();
const currentUser = useMapGetter('getCurrentUser'); const currentUser = useMapGetter('getCurrentUser');
const assistants = useMapGetter('captainAssistants/getRecords'); const assistants = useMapGetter('captainAssistants/getRecords');
const inboxAssistant = useMapGetter('getCopilotAssistant'); const inboxAssistant = useMapGetter('getCopilotAssistant');
const { uiSettings, updateUISettings } = useUISettings(); const { uiSettings, updateUISettings } = useUISettings();
const currentChat = useMapGetter('getSelectedChat');
const getUIState = useMapGetter('uiState/getUIState');
const isSidebarOpen = computed(() => getUIState.value('isCopilotSidebarOpen'));
const messages = ref([]); const messages = ref([]);
const isCaptainTyping = ref(false); const isCaptainTyping = ref(false);
const selectedAssistantId = ref(null); const selectedAssistantId = ref(null);
const copilotConnector = ref(null);
const activeAssistant = computed(() => { const activeAssistant = computed(() => {
const preferredId = uiSettings.value.preferred_captain_assistant_id; const preferredId = uiSettings.value.preferred_captain_assistant_id;
@@ -52,12 +59,7 @@ const handleReset = () => {
messages.value = []; messages.value = [];
}; };
const sendMessage = message => { const sendMessage = async message => {
// Ensure WebSocket is connected before sending
if (!copilotConnector.value || !isSidebarOpen.value) {
return;
}
// Add user message // Add user message
messages.value.push({ messages.value.push({
id: messages.value.length + 1, id: messages.value.length + 1,
@@ -66,71 +68,55 @@ const sendMessage = message => {
}); });
isCaptainTyping.value = true; isCaptainTyping.value = true;
copilotConnector.value.sendMessage({ try {
assistantId: activeAssistant.value.id, const { data } = await ConversationAPI.requestCopilot(
conversationId: currentChat.value?.id, props.conversationId,
previousHistory: messages.value {
.filter(m => m.role !== 'assistant_thinking') previous_history: messages.value
.map(m => ({ .map(m => ({
role: m.role, role: m.role,
content: m.content, content: m.content,
})) }))
.slice(0, -1), .slice(0, -1),
message, message,
}); assistant_id: selectedAssistantId.value,
}
);
messages.value.push({
id: new Date().getTime(),
role: 'assistant',
content: data.message,
});
} catch (error) {
// eslint-disable-next-line
console.log(error);
} finally {
isCaptainTyping.value = false;
}
}; };
onMounted(() => { onMounted(() => {
store.dispatch('captainAssistants/get'); store.dispatch('captainAssistants/get');
}); });
// const onCopilotResponse = data => { watchEffect(() => {
// if (data.type === 'final_response') { if (props.conversationId) {
// messages.value.push({ store.dispatch('getInboxCaptainAssistantById', props.conversationId);
// id: new Date().getTime(), selectedAssistantId.value = activeAssistant.value?.id;
// role: 'assistant', }
// content: data.response.response, });
// });
// isCaptainTyping.value = false;
// } else if (data.type === 'ui_event') {
// if (data.event === 'ui:linear_ticket_create') {
// emitter.emit('ui:linear_ticket_create');
// setTimeout(() => {
// emitter.emit('ui:linear_ticket_create_data', data.response);
// }, 100);
// }
// } else {
// messages.value.push({
// id: new Date().getTime(),
// role: 'assistant_thinking',
// content: data.response.response,
// reasoning: data.response.reasoning,
// });
// }
// };
const handleClose = () => {
store.dispatch('uiState/set', { isCopilotSidebarOpen: false });
};
</script> </script>
<template> <template>
<div <Copilot
v-if="isSidebarOpen" :messages="messages"
class="border-l border-n-weak w-[20rem] min-w-[20rem]" :support-agent="currentUser"
> :is-captain-typing="isCaptainTyping"
<Copilot :conversation-inbox-type="conversationInboxType"
:messages="messages" :assistants="assistants"
:support-agent="currentUser" :active-assistant="activeAssistant"
:is-captain-typing="isCaptainTyping" @set-assistant="setAssistant"
:conversation-inbox-type="conversationInboxType" @send-message="sendMessage"
:assistants="assistants" @reset="handleReset"
:active-assistant="activeAssistant" />
@set-assistant="setAssistant"
@send-message="sendMessage"
@reset="handleReset"
@close="handleClose"
/>
</div>
<div v-else class="hidden" />
</template> </template>
@@ -1,7 +1,6 @@
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import { useAlert } from 'dashboard/composables'; import { useAlert } from 'dashboard/composables';
import { useImpersonation } from 'dashboard/composables/useImpersonation';
import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue'; import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue';
import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue'; import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue';
import WootDropdownHeader from 'shared/components/ui/dropdown/DropdownHeader.vue'; import WootDropdownHeader from 'shared/components/ui/dropdown/DropdownHeader.vue';
@@ -21,10 +20,6 @@ export default {
AvailabilityStatusBadge, AvailabilityStatusBadge,
NextButton, NextButton,
}, },
setup() {
const { isImpersonating } = useImpersonation();
return { isImpersonating };
},
data() { data() {
return { return {
isStatusMenuOpened: false, isStatusMenuOpened: false,
@@ -78,13 +73,6 @@ export default {
}); });
}, },
changeAvailabilityStatus(availability) { changeAvailabilityStatus(availability) {
if (this.isImpersonating) {
useAlert(
this.$t('PROFILE_SETTINGS.FORM.AVAILABILITY.IMPERSONATING_ERROR')
);
return;
}
if (this.isUpdating) { if (this.isUpdating) {
return; return;
} }
@@ -48,7 +48,7 @@ useKeyboardEvents(keyboardEvents);
<template> <template>
<woot-tabs <woot-tabs
:index="activeTabIndex" :index="activeTabIndex"
class="w-full px-3 -mt-1 py-0 tab--chat-type" class="w-full px-4 py-0 tab--chat-type"
@change="onTabChange" @change="onTabChange"
> >
<woot-tabs-item <woot-tabs-item
@@ -83,7 +83,7 @@ export default {
<!-- eslint-disable-next-line vue/no-root-v-if --> <!-- eslint-disable-next-line vue/no-root-v-if -->
<template> <template>
<div v-if="hasOpenedAtleastOnce" class="flex-1"> <div v-if="hasOpenedAtleastOnce" class="dashboard-app--container">
<div <div
v-for="(configItem, index) in config" v-for="(configItem, index) in config"
:key="index" :key="index"
@@ -115,7 +115,6 @@ export default {
.dashboard-app--list iframe { .dashboard-app--list iframe {
border: 0; border: 0;
} }
.dashboard-app_loading-container { .dashboard-app_loading-container {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -38,7 +38,7 @@ const currentSortBy = computed(() => {
); );
}); });
const chatStatusOptions = computed(() => [ const chatStatusOptions = [
{ {
label: t('CHAT_LIST.CHAT_STATUS_FILTER_ITEMS.open.TEXT'), label: t('CHAT_LIST.CHAT_STATUS_FILTER_ITEMS.open.TEXT'),
value: 'open', value: 'open',
@@ -59,9 +59,9 @@ const chatStatusOptions = computed(() => [
label: t('CHAT_LIST.CHAT_STATUS_FILTER_ITEMS.all.TEXT'), label: t('CHAT_LIST.CHAT_STATUS_FILTER_ITEMS.all.TEXT'),
value: 'all', value: 'all',
}, },
]); ];
const chatSortOptions = computed(() => [ const chatSortOptions = [
{ {
label: t('CHAT_LIST.SORT_ORDER_ITEMS.last_activity_at_asc.TEXT'), label: t('CHAT_LIST.SORT_ORDER_ITEMS.last_activity_at_asc.TEXT'),
value: 'last_activity_at_asc', value: 'last_activity_at_asc',
@@ -94,18 +94,15 @@ const chatSortOptions = computed(() => [
label: t('CHAT_LIST.SORT_ORDER_ITEMS.waiting_since_desc.TEXT'), label: t('CHAT_LIST.SORT_ORDER_ITEMS.waiting_since_desc.TEXT'),
value: 'waiting_since_desc', value: 'waiting_since_desc',
}, },
]); ];
const activeChatStatusLabel = computed( const activeChatStatusLabel = computed(
() => () =>
chatStatusOptions.value.find(m => m.value === chatStatusFilter.value) chatStatusOptions.find(m => m.value === chatStatusFilter.value)?.label || ''
?.label || ''
); );
const activeChatSortLabel = computed( const activeChatSortLabel = computed(
() => () => chatSortOptions.find(m => m.value === chatSortFilter.value)?.label || ''
chatSortOptions.value.find(m => m.value === chatSortFilter.value)?.label ||
''
); );
const saveSelectedFilter = (type, value) => { const saveSelectedFilter = (type, value) => {
@@ -4,9 +4,11 @@ import ConversationHeader from './ConversationHeader.vue';
import DashboardAppFrame from '../DashboardApp/Frame.vue'; import DashboardAppFrame from '../DashboardApp/Frame.vue';
import EmptyState from './EmptyState/EmptyState.vue'; import EmptyState from './EmptyState/EmptyState.vue';
import MessagesView from './MessagesView.vue'; import MessagesView from './MessagesView.vue';
import ConversationSidebar from './ConversationSidebar.vue';
export default { export default {
components: { components: {
ConversationSidebar,
ConversationHeader, ConversationHeader,
DashboardAppFrame, DashboardAppFrame,
EmptyState, EmptyState,
@@ -23,11 +25,16 @@ export default {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
isContactPanelOpen: {
type: Boolean,
default: true,
},
isOnExpandedLayout: { isOnExpandedLayout: {
type: Boolean, type: Boolean,
default: true, default: true,
}, },
}, },
emits: ['contactPanelToggle'],
data() { data() {
return { activeIndex: 0 }; return { activeIndex: 0 };
}, },
@@ -50,6 +57,9 @@ export default {
})), })),
]; ];
}, },
showContactPanel() {
return this.isContactPanelOpen && this.currentChat.id;
},
}, },
watch: { watch: {
'currentChat.inbox_id': { 'currentChat.inbox_id': {
@@ -76,6 +86,9 @@ export default {
} }
this.$store.dispatch('conversationLabels/get', this.currentChat.id); this.$store.dispatch('conversationLabels/get', this.currentChat.id);
}, },
onToggleContactPanel() {
this.$emit('contactPanelToggle');
},
onDashboardAppTabChange(index) { onDashboardAppTabChange(index) {
this.activeIndex = index; this.activeIndex = index;
}, },
@@ -85,7 +98,7 @@ export default {
<template> <template>
<div <div
class="conversation-details-wrap bg-n-background relative" class="conversation-details-wrap bg-n-background"
:class="{ :class="{
'border-l rtl:border-l-0 rtl:border-r border-n-weak': !isOnExpandedLayout, 'border-l rtl:border-l-0 rtl:border-r border-n-weak': !isOnExpandedLayout,
}" }"
@@ -94,12 +107,14 @@ export default {
v-if="currentChat.id" v-if="currentChat.id"
:chat="currentChat" :chat="currentChat"
:is-inbox-view="isInboxView" :is-inbox-view="isInboxView"
:is-contact-panel-open="isContactPanelOpen"
:show-back-button="isOnExpandedLayout && !isInboxView" :show-back-button="isOnExpandedLayout && !isInboxView"
@contact-panel-toggle="onToggleContactPanel"
/> />
<woot-tabs <woot-tabs
v-if="dashboardApps.length && currentChat.id" v-if="dashboardApps.length && currentChat.id"
:index="activeIndex" :index="activeIndex"
class="-mt-px border-t border-t-n-background bg-n-background dashboard-app--tabs" class="-mt-px bg-white dashboard-app--tabs dark:bg-slate-900"
@change="onDashboardAppTabChange" @change="onDashboardAppTabChange"
> >
<woot-tabs-item <woot-tabs-item
@@ -110,17 +125,23 @@ export default {
:show-badge="false" :show-badge="false"
/> />
</woot-tabs> </woot-tabs>
<div v-show="!activeIndex" class="flex-1 h-full min-h-0 m-0"> <div v-show="!activeIndex" class="flex h-full min-h-0 m-0">
<MessagesView <MessagesView
v-if="currentChat.id" v-if="currentChat.id"
:inbox-id="inboxId" :inbox-id="inboxId"
:is-inbox-view="isInboxView" :is-inbox-view="isInboxView"
:is-contact-panel-open="isContactPanelOpen"
@contact-panel-toggle="onToggleContactPanel"
/> />
<EmptyState <EmptyState
v-if="!currentChat.id && !isInboxView" v-if="!currentChat.id && !isInboxView"
:is-on-expanded-layout="isOnExpandedLayout" :is-on-expanded-layout="isOnExpandedLayout"
/> />
<slot /> <ConversationSidebar
v-if="showContactPanel"
:current-chat="currentChat"
@toggle-contact-panel="onToggleContactPanel"
/>
</div> </div>
<DashboardAppFrame <DashboardAppFrame
v-for="(dashboardApp, index) in dashboardApps" v-for="(dashboardApp, index) in dashboardApps"
@@ -243,7 +243,7 @@ export default {
<template> <template>
<div <div
class="relative flex items-start flex-grow-0 flex-shrink-0 w-auto max-w-full px-3 py-0 border-t-0 border-b-0 border-l-2 border-r-0 border-transparent border-solid cursor-pointer conversation hover:bg-n-alpha-1 dark:hover:bg-n-alpha-3 group" class="relative flex items-start flex-grow-0 flex-shrink-0 w-auto max-w-full px-4 py-0 border-t-0 border-b-0 border-l-2 border-r-0 border-transparent border-solid cursor-pointer conversation hover:bg-n-alpha-1 dark:hover:bg-n-alpha-3 group"
:class="{ :class="{
'active animate-card-select bg-n-alpha-1 dark:bg-n-alpha-3 border-n-weak': 'active animate-card-select bg-n-alpha-1 dark:bg-n-alpha-3 border-n-weak':
isActiveChat, isActiveChat,
@@ -278,7 +278,7 @@ export default {
:badge="inboxBadge" :badge="inboxBadge"
:username="currentContact.name" :username="currentContact.name"
:status="currentContact.availability_status" :status="currentContact.availability_status"
size="32px" size="40px"
/> />
</div> </div>
<div <div
@@ -1,5 +1,6 @@
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents';
import BackButton from '../BackButton.vue'; import BackButton from '../BackButton.vue';
import inboxMixin from 'shared/mixins/inboxMixin'; import inboxMixin from 'shared/mixins/inboxMixin';
import InboxName from '../InboxName.vue'; import InboxName from '../InboxName.vue';
@@ -12,6 +13,8 @@ import { snoozedReopenTime } from 'dashboard/helper/snoozeHelpers';
import { FEATURE_FLAGS } from 'dashboard/featureFlags'; import { FEATURE_FLAGS } from 'dashboard/featureFlags';
import Linear from './linear/index.vue'; import Linear from './linear/index.vue';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
components: { components: {
BackButton, BackButton,
@@ -20,6 +23,7 @@ export default {
Thumbnail, Thumbnail,
SLACardLabel, SLACardLabel,
Linear, Linear,
NextButton,
}, },
mixins: [inboxMixin], mixins: [inboxMixin],
props: { props: {
@@ -27,6 +31,10 @@ export default {
type: Object, type: Object,
default: () => {}, default: () => {},
}, },
isContactPanelOpen: {
type: Boolean,
default: false,
},
showBackButton: { showBackButton: {
type: Boolean, type: Boolean,
default: false, default: false,
@@ -36,6 +44,15 @@ export default {
default: false, default: false,
}, },
}, },
emits: ['contactPanelToggle'],
setup(props, { emit }) {
const keyboardEvents = {
'Alt+KeyO': {
action: () => emit('contactPanelToggle'),
},
};
useKeyboardEvents(keyboardEvents);
},
computed: { computed: {
...mapGetters({ ...mapGetters({
currentChat: 'getSelectedChat', currentChat: 'getSelectedChat',
@@ -82,7 +99,13 @@ export default {
} }
return this.$t('CONVERSATION.HEADER.SNOOZED_UNTIL_NEXT_REPLY'); return this.$t('CONVERSATION.HEADER.SNOOZED_UNTIL_NEXT_REPLY');
}, },
contactPanelToggleText() {
return `${
this.isContactPanelOpen
? this.$t('CONVERSATION.HEADER.CLOSE')
: this.$t('CONVERSATION.HEADER.OPEN')
} ${this.$t('CONVERSATION.HEADER.DETAILS')}`;
},
inbox() { inbox() {
const { inbox_id: inboxId } = this.chat; const { inbox_id: inboxId } = this.chat;
return this.$store.getters['inboxes/getInbox'](inboxId); return this.$store.getters['inboxes/getInbox'](inboxId);
@@ -110,7 +133,7 @@ export default {
<template> <template>
<div <div
class="flex flex-col items-center justify-between px-3 border-b bg-n-background border-n-weak md:flex-row h-12" class="flex flex-col items-center justify-between px-4 py-2 border-b bg-n-background border-n-weak md:flex-row"
> >
<div <div
class="flex flex-col items-center justify-center flex-1 w-full min-w-0" class="flex flex-col items-center justify-center flex-1 w-full min-w-0"
@@ -127,18 +150,20 @@ export default {
:badge="inboxBadge" :badge="inboxBadge"
:username="currentContact.name" :username="currentContact.name"
:status="currentContact.availability_status" :status="currentContact.availability_status"
size="32px"
/> />
<div <div
class="flex flex-col items-start min-w-0 ml-2 overflow-hidden rtl:ml-0 rtl:mr-2 w-fit" class="flex flex-col items-start min-w-0 ml-2 overflow-hidden rtl:ml-0 rtl:mr-2 w-fit"
> >
<div class="flex items-center max-w-full gap-1 p-0 m-0 w-fit"> <div
<span class="flex flex-row items-center max-w-full gap-1 p-0 m-0 w-fit"
class="text-sm font-medium truncate leading-tight text-n-slate-12" >
> <NextButton link slate @click.prevent="$emit('contactPanelToggle')">
{{ currentContact.name }} <span
</span> class="text-base font-medium truncate leading-tight text-n-slate-12"
>
{{ currentContact.name }}
</span>
</NextButton>
<fluent-icon <fluent-icon
v-if="!isHMACVerified" v-if="!isHMACVerified"
v-tooltip="$t('CONVERSATION.UNVERIFIED_SESSION')" v-tooltip="$t('CONVERSATION.UNVERIFIED_SESSION')"
@@ -155,11 +180,19 @@ export default {
<span v-if="isSnoozed" class="font-medium text-n-amber-10"> <span v-if="isSnoozed" class="font-medium text-n-amber-10">
{{ snoozedDisplayText }} {{ snoozedDisplayText }}
</span> </span>
<NextButton
link
xs
blue
:label="contactPanelToggleText"
@click="$emit('contactPanelToggle')"
/>
</div> </div>
</div> </div>
</div> </div>
<div <div
class="flex flex-row items-center justify-end flex-grow gap-2 mt-3 header-actions-wrap lg:mt-0" class="flex flex-row items-center justify-end flex-grow gap-2 mt-3 header-actions-wrap lg:mt-0"
:class="{ 'justify-end': isContactPanelOpen }"
> >
<SLACardLabel v-if="hasSlaPolicyId" :chat="chat" show-extended-info /> <SLACardLabel v-if="hasSlaPolicyId" :chat="chat" show-extended-info />
<Linear <Linear
@@ -1,8 +1,11 @@
<script setup> <script setup>
import { computed, ref } from 'vue';
import CopilotContainer from '../../copilot/CopilotContainer.vue';
import ContactPanel from 'dashboard/routes/dashboard/conversation/ContactPanel.vue'; import ContactPanel from 'dashboard/routes/dashboard/conversation/ContactPanel.vue';
import Button from 'dashboard/components-next/button/Button.vue'; import TabBar from 'dashboard/components-next/tabbar/TabBar.vue';
import { computed } from 'vue'; import { useI18n } from 'vue-i18n';
import { useMapGetter, useStore } from 'dashboard/composables/store'; import { useMapGetter } from 'dashboard/composables/store';
import { FEATURE_FLAGS } from '../../../featureFlags';
const props = defineProps({ const props = defineProps({
currentChat: { currentChat: {
@@ -11,48 +14,69 @@ const props = defineProps({
}, },
}); });
const getUIState = useMapGetter('uiState/getUIState'); const emit = defineEmits(['toggleContactPanel']);
const isCopilotSidebarOpen = computed(() =>
getUIState.value('isCopilotSidebarOpen')
);
const isConversationSidebarOpen = computed(() =>
getUIState.value('isConversationSidebarOpen')
);
const showConversationSidebar = computed( const { t } = useI18n();
() =>
props.currentChat.id &&
!isCopilotSidebarOpen.value &&
isConversationSidebarOpen.value
);
const store = useStore(); const channelType = computed(() => props.currentChat?.meta?.channel || '');
const closeConversationPanel = () => {
store.dispatch('uiState/set', { isConversationSidebarOpen: false }); const CONTACT_TABS_OPTIONS = [
{ key: 'CONTACT', value: 'contact' },
{ key: 'COPILOT', value: 'copilot' },
];
const tabs = computed(() => {
return CONTACT_TABS_OPTIONS.map(tab => ({
label: t(`CONVERSATION.SIDEBAR.${tab.key}`),
value: tab.value,
}));
});
const activeTab = ref(0);
const toggleContactPanel = () => {
emit('toggleContactPanel');
}; };
const handleTabChange = selectedTab => {
activeTab.value = tabs.value.findIndex(
tabItem => tabItem.value === selectedTab.value
);
};
const currentAccountId = useMapGetter('getCurrentAccountId');
const isFeatureEnabledonAccount = useMapGetter(
'accounts/isFeatureEnabledonAccount'
);
const showCopilotTab = computed(() =>
isFeatureEnabledonAccount.value(currentAccountId.value, FEATURE_FLAGS.CAPTAIN)
);
</script> </script>
<template> <template>
<div <div
v-if="showConversationSidebar" class="ltr:border-l rtl:border-r border-n-weak h-full overflow-hidden z-10 w-80 min-w-80 2xl:min-w-96 2xl:w-96 flex flex-col bg-n-background"
class="ltr:border-l rtl:border-r border-n-weak h-full overflow-hidden z-10 w-[20rem] min-w-[20rem] flex flex-col"
> >
<div class="flex flex-1 flex-col overflow-auto"> <div v-if="showCopilotTab" class="p-2">
<div <TabBar
class="flex items-center justify-between gap-2 px-4 py-2 border-b border-n-weak h-12" :tabs="tabs"
> :initial-active-tab="activeTab"
<span class="font-medium text-sm text-n-slate-12"> class="w-full [&>button]:w-full"
{{ $t('CONVERSATION.SIDEBAR.ACTIONS') }} @tab-changed="handleTabChange"
</span> />
<div class="flex items-center"> </div>
<Button icon="i-lucide-x" ghost sm @click="closeConversationPanel" /> <div class="flex flex-1 overflow-auto">
</div>
</div>
<ContactPanel <ContactPanel
:conversation-id="props.currentChat.id" v-if="!activeTab"
:inbox-id="props.currentChat.inbox_id" :conversation-id="currentChat.id"
:inbox-id="currentChat.inbox_id"
:on-toggle="toggleContactPanel"
/>
<CopilotContainer
v-else-if="activeTab === 1 && showCopilotTab"
:key="currentChat.id"
:conversation-inbox-type="channelType"
:conversation-id="currentChat.id"
class="flex-1"
/> />
</div> </div>
</div> </div>
<div v-else class="hidden" />
</template> </template>
@@ -38,6 +38,8 @@ import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage';
import { FEATURE_FLAGS } from '../../../featureFlags'; import { FEATURE_FLAGS } from '../../../featureFlags';
import { INBOX_TYPES } from 'dashboard/helper/inbox'; import { INBOX_TYPES } from 'dashboard/helper/inbox';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
components: { components: {
Message, Message,
@@ -45,8 +47,20 @@ export default {
ReplyBox, ReplyBox,
Banner, Banner,
ConversationLabelSuggestion, ConversationLabelSuggestion,
NextButton,
}, },
mixins: [inboxMixin], mixins: [inboxMixin],
props: {
isContactPanelOpen: {
type: Boolean,
default: false,
},
isInboxView: {
type: Boolean,
default: false,
},
},
emits: ['contactPanelToggle'],
setup() { setup() {
const isPopOutReplyBox = ref(false); const isPopOutReplyBox = ref(false);
const { isEnterprise } = useConfig(); const { isEnterprise } = useConfig();
@@ -185,6 +199,12 @@ export default {
isATweet() { isATweet() {
return this.conversationType === 'tweet'; return this.conversationType === 'tweet';
}, },
isRightOrLeftIcon() {
if (this.isContactPanelOpen) {
return 'arrow-chevron-right';
}
return 'arrow-chevron-left';
},
getLastSeenAt() { getLastSeenAt() {
const { contact_last_seen_at: contactLastSeenAt } = this.currentChat; const { contact_last_seen_at: contactLastSeenAt } = this.currentChat;
return contactLastSeenAt; return contactLastSeenAt;
@@ -420,6 +440,9 @@ export default {
relevantMessages relevantMessages
); );
}, },
onToggleContactPanel() {
this.$emit('contactPanelToggle');
},
setScrollParams() { setScrollParams() {
this.heightBeforeLoad = this.conversationPanel.scrollHeight; this.heightBeforeLoad = this.conversationPanel.scrollHeight;
this.scrollTopBeforeLoad = this.conversationPanel.scrollTop; this.scrollTopBeforeLoad = this.conversationPanel.scrollTop;
@@ -503,7 +526,19 @@ export default {
class="mx-2 mt-2 overflow-hidden rounded-lg" class="mx-2 mt-2 overflow-hidden rounded-lg"
:banner-message="$t('CONVERSATION.OLD_INSTAGRAM_INBOX_REPLY_BANNER')" :banner-message="$t('CONVERSATION.OLD_INSTAGRAM_INBOX_REPLY_BANNER')"
/> />
<div class="flex justify-end">
<NextButton
faded
xs
slate
class="!rounded-r-none rtl:rotate-180 !rounded-2xl !fixed z-10"
:icon="
isContactPanelOpen ? 'i-ph-caret-right-fill' : 'i-ph-caret-left-fill'
"
:class="isInboxView ? 'top-52 md:top-40' : 'top-32'"
@click="onToggleContactPanel"
/>
</div>
<NextMessageList <NextMessageList
v-if="showNextBubbles" v-if="showNextBubbles"
class="conversation-panel" class="conversation-panel"
@@ -10,7 +10,6 @@ import { parseLinearAPIErrorResponse } from 'dashboard/store/utils/api';
import SearchableDropdown from './SearchableDropdown.vue'; import SearchableDropdown from './SearchableDropdown.vue';
import { LINEAR_EVENTS } from 'dashboard/helper/AnalyticsHelper/events'; import { LINEAR_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
import Button from 'dashboard/components-next/button/Button.vue'; import Button from 'dashboard/components-next/button/Button.vue';
import { useEmitter } from 'dashboard/composables/emitter';
const props = defineProps({ const props = defineProps({
conversationId: { conversationId: {
@@ -205,12 +204,6 @@ const createIssue = async () => {
} }
}; };
useEmitter('ui:linear_ticket_create_data', data => {
formState.title = data.title;
formState.description = data.description;
formState.priority = data.priority;
});
onMounted(getTeams); onMounted(getTeams);
</script> </script>
@@ -10,7 +10,6 @@ import { useTrack } from 'dashboard/composables';
import { LINEAR_EVENTS } from 'dashboard/helper/AnalyticsHelper/events'; import { LINEAR_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
import { parseLinearAPIErrorResponse } from 'dashboard/store/utils/api'; import { parseLinearAPIErrorResponse } from 'dashboard/store/utils/api';
import Button from 'dashboard/components-next/button/Button.vue'; import Button from 'dashboard/components-next/button/Button.vue';
import { useEmitter } from 'dashboard/composables/emitter';
const props = defineProps({ const props = defineProps({
conversationId: { conversationId: {
@@ -95,10 +94,6 @@ watch(
} }
); );
useEmitter('ui:linear_ticket_create', () => {
shouldShowPopup.value = true;
});
onMounted(() => { onMounted(() => {
loadLinkedIssue(); loadLinkedIssue();
}); });
@@ -1,37 +0,0 @@
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { useImpersonation } from '../useImpersonation';
vi.mock('shared/helpers/sessionStorage', () => ({
__esModule: true,
default: {
get: vi.fn(),
set: vi.fn(),
},
}));
import SessionStorage from 'shared/helpers/sessionStorage';
import { SESSION_STORAGE_KEYS } from 'dashboard/constants/sessionStorage';
describe('useImpersonation', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('should return true if impersonation flag is set in session storage', () => {
SessionStorage.get.mockReturnValue(true);
const { isImpersonating } = useImpersonation();
expect(isImpersonating.value).toBe(true);
expect(SessionStorage.get).toHaveBeenCalledWith(
SESSION_STORAGE_KEYS.IMPERSONATION_USER
);
});
it('should return false if impersonation flag is not set in session storage', () => {
SessionStorage.get.mockReturnValue(false);
const { isImpersonating } = useImpersonation();
expect(isImpersonating.value).toBe(false);
expect(SessionStorage.get).toHaveBeenCalledWith(
SESSION_STORAGE_KEYS.IMPERSONATION_USER
);
});
});
@@ -1,10 +0,0 @@
import { computed } from 'vue';
import SessionStorage from 'shared/helpers/sessionStorage';
import { SESSION_STORAGE_KEYS } from 'dashboard/constants/sessionStorage';
export function useImpersonation() {
const isImpersonating = computed(() => {
return SessionStorage.get(SESSION_STORAGE_KEYS.IMPERSONATION_USER);
});
return { isImpersonating };
}
@@ -1,3 +0,0 @@
export const SESSION_STORAGE_KEYS = {
IMPERSONATION_USER: 'impersonationUser',
};
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Pre Chat Form", "PRE_CHAT_FORM": "Pre Chat Form",
"BUSINESS_HOURS": "Business Hours", "BUSINESS_HOURS": "Business Hours",
"WIDGET_BUILDER": "Widget Builder", "WIDGET_BUILDER": "Widget Builder",
"BOT_CONFIGURATION": "Bot Configuration", "BOT_CONFIGURATION": "Bot Configuration"
"CSAT": "CSAT"
}, },
"SETTINGS": "Settings", "SETTINGS": "Settings",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"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",
"AUTO_ASSIGNMENT": "Enable auto assignment", "AUTO_ASSIGNMENT": "Enable auto assignment",
"ENABLE_CSAT": "Enable CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Enable/Disable CSAT(Customer satisfaction) survey after resolving a conversation",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email", "ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.",
@@ -577,32 +578,6 @@
"LABEL": "Visitors should provide their name and email address before starting the chat" "LABEL": "Visitors should provide their name and email address before starting the chat"
} }
}, },
"CSAT": {
"TITLE": "Enable CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Message",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "contains",
"DOES_NOT_CONTAINS": "does not contain"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Set your availability", "TITLE": "Set your availability",
"SUBTITLE": "Set your availability on your livechat widget", "SUBTITLE": "Set your availability on your livechat widget",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "نموذج ما قبل الدردشة", "PRE_CHAT_FORM": "نموذج ما قبل الدردشة",
"BUSINESS_HOURS": "ساعات العمل", "BUSINESS_HOURS": "ساعات العمل",
"WIDGET_BUILDER": "منشئ اللايف شات", "WIDGET_BUILDER": "منشئ اللايف شات",
"BOT_CONFIGURATION": "اعدادات البوت", "BOT_CONFIGURATION": "اعدادات البوت"
"CSAT": "تقييم رضاء العملاء"
}, },
"SETTINGS": "الإعدادات", "SETTINGS": "الإعدادات",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"ENABLE_EMAIL_COLLECT_BOX": "تفعيل صندوق جمع البريد الإلكتروني", "ENABLE_EMAIL_COLLECT_BOX": "تفعيل صندوق جمع البريد الإلكتروني",
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "تمكين أو تعطيل مربع جمع البريد الإلكتروني في محادثة جديدة", "ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "تمكين أو تعطيل مربع جمع البريد الإلكتروني في محادثة جديدة",
"AUTO_ASSIGNMENT": "تفعيل الإسناد التلقائي", "AUTO_ASSIGNMENT": "تفعيل الإسناد التلقائي",
"ENABLE_CSAT": "تمكين تقييم خدمة العملاء",
"SENDER_NAME_SECTION": "تمكين اسم الوكيل في البريد الإلكتروني", "SENDER_NAME_SECTION": "تمكين اسم الوكيل في البريد الإلكتروني",
"ENABLE_CSAT_SUB_TEXT": "تمكين/تعطيل تقييم خدمة العملاء بعد إنتهاء المحادثة",
"SENDER_NAME_SECTION_TEXT": "تمكين/تعطيل إظهار اسم الوكيل في البريد الإلكتروني، إذا تم تعطيله فسيظهر اسم المنشأة", "SENDER_NAME_SECTION_TEXT": "تمكين/تعطيل إظهار اسم الوكيل في البريد الإلكتروني، إذا تم تعطيله فسيظهر اسم المنشأة",
"ENABLE_CONTINUITY_VIA_EMAIL": "تمكين استمرارية المحادثة عبر البريد الإلكتروني", "ENABLE_CONTINUITY_VIA_EMAIL": "تمكين استمرارية المحادثة عبر البريد الإلكتروني",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "المحادثات ستستمر عبر البريد الإلكتروني إذا كان عنوان البريد الإلكتروني لجهة الاتصال متاحاً.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "المحادثات ستستمر عبر البريد الإلكتروني إذا كان عنوان البريد الإلكتروني لجهة الاتصال متاحاً.",
@@ -577,32 +578,6 @@
"LABEL": "يجب على الزوار تقديم اسمهم وعنوان بريدهم الإلكتروني قبل بدء المحادثة" "LABEL": "يجب على الزوار تقديم اسمهم وعنوان بريدهم الإلكتروني قبل بدء المحادثة"
} }
}, },
"CSAT": {
"TITLE": "تمكين تقييم خدمة العملاء",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "رسالة",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "يحتوي",
"DOES_NOT_CONTAINS": "لا يحتوي"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "قم بتعيين توافرك", "TITLE": "قم بتعيين توافرك",
"SUBTITLE": "تعيين توافرك على أداة الدردشة المباشرة الخاصة بك", "SUBTITLE": "تعيين توافرك على أداة الدردشة المباشرة الخاصة بك",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Pre Chat Form", "PRE_CHAT_FORM": "Pre Chat Form",
"BUSINESS_HOURS": "Business Hours", "BUSINESS_HOURS": "Business Hours",
"WIDGET_BUILDER": "Widget Builder", "WIDGET_BUILDER": "Widget Builder",
"BOT_CONFIGURATION": "Bot Configuration", "BOT_CONFIGURATION": "Bot Configuration"
"CSAT": "CSAT"
}, },
"SETTINGS": "Settings", "SETTINGS": "Settings",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"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",
"AUTO_ASSIGNMENT": "Enable auto assignment", "AUTO_ASSIGNMENT": "Enable auto assignment",
"ENABLE_CSAT": "Enable CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Enable/Disable CSAT(Customer satisfaction) survey after resolving a conversation",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email", "ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.",
@@ -577,32 +578,6 @@
"LABEL": "Visitors should provide their name and email address before starting the chat" "LABEL": "Visitors should provide their name and email address before starting the chat"
} }
}, },
"CSAT": {
"TITLE": "Enable CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Message",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "contains",
"DOES_NOT_CONTAINS": "does not contain"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Set your availability", "TITLE": "Set your availability",
"SUBTITLE": "Set your availability on your livechat widget", "SUBTITLE": "Set your availability on your livechat widget",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Pre Chat Form", "PRE_CHAT_FORM": "Pre Chat Form",
"BUSINESS_HOURS": "Business Hours", "BUSINESS_HOURS": "Business Hours",
"WIDGET_BUILDER": "Widget Builder", "WIDGET_BUILDER": "Widget Builder",
"BOT_CONFIGURATION": "Bot Configuration", "BOT_CONFIGURATION": "Bot Configuration"
"CSAT": "CSAT"
}, },
"SETTINGS": "Settings", "SETTINGS": "Settings",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"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",
"AUTO_ASSIGNMENT": "Enable auto assignment", "AUTO_ASSIGNMENT": "Enable auto assignment",
"ENABLE_CSAT": "Enable CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Enable/Disable CSAT(Customer satisfaction) survey after resolving a conversation",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email", "ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.",
@@ -577,32 +578,6 @@
"LABEL": "Visitors should provide their name and email address before starting the chat" "LABEL": "Visitors should provide their name and email address before starting the chat"
} }
}, },
"CSAT": {
"TITLE": "Enable CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Съобщение",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "съдържа",
"DOES_NOT_CONTAINS": "не съдържа"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Set your availability", "TITLE": "Set your availability",
"SUBTITLE": "Set your availability on your livechat widget", "SUBTITLE": "Set your availability on your livechat widget",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Formulari de xat previ", "PRE_CHAT_FORM": "Formulari de xat previ",
"BUSINESS_HOURS": "Horari comercial", "BUSINESS_HOURS": "Horari comercial",
"WIDGET_BUILDER": "Creador del widget", "WIDGET_BUILDER": "Creador del widget",
"BOT_CONFIGURATION": "Configuracions del bot", "BOT_CONFIGURATION": "Configuracions del bot"
"CSAT": "CSAT"
}, },
"SETTINGS": "Configuracions", "SETTINGS": "Configuracions",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"ENABLE_EMAIL_COLLECT_BOX": "Activa la bústia de recollida de correu electrònic", "ENABLE_EMAIL_COLLECT_BOX": "Activa la bústia de recollida de correu electrònic",
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Activa o desactiva la casella de recollida de correu electrònic en una conversa nova", "ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Activa o desactiva la casella de recollida de correu electrònic en una conversa nova",
"AUTO_ASSIGNMENT": "Activa l'assignació automàtica", "AUTO_ASSIGNMENT": "Activa l'assignació automàtica",
"ENABLE_CSAT": "Habilita CSAT",
"SENDER_NAME_SECTION": "Activa el nom de l'agent al correu electrònic", "SENDER_NAME_SECTION": "Activa el nom de l'agent al correu electrònic",
"ENABLE_CSAT_SUB_TEXT": "Activa/desactiva l'enquesta CSAT (satisfacció del client) després de resoldre una conversa",
"SENDER_NAME_SECTION_TEXT": "Activa/Desactiva la mostra del nom de l'agent al correu electrònic, si està desactivat, mostrarà el nom de l'empresa", "SENDER_NAME_SECTION_TEXT": "Activa/Desactiva la mostra del nom de l'agent al correu electrònic, si està desactivat, mostrarà el nom de l'empresa",
"ENABLE_CONTINUITY_VIA_EMAIL": "Activa la continuïtat de la conversa per correu electrònic", "ENABLE_CONTINUITY_VIA_EMAIL": "Activa la continuïtat de la conversa per correu electrònic",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Les converses continuaran per correu electrònic si l'adreça electrònica de contacte està disponible.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Les converses continuaran per correu electrònic si l'adreça electrònica de contacte està disponible.",
@@ -577,32 +578,6 @@
"LABEL": "Els visitants han de proporcionar el seu nom i adreça de correu electrònic abans d'iniciar el xat" "LABEL": "Els visitants han de proporcionar el seu nom i adreça de correu electrònic abans d'iniciar el xat"
} }
}, },
"CSAT": {
"TITLE": "Habilita CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Missatge",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "conté",
"DOES_NOT_CONTAINS": "no conté"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Estableix la vostra disponibilitat", "TITLE": "Estableix la vostra disponibilitat",
"SUBTITLE": "Estableix la teva disponibilitat al widget del xat en directe", "SUBTITLE": "Estableix la teva disponibilitat al widget del xat en directe",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Formulář před chatem", "PRE_CHAT_FORM": "Formulář před chatem",
"BUSINESS_HOURS": "Pracovní doba", "BUSINESS_HOURS": "Pracovní doba",
"WIDGET_BUILDER": "Widget Builder", "WIDGET_BUILDER": "Widget Builder",
"BOT_CONFIGURATION": "Bot Configuration", "BOT_CONFIGURATION": "Bot Configuration"
"CSAT": "CSAT"
}, },
"SETTINGS": "Nastavení", "SETTINGS": "Nastavení",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"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",
"AUTO_ASSIGNMENT": "Povolit automatické přiřazení", "AUTO_ASSIGNMENT": "Povolit automatické přiřazení",
"ENABLE_CSAT": "Enable CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Enable/Disable CSAT(Customer satisfaction) survey after resolving a conversation",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email", "ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.",
@@ -577,32 +578,6 @@
"LABEL": "Visitors should provide their name and email address before starting the chat" "LABEL": "Visitors should provide their name and email address before starting the chat"
} }
}, },
"CSAT": {
"TITLE": "Enable CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Zpráva",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "contains",
"DOES_NOT_CONTAINS": "does not contain"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Nastavte svou dostupnost", "TITLE": "Nastavte svou dostupnost",
"SUBTITLE": "Set your availability on your livechat widget", "SUBTITLE": "Set your availability on your livechat widget",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Pre Chat Form", "PRE_CHAT_FORM": "Pre Chat Form",
"BUSINESS_HOURS": "Forretningstider", "BUSINESS_HOURS": "Forretningstider",
"WIDGET_BUILDER": "Widget Builder", "WIDGET_BUILDER": "Widget Builder",
"BOT_CONFIGURATION": "Bot konfiguration", "BOT_CONFIGURATION": "Bot konfiguration"
"CSAT": "CSAT"
}, },
"SETTINGS": "Indstillinger", "SETTINGS": "Indstillinger",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"ENABLE_EMAIL_COLLECT_BOX": "Aktiver boks til indsamling af e-mail", "ENABLE_EMAIL_COLLECT_BOX": "Aktiver boks til indsamling af e-mail",
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Aktiver eller deaktivér opsamlingsboks for e-mail ved ny samtale", "ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Aktiver eller deaktivér opsamlingsboks for e-mail ved ny samtale",
"AUTO_ASSIGNMENT": "Aktiver automatisk tildeling", "AUTO_ASSIGNMENT": "Aktiver automatisk tildeling",
"ENABLE_CSAT": "Aktiver CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Aktiver/deaktivér CSAT(Customer satisfaction) undersøgelse efter at have løst en samtale",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "Aktivér konversationskontinuitet via e-mail", "ENABLE_CONTINUITY_VIA_EMAIL": "Aktivér konversationskontinuitet via e-mail",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Samtaler vil fortsætte via e-mail, hvis kontaktpersonens e-mailadresse er tilgængelig.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Samtaler vil fortsætte via e-mail, hvis kontaktpersonens e-mailadresse er tilgængelig.",
@@ -577,32 +578,6 @@
"LABEL": "Besøgende skal angive deres navn og e-mailadresse, før du starter chatten" "LABEL": "Besøgende skal angive deres navn og e-mailadresse, før du starter chatten"
} }
}, },
"CSAT": {
"TITLE": "Aktiver CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Besked",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "indeholder",
"DOES_NOT_CONTAINS": "indeholder ikke"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Indstil din tilgængelighed", "TITLE": "Indstil din tilgængelighed",
"SUBTITLE": "Indstil din tilgængelighed på din livechat widget", "SUBTITLE": "Indstil din tilgængelighed på din livechat widget",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Pre-Chat-Formular", "PRE_CHAT_FORM": "Pre-Chat-Formular",
"BUSINESS_HOURS": "Öffnungszeiten", "BUSINESS_HOURS": "Öffnungszeiten",
"WIDGET_BUILDER": "Widget-Generator", "WIDGET_BUILDER": "Widget-Generator",
"BOT_CONFIGURATION": "Bot-Konfiguration", "BOT_CONFIGURATION": "Bot-Konfiguration"
"CSAT": "CSAT"
}, },
"SETTINGS": "Einstellungen", "SETTINGS": "Einstellungen",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"ENABLE_EMAIL_COLLECT_BOX": "E-Mail-Sammelbox aktivieren", "ENABLE_EMAIL_COLLECT_BOX": "E-Mail-Sammelbox aktivieren",
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "E-Mail-Sammelbox für neue Konversation aktivieren oder deaktivieren", "ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "E-Mail-Sammelbox für neue Konversation aktivieren oder deaktivieren",
"AUTO_ASSIGNMENT": "Aktivieren Sie die automatische Zuweisung", "AUTO_ASSIGNMENT": "Aktivieren Sie die automatische Zuweisung",
"ENABLE_CSAT": "CSAT aktivieren",
"SENDER_NAME_SECTION": "Aktivieren Sie den Agentennamen in der E-Mail", "SENDER_NAME_SECTION": "Aktivieren Sie den Agentennamen in der E-Mail",
"ENABLE_CSAT_SUB_TEXT": "CSAT(Kundenzufriedenheit) Umfrage aktivieren/deaktivieren nach Abschluss eines Gesprächs",
"SENDER_NAME_SECTION_TEXT": "Aktivieren/Deaktivieren Sie die Anzeige des Agentennamens in der E-Mail. Wenn deaktiviert, wird der Firmenname angezeigt", "SENDER_NAME_SECTION_TEXT": "Aktivieren/Deaktivieren Sie die Anzeige des Agentennamens in der E-Mail. Wenn deaktiviert, wird der Firmenname angezeigt",
"ENABLE_CONTINUITY_VIA_EMAIL": "Konversationskontinuität per E-Mail aktivieren", "ENABLE_CONTINUITY_VIA_EMAIL": "Konversationskontinuität per E-Mail aktivieren",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Konversationen werden per E-Mail fortgesetzt, wenn die Kontakt-E-Mail-Adresse verfügbar ist.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Konversationen werden per E-Mail fortgesetzt, wenn die Kontakt-E-Mail-Adresse verfügbar ist.",
@@ -577,32 +578,6 @@
"LABEL": "Besucher sollten ihren Namen und ihre E-Mail-Adresse angeben, bevor sie den Chat starten" "LABEL": "Besucher sollten ihren Namen und ihre E-Mail-Adresse angeben, bevor sie den Chat starten"
} }
}, },
"CSAT": {
"TITLE": "CSAT aktivieren",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Nachricht",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "enthält",
"DOES_NOT_CONTAINS": "beinhaltet nicht"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Legen Sie Ihre Verfügbarkeit fest", "TITLE": "Legen Sie Ihre Verfügbarkeit fest",
"SUBTITLE": "Legen Sie die Verfügbarkeit für das Live-Chat-Widget fest", "SUBTITLE": "Legen Sie die Verfügbarkeit für das Live-Chat-Widget fest",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Φόρμα Προ-Συνομιλίας", "PRE_CHAT_FORM": "Φόρμα Προ-Συνομιλίας",
"BUSINESS_HOURS": "Ώρες Εργασίας", "BUSINESS_HOURS": "Ώρες Εργασίας",
"WIDGET_BUILDER": "Δημιουργός Widget", "WIDGET_BUILDER": "Δημιουργός Widget",
"BOT_CONFIGURATION": "Ρυθμίσεις Bot", "BOT_CONFIGURATION": "Ρυθμίσεις Bot"
"CSAT": "CSAT"
}, },
"SETTINGS": "Ρυθμίσεις", "SETTINGS": "Ρυθμίσεις",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"ENABLE_EMAIL_COLLECT_BOX": "Ενεργοποιήσετε το πλαίσιο συλλογής email", "ENABLE_EMAIL_COLLECT_BOX": "Ενεργοποιήσετε το πλαίσιο συλλογής email",
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Ενεργοποίηση ή απενεργοποίηση του πλαισίου συλλογής μηνυμάτων ηλεκτρονικού ταχυδρομείου στη νέα συνομιλία", "ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Ενεργοποίηση ή απενεργοποίηση του πλαισίου συλλογής μηνυμάτων ηλεκτρονικού ταχυδρομείου στη νέα συνομιλία",
"AUTO_ASSIGNMENT": "Επιτρέπεται η αυτόματη αντιστοίχιση", "AUTO_ASSIGNMENT": "Επιτρέπεται η αυτόματη αντιστοίχιση",
"ENABLE_CSAT": "Ενεργοποίηση CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Ενεργοποίηση/Απενεργοποίηση της έρευνας CSAT (ικανοποίηση πελατών) μετά την επίλυση μιας συνομιλίας",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "Ενεργοποίηση της συνέχειας συνομιλίας μέσω email", "ENABLE_CONTINUITY_VIA_EMAIL": "Ενεργοποίηση της συνέχειας συνομιλίας μέσω email",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Οι συζητήσεις θα συνεχίσουν μέσω email αν η διεύθυνση ηλεκτρονικού ταχυδρομείου επαφής είναι διαθέσιμη.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Οι συζητήσεις θα συνεχίσουν μέσω email αν η διεύθυνση ηλεκτρονικού ταχυδρομείου επαφής είναι διαθέσιμη.",
@@ -577,32 +578,6 @@
"LABEL": "Οι επισκέπτες θα πρέπει να συμπληρώνουν το όνομα και τη διεύθυνση ηλεκτρονικού ταχυδρομείου τους πριν από την έναρξη της συνομιλίας" "LABEL": "Οι επισκέπτες θα πρέπει να συμπληρώνουν το όνομα και τη διεύθυνση ηλεκτρονικού ταχυδρομείου τους πριν από την έναρξη της συνομιλίας"
} }
}, },
"CSAT": {
"TITLE": "Ενεργοποίηση CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Μήνυμα",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "περιέχει",
"DOES_NOT_CONTAINS": "δεν περιέχει"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Ορίστε τη διαθεσιμότητά σας", "TITLE": "Ορίστε τη διαθεσιμότητά σας",
"SUBTITLE": "Ορίστε τη διαθεσιμότητα στο livechat widget σας", "SUBTITLE": "Ορίστε τη διαθεσιμότητα στο livechat widget σας",
@@ -59,11 +59,6 @@
"ERROR_MESSAGE": "Could not update bot. Please try again." "ERROR_MESSAGE": "Could not update bot. Please try again."
} }
}, },
"ACCESS_TOKEN": {
"TITLE": "Access Token",
"DESCRIPTION": "Copy the access token and save it securely",
"COPY_SUCCESSFUL": "Access token copied to clipboard"
},
"FORM": { "FORM": {
"AVATAR": { "AVATAR": {
"LABEL": "Bot avatar" "LABEL": "Bot avatar"
@@ -458,10 +458,6 @@
"PLACEHOLDER": "Add Twitter" "PLACEHOLDER": "Add Twitter"
} }
} }
},
"DELETE_CONTACT": {
"MESSAGE": "This action is permanent and irreversible.",
"BUTTON": "Delete now"
} }
}, },
"DETAILS": { "DETAILS": {
@@ -471,7 +467,7 @@
"DELETE_CONTACT": "Delete contact", "DELETE_CONTACT": "Delete contact",
"DELETE_DIALOG": { "DELETE_DIALOG": {
"TITLE": "Confirm Deletion", "TITLE": "Confirm Deletion",
"DESCRIPTION": "Are you sure you want to delete this contact?", "DESCRIPTION": "Are you sure you want to delete this {contactName} contact?",
"CONFIRM": "Yes, Delete", "CONFIRM": "Yes, Delete",
"API": { "API": {
"SUCCESS_MESSAGE": "Contact deleted successfully", "SUCCESS_MESSAGE": "Contact deleted successfully",
@@ -234,7 +234,8 @@
} }
}, },
"SIDEBAR": { "SIDEBAR": {
"ACTIONS": "Actions" "CONTACT": "Contact",
"COPILOT": "Copilot"
} }
}, },
"EMAIL_TRANSCRIPT": { "EMAIL_TRANSCRIPT": {
@@ -379,6 +380,9 @@
"TWO": "{user} and {secondUser} are typing", "TWO": "{user} and {secondUser} are typing",
"MULTIPLE": "{user} and {count} others are typing" "MULTIPLE": "{user} and {count} others are typing"
}, },
"COPILOT": {
"TRY_THESE_PROMPTS": "Try these prompts"
},
"GALLERY_VIEW": { "GALLERY_VIEW": {
"ERROR_DOWNLOADING": "Unable to download attachment. Please try again" "ERROR_DOWNLOADING": "Unable to download attachment. Please try again"
} }
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Pre Chat Form", "PRE_CHAT_FORM": "Pre Chat Form",
"BUSINESS_HOURS": "Business Hours", "BUSINESS_HOURS": "Business Hours",
"WIDGET_BUILDER": "Widget Builder", "WIDGET_BUILDER": "Widget Builder",
"BOT_CONFIGURATION": "Bot Configuration", "BOT_CONFIGURATION": "Bot Configuration"
"CSAT": "CSAT"
}, },
"SETTINGS": "Settings", "SETTINGS": "Settings",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"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",
"AUTO_ASSIGNMENT": "Enable auto assignment", "AUTO_ASSIGNMENT": "Enable auto assignment",
"ENABLE_CSAT": "Enable CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Enable/Disable CSAT(Customer satisfaction) survey after resolving a conversation",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email", "ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.",
@@ -577,32 +578,6 @@
"LABEL": "Visitors should provide their name and email address before starting the chat" "LABEL": "Visitors should provide their name and email address before starting the chat"
} }
}, },
"CSAT": {
"TITLE": "Enable CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Message",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "contains",
"DOES_NOT_CONTAINS": "does not contain"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Set your availability", "TITLE": "Set your availability",
"SUBTITLE": "Set your availability on your livechat widget", "SUBTITLE": "Set your availability on your livechat widget",
@@ -327,10 +327,6 @@
"NAME": "Captain", "NAME": "Captain",
"HEADER_KNOW_MORE": "Know more", "HEADER_KNOW_MORE": "Know more",
"COPILOT": { "COPILOT": {
"TITLE": "Copilot",
"TRY_THESE_PROMPTS": "Try these prompts",
"PANEL_TITLE": "Get started with Copilot",
"KICK_OFF_MESSAGE": "Need a quick summary, want to check past conversations, or draft a better reply? Copilot’s here to speed things up.",
"SEND_MESSAGE": "Send message...", "SEND_MESSAGE": "Send message...",
"EMPTY_MESSAGE": "There was an error generating the response. Please try again.", "EMPTY_MESSAGE": "There was an error generating the response. Please try again.",
"LOADER": "Captain is thinking", "LOADER": "Captain is thinking",
@@ -338,7 +334,6 @@
"USE": "Use this", "USE": "Use this",
"RESET": "Reset", "RESET": "Reset",
"SELECT_ASSISTANT": "Select Assistant", "SELECT_ASSISTANT": "Select Assistant",
"SHOW_STEPS": "Show steps",
"PROMPTS": { "PROMPTS": {
"SUMMARIZE": { "SUMMARIZE": {
"LABEL": "Summarize this conversation", "LABEL": "Summarize this conversation",
@@ -185,8 +185,7 @@
"OFFLINE": "Offline" "OFFLINE": "Offline"
}, },
"SET_AVAILABILITY_SUCCESS": "Availability has been set successfully", "SET_AVAILABILITY_SUCCESS": "Availability has been set successfully",
"SET_AVAILABILITY_ERROR": "Couldn't set availability, please try again", "SET_AVAILABILITY_ERROR": "Couldn't set availability, please try again"
"IMPERSONATING_ERROR": "Cannot change availability while impersonating a user"
}, },
"EMAIL": { "EMAIL": {
"LABEL": "Your email address", "LABEL": "Your email address",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Pre-formulario de chat", "PRE_CHAT_FORM": "Pre-formulario de chat",
"BUSINESS_HOURS": "Horarios", "BUSINESS_HOURS": "Horarios",
"WIDGET_BUILDER": "Constructor de Widget", "WIDGET_BUILDER": "Constructor de Widget",
"BOT_CONFIGURATION": "Configuración del bot", "BOT_CONFIGURATION": "Configuración del bot"
"CSAT": "Encuestas de Satisfacción"
}, },
"SETTINGS": "Ajustes", "SETTINGS": "Ajustes",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"ENABLE_EMAIL_COLLECT_BOX": "Activar caja de recolección de correo electrónico", "ENABLE_EMAIL_COLLECT_BOX": "Activar caja de recolección de correo electrónico",
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Activar o desactivar la caja de recolección de correo electrónico", "ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Activar o desactivar la caja de recolección de correo electrónico",
"AUTO_ASSIGNMENT": "Activar asignación automática", "AUTO_ASSIGNMENT": "Activar asignación automática",
"ENABLE_CSAT": "Habilitar Encuesta de Satisfacción",
"SENDER_NAME_SECTION": "Habilitar nombre del agente en el correo electrónico", "SENDER_NAME_SECTION": "Habilitar nombre del agente en el correo electrónico",
"ENABLE_CSAT_SUB_TEXT": "Habilitar/deshabilitar encuesta CSAT(satisfacción del cliente) después de resolver una conversación",
"SENDER_NAME_SECTION_TEXT": "Habilitar/Deshabilitar mostrando el nombre del agente en el correo electrónico, si está deshabilitado, mostrará el nombre del negocio", "SENDER_NAME_SECTION_TEXT": "Habilitar/Deshabilitar mostrando el nombre del agente en el correo electrónico, si está deshabilitado, mostrará el nombre del negocio",
"ENABLE_CONTINUITY_VIA_EMAIL": "Habilitar continuidad de conversación por correo electrónico", "ENABLE_CONTINUITY_VIA_EMAIL": "Habilitar continuidad de conversación por correo electrónico",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Las conversaciones continuarán por correo electrónico si la dirección de correo electrónico de contacto está disponible.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Las conversaciones continuarán por correo electrónico si la dirección de correo electrónico de contacto está disponible.",
@@ -577,32 +578,6 @@
"LABEL": "Los visitantes deben proporcionar su nombre y dirección de correo electrónico antes de iniciar el chat" "LABEL": "Los visitantes deben proporcionar su nombre y dirección de correo electrónico antes de iniciar el chat"
} }
}, },
"CSAT": {
"TITLE": "Habilitar Encuesta de Satisfacción",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Mensaje",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "contiene",
"DOES_NOT_CONTAINS": "no contiene"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Establecer su disponibilidad", "TITLE": "Establecer su disponibilidad",
"SUBTITLE": "Establezca su disponibilidad en su widget de livechat", "SUBTITLE": "Establezca su disponibilidad en su widget de livechat",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "فرم پیش چت", "PRE_CHAT_FORM": "فرم پیش چت",
"BUSINESS_HOURS": "ساعت کاری", "BUSINESS_HOURS": "ساعت کاری",
"WIDGET_BUILDER": "سازنده ابزارک", "WIDGET_BUILDER": "سازنده ابزارک",
"BOT_CONFIGURATION": "پیکربندی ربات", "BOT_CONFIGURATION": "پیکربندی ربات"
"CSAT": "رضایت مشتری"
}, },
"SETTINGS": "تنظیمات", "SETTINGS": "تنظیمات",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"ENABLE_EMAIL_COLLECT_BOX": "فعال سازی فرم دریافت ایمیل از کاربر", "ENABLE_EMAIL_COLLECT_BOX": "فعال سازی فرم دریافت ایمیل از کاربر",
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "فعال یا غیرفعال کردن فرم دریافت ایمیل از کاربر", "ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "فعال یا غیرفعال کردن فرم دریافت ایمیل از کاربر",
"AUTO_ASSIGNMENT": "فعال کردن واگذاری خودکار گفتگو به ایجنت ها", "AUTO_ASSIGNMENT": "فعال کردن واگذاری خودکار گفتگو به ایجنت ها",
"ENABLE_CSAT": "فعال کردن رضایت مشتری",
"SENDER_NAME_SECTION": "فعال سازی نام اپراتور در ایمیل", "SENDER_NAME_SECTION": "فعال سازی نام اپراتور در ایمیل",
"ENABLE_CSAT_SUB_TEXT": "پس از پایان گفتگو ، نظرسنجی CSAT (رضایت مشتری) را فعال/غیرفعال کنید",
"SENDER_NAME_SECTION_TEXT": "فعال/غیرفعال کردن نمایش نام اپراتور در ایمیل، اگر غیرفعال باشد نام کسب و کار نشان داده می شود", "SENDER_NAME_SECTION_TEXT": "فعال/غیرفعال کردن نمایش نام اپراتور در ایمیل، اگر غیرفعال باشد نام کسب و کار نشان داده می شود",
"ENABLE_CONTINUITY_VIA_EMAIL": "ادامه مکالمه را از طریق ایمیل فعال کنید", "ENABLE_CONTINUITY_VIA_EMAIL": "ادامه مکالمه را از طریق ایمیل فعال کنید",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "اگر آدرس ایمیل تماس در دسترس باشد، مکالمات از طریق ایمیل ادامه خواهد یافت.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "اگر آدرس ایمیل تماس در دسترس باشد، مکالمات از طریق ایمیل ادامه خواهد یافت.",
@@ -577,32 +578,6 @@
"LABEL": "بازدیدکنندگان باید قبل از شروع چت نام و آدرس ایمیل خود را ارائه دهند" "LABEL": "بازدیدکنندگان باید قبل از شروع چت نام و آدرس ایمیل خود را ارائه دهند"
} }
}, },
"CSAT": {
"TITLE": "فعال کردن رضایت مشتری",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "پیام",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "شامل",
"DOES_NOT_CONTAINS": "شامل نمی‌شود"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "در دسترس بودن خود را تنظیم کنید", "TITLE": "در دسترس بودن خود را تنظیم کنید",
"SUBTITLE": "زمان در دسترس بودن خود را بر روی چت زنده مشخص کنید", "SUBTITLE": "زمان در دسترس بودن خود را بر روی چت زنده مشخص کنید",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Pre Chat Form", "PRE_CHAT_FORM": "Pre Chat Form",
"BUSINESS_HOURS": "Business Hours", "BUSINESS_HOURS": "Business Hours",
"WIDGET_BUILDER": "Widget Builder", "WIDGET_BUILDER": "Widget Builder",
"BOT_CONFIGURATION": "Bot Configuration", "BOT_CONFIGURATION": "Bot Configuration"
"CSAT": "CSAT"
}, },
"SETTINGS": "Asetukset", "SETTINGS": "Asetukset",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"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",
"AUTO_ASSIGNMENT": "Ota automaattinen delegointi käyttöön", "AUTO_ASSIGNMENT": "Ota automaattinen delegointi käyttöön",
"ENABLE_CSAT": "Enable CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Enable/Disable CSAT(Customer satisfaction) survey after resolving a conversation",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email", "ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.",
@@ -577,32 +578,6 @@
"LABEL": "Visitors should provide their name and email address before starting the chat" "LABEL": "Visitors should provide their name and email address before starting the chat"
} }
}, },
"CSAT": {
"TITLE": "Enable CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Viesti",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "contains",
"DOES_NOT_CONTAINS": "does not contain"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Set your availability", "TITLE": "Set your availability",
"SUBTITLE": "Set your availability on your livechat widget", "SUBTITLE": "Set your availability on your livechat widget",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Formulaire avant chat", "PRE_CHAT_FORM": "Formulaire avant chat",
"BUSINESS_HOURS": "Heures de bureau", "BUSINESS_HOURS": "Heures de bureau",
"WIDGET_BUILDER": "Constructeur de Widget", "WIDGET_BUILDER": "Constructeur de Widget",
"BOT_CONFIGURATION": "Configuration du bot", "BOT_CONFIGURATION": "Configuration du bot"
"CSAT": "CSAT"
}, },
"SETTINGS": "Paramètres", "SETTINGS": "Paramètres",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"ENABLE_EMAIL_COLLECT_BOX": "Activer la boîte de collecte des courriels", "ENABLE_EMAIL_COLLECT_BOX": "Activer la boîte de collecte des courriels",
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Activer ou désactiver la boîte de collecte des courriels pour les nouvelles conversations", "ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Activer ou désactiver la boîte de collecte des courriels pour les nouvelles conversations",
"AUTO_ASSIGNMENT": "Activer l'assignation automatique", "AUTO_ASSIGNMENT": "Activer l'assignation automatique",
"ENABLE_CSAT": "Activer CSAT",
"SENDER_NAME_SECTION": "Activer le nom de l'agent dans l'e-mail", "SENDER_NAME_SECTION": "Activer le nom de l'agent dans l'e-mail",
"ENABLE_CSAT_SUB_TEXT": "Activer/Désactiver l'enquête CSAT(satisfaction du client) après avoir résolu une conversation",
"SENDER_NAME_SECTION_TEXT": "Activer/Désactiver l'affichage du nom de l'agent dans l'e-mail, si désactivé, il affichera le nom de l'entreprise", "SENDER_NAME_SECTION_TEXT": "Activer/Désactiver l'affichage du nom de l'agent dans l'e-mail, si désactivé, il affichera le nom de l'entreprise",
"ENABLE_CONTINUITY_VIA_EMAIL": "Activer la continuité de la conversation par e-mail", "ENABLE_CONTINUITY_VIA_EMAIL": "Activer la continuité de la conversation par e-mail",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Les conversations se poursuivront par courrier électronique si l'adresse e-mail du contact est disponible.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Les conversations se poursuivront par courrier électronique si l'adresse e-mail du contact est disponible.",
@@ -577,32 +578,6 @@
"LABEL": "Les visiteurs doivent indiquer leur nom et leur courriel avant de commencer le chat" "LABEL": "Les visiteurs doivent indiquer leur nom et leur courriel avant de commencer le chat"
} }
}, },
"CSAT": {
"TITLE": "Activer CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Message",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "contient",
"DOES_NOT_CONTAINS": "ne contient pas"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Définissez votre disponibilité", "TITLE": "Définissez votre disponibilité",
"SUBTITLE": "Définissez votre disponibilité sur votre widget livechat", "SUBTITLE": "Définissez votre disponibilité sur votre widget livechat",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "טופס צ'אט מקדים", "PRE_CHAT_FORM": "טופס צ'אט מקדים",
"BUSINESS_HOURS": "שעות פעילות", "BUSINESS_HOURS": "שעות פעילות",
"WIDGET_BUILDER": "בונה יישומונים", "WIDGET_BUILDER": "בונה יישומונים",
"BOT_CONFIGURATION": "הגדרות בוט", "BOT_CONFIGURATION": "הגדרות בוט"
"CSAT": "CSAT"
}, },
"SETTINGS": "הגדרות", "SETTINGS": "הגדרות",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"ENABLE_EMAIL_COLLECT_BOX": "אפשר תיבת איסוף דוא\"ל", "ENABLE_EMAIL_COLLECT_BOX": "אפשר תיבת איסוף דוא\"ל",
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "הפעל או השבת את תיבת איסוף הדוא\"ל בשיחה חדשה", "ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "הפעל או השבת את תיבת איסוף הדוא\"ל בשיחה חדשה",
"AUTO_ASSIGNMENT": "אפשר הקצאה אוטומטית", "AUTO_ASSIGNMENT": "אפשר הקצאה אוטומטית",
"ENABLE_CSAT": "אפשר CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "הפעל/השבת סקר CSAT (שביעות רצון לקוחות) לאחר פתרון שיחה",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "אפשר המשך שיחה באמצעות הדוא\"ל", "ENABLE_CONTINUITY_VIA_EMAIL": "אפשר המשך שיחה באמצעות הדוא\"ל",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "שיחות ימשיכו באמצעות הדוא\"ל אם לאיש הקשר קיימת כתובת דוא\"ל תקנית.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "שיחות ימשיכו באמצעות הדוא\"ל אם לאיש הקשר קיימת כתובת דוא\"ל תקנית.",
@@ -577,32 +578,6 @@
"LABEL": "המבקרים צריכים לספק את שמם וכתובת האימייל שלהם לפני תחילת הצ'אט" "LABEL": "המבקרים צריכים לספק את שמם וכתובת האימייל שלהם לפני תחילת הצ'אט"
} }
}, },
"CSAT": {
"TITLE": "אפשר CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "הודעה",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "מכיל",
"DOES_NOT_CONTAINS": "לא מכיל"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "הגדר את הזמינות שלך", "TITLE": "הגדר את הזמינות שלך",
"SUBTITLE": "הגדר את הזמינות שלך בווידג'ט הצ'אט החי שלך", "SUBTITLE": "הגדר את הזמינות שלך בווידג'ט הצ'אט החי שלך",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Pre Chat Form", "PRE_CHAT_FORM": "Pre Chat Form",
"BUSINESS_HOURS": "Business Hours", "BUSINESS_HOURS": "Business Hours",
"WIDGET_BUILDER": "Widget Builder", "WIDGET_BUILDER": "Widget Builder",
"BOT_CONFIGURATION": "Bot Configuration", "BOT_CONFIGURATION": "Bot Configuration"
"CSAT": "CSAT"
}, },
"SETTINGS": "Settings", "SETTINGS": "Settings",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"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",
"AUTO_ASSIGNMENT": "Enable auto assignment", "AUTO_ASSIGNMENT": "Enable auto assignment",
"ENABLE_CSAT": "Enable CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Enable/Disable CSAT(Customer satisfaction) survey after resolving a conversation",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email", "ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.",
@@ -577,32 +578,6 @@
"LABEL": "Visitors should provide their name and email address before starting the chat" "LABEL": "Visitors should provide their name and email address before starting the chat"
} }
}, },
"CSAT": {
"TITLE": "Enable CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Message",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "contains",
"DOES_NOT_CONTAINS": "does not contain"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Set your availability", "TITLE": "Set your availability",
"SUBTITLE": "Set your availability on your livechat widget", "SUBTITLE": "Set your availability on your livechat widget",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Pre Chat Form", "PRE_CHAT_FORM": "Pre Chat Form",
"BUSINESS_HOURS": "Business Hours", "BUSINESS_HOURS": "Business Hours",
"WIDGET_BUILDER": "Widget Builder", "WIDGET_BUILDER": "Widget Builder",
"BOT_CONFIGURATION": "Bot Configuration", "BOT_CONFIGURATION": "Bot Configuration"
"CSAT": "CSAT"
}, },
"SETTINGS": "Settings", "SETTINGS": "Settings",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"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",
"AUTO_ASSIGNMENT": "Enable auto assignment", "AUTO_ASSIGNMENT": "Enable auto assignment",
"ENABLE_CSAT": "Enable CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Enable/Disable CSAT(Customer satisfaction) survey after resolving a conversation",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email", "ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.",
@@ -577,32 +578,6 @@
"LABEL": "Visitors should provide their name and email address before starting the chat" "LABEL": "Visitors should provide their name and email address before starting the chat"
} }
}, },
"CSAT": {
"TITLE": "Enable CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Poruka",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "sadrži",
"DOES_NOT_CONTAINS": "ne sadrži"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Set your availability", "TITLE": "Set your availability",
"SUBTITLE": "Set your availability on your livechat widget", "SUBTITLE": "Set your availability on your livechat widget",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Chat előtti űrlap", "PRE_CHAT_FORM": "Chat előtti űrlap",
"BUSINESS_HOURS": "Nyitvatartás", "BUSINESS_HOURS": "Nyitvatartás",
"WIDGET_BUILDER": "Widget építő", "WIDGET_BUILDER": "Widget építő",
"BOT_CONFIGURATION": "Bot konfiguráció", "BOT_CONFIGURATION": "Bot konfiguráció"
"CSAT": "CSAT"
}, },
"SETTINGS": "Beállítások", "SETTINGS": "Beállítások",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"ENABLE_EMAIL_COLLECT_BOX": "E-mail gyűjtődoboz engedélyezése", "ENABLE_EMAIL_COLLECT_BOX": "E-mail gyűjtődoboz engedélyezése",
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Az e-mailek gyűjtődobozának engedélyezése vagy letiltása új beszélgetéseknél", "ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Az e-mailek gyűjtődobozának engedélyezése vagy letiltása új beszélgetéseknél",
"AUTO_ASSIGNMENT": "Automata hozzárendelés engedélyezése", "AUTO_ASSIGNMENT": "Automata hozzárendelés engedélyezése",
"ENABLE_CSAT": "CSAT engedélyezése",
"SENDER_NAME_SECTION": "Ügynök nevének engedélyezése e-mailben", "SENDER_NAME_SECTION": "Ügynök nevének engedélyezése e-mailben",
"ENABLE_CSAT_SUB_TEXT": "A CSAT (Ügyfél-elégedettség) felmérés engedélyezése/letiltása egy beszélgetés megoldása után",
"SENDER_NAME_SECTION_TEXT": "Az ügynök nevének megjelenítésének engedélyezése/letiltása az e-mailben, ha le van tiltva, akkor a cég neve jelenik meg", "SENDER_NAME_SECTION_TEXT": "Az ügynök nevének megjelenítésének engedélyezése/letiltása az e-mailben, ha le van tiltva, akkor a cég neve jelenik meg",
"ENABLE_CONTINUITY_VIA_EMAIL": "Beszélgetés folytatásának engedélyezése emailen keresztül", "ENABLE_CONTINUITY_VIA_EMAIL": "Beszélgetés folytatásának engedélyezése emailen keresztül",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "A beszélgetések e-mailben folytatódnak, ha elérhető a kapcsolattartási e-mail cím.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "A beszélgetések e-mailben folytatódnak, ha elérhető a kapcsolattartási e-mail cím.",
@@ -577,32 +578,6 @@
"LABEL": "A látogatóknak nevük és e-mailcímük megadása szükséges a beszélgetés megkezdése előtt" "LABEL": "A látogatóknak nevük és e-mailcímük megadása szükséges a beszélgetés megkezdése előtt"
} }
}, },
"CSAT": {
"TITLE": "CSAT engedélyezése",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Üzenet",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "tartalmaz",
"DOES_NOT_CONTAINS": "nem tartalmaz"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Elérhetőség beállítása", "TITLE": "Elérhetőség beállítása",
"SUBTITLE": "Állításd be az elérhetőséged idejét a chat widgeten", "SUBTITLE": "Állításd be az elérhetőséged idejét a chat widgeten",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Pre Chat Form", "PRE_CHAT_FORM": "Pre Chat Form",
"BUSINESS_HOURS": "Business Hours", "BUSINESS_HOURS": "Business Hours",
"WIDGET_BUILDER": "Widget Builder", "WIDGET_BUILDER": "Widget Builder",
"BOT_CONFIGURATION": "Bot Configuration", "BOT_CONFIGURATION": "Bot Configuration"
"CSAT": "CSAT"
}, },
"SETTINGS": "Settings", "SETTINGS": "Settings",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"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",
"AUTO_ASSIGNMENT": "Enable auto assignment", "AUTO_ASSIGNMENT": "Enable auto assignment",
"ENABLE_CSAT": "Enable CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Enable/Disable CSAT(Customer satisfaction) survey after resolving a conversation",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email", "ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.",
@@ -577,32 +578,6 @@
"LABEL": "Visitors should provide their name and email address before starting the chat" "LABEL": "Visitors should provide their name and email address before starting the chat"
} }
}, },
"CSAT": {
"TITLE": "Enable CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Message",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "contains",
"DOES_NOT_CONTAINS": "does not contain"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Set your availability", "TITLE": "Set your availability",
"SUBTITLE": "Set your availability on your livechat widget", "SUBTITLE": "Set your availability on your livechat widget",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Formulir Pra Obrolan", "PRE_CHAT_FORM": "Formulir Pra Obrolan",
"BUSINESS_HOURS": "Jam Kerja", "BUSINESS_HOURS": "Jam Kerja",
"WIDGET_BUILDER": "Pembuat Widget", "WIDGET_BUILDER": "Pembuat Widget",
"BOT_CONFIGURATION": "Konfigurasi Bot", "BOT_CONFIGURATION": "Konfigurasi Bot"
"CSAT": "CSAT"
}, },
"SETTINGS": "Pengaturan", "SETTINGS": "Pengaturan",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"ENABLE_EMAIL_COLLECT_BOX": "Aktifkan kotak pengumpulan email", "ENABLE_EMAIL_COLLECT_BOX": "Aktifkan kotak pengumpulan email",
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Aktifkan atau nonaktifkan kotak pengumpulan email pada percakpaan baru", "ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Aktifkan atau nonaktifkan kotak pengumpulan email pada percakpaan baru",
"AUTO_ASSIGNMENT": "Aktifkan penugasan otomatis", "AUTO_ASSIGNMENT": "Aktifkan penugasan otomatis",
"ENABLE_CSAT": "Aktifkan CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Aktifkan/Nonaktifkan survey CSAT (Kepuasan pelanggan) setelah penyelesaian percakapan",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "Aktifkan kontinuitas percakapan melalui email", "ENABLE_CONTINUITY_VIA_EMAIL": "Aktifkan kontinuitas percakapan melalui email",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Percakapan akan berlanjut melalui email jika alamat email kontak tersedia.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Percakapan akan berlanjut melalui email jika alamat email kontak tersedia.",
@@ -577,32 +578,6 @@
"LABEL": "Pengunjung harus memberikan nama dan alamat email mereka sebelum memulai obrolan" "LABEL": "Pengunjung harus memberikan nama dan alamat email mereka sebelum memulai obrolan"
} }
}, },
"CSAT": {
"TITLE": "Aktifkan CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Pesan",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "berisi",
"DOES_NOT_CONTAINS": "tidak berisi"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Atur ketersediaan Anda", "TITLE": "Atur ketersediaan Anda",
"SUBTITLE": "Atur ketersediaan Anda di widget livechat", "SUBTITLE": "Atur ketersediaan Anda di widget livechat",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Pre Chat Form", "PRE_CHAT_FORM": "Pre Chat Form",
"BUSINESS_HOURS": "Business Hours", "BUSINESS_HOURS": "Business Hours",
"WIDGET_BUILDER": "Widget Builder", "WIDGET_BUILDER": "Widget Builder",
"BOT_CONFIGURATION": "Bot stillingar", "BOT_CONFIGURATION": "Bot stillingar"
"CSAT": "CSAT"
}, },
"SETTINGS": "Stillingar", "SETTINGS": "Stillingar",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"ENABLE_EMAIL_COLLECT_BOX": "Enable email collect box", "ENABLE_EMAIL_COLLECT_BOX": "Enable email collect box",
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Virkja eða slökkva á söfnunarreit tölvupósts í nýju samtali", "ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Virkja eða slökkva á söfnunarreit tölvupósts í nýju samtali",
"AUTO_ASSIGNMENT": "Enable auto assignment", "AUTO_ASSIGNMENT": "Enable auto assignment",
"ENABLE_CSAT": "Enable CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Virkja/slökkva á CSAT (ánægju viðskiptavina) könnun eftir að hafa leyst samtal",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email", "ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Samtöl halda áfram með tölvupósti ef tengiliðanetfangið er tiltækt.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Samtöl halda áfram með tölvupósti ef tengiliðanetfangið er tiltækt.",
@@ -577,32 +578,6 @@
"LABEL": "Gestir ættu að gefa upp nafn sitt og netfang áður en spjallið hefst" "LABEL": "Gestir ættu að gefa upp nafn sitt og netfang áður en spjallið hefst"
} }
}, },
"CSAT": {
"TITLE": "Enable CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Skilaboð",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "contains",
"DOES_NOT_CONTAINS": "does not contain"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Set your availability", "TITLE": "Set your availability",
"SUBTITLE": "Stilltu framboð þitt á netspjalli", "SUBTITLE": "Stilltu framboð þitt á netspjalli",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Modulo pre-chat", "PRE_CHAT_FORM": "Modulo pre-chat",
"BUSINESS_HOURS": "Ore di lavoro", "BUSINESS_HOURS": "Ore di lavoro",
"WIDGET_BUILDER": "Costruttore Widget", "WIDGET_BUILDER": "Costruttore Widget",
"BOT_CONFIGURATION": "Bot Configuration", "BOT_CONFIGURATION": "Bot Configuration"
"CSAT": "CSAT"
}, },
"SETTINGS": "Impostazioni", "SETTINGS": "Impostazioni",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"ENABLE_EMAIL_COLLECT_BOX": "Abilita casella di raccolta email", "ENABLE_EMAIL_COLLECT_BOX": "Abilita casella di raccolta email",
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Abilita o disabilita la casella di raccolta email nella nuova conversazione", "ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Abilita o disabilita la casella di raccolta email nella nuova conversazione",
"AUTO_ASSIGNMENT": "Abilita assegnazione automatica", "AUTO_ASSIGNMENT": "Abilita assegnazione automatica",
"ENABLE_CSAT": "Abilita CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Attiva/Disabilita il sondaggio CSAT (soddisfazione del cliente) dopo aver risolto una conversazione",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "Abilita la continuità della conversazione via email", "ENABLE_CONTINUITY_VIA_EMAIL": "Abilita la continuità della conversazione via email",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Le conversazioni continueranno via email se l'indirizzo email del contatto è disponibile.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Le conversazioni continueranno via email se l'indirizzo email del contatto è disponibile.",
@@ -577,32 +578,6 @@
"LABEL": "I visitatori devono fornire il proprio nome e indirizzo email prima di iniziare la chat" "LABEL": "I visitatori devono fornire il proprio nome e indirizzo email prima di iniziare la chat"
} }
}, },
"CSAT": {
"TITLE": "Abilita CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Messaggio",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "contiene",
"DOES_NOT_CONTAINS": "non contiene"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Imposta la tua disponibilità", "TITLE": "Imposta la tua disponibilità",
"SUBTITLE": "Imposta la tua disponibilità sul tuo widget live chat", "SUBTITLE": "Imposta la tua disponibilità sul tuo widget live chat",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "プレチャットフォーム", "PRE_CHAT_FORM": "プレチャットフォーム",
"BUSINESS_HOURS": "営業時間", "BUSINESS_HOURS": "営業時間",
"WIDGET_BUILDER": "ウィジェットビルダー", "WIDGET_BUILDER": "ウィジェットビルダー",
"BOT_CONFIGURATION": "ボット設定", "BOT_CONFIGURATION": "ボット設定"
"CSAT": "顧客満足度"
}, },
"SETTINGS": "設定", "SETTINGS": "設定",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"ENABLE_EMAIL_COLLECT_BOX": "メール収集ボックスを有効にする", "ENABLE_EMAIL_COLLECT_BOX": "メール収集ボックスを有効にする",
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "新しい会話でメール収集ボックスを有効または無効にする", "ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "新しい会話でメール収集ボックスを有効または無効にする",
"AUTO_ASSIGNMENT": "自動割り当てを有効にする", "AUTO_ASSIGNMENT": "自動割り当てを有効にする",
"ENABLE_CSAT": "CSATを有効にする",
"SENDER_NAME_SECTION": "メールに担当者名を表示する", "SENDER_NAME_SECTION": "メールに担当者名を表示する",
"ENABLE_CSAT_SUB_TEXT": "会話解決後にCSAT(顧客満足度)調査を有効または無効にする",
"SENDER_NAME_SECTION_TEXT": "担当者名をメールに表示するかどうかを設定します。無効にするとビジネス名が表示されます。", "SENDER_NAME_SECTION_TEXT": "担当者名をメールに表示するかどうかを設定します。無効にするとビジネス名が表示されます。",
"ENABLE_CONTINUITY_VIA_EMAIL": "メールによる会話の継続を有効にする", "ENABLE_CONTINUITY_VIA_EMAIL": "メールによる会話の継続を有効にする",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "連絡先のメールアドレスが利用可能な場合、会話はメールで継続されます。", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "連絡先のメールアドレスが利用可能な場合、会話はメールで継続されます。",
@@ -577,32 +578,6 @@
"LABEL": "訪問者はチャットを開始する前に名前とメールアドレスを提供する必要があります" "LABEL": "訪問者はチャットを開始する前に名前とメールアドレスを提供する必要があります"
} }
}, },
"CSAT": {
"TITLE": "CSATを有効にする",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "メッセージ",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "含む",
"DOES_NOT_CONTAINS": "含まない"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "営業時間を設定する", "TITLE": "営業時間を設定する",
"SUBTITLE": "ライブチャットウィジェットでの利用可能時間を設定します", "SUBTITLE": "ライブチャットウィジェットでの利用可能時間を設定します",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Pre Chat Form", "PRE_CHAT_FORM": "Pre Chat Form",
"BUSINESS_HOURS": "Business Hours", "BUSINESS_HOURS": "Business Hours",
"WIDGET_BUILDER": "Widget Builder", "WIDGET_BUILDER": "Widget Builder",
"BOT_CONFIGURATION": "Bot Configuration", "BOT_CONFIGURATION": "Bot Configuration"
"CSAT": "CSAT"
}, },
"SETTINGS": "Settings", "SETTINGS": "Settings",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"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",
"AUTO_ASSIGNMENT": "Enable auto assignment", "AUTO_ASSIGNMENT": "Enable auto assignment",
"ENABLE_CSAT": "Enable CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Enable/Disable CSAT(Customer satisfaction) survey after resolving a conversation",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email", "ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.",
@@ -577,32 +578,6 @@
"LABEL": "Visitors should provide their name and email address before starting the chat" "LABEL": "Visitors should provide their name and email address before starting the chat"
} }
}, },
"CSAT": {
"TITLE": "Enable CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Message",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "contains",
"DOES_NOT_CONTAINS": "does not contain"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Set your availability", "TITLE": "Set your availability",
"SUBTITLE": "Set your availability on your livechat widget", "SUBTITLE": "Set your availability on your livechat widget",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "대화 전 설문", "PRE_CHAT_FORM": "대화 전 설문",
"BUSINESS_HOURS": "영업시간", "BUSINESS_HOURS": "영업시간",
"WIDGET_BUILDER": "Widget Builder", "WIDGET_BUILDER": "Widget Builder",
"BOT_CONFIGURATION": "Bot Configuration", "BOT_CONFIGURATION": "Bot Configuration"
"CSAT": "CSAT"
}, },
"SETTINGS": "설정", "SETTINGS": "설정",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"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",
"AUTO_ASSIGNMENT": "자동 할당 사용", "AUTO_ASSIGNMENT": "자동 할당 사용",
"ENABLE_CSAT": "Enable CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Enable/Disable CSAT(Customer satisfaction) survey after resolving a conversation",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email", "ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.",
@@ -577,32 +578,6 @@
"LABEL": "대화 전 사용자들에게 이름과 이메일 주소를 요구합니다." "LABEL": "대화 전 사용자들에게 이름과 이메일 주소를 요구합니다."
} }
}, },
"CSAT": {
"TITLE": "Enable CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "메시지",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "포함된",
"DOES_NOT_CONTAINS": "포함되지 않은"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "영업시간 설정", "TITLE": "영업시간 설정",
"SUBTITLE": "라이브챗 위젯의 대화용 영업시간을 설정하세요.", "SUBTITLE": "라이브챗 위젯의 대화용 영업시간을 설정하세요.",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Anketa, rodoma prieš pokalbio internetu pradžią", "PRE_CHAT_FORM": "Anketa, rodoma prieš pokalbio internetu pradžią",
"BUSINESS_HOURS": "Darbo valandos", "BUSINESS_HOURS": "Darbo valandos",
"WIDGET_BUILDER": "Valdiklių kūrimo priemonė", "WIDGET_BUILDER": "Valdiklių kūrimo priemonė",
"BOT_CONFIGURATION": "Boto konfiguracija", "BOT_CONFIGURATION": "Boto konfiguracija"
"CSAT": "CSAT"
}, },
"SETTINGS": "Nustatymai", "SETTINGS": "Nustatymai",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"ENABLE_EMAIL_COLLECT_BOX": "Leisti el. pašto surinkimo dėžutę", "ENABLE_EMAIL_COLLECT_BOX": "Leisti el. pašto surinkimo dėžutę",
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Naujame pokalbyje leiskite arba drauskite el. pašto surinkimo dėžutę", "ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Naujame pokalbyje leiskite arba drauskite el. pašto surinkimo dėžutę",
"AUTO_ASSIGNMENT": "Įjunkti automatinį priskyrimą", "AUTO_ASSIGNMENT": "Įjunkti automatinį priskyrimą",
"ENABLE_CSAT": "Leisti CSAT",
"SENDER_NAME_SECTION": "Leisti agento vardą el. pašte", "SENDER_NAME_SECTION": "Leisti agento vardą el. pašte",
"ENABLE_CSAT_SUB_TEXT": "Leisti/neleisti CSAT (klientų pasitenkinimo) apklausą, kai baigsite pokalbį",
"SENDER_NAME_SECTION_TEXT": "Įjungti/išjungti agento vardo rodymą el. pašte, jei išjungta, bus rodomas įmonės pavadinimas", "SENDER_NAME_SECTION_TEXT": "Įjungti/išjungti agento vardo rodymą el. pašte, jei išjungta, bus rodomas įmonės pavadinimas",
"ENABLE_CONTINUITY_VIA_EMAIL": "Leisti pokalbio tęstinumą el. paštu", "ENABLE_CONTINUITY_VIA_EMAIL": "Leisti pokalbio tęstinumą el. paštu",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Jei kontaktinis el. pašto adresas yra pasiekiamas, pokalbiai bus tęsiami el. paštu.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Jei kontaktinis el. pašto adresas yra pasiekiamas, pokalbiai bus tęsiami el. paštu.",
@@ -577,32 +578,6 @@
"LABEL": "Prieš pradėdami pokalbį lankytojai turėtų nurodyti savo vardą ir el. pašto adresą" "LABEL": "Prieš pradėdami pokalbį lankytojai turėtų nurodyti savo vardą ir el. pašto adresą"
} }
}, },
"CSAT": {
"TITLE": "Leisti CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Žinutė",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "sudėtyje yra",
"DOES_NOT_CONTAINS": "sudėtyje nėra"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Nustatykite savo pasiekiamumą", "TITLE": "Nustatykite savo pasiekiamumą",
"SUBTITLE": "Nustatykite savo pasiekiamumą tiesioginio pokalbio valdiklyje", "SUBTITLE": "Nustatykite savo pasiekiamumą tiesioginio pokalbio valdiklyje",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Pirms-Tērzēšanas Veidlapa", "PRE_CHAT_FORM": "Pirms-Tērzēšanas Veidlapa",
"BUSINESS_HOURS": "Darba Laiks", "BUSINESS_HOURS": "Darba Laiks",
"WIDGET_BUILDER": "Logrīku Veidotājs", "WIDGET_BUILDER": "Logrīku Veidotājs",
"BOT_CONFIGURATION": "Robota Konfigurācija", "BOT_CONFIGURATION": "Robota Konfigurācija"
"CSAT": "CSAT"
}, },
"SETTINGS": "Iestatījumi", "SETTINGS": "Iestatījumi",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"ENABLE_EMAIL_COLLECT_BOX": "Iespējot e-pasta iegūšanas lodziņu", "ENABLE_EMAIL_COLLECT_BOX": "Iespējot e-pasta iegūšanas lodziņu",
"ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Iespējot vai atspējot e-pasta iegūšanas lodziņu jaunai sarunai", "ENABLE_EMAIL_COLLECT_BOX_SUB_TEXT": "Iespējot vai atspējot e-pasta iegūšanas lodziņu jaunai sarunai",
"AUTO_ASSIGNMENT": "Iespējot automātisko piešķiršanu", "AUTO_ASSIGNMENT": "Iespējot automātisko piešķiršanu",
"ENABLE_CSAT": "Iespējot CSAT",
"SENDER_NAME_SECTION": "Iespējot Aģenta Vārdu E-pastā", "SENDER_NAME_SECTION": "Iespējot Aģenta Vārdu E-pastā",
"ENABLE_CSAT_SUB_TEXT": "Iespējot/Atspējot CSAT (klientu apmierinātības) aptauju pēc sarunas atrisināšanas",
"SENDER_NAME_SECTION_TEXT": "Iespējot/Atspējot aģenta vārda rādīšanu e-pastā. Ja tas ir atspējots, tiks rādīts uzņēmuma nosaukums", "SENDER_NAME_SECTION_TEXT": "Iespējot/Atspējot aģenta vārda rādīšanu e-pastā. Ja tas ir atspējots, tiks rādīts uzņēmuma nosaukums",
"ENABLE_CONTINUITY_VIA_EMAIL": "Iespējot sarunas nepārtrauktību, izmantojot e-pastu", "ENABLE_CONTINUITY_VIA_EMAIL": "Iespējot sarunas nepārtrauktību, izmantojot e-pastu",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Sarunas turpināsies pa e-pastu, ja saziņas e-pasta adrese ir pieejama.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Sarunas turpināsies pa e-pastu, ja saziņas e-pasta adrese ir pieejama.",
@@ -577,32 +578,6 @@
"LABEL": "Apmeklētājiem pirms tērzēšanas ir jānorāda savs vārds un e-pasta adrese" "LABEL": "Apmeklētājiem pirms tērzēšanas ir jānorāda savs vārds un e-pasta adrese"
} }
}, },
"CSAT": {
"TITLE": "Iespējot CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Ziņojums",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "satur",
"DOES_NOT_CONTAINS": "nesatur"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Iestatīt savu pieejamību", "TITLE": "Iestatīt savu pieejamību",
"SUBTITLE": "Iestatīt savu pieejamību tiešraides tērzēšanas logrīkā", "SUBTITLE": "Iestatīt savu pieejamību tiešraides tērzēšanas logrīkā",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Pre Chat Form", "PRE_CHAT_FORM": "Pre Chat Form",
"BUSINESS_HOURS": "Business Hours", "BUSINESS_HOURS": "Business Hours",
"WIDGET_BUILDER": "Widget Builder", "WIDGET_BUILDER": "Widget Builder",
"BOT_CONFIGURATION": "Bot Configuration", "BOT_CONFIGURATION": "Bot Configuration"
"CSAT": "CSAT"
}, },
"SETTINGS": "ക്രമീകരണങ്ങൾ", "SETTINGS": "ക്രമീകരണങ്ങൾ",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"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",
"AUTO_ASSIGNMENT": "ഓട്ടോ അസൈൻമെന്റ് പ്രവർത്തനക്ഷമമാക്കുക", "AUTO_ASSIGNMENT": "ഓട്ടോ അസൈൻമെന്റ് പ്രവർത്തനക്ഷമമാക്കുക",
"ENABLE_CSAT": "Enable CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Enable/Disable CSAT(Customer satisfaction) survey after resolving a conversation",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "ഇമെയിൽ വഴി സംഭാഷണ തുടർച്ച പ്രവർത്തനക്ഷമമാക്കുക", "ENABLE_CONTINUITY_VIA_EMAIL": "ഇമെയിൽ വഴി സംഭാഷണ തുടർച്ച പ്രവർത്തനക്ഷമമാക്കുക",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "ബന്ധപ്പെടാനുള്ള ഇമെയിൽ വിലാസം ലഭ്യമാണെങ്കിൽ സംഭാഷണങ്ങൾ ഇമെയിൽ വഴി തുടരും.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "ബന്ധപ്പെടാനുള്ള ഇമെയിൽ വിലാസം ലഭ്യമാണെങ്കിൽ സംഭാഷണങ്ങൾ ഇമെയിൽ വഴി തുടരും.",
@@ -577,32 +578,6 @@
"LABEL": "Visitors should provide their name and email address before starting the chat" "LABEL": "Visitors should provide their name and email address before starting the chat"
} }
}, },
"CSAT": {
"TITLE": "Enable CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "സന്ദേശം",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "അടങ്ങിയിരിക്കുന്നു",
"DOES_NOT_CONTAINS": "ഉൾപ്പെട്ടിട്ടില്ല"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Set your availability", "TITLE": "Set your availability",
"SUBTITLE": "Set your availability on your livechat widget", "SUBTITLE": "Set your availability on your livechat widget",
@@ -481,8 +481,7 @@
"PRE_CHAT_FORM": "Pre Chat Form", "PRE_CHAT_FORM": "Pre Chat Form",
"BUSINESS_HOURS": "Business Hours", "BUSINESS_HOURS": "Business Hours",
"WIDGET_BUILDER": "Widget Builder", "WIDGET_BUILDER": "Widget Builder",
"BOT_CONFIGURATION": "Bot Configuration", "BOT_CONFIGURATION": "Bot Configuration"
"CSAT": "CSAT"
}, },
"SETTINGS": "Settings", "SETTINGS": "Settings",
"FEATURES": { "FEATURES": {
@@ -503,7 +502,9 @@
"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",
"AUTO_ASSIGNMENT": "Enable auto assignment", "AUTO_ASSIGNMENT": "Enable auto assignment",
"ENABLE_CSAT": "Enable CSAT",
"SENDER_NAME_SECTION": "Enable Agent Name in Email", "SENDER_NAME_SECTION": "Enable Agent Name in Email",
"ENABLE_CSAT_SUB_TEXT": "Enable/Disable CSAT(Customer satisfaction) survey after resolving a conversation",
"SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name", "SENDER_NAME_SECTION_TEXT": "Enable/Disable showing Agent's name in email, if disabled it will show business name",
"ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email", "ENABLE_CONTINUITY_VIA_EMAIL": "Enable conversation continuity via email",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.", "ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "Conversations will continue over email if the contact email address is available.",
@@ -577,32 +578,6 @@
"LABEL": "Visitors should provide their name and email address before starting the chat" "LABEL": "Visitors should provide their name and email address before starting the chat"
} }
}, },
"CSAT": {
"TITLE": "Enable CSAT",
"SUBTITLE": "Automatically trigger CSAT surveys at the end of conversations to understand how customers feel about their support experience. Track satisfaction trends and identify areas for improvement over time.",
"DISPLAY_TYPE": {
"LABEL": "Display type"
},
"MESSAGE": {
"LABEL": "Message",
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
"DESCRIPTION_SUFFIX": "any of the labels",
"OPERATOR": {
"CONTAINS": "mengandungi",
"DOES_NOT_CONTAINS": "tidak mengandungi"
},
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
}
},
"BUSINESS_HOURS": { "BUSINESS_HOURS": {
"TITLE": "Set your availability", "TITLE": "Set your availability",
"SUBTITLE": "Set your availability on your livechat widget", "SUBTITLE": "Set your availability on your livechat widget",

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