diff --git a/.env.example b/.env.example
index 110bd4292..281cd64d1 100644
--- a/.env.example
+++ b/.env.example
@@ -4,6 +4,9 @@ SECRET_KEY_BASE=replace_with_lengthy_secure_hex
# Replace with the URL you are planning to use for your app
FRONTEND_URL=http://0.0.0.0:3000
+# If you plan to use CDN for your assets, set Asset CDN Host
+ASSET_CDN_HOST=
+
# Force all access to the app over SSL, default is set to false
FORCE_SSL=false
@@ -103,7 +106,7 @@ IOS_APP_ID=6C953F3RX2.com.chatwoot.app
# VAPID_PUBLIC_KEY=
# VAPID_PRIVATE_KEY=
#
-# for mobile apps
+# for mobile apps
# FCM_SERVER_KEY=
## Bot Customizations
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index dd84ea782..66e142ad6 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -2,15 +2,16 @@
name: Bug report
about: Create a report to help us improve
title: ''
-labels: ''
+labels: 'Bug'
assignees: ''
---
-
**Describe the bug**
+
A clear and concise description of what the bug is.
**To Reproduce**
+
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
@@ -18,11 +19,17 @@ Steps to reproduce the behavior:
4. See error
**Expected behavior**
+
A clear and concise description of what you expected to happen.
**Screenshots**
+
If applicable, add screenshots to help explain your problem.
+**Environment**
+
+Describe whether you are using Chatwoot Cloud (app.chatwoot.com) or a self hosted installation of Chatwoot. If you are using a self hosted installation of Chatwoot describe the type of deployment (Docker/Linux VM installation/Heroku)
+
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
@@ -35,4 +42,5 @@ If applicable, add screenshots to help explain your problem.
- Version [e.g. 22]
**Additional context**
+
Add any other context about the problem here.
diff --git a/.rubocop.yml b/.rubocop.yml
index ab5efd6c8..c27b9651b 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -4,20 +4,8 @@ require:
- rubocop-rspec
inherit_from: .rubocop_todo.yml
-Lint/RaiseException:
- Enabled: true
-Lint/StructNewOverride:
- Enabled: true
-Lint/DeprecatedOpenSSLConstant:
- Enabled: true
-Lint/MixedRegexpCaptureTypes:
- Enabled: true
Layout/LineLength:
Max: 150
-Layout/EmptyLinesAroundAttributeAccessor:
- Enabled: true
-Layout/SpaceAroundMethodCallOperator:
- Enabled: true
Metrics/ClassLength:
Max: 125
@@ -33,25 +21,21 @@ Style/FrozenStringLiteralComment:
Enabled: false
Style/SymbolArray:
Enabled: false
-Style/HashEachMethods:
- Enabled: true
-Style/HashTransformKeys:
- Enabled: true
-Style/HashTransformValues:
- Enabled: true
-Style/RedundantFetchBlock:
- Enabled: true
-Style/RedundantRegexpCharacterClass:
- Enabled: true
-Style/RedundantRegexpEscape:
- Enabled: true
-Style/SlicingWithRange:
- Enabled: true
+Style/OptionalBooleanParameter:
+ Exclude:
+ - 'app/services/email_templates/db_resolver_service.rb'
+ - 'app/dispatchers/dispatcher.rb'
Style/GlobalVars:
Exclude:
- 'config/initializers/redis.rb'
- 'lib/redis/alfred.rb'
- 'lib/global_config.rb'
+Style/ClassVars:
+ Exclude:
+ - 'app/services/email_templates/db_resolver_service.rb'
+Lint/MissingSuper:
+ Exclude:
+ - 'app/drops/base_drop.rb'
Metrics/BlockLength:
Exclude:
- spec/**/*
@@ -87,8 +71,11 @@ Style/GuardClause:
- 'db/migrate/20190819005836_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb'
Metrics/AbcSize:
Exclude:
+ - 'app/controllers/concerns/auth_helper.rb'
- 'db/migrate/20190819005836_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb'
+ - 'db/migrate/20161123131628_devise_token_auth_create_users.rb'
Metrics/CyclomaticComplexity:
+ Max: 7
Exclude:
- 'db/migrate/20190819005836_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb'
Rails/ReversibleMigration:
@@ -115,9 +102,16 @@ Rails/UniqueValidationWithoutIndex:
Exclude:
- 'app/models/channel/twitter_profile.rb'
- 'app/models/webhook.rb'
+Rails/RenderInline:
+ Exclude:
+ - 'app/controllers/swagger_controller.rb'
RSpec/NamedSubject:
Enabled: false
+# we should bring this down
+RSpec/MultipleMemoizedHelpers:
+ Max: 12
AllCops:
+ NewCops: enable
Exclude:
- 'bin/**/*'
- 'db/schema.rb'
@@ -129,3 +123,4 @@ AllCops:
- 'config/environments/**/*'
- 'tmp/**/*'
- 'storage/**/*'
+ - 'db/migrate/20200225162150_init_schema.rb'
diff --git a/Gemfile b/Gemfile
index 591630a82..32dab102c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -48,6 +48,8 @@ gem 'dotenv-rails'
gem 'foreman'
gem 'puma'
gem 'webpacker', '~> 5.x'
+# metrics on heroku
+gem 'barnes'
##--- gems for authentication & authorization ---##
gem 'devise'
@@ -63,7 +65,8 @@ gem 'administrate'
gem 'wisper', '2.0.0'
##--- gems for channels ---##
-gem 'facebook-messenger'
+# TODO: bump up gem to 2.0
+gem 'facebook-messenger', '1.5.0'
gem 'telegram-bot-ruby'
gem 'twilio-ruby', '~> 5.32.0'
# twitty will handle subscription of twitter account events
@@ -95,6 +98,9 @@ group :development do
# used in swagger build
gem 'json_refs', git: 'https://github.com/tzmfreedom/json_refs', ref: 'e32deb0'
+
+ # When we want to squash migrations
+ gem 'squasher'
end
group :test do
diff --git a/Gemfile.lock b/Gemfile.lock
index fc5c613bb..0c9cda2ec 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -18,56 +18,56 @@ GEM
specs:
action-cable-testing (0.6.1)
actioncable (>= 5.0)
- actioncable (6.0.3.2)
- actionpack (= 6.0.3.2)
+ actioncable (6.0.3.3)
+ actionpack (= 6.0.3.3)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
- actionmailbox (6.0.3.2)
- actionpack (= 6.0.3.2)
- activejob (= 6.0.3.2)
- activerecord (= 6.0.3.2)
- activestorage (= 6.0.3.2)
- activesupport (= 6.0.3.2)
+ actionmailbox (6.0.3.3)
+ actionpack (= 6.0.3.3)
+ activejob (= 6.0.3.3)
+ activerecord (= 6.0.3.3)
+ activestorage (= 6.0.3.3)
+ activesupport (= 6.0.3.3)
mail (>= 2.7.1)
- actionmailer (6.0.3.2)
- actionpack (= 6.0.3.2)
- actionview (= 6.0.3.2)
- activejob (= 6.0.3.2)
+ actionmailer (6.0.3.3)
+ actionpack (= 6.0.3.3)
+ actionview (= 6.0.3.3)
+ activejob (= 6.0.3.3)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (6.0.3.2)
- actionview (= 6.0.3.2)
- activesupport (= 6.0.3.2)
+ actionpack (6.0.3.3)
+ actionview (= 6.0.3.3)
+ activesupport (= 6.0.3.3)
rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
- actiontext (6.0.3.2)
- actionpack (= 6.0.3.2)
- activerecord (= 6.0.3.2)
- activestorage (= 6.0.3.2)
- activesupport (= 6.0.3.2)
+ actiontext (6.0.3.3)
+ actionpack (= 6.0.3.3)
+ activerecord (= 6.0.3.3)
+ activestorage (= 6.0.3.3)
+ activesupport (= 6.0.3.3)
nokogiri (>= 1.8.5)
- actionview (6.0.3.2)
- activesupport (= 6.0.3.2)
+ actionview (6.0.3.3)
+ activesupport (= 6.0.3.3)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
- activejob (6.0.3.2)
- activesupport (= 6.0.3.2)
+ activejob (6.0.3.3)
+ activesupport (= 6.0.3.3)
globalid (>= 0.3.6)
- activemodel (6.0.3.2)
- activesupport (= 6.0.3.2)
- activerecord (6.0.3.2)
- activemodel (= 6.0.3.2)
- activesupport (= 6.0.3.2)
- activestorage (6.0.3.2)
- actionpack (= 6.0.3.2)
- activejob (= 6.0.3.2)
- activerecord (= 6.0.3.2)
+ activemodel (6.0.3.3)
+ activesupport (= 6.0.3.3)
+ activerecord (6.0.3.3)
+ activemodel (= 6.0.3.3)
+ activesupport (= 6.0.3.3)
+ activestorage (6.0.3.3)
+ actionpack (= 6.0.3.3)
+ activejob (= 6.0.3.3)
+ activerecord (= 6.0.3.3)
marcel (~> 0.3.1)
- activesupport (6.0.3.2)
+ activesupport (6.0.3.3)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
@@ -77,7 +77,7 @@ GEM
activerecord (>= 5.0, < 6.1)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
- administrate (0.13.0)
+ administrate (0.14.0)
actionpack (>= 4.2)
actionview (>= 4.2)
activerecord (>= 4.2)
@@ -93,23 +93,23 @@ GEM
rake (>= 10.4, < 14.0)
ast (2.4.1)
attr_extras (6.2.4)
- autoprefixer-rails (9.8.2)
+ autoprefixer-rails (9.8.6.3)
execjs
aws-eventstream (1.1.0)
- aws-partitions (1.332.0)
- aws-sdk-core (3.100.0)
+ aws-partitions (1.360.0)
+ aws-sdk-core (3.105.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.239.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
- aws-sdk-kms (1.34.1)
+ aws-sdk-kms (1.37.0)
aws-sdk-core (~> 3, >= 3.99.0)
aws-sigv4 (~> 1.1)
- aws-sdk-s3 (1.69.1)
- aws-sdk-core (~> 3, >= 3.99.0)
+ aws-sdk-s3 (1.79.1)
+ aws-sdk-core (~> 3, >= 3.104.3)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.1)
- aws-sigv4 (1.2.0)
+ aws-sigv4 (1.2.2)
aws-eventstream (~> 1, >= 1.0.2)
axiom-types (0.1.1)
descendants_tracker (~> 0.0.4)
@@ -122,11 +122,14 @@ GEM
faraday (~> 1.0)
faraday_middleware (~> 1.0.0.rc1)
nokogiri (~> 1.10.4)
- bcrypt (3.1.13)
+ barnes (0.0.8)
+ multi_json (~> 1)
+ statsd-ruby (~> 1.1)
+ bcrypt (3.1.15)
bindex (0.8.1)
- bootsnap (1.4.6)
+ bootsnap (1.4.8)
msgpack (~> 1.0)
- brakeman (4.8.2)
+ brakeman (4.9.0)
browser (4.2.0)
builder (3.2.4)
bullet (6.1.0)
@@ -146,12 +149,12 @@ GEM
crack (0.4.3)
safe_yaml (~> 1.0.0)
crass (1.0.6)
- cypress-on-rails (1.7.0)
+ cypress-on-rails (1.8.0)
rack
database_cleaner (1.8.5)
datetime_picker_rails (0.0.7)
momentjs-rails (>= 2.8.1)
- declarative (0.0.10)
+ declarative (0.0.20)
declarative-option (0.1.0)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
@@ -166,41 +169,42 @@ GEM
devise (> 3.5.2, < 5)
rails (>= 4.2.0, < 6.1)
sprockets (= 3.7.2)
- diff-lcs (1.4)
- digest-crc (0.5.1)
+ diff-lcs (1.4.4)
+ digest-crc (0.6.1)
+ rake (~> 13.0)
docile (1.3.2)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
- dotenv (2.7.5)
- dotenv-rails (2.7.5)
- dotenv (= 2.7.5)
- railties (>= 3.2, < 6.1)
+ dotenv (2.7.6)
+ dotenv-rails (2.7.6)
+ dotenv (= 2.7.6)
+ railties (>= 3.2)
equalizer (0.0.11)
erubi (1.9.0)
execjs (2.7.0)
facebook-messenger (1.5.0)
httparty (~> 0.13, >= 0.13.7)
rack (>= 1.4.5)
- factory_bot (6.0.2)
+ factory_bot (6.1.0)
activesupport (>= 5.0.0)
- factory_bot_rails (6.0.0)
- factory_bot (~> 6.0.0)
+ factory_bot_rails (6.1.0)
+ factory_bot (~> 6.1.0)
railties (>= 5.0.0)
- faker (2.12.0)
+ faker (2.13.0)
i18n (>= 1.6, < 2)
faraday (1.0.1)
multipart-post (>= 1.2, < 3)
faraday_middleware (1.0.0)
faraday (~> 1.0)
- fcm (1.0.1)
+ fcm (1.0.2)
faraday (~> 1.0.0)
ffi (1.13.1)
flag_shih_tzu (0.3.23)
- foreman (0.87.1)
- gli (2.19.1)
+ foreman (0.87.2)
+ gli (2.19.2)
globalid (0.4.2)
activesupport (>= 4.2.0)
- google-api-client (0.41.0)
+ google-api-client (0.43.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (~> 0.9)
httpclient (>= 2.8.1, < 3.0)
@@ -211,24 +215,24 @@ GEM
google-cloud-core (1.5.0)
google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0)
- google-cloud-env (1.3.2)
+ google-cloud-env (1.3.3)
faraday (>= 0.17.3, < 2.0)
google-cloud-errors (1.0.1)
- google-cloud-storage (1.26.2)
+ google-cloud-storage (1.28.0)
addressable (~> 2.5)
digest-crc (~> 0.4)
google-api-client (~> 0.33)
google-cloud-core (~> 1.2)
googleauth (~> 0.9)
mini_mime (~> 1.0)
- googleauth (0.13.0)
+ googleauth (0.13.1)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (~> 0.14)
- groupdate (5.0.0)
+ groupdate (5.1.0)
activesupport (>= 5)
haikunator (1.1.0)
hana (1.3.6)
@@ -253,8 +257,8 @@ GEM
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
- json (2.3.0)
- jwt (2.2.1)
+ json (2.3.1)
+ jwt (2.2.2)
kaminari (1.2.1)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.1)
@@ -279,7 +283,7 @@ GEM
listen (3.2.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
- loofah (2.6.0)
+ loofah (2.7.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
@@ -295,20 +299,20 @@ GEM
mini_magick (4.10.1)
mini_mime (1.0.2)
mini_portile2 (2.4.0)
- minitest (5.14.1)
+ minitest (5.14.2)
momentjs-rails (2.20.1)
railties (>= 3.1)
msgpack (1.3.3)
- multi_json (1.14.1)
+ multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.1.1)
netrc (0.11.0)
- nio4r (2.5.2)
+ nio4r (2.5.3)
nokogiri (1.10.10)
mini_portile2 (~> 2.4.0)
oauth (0.5.4)
orm_adapter (0.5.0)
- os (1.1.0)
+ os (1.1.1)
parallel (1.19.2)
parser (2.7.1.4)
ast (~> 2.4.1)
@@ -328,35 +332,33 @@ GEM
rack (>= 0.4)
rack-cors (1.1.1)
rack (>= 2.0.0)
- rack-protection (2.0.8.1)
- rack
rack-proxy (0.6.5)
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
- rails (6.0.3.2)
- actioncable (= 6.0.3.2)
- actionmailbox (= 6.0.3.2)
- actionmailer (= 6.0.3.2)
- actionpack (= 6.0.3.2)
- actiontext (= 6.0.3.2)
- actionview (= 6.0.3.2)
- activejob (= 6.0.3.2)
- activemodel (= 6.0.3.2)
- activerecord (= 6.0.3.2)
- activestorage (= 6.0.3.2)
- activesupport (= 6.0.3.2)
+ rails (6.0.3.3)
+ actioncable (= 6.0.3.3)
+ actionmailbox (= 6.0.3.3)
+ actionmailer (= 6.0.3.3)
+ actionpack (= 6.0.3.3)
+ actiontext (= 6.0.3.3)
+ actionview (= 6.0.3.3)
+ activejob (= 6.0.3.3)
+ activemodel (= 6.0.3.3)
+ activerecord (= 6.0.3.3)
+ activestorage (= 6.0.3.3)
+ activesupport (= 6.0.3.3)
bundler (>= 1.3.0)
- railties (= 6.0.3.2)
+ railties (= 6.0.3.3)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.3.0)
loofah (~> 2.3)
- railties (6.0.3.2)
- actionpack (= 6.0.3.2)
- activesupport (= 6.0.3.2)
+ railties (6.0.3.3)
+ actionpack (= 6.0.3.3)
+ activesupport (= 6.0.3.3)
method_source
rake (>= 0.8.7)
thor (>= 0.20.3, < 2.0)
@@ -366,7 +368,7 @@ GEM
rb-inotify (0.10.1)
ffi (~> 1.0)
redis (4.2.1)
- redis-namespace (1.7.0)
+ redis-namespace (1.8.0)
redis (>= 3.0.4)
redis-rack-cache (2.2.1)
rack-cache (>= 1.10, < 2)
@@ -405,25 +407,25 @@ GEM
rspec-mocks (~> 3.9)
rspec-support (~> 3.9)
rspec-support (3.9.3)
- rubocop (0.86.0)
+ rubocop (0.89.1)
parallel (~> 1.10)
- parser (>= 2.7.0.1)
+ parser (>= 2.7.1.1)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.7)
rexml
- rubocop-ast (>= 0.0.3, < 1.0)
+ rubocop-ast (>= 0.3.0, < 1.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
- rubocop-ast (0.0.3)
- parser (>= 2.7.0.1)
- rubocop-performance (1.6.1)
- rubocop (>= 0.71.0)
- rubocop-rails (2.6.0)
+ rubocop-ast (0.3.0)
+ parser (>= 2.7.1.4)
+ rubocop-performance (1.7.1)
+ rubocop (>= 0.82.0)
+ rubocop-rails (2.7.1)
activesupport (>= 4.2.0)
rack (>= 1.1)
- rubocop (>= 0.82.0)
- rubocop-rspec (1.40.0)
- rubocop (>= 0.68.1)
+ rubocop (>= 0.87.0)
+ rubocop-rspec (1.43.2)
+ rubocop (~> 0.87)
ruby-progressbar (1.10.1)
safe_yaml (1.0.5)
sass (3.7.4)
@@ -439,7 +441,7 @@ GEM
sprockets (> 3.0)
sprockets-rails
tilt
- scout_apm (2.6.7)
+ scout_apm (2.6.9)
parser
scss_lint (0.59.0)
sass (~> 3.5, >= 3.5.5)
@@ -448,15 +450,14 @@ GEM
activesupport (>= 4)
selectize-rails (0.12.6)
semantic_range (2.3.0)
- sentry-raven (3.0.0)
+ sentry-raven (3.0.3)
faraday (>= 1.0)
- shoulda-matchers (4.3.0)
+ shoulda-matchers (4.4.1)
activesupport (>= 4.2.0)
- sidekiq (6.0.7)
+ sidekiq (6.1.1)
connection_pool (>= 2.2.2)
rack (~> 2.0)
- rack-protection (>= 2.0.0)
- redis (>= 4.1.0)
+ redis (>= 4.2.0)
signet (0.14.0)
addressable (~> 2.3)
faraday (>= 0.17.3, < 2.0)
@@ -467,14 +468,13 @@ GEM
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
- slack-ruby-client (0.14.6)
- activesupport
- faraday (>= 0.9)
+ slack-ruby-client (0.15.0)
+ faraday (>= 1.0)
faraday_middleware
gli
hashie
websocket-driver
- spring (2.1.0)
+ spring (2.1.1)
spring-watcher-listen (2.0.1)
listen (>= 2.7, < 4.0)
spring (>= 1.2, < 3.0)
@@ -485,11 +485,13 @@ GEM
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
+ squasher (0.6.2)
+ statsd-ruby (1.4.0)
telegram-bot-ruby (0.12.0)
faraday
inflecto
virtus
- telephone_number (1.4.7)
+ telephone_number (1.4.9)
thor (1.0.1)
thread_safe (0.3.6)
tilt (2.0.10)
@@ -514,7 +516,7 @@ GEM
unf_ext (0.0.7.7)
unicode-display_width (1.7.0)
uniform_notifier (1.13.0)
- valid_email2 (3.2.2)
+ valid_email2 (3.3.1)
activemodel (>= 3.2)
mail (~> 2.5)
virtus (1.0.5)
@@ -524,7 +526,7 @@ GEM
equalizer (~> 0.0, >= 0.0.9)
warden (1.2.8)
rack (>= 2.0.6)
- web-console (4.0.3)
+ web-console (4.0.4)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
bindex (>= 0.4.0)
@@ -541,7 +543,7 @@ GEM
webpush (1.0.0)
hkdf (~> 0.2)
jwt (~> 2.0)
- websocket-driver (0.7.2)
+ websocket-driver (0.7.3)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
wisper (2.0.0)
@@ -558,6 +560,7 @@ DEPENDENCIES
attr_extras
aws-sdk-s3
azure-storage-blob
+ barnes
bootsnap
brakeman
browser
@@ -569,7 +572,7 @@ DEPENDENCIES
devise
devise_token_auth
dotenv-rails
- facebook-messenger
+ facebook-messenger (= 1.5.0)
factory_bot_rails
faker
fcm
@@ -615,6 +618,7 @@ DEPENDENCIES
slack-ruby-client
spring
spring-watcher-listen
+ squasher
telegram-bot-ruby
telephone_number
time_diff
diff --git a/app/bot/facebook_bot.rb b/app/bot/facebook_bot.rb
index f0e04ebc2..f3f87220d 100644
--- a/app/bot/facebook_bot.rb
+++ b/app/bot/facebook_bot.rb
@@ -19,4 +19,10 @@ class FacebookBot
updater.perform
Rails.logger.info "Human was online at #{delivery.at}"
end
+
+ Bot.on :message_echo do |message|
+ Rails.logger.info "MESSAGE_ECHO #{message}"
+ response = ::Integrations::Facebook::MessageParser.new(message)
+ ::Integrations::Facebook::MessageCreator.new(response).perform
+ end
end
diff --git a/app/builders/messages/facebook/message_builder.rb b/app/builders/messages/facebook/message_builder.rb
index 0095b9e1b..40b0aebc2 100644
--- a/app/builders/messages/facebook/message_builder.rb
+++ b/app/builders/messages/facebook/message_builder.rb
@@ -7,11 +7,12 @@
class Messages::Facebook::MessageBuilder
attr_reader :response
- def initialize(response, inbox, outgoing_echo = false)
+ def initialize(response, inbox, outgoing_echo: false)
@response = response
@inbox = inbox
- @sender_id = (outgoing_echo ? @response.recipient_id : @response.sender_id)
- @message_type = (outgoing_echo ? :outgoing : :incoming)
+ @outgoing_echo = outgoing_echo
+ @sender_id = (@outgoing_echo ? @response.recipient_id : @response.sender_id)
+ @message_type = (@outgoing_echo ? :outgoing : :incoming)
end
def perform
@@ -50,6 +51,8 @@ class Messages::Facebook::MessageBuilder
def attach_file(attachment, file_url)
file_resource = LocalResource.new(file_url)
attachment.file.attach(io: file_resource.file, filename: file_resource.tmp_filename, content_type: file_resource.encoding)
+ rescue Errno::ETIMEDOUT, Errno::ECONNREFUSED, SocketError => e
+ Rails.logger.info "invalid url #{file_url} : #{e.message}"
end
def conversation
@@ -118,7 +121,7 @@ class Messages::Facebook::MessageBuilder
message_type: @message_type,
content: response.content,
source_id: response.identifier,
- sender: contact
+ sender: @outgoing_echo ? nil : contact
}
end
diff --git a/app/builders/messages/message_builder.rb b/app/builders/messages/message_builder.rb
index 24f2f3aa6..6fc3bab5d 100644
--- a/app/builders/messages/message_builder.rb
+++ b/app/builders/messages/message_builder.rb
@@ -3,12 +3,11 @@ class Messages::MessageBuilder
attr_reader :message
def initialize(user, conversation, params)
- @content = params[:content]
+ @params = params
@private = params[:private] || false
@conversation = conversation
@user = user
@message_type = params[:message_type] || 'outgoing'
- @content_type = params[:content_type]
@items = params.to_unsafe_h&.dig(:content_attributes, :items)
@attachments = params[:attachments]
@in_reply_to = params.to_unsafe_h&.dig(:content_attributes, :in_reply_to)
@@ -48,12 +47,13 @@ class Messages::MessageBuilder
account_id: @conversation.account_id,
inbox_id: @conversation.inbox_id,
message_type: message_type,
- content: @content,
+ content: @params[:content],
private: @private,
sender: sender,
- content_type: @content_type,
+ content_type: @params[:content_type],
items: @items,
- in_reply_to: @in_reply_to
+ in_reply_to: @in_reply_to,
+ echo_id: @params[:echo_id]
}
end
end
diff --git a/app/controllers/api/v1/accounts/callbacks_controller.rb b/app/controllers/api/v1/accounts/callbacks_controller.rb
index 77e46d669..37116d8d0 100644
--- a/app/controllers/api/v1/accounts/callbacks_controller.rb
+++ b/app/controllers/api/v1/accounts/callbacks_controller.rb
@@ -81,6 +81,8 @@ class Api::V1::Accounts::CallbacksController < Api::V1::Accounts::BaseController
avatar_resource = LocalResource.new(uri)
facebook_inbox.avatar.attach(io: avatar_resource.file, filename: avatar_resource.tmp_filename, content_type: avatar_resource.encoding)
+ rescue Errno::ETIMEDOUT, Errno::ECONNREFUSED, SocketError => e
+ Rails.logger.info "invalid url #{file_url} : #{e.message}"
end
def get_avatar_url(page_id)
diff --git a/app/controllers/api/v1/accounts/conversations_controller.rb b/app/controllers/api/v1/accounts/conversations_controller.rb
index 51b6aa079..2f1bdcbfb 100644
--- a/app/controllers/api/v1/accounts/conversations_controller.rb
+++ b/app/controllers/api/v1/accounts/conversations_controller.rb
@@ -1,5 +1,6 @@
class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseController
include Events::Types
+
before_action :conversation, except: [:index]
before_action :contact_inbox, only: [:create]
@@ -40,9 +41,10 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro
end
def toggle_typing_status
- if params[:typing_status] == 'on'
+ case params[:typing_status]
+ when 'on'
trigger_typing_event(CONVERSATION_TYPING_ON)
- elsif params[:typing_status] == 'off'
+ when 'off'
trigger_typing_event(CONVERSATION_TYPING_OFF)
end
head :ok
diff --git a/app/controllers/api/v1/accounts/inbox_members_controller.rb b/app/controllers/api/v1/accounts/inbox_members_controller.rb
index 9ad2ef93d..fc960d9ec 100644
--- a/app/controllers/api/v1/accounts/inbox_members_controller.rb
+++ b/app/controllers/api/v1/accounts/inbox_members_controller.rb
@@ -12,7 +12,7 @@ class Api::V1::Accounts::InboxMembersController < Api::V1::Accounts::BaseControl
end
def show
- @agents = Current.account.users.where(id: @inbox.members.pluck(:user_id))
+ @agents = Current.account.users.where(id: @inbox.members.select(:user_id))
end
private
diff --git a/app/controllers/api/v1/accounts/inboxes_controller.rb b/app/controllers/api/v1/accounts/inboxes_controller.rb
index d2b0dcb60..6c4a3cf7d 100644
--- a/app/controllers/api/v1/accounts/inboxes_controller.rb
+++ b/app/controllers/api/v1/accounts/inboxes_controller.rb
@@ -91,7 +91,7 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController
:welcome_tagline,
:webhook_url,
:email,
- selected_feature_flags: []
+ { selected_feature_flags: [] }
])
end
end
diff --git a/app/controllers/api/v1/accounts/integrations/slack_controller.rb b/app/controllers/api/v1/accounts/integrations/slack_controller.rb
index 77cf05ade..1002f5752 100644
--- a/app/controllers/api/v1/accounts/integrations/slack_controller.rb
+++ b/app/controllers/api/v1/accounts/integrations/slack_controller.rb
@@ -3,7 +3,7 @@ class Api::V1::Accounts::Integrations::SlackController < Api::V1::Accounts::Base
def create
builder = Integrations::Slack::HookBuilder.new(
- account: current_account,
+ account: Current.account,
code: params[:code],
inbox_id: params[:inbox_id]
)
@@ -25,7 +25,7 @@ class Api::V1::Accounts::Integrations::SlackController < Api::V1::Accounts::Base
private
def fetch_hook
- @hook = Integrations::Hook.find_by(app_id: 'slack')
+ @hook = Integrations::Hook.where(account: Current.account).find_by(app_id: 'slack')
end
def create_chatwoot_slack_channel
diff --git a/app/controllers/api/v1/widget/conversations_controller.rb b/app/controllers/api/v1/widget/conversations_controller.rb
index 66b54d4b9..bafd008f9 100644
--- a/app/controllers/api/v1/widget/conversations_controller.rb
+++ b/app/controllers/api/v1/widget/conversations_controller.rb
@@ -8,7 +8,7 @@ class Api::V1::Widget::ConversationsController < Api::V1::Widget::BaseController
def update_last_seen
head :ok && return if conversation.nil?
- conversation.user_last_seen_at = DateTime.now.utc
+ conversation.contact_last_seen_at = DateTime.now.utc
conversation.save!
head :ok
end
@@ -26,9 +26,10 @@ class Api::V1::Widget::ConversationsController < Api::V1::Widget::BaseController
def toggle_typing
head :ok && return if conversation.nil?
- if permitted_params[:typing_status] == 'on'
+ case permitted_params[:typing_status]
+ when 'on'
trigger_typing_event(CONVERSATION_TYPING_ON)
- elsif permitted_params[:typing_status] == 'off'
+ when 'off'
trigger_typing_event(CONVERSATION_TYPING_OFF)
end
diff --git a/app/controllers/api/v1/widget/messages_controller.rb b/app/controllers/api/v1/widget/messages_controller.rb
index afc0d71b2..a3fed9fb4 100644
--- a/app/controllers/api/v1/widget/messages_controller.rb
+++ b/app/controllers/api/v1/widget/messages_controller.rb
@@ -48,6 +48,7 @@ class Api::V1::Widget::MessagesController < Api::V1::Widget::BaseController
sender: @contact,
content: permitted_params[:message][:content],
inbox_id: conversation.inbox_id,
+ echo_id: permitted_params[:message][:echo_id],
message_type: :incoming
}
end
@@ -112,11 +113,11 @@ class Api::V1::Widget::MessagesController < Api::V1::Widget::BaseController
end
def message_update_params
- params.permit(message: [submitted_values: [:name, :title, :value]])
+ params.permit(message: [{ submitted_values: [:name, :title, :value] }])
end
def permitted_params
- params.permit(:id, :before, :website_token, contact: [:email], message: [:content, :referer_url, :timestamp])
+ params.permit(:id, :before, :website_token, contact: [:email], message: [:content, :referer_url, :timestamp, :echo_id])
end
def set_message
diff --git a/app/controllers/devise_overrides/confirmations_controller.rb b/app/controllers/devise_overrides/confirmations_controller.rb
index 96d16eafe..057e77b12 100644
--- a/app/controllers/devise_overrides/confirmations_controller.rb
+++ b/app/controllers/devise_overrides/confirmations_controller.rb
@@ -25,6 +25,6 @@ class DeviseOverrides::ConfirmationsController < Devise::ConfirmationsController
user.reset_password_token = enc
user.reset_password_sent_at = Time.now.utc
user.save(validate: false)
- '/app/auth/password/edit?config=default&redirect_url=&reset_password_token=' + raw
+ "/app/auth/password/edit?config=default&redirect_url=&reset_password_token=#{raw}"
end
end
diff --git a/app/controllers/twitter/callbacks_controller.rb b/app/controllers/twitter/callbacks_controller.rb
index f317f3ffa..b3cafbe12 100644
--- a/app/controllers/twitter/callbacks_controller.rb
+++ b/app/controllers/twitter/callbacks_controller.rb
@@ -27,7 +27,7 @@ class Twitter::CallbacksController < Twitter::BaseController
end
def account
- @account ||= Account.find_by!(id: account_id)
+ @account ||= Account.find(account_id)
end
def twitter_app_redirect_url
diff --git a/app/dispatchers/async_dispatcher.rb b/app/dispatchers/async_dispatcher.rb
index c24b633aa..e5fbdd7f7 100644
--- a/app/dispatchers/async_dispatcher.rb
+++ b/app/dispatchers/async_dispatcher.rb
@@ -9,7 +9,10 @@ class AsyncDispatcher < BaseDispatcher
end
def listeners
- listeners = [EventListener.instance, WebhookListener.instance, HookListener.instance]
- listeners
+ [
+ EventListener.instance,
+ WebhookListener.instance,
+ InstallationWebhookListener.instance, HookListener.instance
+ ]
end
end
diff --git a/app/finders/conversation_finder.rb b/app/finders/conversation_finder.rb
index 495bddf63..5ca1e12f6 100644
--- a/app/finders/conversation_finder.rb
+++ b/app/finders/conversation_finder.rb
@@ -67,9 +67,10 @@ class ConversationFinder
end
def filter_by_assignee_type
- if @assignee_type == 'me'
+ case @assignee_type
+ when 'me'
@conversations = @conversations.assigned_to(current_user)
- elsif @assignee_type == 'unassigned'
+ when 'unassigned'
@conversations = @conversations.unassigned
end
@conversations
diff --git a/app/javascript/dashboard/assets/scss/_helper-classes.scss b/app/javascript/dashboard/assets/scss/_helper-classes.scss
index cbcc31e42..a1bfa1462 100644
--- a/app/javascript/dashboard/assets/scss/_helper-classes.scss
+++ b/app/javascript/dashboard/assets/scss/_helper-classes.scss
@@ -69,3 +69,11 @@ select {
border-top-left-radius: 0 !important;
}
}
+
+.justify-space-between {
+ justify-content: space-between;
+}
+
+.w-100 {
+ width: 100%;
+}
diff --git a/app/javascript/dashboard/assets/scss/_mixins.scss b/app/javascript/dashboard/assets/scss/_mixins.scss
index 36a87a4f9..a20a32ffe 100644
--- a/app/javascript/dashboard/assets/scss/_mixins.scss
+++ b/app/javascript/dashboard/assets/scss/_mixins.scss
@@ -1,3 +1,4 @@
+@import '~dashboard/assets/scss/variables';
@import '~widget/assets/scss/mixins';
$spinner-before-border-color: rgba(255, 255, 255, 0.7);
@@ -235,12 +236,3 @@ $spinner-before-border-color: rgba(255, 255, 255, 0.7);
text-overflow: ellipsis;
white-space: nowrap;
}
-
-
-.justify-space-between {
- justify-content: space-between;
-}
-
-.w-100 {
- width: 100%;
-}
diff --git a/app/javascript/dashboard/assets/scss/widgets/_conv-header.scss b/app/javascript/dashboard/assets/scss/widgets/_conv-header.scss
index 878e5a788..20919a73a 100644
--- a/app/javascript/dashboard/assets/scss/widgets/_conv-header.scss
+++ b/app/javascript/dashboard/assets/scss/widgets/_conv-header.scss
@@ -41,6 +41,10 @@
@include flex;
@include flex-align($x: center, $y: middle);
+ &.hide {
+ visibility: hidden;
+ }
+
.user--name {
@include margin(0);
font-size: $font-size-medium;
@@ -83,3 +87,15 @@
}
}
}
+
+
+.header-actions-wrap {
+ display: flex;
+ flex-direction: row;
+ flex-grow: 1;
+ justify-content: flex-end;
+
+ &.has-open-sidebar {
+ justify-content: flex-end;
+ }
+}
diff --git a/app/javascript/dashboard/assets/scss/widgets/_conversation-view.scss b/app/javascript/dashboard/assets/scss/widgets/_conversation-view.scss
index 257ad16d7..dde956eaa 100644
--- a/app/javascript/dashboard/assets/scss/widgets/_conversation-view.scss
+++ b/app/javascript/dashboard/assets/scss/widgets/_conversation-view.scss
@@ -103,11 +103,6 @@
}
}
-.emojione {
- height: $font-size-medium;
- width: $font-size-medium;
-}
-
.conversation-wrap {
@include background-gray;
@include margin(0);
diff --git a/app/javascript/dashboard/assets/scss/widgets/_emojiinput.scss b/app/javascript/dashboard/assets/scss/widgets/_emojiinput.scss
deleted file mode 100644
index f4bc48e7c..000000000
--- a/app/javascript/dashboard/assets/scss/widgets/_emojiinput.scss
+++ /dev/null
@@ -1,107 +0,0 @@
-@import '../variables';
-@import '../mixins';
-
-.emoji-dialog {
- @include elegant-card;
- background: $color-white;
- box-sizing: content-box;
- position: absolute;
- right: 0;
- top: -22rem;
- width: 28.6rem;
-
- &::before {
- @include arrow(bottom, $color-white, $space-slab);
- bottom: -$space-slab;
- position: absolute;
- right: $space-two;
- }
-
- .emojione {
- font-size: $font-size-default;
- margin: $zero;
- }
-
- .emoji-row {
- box-sizing: border-box;
- height: 180px;
- overflow-y: auto;
- padding: $space-small;
-
- .emoji {
- border-radius: 4px;
- display: inline-block;
- padding: 5px;
- }
-
- .emojione {
- cursor: pointer;
- float: left;
- margin: .6rem;
- }
- }
-
- .emoji-category-title {
- color: $color-heading;
- font-size: $font-size-small;
- font-weight: $font-weight-medium;
- margin: 0;
- text-transform: capitalize;
- }
-
- .emoji-category-heading-decoration {
- text-align: right;
- }
-}
-
-.emoji-dialog-header {
- background-color: $color-body;
- border-top-left-radius: $space-small;
- border-top-right-radius: $space-small;
- padding: $zero $space-smaller;
-
- ul {
- display: flex;
- list-style: none;
- margin: 0;
- padding: $space-smaller 0 0;
-
- >li {
- align-items: center;
- cursor: pointer;
- display: flex;
- height: $space-medium;
- justify-content: center;
- padding: $space-smaller $space-small;
- }
-
- .emojione {
- height: $space-two;
- width: $space-normal;
- }
-
- >.active {
- background: $color-white;
- border-top-left-radius: $space-small;
- border-top-right-radius: $space-small;
- }
-
- img,
- svg {
- filter: grayscale(100%);
- }
- }
-
- .active {
-
- img,
- svg {
- filter: grayscale(0);
- }
- }
-
- >* {
- display: table-cell;
- vertical-align: middle;
- }
-}
diff --git a/app/javascript/dashboard/components/widgets/conversation/ConversationHeader.vue b/app/javascript/dashboard/components/widgets/conversation/ConversationHeader.vue
index 65567ae26..10860a2bd 100644
--- a/app/javascript/dashboard/components/widgets/conversation/ConversationHeader.vue
+++ b/app/javascript/dashboard/components/widgets/conversation/ConversationHeader.vue
@@ -1,6 +1,6 @@
Webhooks Webhooks are HTTP callbacks which can be defined for every account. They are triggered by events like message creation in Chatwoot. You can create more than one webhook for this account. Webhooks Webhooks هي إعادات HTTP callbacks التي يمكن تعريفها لكل حساب. يتم تشغيلها بأحداث مثل إنشاء الرسائل في Chatwoot. يمكنك إنشاء أكثر من Webhook واحد لهذا الحساب. Labels Labels help you to categorize conversations and prioritize them. You can assign label to a conversation from the sidepanel. الوسوم تساعدك الوسو على تصنيف المحادثات وإعطائها الأولوية. يمكنك تعيين وسم إلى محادثة من القائمة الجانبية. พนักงาน พนักงาน คือสมาชิกของทีมสนับสนุนลูกค้าของคุณ พนักงานจะสามารถดูและตอบกลับข้อความจากผู้ใช้ของคุณได้ รายการนี้แสดงพนักงานทั้งหมดที่อยู่ในบัญชีของคุณ คลิกที่ เพิ่มตัวแทน เพื่อเพิ่มตัวแทนใหม่ ตัวแทนที่คุณเพิ่มจะได้รับอีเมลพร้อมลิงก์ยืนยันเพื่อเปิดใช้งานบัญชีของพวกเขาหลังจากนั้นพวกเขาสามารถเข้าถึง Chatwoot และตอบกลับข้อความได้ การเข้าถึงคุณสมบัติของ Chatwoot ขึ้นอยู่กับบทบาทต่อไปนี้ พนักงาน - ตัวแทนที่มีบทบาทนี้สามารถเข้าถึงได้เฉพาะกล่องจดหมายรายงานและการสนทนา พวกเขาสามารถกำหนดการสนทนาให้กับตัวแทนคนอื่น ๆ หรือตัวเองและแก้ไขการสนทนาได้ ผู้ดูแลระบบ - ผู้ดูแลระบบจะสามารถเข้าถึงคุณลักษณะ Chatwoot ทั้งหมดที่เปิดใช้งานสำหรับบัญชีของคุณรวมถึงการตั้งค่าพร้อมด้วย สิทธิพิเศษของตัวแทนทั่วไป การตอบกลับสำเร็จรูป คำตอบสำเร็จรูปคือเทมเพลตการตอบกลับที่บันทึกไว้ซึ่งสามารถใช้เพื่อตอบกลับการสนทนาได้อย่างรวดเร็ว สำหรับการสร้างคำตอบสำเร็จรูปเพียงคลิกที่ เพิ่มการตอบกลับสำเร็จรูป คุณยังสามารถแก้ไขหรือลบคำตอบสำเร็จรูปที่มีอยู่ได้โดยคลิกที่ปุ่มแก้ไขหรือลบ คำตอบสำเร็จรูปถูกใช้โดยใช้ รหัสย่อ ตัวแทนสามารถเข้าถึงคำตอบสำเร็จรูปขณะสนทนาได้โดยพิมพ์ '/' ตามด้วยรหัสสั้น ๆ กล่องข้อความ เมื่อคุณเชื่อมต่อเว็บไซต์หรือหน้า Facebook กับ Chatwoot จะเรียกว่า Inbox คุณสามารถมีกล่องจดหมายได้ไม่ จำกัด ในบัญชี Chatwoot ของคุณ คลิกที่ เพิ่มกล่องจดหมาย เพื่อเชื่อมต่อเว็บไซต์หรือเพจ Facebook ในแดชบอร์ดคุณสามารถดูการสนทนาทั้งหมดจากกล่องจดหมายทั้งหมดของคุณในที่เดียวและตอบกลับได้ในแท็บ \"การสนทนา\" คุณยังสามารถดูการสนทนาเฉพาะสำหรับกล่องจดหมายได้โดยคลิกที่ชื่อกล่องจดหมายในบานหน้าต่างด้านซ้ายของแผงควบคุม Webhooks Webhooks are HTTP callbacks which can be defined for every account. They are triggered by events like message creation in Chatwoot. You can create more than one webhook for this account. Labels Labels help you to categorize conversations and prioritize them. You can assign label to a conversation from the sidepanel. Canned Responses Canned Responses are saved reply templates which can be used to quickly send out a reply to a conversation . For creating a Canned Response, just click on the Add Canned Response. You can also edit or delete an existing Canned Response by clicking on the Edit or Delete button Canned responses are used with the help of Short Codes. Agents can access canned responses while on a chat by typing '/' followed by the short code. 预设回复 预设的回复已保存的回复模板,可以用来快速发送回复到对话。 若要创建预设反应,只需点击 添加预设回应。 您也可以通过点击编辑或删除按钮来编辑或删除现有的预定响应 在 短代码的帮助下使用预定的响应方式。 代理人在聊天时可以通过输入 '/' 然后是短代码访问预设响应 Inbox When you connect a website or a facebook Page to Chatwoot, it is called an Inbox. You can have unlimited inboxes in your Chatwoot account. Click on Add Inbox to connect a website or a Facebook Page. In the Dashboard, you can see all the conversations from all your inboxes in a single place and respond to them under the `Conversations` tab. You can also see conversations specific to an inbox by clicking on the inbox name on the left pane of the dashboard. 收件箱 当您将网站或Facebook页面连接到Chatwoot 它被称为一个 收件箱。 您可以在Chatwoot 帐户中拥有无限的收件箱。 点击 添加收件箱 连接网站或 Facebook 页面。 在仪表盘中 您可以在一个地方看到所有收件箱中的所有对话,并在“对话”选项卡下回复。 您也可以通过点击仪表板左侧面板上的收件箱名称看到针对收件箱的对话。 Webhooks Webhooks 是 HTTP 回调,可以为每个账户定义的。 他们是由诸如在Chatwoot 中创建消息等事件所触发的。您可以为此帐户创建多个web钩子。 Webhooks Webhooks are HTTP callbacks which can be defined for every account. They are triggered by events like message creation in Chatwoot. You can create more than one webhook for this account. 客服代理 客服代理 是您的客户支持团队成员。 客服 代理人将能够查看和回复您用户的消息。 列表显示当前帐户中的所有客服代理人。 点击 添加客服代理 添加新客服代理人。 您添加的客服代理将收到一封含有确认链接的电子邮件来激活他们的帐户,然后他们可以访问Chatwoot 并回复消息。 聊天窗口的功能基于以下角色。 Agent - 具有此角色的代理只能访问收件箱、报告和会话。 他们可以将对话分配给其他客服代理人或自己,并解决会话。 管理员 - 管理员将可以访问您账户中所有已启用的聊天功能。 包括设置,以及所有正常客服代理的权限。 预设回复 预设的回复已保存的回复模板,可以用来快速发送回复到对话。 若要创建预设反应,只需点击 添加预设回应。 您也可以通过点击编辑或删除按钮来编辑或删除现有的预定响应 在 短代码的帮助下使用预定的响应方式。 代理人在聊天时可以通过输入 '/' 然后是短代码访问预设响应 收件箱 当您将网站或Facebook页面连接到Chatwoot 它被称为一个 收件箱。 您可以在Chatwoot 帐户中拥有无限的收件箱。 点击 添加收件箱 连接网站或 Facebook 页面。 在仪表盘中 您可以在一个地方看到所有收件箱中的所有对话,并在“对话”选项卡下回复。 您也可以通过点击仪表板左侧面板上的收件箱名称看到针对收件箱的对话。 Webhooks Webhooks 是 HTTP 回调,可以为每个账户定义的。 他们是由诸如在Chatwoot 中创建消息等事件所触发的。您可以为此帐户创建多个web钩子。 标签 可以帮助您对对话进行分类和排序。 您可以从侧面板给对话指定标签。 Agents An Agent is a member of your Customer Support team. Agents will be able to view and reply to messages from your users. The list shows all agents currently in your account. Click on Add Agent to add a new agent. Agent you add will receive an email with a confirmation link to activate their account, after which they can access Chatwoot and respond to messages. Access to Chatwoot's features are based on following roles. Agent - Agents with this role can only access inboxes, reports and conversations. They can assign conversations to other agents or themselves and resolve conversations. Administrator - Administrator will have access to all Chatwoot features enabled for your account, including settings, along with all of a normal agents' privileges. Canned Responses Canned Responses are saved reply templates which can be used to quickly send out a reply to a conversation . For creating a Canned Response, just click on the Add Canned Response. You can also edit or delete an existing Canned Response by clicking on the Edit or Delete button Canned responses are used with the help of Short Codes. Agents can access canned responses while on a chat by typing '/' followed by the short code. Inbox When you connect a website or a facebook Page to Chatwoot, it is called an Inbox. You can have unlimited inboxes in your Chatwoot account. Click on Add Inbox to connect a website or a Facebook Page. In the Dashboard, you can see all the conversations from all your inboxes in a single place and respond to them under the `Conversations` tab. You can also see conversations specific to an inbox by clicking on the inbox name on the left pane of the dashboard. Webhooks Webhooks are HTTP callbacks which can be defined for every account. They are triggered by events like message creation in Chatwoot. You can create more than one webhook for this account. Labels Labels help you to categorize conversations and prioritize them. You can assign label to a conversation from the sidepanel.
For creating a webhook, click on the Add new webhook button. You can also remove any existing webhook by clicking on the Delete button.
لإنشاء webhook، انقر فوق إضافة Webhooks جديد. يمكنك أيضا إزالة أي رابط ويب موجود بالنقر على زر الحذف.
Labels are tied to the account and can be used to create custom workflows in your organization. You can assign custom color to a label, it makes it easier to identify the label. You will be able to display the label on the sidebar to filter the conversations easily.
الوسوم مرتبطة بالحساب ويمكن استخدامها لإنشاء سير عمل مخصص في مؤسستك. يمكنك تعيين لون مخصص للوسم، مما يسهل التعرف على الوسم. ستتمكن من عرض الوسم على الشريط الجانبي لتصفية المحادثات بسهولة.
PS: As an administrator, if you need access to all inboxes, you should add yourself as agent to all inboxes that you create."
+ },
+ "DETAILS": {
+ "TITLE": "Inbox Details",
+ "DESC": "From the dropdown below, select the Facebook Page you want to connect to Chatwoot. You can also give a custom name to your inbox for better identification."
+ },
+ "FINISH": {
+ "TITLE": "Nailed It!",
+ "DESC": "You have successfully finished integrating your Facebook Page with Chatwoot. Next time a customer messages your Page, the conversation will automatically appear on your inbox.
We are also providing you with a widget script that you can easily add to your website. Once this is live on your website, customers can message you right from your website without the help of any external tool and the conversation will appear right here, on Chatwoot.
Cool, huh? Well, we sure try to be :)"
+ }
+ },
+ "DETAILS": {
+ "LOADING_FB": "Authenticating you with Facebook...",
+ "ERROR_FB_AUTH": "Something went wrong, Please refresh page...",
+ "CREATING_CHANNEL": "Creating your Inbox...",
+ "TITLE": "Configure Inbox Details",
+ "DESC": ""
+ },
+ "AGENTS": {
+ "BUTTON_TEXT": "Add agents",
+ "ADD_AGENTS": "Adding Agents to your Inbox..."
+ },
+ "FINISH": {
+ "TITLE": "Your Inbox is ready!",
+ "MESSAGE": "You can now engage with your customers through your new Channel. Happy supporting ",
+ "BUTTON_TEXT": "Take me there",
+ "WEBSITE_SUCCESS": "You have successfully finished creating a website channel. Copy the code shown below and paste it on your website. Next time a customer use the live chat, the conversation will automatically appear on your inbox."
+ },
+ "REAUTH": "Reauthorize",
+ "VIEW": "View",
+ "EDIT": {
+ "API": {
+ "SUCCESS_MESSAGE": "Inbox settings updated successfully",
+ "AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "Auto assignment updated successfully",
+ "ERROR_MESSAGE": "Could not update widget color. Please try again later."
+ },
+ "AUTO_ASSIGNMENT": {
+ "ENABLED": "Enabled",
+ "DISABLED": "Disabled"
+ }
+ },
+ "DELETE": {
+ "BUTTON_TEXT": "ลบ",
+ "CONFIRM": {
+ "TITLE": "ยืนยันการลบ",
+ "MESSAGE": "คุณต้องการที่จะลบไหม ",
+ "YES": "เอาเลย ",
+ "NO": "ไม่อะเก็บไว้ "
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "Inbox deleted successfully",
+ "ERROR_MESSAGE": "Could not delete inbox. Please try again later."
+ }
+ },
+ "TABS": {
+ "SETTINGS": "Settings",
+ "COLLABORATORS": "Collaborators",
+ "CONFIGURATION": "Configuration"
+ },
+ "SETTINGS": "Settings",
+ "FEATURES": {
+ "LABEL": "Features",
+ "DISPLAY_FILE_PICKER": "Display file picker on the widget",
+ "DISPLAY_EMOJI_PICKER": "Display emoji picker on the widget"
+ },
+ "SETTINGS_POPUP": {
+ "MESSENGER_HEADING": "Messenger Script",
+ "MESSENGER_SUB_HEAD": "Place this button inside your body tag",
+ "INBOX_AGENTS": "พนักงาน",
+ "INBOX_AGENTS_SUB_TEXT": "Add or remove agents from this inbox",
+ "UPDATE": "Update",
+ "AUTO_ASSIGNMENT": "Enable auto assignment",
+ "INBOX_UPDATE_TITLE": "Inbox Settings",
+ "INBOX_UPDATE_SUB_TEXT": "Update your inbox settings",
+ "AUTO_ASSIGNMENT_SUB_TEXT": "Enable or disable the automatic assignment of new conversations to the agents added to this inbox."
+ }
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/th/integrations.json b/app/javascript/dashboard/i18n/locale/th/integrations.json
new file mode 100644
index 000000000..aae0af346
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/th/integrations.json
@@ -0,0 +1,63 @@
+{
+ "INTEGRATION_SETTINGS": {
+ "HEADER": "Integrations",
+ "WEBHOOK": {
+ "TITLE": "Webhook",
+ "CONFIGURE": "Configure",
+ "HEADER": "Webhook settings",
+ "HEADER_BTN_TXT": "Add new webhook",
+ "INTEGRATION_TXT": "Webhook events provide you the realtime information about what's happening in your Chatwoot account. You can make use of the webhooks to communicate the events to your favourite apps like Slack or Github. Click on Configure to set up your webhooks.",
+ "LOADING": "Fetching attached webhooks",
+ "SEARCH_404": "ไม่มีรายการที่ตรงกับเนื้อหานี้",
+ "SIDEBAR_TXT": "
For creating a webhook, click on the Add new webhook button. You can also remove any existing webhook by clicking on the Delete button.
Labels are tied to the account and can be used to create custom workflows in your organization. You can assign custom color to a label, it makes it easier to identify the label. You will be able to display the label on the sidebar to filter the conversations easily.
PS: As an administrator, if you need access to all inboxes, you should add yourself as agent to all inboxes that you create."
+ "TITLE": "客服代理们",
+ "DESC": "在这里您可以添加代理来管理您新创建的收件箱。只有这些选定的代理才能访问您的收件箱。 不属于此收件箱的代理人在登录时将无法看到或回复此收件箱中的消息。
PS: 作为管理员,如果您需要访问所有收件箱, 您应该将自己添加到您创建的所有收件箱中。"
},
"DETAILS": {
- "TITLE": "Inbox Details",
- "DESC": "From the dropdown below, select the Facebook Page you want to connect to Chatwoot. You can also give a custom name to your inbox for better identification."
+ "TITLE": "收件箱详细信息",
+ "DESC": "从下面的下拉菜单中选择您想要连接到聊天室的 Facebook 页面。 您也可以给您的收件箱提供一个自定义名称以便更好地识别身份。"
},
"FINISH": {
- "TITLE": "Nailed It!",
- "DESC": "You have successfully finished integrating your Facebook Page with Chatwoot. Next time a customer messages your Page, the conversation will automatically appear on your inbox.
We are also providing you with a widget script that you can easily add to your website. Once this is live on your website, customers can message you right from your website without the help of any external tool and the conversation will appear right here, on Chatwoot.
Cool, huh? Well, we sure try to be :)"
+ "TITLE": "已被注明!",
+ "DESC": "您已成功地将您的Facebook页面与Chatwoot集成。下次客户消息您的页面时,对话将自动出现在收件箱中。
我们还为您提供了一个小部件脚本,您可以轻松地添加到您的网站。 在您的网站上登录后, 客户可以在没有任何外部工具帮助的情况下从您的网站向您发送消息,对话将会在这里出现在Chatwoot 上。
酷,好吧?好吧,我们肯定试着是 :)"
}
},
"DETAILS": {
- "LOADING_FB": "Authenticating you with Facebook...",
- "ERROR_FB_AUTH": "Something went wrong, Please refresh page...",
- "CREATING_CHANNEL": "Creating your Inbox...",
- "TITLE": "Configure Inbox Details",
+ "LOADING_FB": "在 Facebook 上认证你... ..",
+ "ERROR_FB_AUTH": "出错了,请刷新页面...",
+ "CREATING_CHANNEL": "创建您的收件箱...",
+ "TITLE": "配置收件箱详情",
"DESC": ""
},
"AGENTS": {
- "BUTTON_TEXT": "Add agents",
- "ADD_AGENTS": "Adding Agents to your Inbox..."
+ "BUTTON_TEXT": "添加客服代理",
+ "ADD_AGENTS": "正在向收件箱添加代理..."
},
"FINISH": {
- "TITLE": "Your Inbox is ready!",
- "MESSAGE": "You can now engage with your customers through your new Channel. Happy supporting ",
- "BUTTON_TEXT": "Take me there",
- "WEBSITE_SUCCESS": "You have successfully finished creating a website channel. Copy the code shown below and paste it on your website. Next time a customer use the live chat, the conversation will automatically appear on your inbox."
+ "TITLE": "您的收件箱已准备就绪!",
+ "MESSAGE": "您现在可以通过您的新频道与您的客户联系。快乐支持 ",
+ "BUTTON_TEXT": "带我到这里",
+ "WEBSITE_SUCCESS": "您已成功完成创建网站频道。复制下面显示的代码并将其粘贴在您的网站上。 下次客户使用实时聊天时,对话将自动出现在您的收件箱中。"
},
- "REAUTH": "Reauthorize",
- "VIEW": "View",
+ "REAUTH": "重新授权",
+ "VIEW": "查看",
"EDIT": {
"API": {
- "SUCCESS_MESSAGE": "Inbox settings updated successfully",
- "AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "Auto assignment updated successfully",
- "ERROR_MESSAGE": "Could not update widget color. Please try again later."
+ "SUCCESS_MESSAGE": "已成功更新收件箱设置",
+ "AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "自动分配成功更新",
+ "ERROR_MESSAGE": "无法更新部件颜色。请稍后再试。"
},
"AUTO_ASSIGNMENT": {
- "ENABLED": "Enabled",
- "DISABLED": "Disabled"
+ "ENABLED": "已启用",
+ "DISABLED": "已禁用"
}
},
"DELETE": {
- "BUTTON_TEXT": "Delete",
+ "BUTTON_TEXT": "删除",
"CONFIRM": {
- "TITLE": "Confirm Deletion",
- "MESSAGE": "Are you sure to delete ",
- "YES": "Yes, Delete ",
- "NO": "No, Keep "
+ "TITLE": "确认删除",
+ "MESSAGE": "您确定要删除吗? ",
+ "YES": "是,删除 ",
+ "NO": "不,保留 "
},
"API": {
- "SUCCESS_MESSAGE": "Inbox deleted successfully",
- "ERROR_MESSAGE": "Could not delete inbox. Please try again later."
+ "SUCCESS_MESSAGE": "收件箱删除成功",
+ "ERROR_MESSAGE": "无法删除收件箱。请稍后再试。"
}
},
"TABS": {
- "SETTINGS": "Settings",
+ "SETTINGS": "设置",
"COLLABORATORS": "Collaborators",
"CONFIGURATION": "Configuration"
},
- "SETTINGS": "Settings",
+ "SETTINGS": "设置",
"FEATURES": {
"LABEL": "Features",
"DISPLAY_FILE_PICKER": "Display file picker on the widget",
"DISPLAY_EMOJI_PICKER": "Display emoji picker on the widget"
},
"SETTINGS_POPUP": {
- "MESSENGER_HEADING": "Messenger Script",
- "MESSENGER_SUB_HEAD": "Place this button inside your body tag",
- "INBOX_AGENTS": "Agents",
- "INBOX_AGENTS_SUB_TEXT": "Add or remove agents from this inbox",
- "UPDATE": "Update",
- "AUTO_ASSIGNMENT": "Enable auto assignment",
- "INBOX_UPDATE_TITLE": "Inbox Settings",
- "INBOX_UPDATE_SUB_TEXT": "Update your inbox settings",
- "AUTO_ASSIGNMENT_SUB_TEXT": "Enable or disable the automatic assignment of new conversations to the agents added to this inbox."
+ "MESSENGER_HEADING": "Messenger 脚本",
+ "MESSENGER_SUB_HEAD": "将此按钮放置在窗体标签中",
+ "INBOX_AGENTS": "客服代理们",
+ "INBOX_AGENTS_SUB_TEXT": "添加或删除此收件箱中的客服",
+ "UPDATE": "更新",
+ "AUTO_ASSIGNMENT": "启用自动分配",
+ "INBOX_UPDATE_TITLE": "收件箱设置",
+ "INBOX_UPDATE_SUB_TEXT": "更新收件箱设置",
+ "AUTO_ASSIGNMENT_SUB_TEXT": "启用或禁用添加到此收件箱的代理人自动分配新的会话。"
}
}
}
diff --git a/app/javascript/dashboard/i18n/locale/zh/integrations.json b/app/javascript/dashboard/i18n/locale/zh/integrations.json
index 944b51f49..17952efd1 100644
--- a/app/javascript/dashboard/i18n/locale/zh/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/zh/integrations.json
@@ -1,63 +1,63 @@
{
"INTEGRATION_SETTINGS": {
- "HEADER": "集成方式",
+ "HEADER": "Integrations",
"WEBHOOK": {
- "TITLE": "回调接口地址",
- "CONFIGURE": "配置",
- "HEADER": "Webhook设置",
- "HEADER_BTN_TXT": "添加新的 webhook",
- "INTEGRATION_TXT": "Webhook 事件为您提供了有关Chatwoot 帐户中发生的事情的实时信息。 您可以使用 webhooks 将事件传递给您喜欢的 Slack 或 Github。 单击配置来设置您的网络钩子。",
- "LOADING": "正在获取已添加的 webhooks",
- "SEARCH_404": "没有任何项目符合此查询",
- "SIDEBAR_TXT": "
创建一个 webhook, 点击 添加新的 webhook 按钮。 您也可以通过点击删除按钮删除任何现有的网络钩子。
For creating a webhook, click on the Add new webhook button. You can also remove any existing webhook by clicking on the Delete button.
PS: 作为管理员,如果您需要访问所有收件箱, 您应该将自己添加到您创建的所有收件箱中。"
+ },
+ "DETAILS": {
+ "TITLE": "收件箱详细信息",
+ "DESC": "从下面的下拉菜单中选择您想要连接到聊天室的 Facebook 页面。 您也可以给您的收件箱提供一个自定义名称以便更好地识别身份。"
+ },
+ "FINISH": {
+ "TITLE": "已被注明!",
+ "DESC": "您已成功地将您的Facebook页面与Chatwoot集成。下次客户消息您的页面时,对话将自动出现在收件箱中。
我们还为您提供了一个小部件脚本,您可以轻松地添加到您的网站。 在您的网站上登录后, 客户可以在没有任何外部工具帮助的情况下从您的网站向您发送消息,对话将会在这里出现在Chatwoot 上。
酷,好吧?好吧,我们肯定试着是 :)"
+ }
+ },
+ "DETAILS": {
+ "LOADING_FB": "在 Facebook 上认证你... ..",
+ "ERROR_FB_AUTH": "出错了,请刷新页面...",
+ "CREATING_CHANNEL": "创建您的收件箱...",
+ "TITLE": "配置收件箱详情",
+ "DESC": ""
+ },
+ "AGENTS": {
+ "BUTTON_TEXT": "添加客服代理",
+ "ADD_AGENTS": "正在向收件箱添加代理..."
+ },
+ "FINISH": {
+ "TITLE": "您的收件箱已准备就绪!",
+ "MESSAGE": "您现在可以通过您的新频道与您的客户联系。快乐支持 ",
+ "BUTTON_TEXT": "带我到这里",
+ "WEBSITE_SUCCESS": "您已成功完成创建网站频道。复制下面显示的代码并将其粘贴在您的网站上。 下次客户使用实时聊天时,对话将自动出现在您的收件箱中。"
+ },
+ "REAUTH": "重新授权",
+ "VIEW": "查看",
+ "EDIT": {
+ "API": {
+ "SUCCESS_MESSAGE": "已成功更新收件箱设置",
+ "AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "自动分配成功更新",
+ "ERROR_MESSAGE": "无法更新部件颜色。请稍后再试。"
+ },
+ "AUTO_ASSIGNMENT": {
+ "ENABLED": "已启用",
+ "DISABLED": "已禁用"
+ }
+ },
+ "DELETE": {
+ "BUTTON_TEXT": "删除",
+ "CONFIRM": {
+ "TITLE": "确认删除",
+ "MESSAGE": "您确定要删除吗? ",
+ "YES": "是,删除 ",
+ "NO": "不,保留 "
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "收件箱删除成功",
+ "ERROR_MESSAGE": "无法删除收件箱。请稍后再试。"
+ }
+ },
+ "TABS": {
+ "SETTINGS": "设置",
+ "COLLABORATORS": "Collaborators",
+ "CONFIGURATION": "Configuration"
+ },
+ "SETTINGS": "设置",
+ "FEATURES": {
+ "LABEL": "Features",
+ "DISPLAY_FILE_PICKER": "Display file picker on the widget",
+ "DISPLAY_EMOJI_PICKER": "Display emoji picker on the widget"
+ },
+ "SETTINGS_POPUP": {
+ "MESSENGER_HEADING": "Messenger 脚本",
+ "MESSENGER_SUB_HEAD": "将此按钮放置在窗体标签中",
+ "INBOX_AGENTS": "客服代理们",
+ "INBOX_AGENTS_SUB_TEXT": "添加或删除此收件箱中的客服",
+ "UPDATE": "更新",
+ "AUTO_ASSIGNMENT": "启用自动分配",
+ "INBOX_UPDATE_TITLE": "收件箱设置",
+ "INBOX_UPDATE_SUB_TEXT": "更新收件箱设置",
+ "AUTO_ASSIGNMENT_SUB_TEXT": "启用或禁用添加到此收件箱的代理人自动分配新的会话。"
+ }
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/zh_CN/integrations.json b/app/javascript/dashboard/i18n/locale/zh_CN/integrations.json
new file mode 100644
index 000000000..944b51f49
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/zh_CN/integrations.json
@@ -0,0 +1,63 @@
+{
+ "INTEGRATION_SETTINGS": {
+ "HEADER": "集成方式",
+ "WEBHOOK": {
+ "TITLE": "回调接口地址",
+ "CONFIGURE": "配置",
+ "HEADER": "Webhook设置",
+ "HEADER_BTN_TXT": "添加新的 webhook",
+ "INTEGRATION_TXT": "Webhook 事件为您提供了有关Chatwoot 帐户中发生的事情的实时信息。 您可以使用 webhooks 将事件传递给您喜欢的 Slack 或 Github。 单击配置来设置您的网络钩子。",
+ "LOADING": "正在获取已添加的 webhooks",
+ "SEARCH_404": "没有任何项目符合此查询",
+ "SIDEBAR_TXT": "
创建一个 webhook, 点击 添加新的 webhook 按钮。 您也可以通过点击删除按钮删除任何现有的网络钩子。
标签被绑定到帐户,可以用于创建您组织中的自定义工作流。 您可以将自定义颜色分配给标签,使它更容易识别标签。 您将能够在侧边栏上显示标签,方便地过滤对话。
PS: As an administrator, if you need access to all inboxes, you should add yourself as agent to all inboxes that you create."
+ },
+ "DETAILS": {
+ "TITLE": "Inbox Details",
+ "DESC": "From the dropdown below, select the Facebook Page you want to connect to Chatwoot. You can also give a custom name to your inbox for better identification."
+ },
+ "FINISH": {
+ "TITLE": "Nailed It!",
+ "DESC": "You have successfully finished integrating your Facebook Page with Chatwoot. Next time a customer messages your Page, the conversation will automatically appear on your inbox.
We are also providing you with a widget script that you can easily add to your website. Once this is live on your website, customers can message you right from your website without the help of any external tool and the conversation will appear right here, on Chatwoot.
Cool, huh? Well, we sure try to be :)"
+ }
+ },
+ "DETAILS": {
+ "LOADING_FB": "Authenticating you with Facebook...",
+ "ERROR_FB_AUTH": "Something went wrong, Please refresh page...",
+ "CREATING_CHANNEL": "Creating your Inbox...",
+ "TITLE": "Configure Inbox Details",
+ "DESC": ""
+ },
+ "AGENTS": {
+ "BUTTON_TEXT": "Add agents",
+ "ADD_AGENTS": "Adding Agents to your Inbox..."
+ },
+ "FINISH": {
+ "TITLE": "Your Inbox is ready!",
+ "MESSAGE": "You can now engage with your customers through your new Channel. Happy supporting ",
+ "BUTTON_TEXT": "Take me there",
+ "WEBSITE_SUCCESS": "You have successfully finished creating a website channel. Copy the code shown below and paste it on your website. Next time a customer use the live chat, the conversation will automatically appear on your inbox."
+ },
+ "REAUTH": "Reauthorize",
+ "VIEW": "View",
+ "EDIT": {
+ "API": {
+ "SUCCESS_MESSAGE": "Inbox settings updated successfully",
+ "AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "Auto assignment updated successfully",
+ "ERROR_MESSAGE": "Could not update widget color. Please try again later."
+ },
+ "AUTO_ASSIGNMENT": {
+ "ENABLED": "Enabled",
+ "DISABLED": "Disabled"
+ }
+ },
+ "DELETE": {
+ "BUTTON_TEXT": "Delete",
+ "CONFIRM": {
+ "TITLE": "Confirm Deletion",
+ "MESSAGE": "Are you sure to delete ",
+ "YES": "Yes, Delete ",
+ "NO": "No, Keep "
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "Inbox deleted successfully",
+ "ERROR_MESSAGE": "Could not delete inbox. Please try again later."
+ }
+ },
+ "TABS": {
+ "SETTINGS": "Settings",
+ "COLLABORATORS": "Collaborators",
+ "CONFIGURATION": "Configuration"
+ },
+ "SETTINGS": "Settings",
+ "FEATURES": {
+ "LABEL": "Features",
+ "DISPLAY_FILE_PICKER": "Display file picker on the widget",
+ "DISPLAY_EMOJI_PICKER": "Display emoji picker on the widget"
+ },
+ "SETTINGS_POPUP": {
+ "MESSENGER_HEADING": "Messenger Script",
+ "MESSENGER_SUB_HEAD": "Place this button inside your body tag",
+ "INBOX_AGENTS": "Agents",
+ "INBOX_AGENTS_SUB_TEXT": "Add or remove agents from this inbox",
+ "UPDATE": "Update",
+ "AUTO_ASSIGNMENT": "Enable auto assignment",
+ "INBOX_UPDATE_TITLE": "Inbox Settings",
+ "INBOX_UPDATE_SUB_TEXT": "Update your inbox settings",
+ "AUTO_ASSIGNMENT_SUB_TEXT": "Enable or disable the automatic assignment of new conversations to the agents added to this inbox."
+ }
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/zh_TW/integrations.json b/app/javascript/dashboard/i18n/locale/zh_TW/integrations.json
new file mode 100644
index 000000000..17952efd1
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/zh_TW/integrations.json
@@ -0,0 +1,63 @@
+{
+ "INTEGRATION_SETTINGS": {
+ "HEADER": "Integrations",
+ "WEBHOOK": {
+ "TITLE": "Webhook",
+ "CONFIGURE": "Configure",
+ "HEADER": "Webhook settings",
+ "HEADER_BTN_TXT": "Add new webhook",
+ "INTEGRATION_TXT": "Webhook events provide you the realtime information about what's happening in your Chatwoot account. You can make use of the webhooks to communicate the events to your favourite apps like Slack or Github. Click on Configure to set up your webhooks.",
+ "LOADING": "Fetching attached webhooks",
+ "SEARCH_404": "There are no items matching this query",
+ "SIDEBAR_TXT": "
For creating a webhook, click on the Add new webhook button. You can also remove any existing webhook by clicking on the Delete button.
Labels are tied to the account and can be used to create custom workflows in your organization. You can assign custom color to a label, it makes it easier to identify the label. You will be able to display the label on the sidebar to filter the conversations easily.
Hi {{user.available_name}},
+ +You have received a new message in your assigned conversation.
+ ++Click here to get cracking. +
diff --git a/app/views/mailers/conversation_reply_mailer/reply_with_summary.html.erb b/app/views/mailers/conversation_reply_mailer/reply_with_summary.html.erb index 31648f2b8..5e182a273 100644 --- a/app/views/mailers/conversation_reply_mailer/reply_with_summary.html.erb +++ b/app/views/mailers/conversation_reply_mailer/reply_with_summary.html.erb @@ -9,7 +9,7 @@+
<% if message.content %>
<%= message.content.gsub("\n", "
").html_safe %>
<% end %>
diff --git a/app/views/super_admin/application/_navigation.html.erb b/app/views/super_admin/application/_navigation.html.erb
index f4c66cc2e..54c2ecc1b 100644
--- a/app/views/super_admin/application/_navigation.html.erb
+++ b/app/views/super_admin/application/_navigation.html.erb
@@ -36,7 +36,7 @@ as defined by the routes in the `admin/` namespace
<%= link_to(
display_resource_name(resource),
- [namespace, resource_index_route_key(resource)],
+ resource_index_route(resource)
) if valid_action? :index, resource %>
<% end %>
diff --git a/app/views/widget_tests/index.html.erb b/app/views/widget_tests/index.html.erb
index 6be67a713..b16465eba 100644
--- a/app/views/widget_tests/index.html.erb
+++ b/app/views/widget_tests/index.html.erb
@@ -5,8 +5,9 @@
window.chatwootSettings = {
hideMessageBubble: false,
position: 'left',
- locale: 'en',
+ locale: 'fr',
type: 'expanded_bubble',
+ showPopoutButton: true,
};
(function(d,t) {
diff --git a/config/app.yml b/config/app.yml
index 3dc909ba6..f904cd23e 100644
--- a/config/app.yml
+++ b/config/app.yml
@@ -1,5 +1,5 @@
shared: &shared
- version: '1.7.2'
+ version: '1.8.0'
development:
<<: *shared
diff --git a/config/environments/production.rb b/config/environments/production.rb
index b796d6acd..5b9acb497 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -31,8 +31,7 @@ Rails.application.configure do
# `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
- # config.action_controller.asset_host = 'http://assets.example.com'
-
+ config.action_controller.asset_host = ENV.fetch('ASSET_CDN_HOST') if ENV['ASSET_CDN_HOST'].present?
# Specifies the header that your server uses for sending files.
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
@@ -79,12 +78,12 @@ Rails.application.configure do
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
if ENV['RAILS_LOG_TO_STDOUT'].present?
- logger = ActiveSupport::Logger.new(STDOUT)
+ logger = ActiveSupport::Logger.new($stdout)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
else
config.logger = ActiveSupport::Logger.new(
- Rails.root.join('log', Rails.env + '.log'),
+ Rails.root.join("log/#{Rails.env}.log"),
1,
ENV.fetch('LOG_SIZE', '1024').to_i.megabytes
)
@@ -119,4 +118,13 @@ Rails.application.configure do
config.action_mailbox.ingress = ENV.fetch('RAILS_INBOUND_EMAIL_SERVICE', 'relay').to_sym
Rails.application.routes.default_url_options = { host: ENV['FRONTEND_URL'] }
+
+ # font cors issue with CDN
+ # Ref: https://stackoverflow.com/questions/56960709/rails-font-cors-policy
+ config.middleware.insert_before 0, Rack::Cors do
+ allow do
+ origins '*'
+ resource '/packs/*', headers: :any, methods: [:get, :options]
+ end
+ end
end
diff --git a/config/environments/staging.rb b/config/environments/staging.rb
index 585f35da4..5243a2d59 100644
--- a/config/environments/staging.rb
+++ b/config/environments/staging.rb
@@ -92,14 +92,23 @@ Rails.application.configure do
# Use a different logger for distributed setups.
# require 'syslog/logger'
- config.logger = ActiveSupport::Logger.new(Rails.root.join('log', Rails.env + '.log'), 1, ENV.fetch('LOG_SIZE', '1024').to_i.megabytes)
+ config.logger = ActiveSupport::Logger.new(Rails.root.join("log/#{Rails.env}.log"), 1, ENV.fetch('LOG_SIZE', '1024').to_i.megabytes)
if ENV['RAILS_LOG_TO_STDOUT'].present?
- logger = ActiveSupport::Logger.new(STDOUT)
+ logger = ActiveSupport::Logger.new($stdout)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
end
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
+
+ # font cors issue with CDN
+ # Ref: https://stackoverflow.com/questions/56960709/rails-font-cors-policy
+ config.middleware.insert_before 0, Rack::Cors do
+ allow do
+ origins '*'
+ resource '/packs/*', headers: :any, methods: [:get, :options]
+ end
+ end
end
diff --git a/config/environments/test.rb b/config/environments/test.rb
index 1dbfa63ef..6a2534654 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -51,4 +51,13 @@ Rails.application.configure do
# Raises error for missing translations.
# config.action_view.raise_on_missing_translations = true
config.log_level = ENV.fetch('LOG_LEVEL', 'debug').to_sym
+
+ # font cors issue with CDN
+ # Ref: https://stackoverflow.com/questions/56960709/rails-font-cors-policy
+ config.middleware.insert_before 0, Rack::Cors do
+ allow do
+ origins '*'
+ resource '/packs/*', headers: :any, methods: [:get, :options]
+ end
+ end
end
diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb
index 351f7b42b..9ac37c731 100644
--- a/config/initializers/assets.rb
+++ b/config/initializers/assets.rb
@@ -13,3 +13,7 @@ Rails.application.config.assets.paths << Rails.root.join('node_modules')
# folder are already added.
# Rails.application.config.assets.precompile += %w( admin.js admin.css )
Rails.application.config.assets.precompile += %w[dashboardChart.js]
+
+# to take care of fonts in assets pre-compiling
+# Ref: https://stackoverflow.com/questions/56960709/rails-font-cors-policy
+Rails.application.config.assets.precompile << /\.(?:svg|eot|woff|ttf|woff2)$/
diff --git a/config/initializers/sentry.rb b/config/initializers/sentry.rb
index 7efef3a92..1237c47b5 100644
--- a/config/initializers/sentry.rb
+++ b/config/initializers/sentry.rb
@@ -21,7 +21,7 @@ module QueryTrace
def log_info_with_trace(event)
log_info_without_trace(event)
trace_log = Rails.backtrace_cleaner.clean(caller).first
- logger.debug(" \\_ \e[33mCalled from:\e[0m " + trace_log) if trace_log && event.payload[:name] != 'SCHEMA'
+ logger.debug(" \\_ \e[33mCalled from:\e[0m #{trace_log}") if trace_log && event.payload[:name] != 'SCHEMA'
end
end
diff --git a/config/installation_config.yml b/config/installation_config.yml
index b48d3a9d3..41c27b6c5 100644
--- a/config/installation_config.yml
+++ b/config/installation_config.yml
@@ -22,3 +22,5 @@
value: false
- name: BRAND_NAME
value: 'Chatwoot'
+- name: 'INSTALLATION_EVENTS_WEBHOOK_URL'
+ value:
diff --git a/config/locales/ar.yml b/config/locales/ar.yml
index 37b9fa0a6..0304da50c 100644
--- a/config/locales/ar.yml
+++ b/config/locales/ar.yml
@@ -41,4 +41,4 @@ ar:
email_input_box_message_body: "احصل على الإشعارات في البريد الإلكتروني"
reply:
email_subject: "رسائل جديدة في هذه المحادثة"
- transcript_subject: "Conversation Transcript"
+ transcript_subject: "نص المحادثة"
diff --git a/config/locales/devise.ar.yml b/config/locales/devise.ar.yml
index 03cd3353f..4157857f5 100644
--- a/config/locales/devise.ar.yml
+++ b/config/locales/devise.ar.yml
@@ -28,7 +28,7 @@ ar:
failure: "تعذر المصادقة من %{kind} لأن \"%{reason}\"."
success: "تمت المصادقة بنجاح من حساب %{kind}."
passwords:
- no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
+ no_token: "لا يمكنك الوصول لهذه الصفحة دون أن تأتي من البريد الإلكتروني لإعادة تعيين كلمة المرور. إذا كنت وصلت إلى هنا عبر البريد إلكتروني لإعادة تعيين كلمة المرور، الرجاء التأكد من أنك استخدمت عنوان URL بأكمله."
send_instructions: "سوف تتلقى رسالة بريد إلكتروني تحتوي على تعليمات إعادة ضبط كلمة المرور خلال بضع دقائق."
send_paranoid_instructions: "إذا كان عنوان بريدك الإلكتروني موجود في قاعدة بياناتنا، سوف تتلقى رسالة بريد إلكتروني مع إرشادات إعادة ضبط كلمة المرور خلال بضع دقائق."
updated: "تم تغيير كلمة المرور الخاصة بك بنجاح وتم تسجيل دخولك الآن."
@@ -37,29 +37,29 @@ ar:
destroyed: "وداعاً! لقد تم إلغاء حسابك بنجاح. نأمل أن نراك مرة أخرى قريباً."
signed_up: "مرحبًا! لقد قمت بالتسجيل بنجاح."
signed_up_but_inactive: "لقد قمت بالتسجيل بنجاح. ومع ذلك، لم نستطع تسجيل دخولك لأن حسابك لم يتم تفعيله بعد."
- signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
- signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
- update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address."
- updated: "Your account has been updated successfully."
+ signed_up_but_locked: "لقد قمت بالتسجيل بنجاح. ومع ذلك، لم نستطع تسجيل دخولك لأن حسابك لم يتم تفعيله بعد."
+ signed_up_but_unconfirmed: "تم إرسال رسالة مع رابط تأكيد إلى عنوان بريدك الإلكتروني. الرجاء اتباع الرابط لتفعيل حسابك."
+ update_needs_confirmation: "لقد قمت بتحديث حسابك بنجاح، ولكن نحن بحاجة إلى التحقق من عنوان بريدك الإلكتروني الجديد. الرجاء التحقق من بريدك الإلكتروني واتبع رابط التأكيد لتأكيد عنوان بريدك الإلكتروني الجديد."
+ updated: "تم تحديث حسابك بنجاح."
sessions:
signed_in: "تم تسجيل الدخول بنجاح."
signed_out: "تم تسجيل الخروج بنجاح."
already_signed_out: "تم تسجيل الخروج بنجاح."
unlocks:
- send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
- send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
- unlocked: "Your account has been unlocked successfully. Please sign in to continue."
+ send_instructions: "سوف تتلقى رسالة بريد إلكتروني تحتوي على تعليمات لكيفية فتح حسابك في بضع دقائق."
+ send_paranoid_instructions: "إذا كان حسابك موجودا، سوف تتلقى رسالة بريد إلكتروني تحتوي على إرشادات لكيفية فتحه في بضع دقائق."
+ unlocked: "تم إلغاء قفل حسابك بنجاح. الرجاء تسجيل الدخول للمتابعة."
errors:
messages:
- already_confirmed: "was already confirmed, please try signing in"
- confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
- expired: "has expired, please request a new one"
+ already_confirmed: "تم تأكيده مسبقا، الرجاء محاولة تسجيل الدخول"
+ confirmation_period_expired: "يحتاج إلى تأكيد في غضون %{period}، الرجاء طلب واحد جديد"
+ expired: "انتهت صلاحيته، الرجاء طلب جديد"
not_found: "غير موجود"
- not_locked: "was not locked"
+ not_locked: "لم يكن مقفلاً"
not_saved:
- zero: "%{count} errors prohibited this %{resource} from being saved:"
- one: "1 error prohibited this %{resource} from being saved:"
+ zero: "%{count} خطأ حظر هذا %{resource} من الحفظ:"
+ one: "خطأ واحد حظر هذا %{resource} من الحفظ:"
two: "%{count} errors prohibited this %{resource} from being saved:"
- few: "%{count} errors prohibited this %{resource} from being saved:"
- many: "%{count} errors prohibited this %{resource} from being saved:"
- other: "%{count} errors prohibited this %{resource} from being saved:"
+ few: "%{count} أخطاء حظرت %{resource} من الحفظ:"
+ many: "%{count} أخطاء حظرت %{resource} من الحفظ:"
+ other: "%{count} أخطاء حظرت %{resource} من الحفظ:"
diff --git a/config/locales/devise.th.yml b/config/locales/devise.th.yml
new file mode 100644
index 000000000..a06ceb177
--- /dev/null
+++ b/config/locales/devise.th.yml
@@ -0,0 +1,60 @@
+#Additional translations at https://github.com/plataformatec/devise/wiki/I18n
+th:
+ devise:
+ confirmations:
+ confirmed: "Your email address has been successfully confirmed."
+ send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
+ send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
+ failure:
+ already_authenticated: "You are already signed in."
+ inactive: "Your account is not activated yet."
+ invalid: "Invalid %{authentication_keys}/password or account is not verified yet."
+ locked: "Your account is locked."
+ last_attempt: "You have one more attempt before your account is locked."
+ not_found_in_database: "Invalid %{authentication_keys} or password."
+ timeout: "Your session expired. Please sign in again to continue."
+ unauthenticated: "You need to sign in or sign up before continuing."
+ unconfirmed: "You have to confirm your email address before continuing."
+ mailer:
+ confirmation_instructions:
+ subject: "Confirmation Instructions"
+ reset_password_instructions:
+ subject: "Reset password instructions"
+ unlock_instructions:
+ subject: "Unlock instructions"
+ password_change:
+ subject: "Password Changed"
+ omniauth_callbacks:
+ failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
+ success: "Successfully authenticated from %{kind} account."
+ passwords:
+ no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
+ send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
+ send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
+ updated: "Your password has been changed successfully. You are now signed in."
+ updated_not_active: "Your password has been changed successfully."
+ registrations:
+ destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
+ signed_up: "Welcome! You have signed up successfully."
+ signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
+ signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
+ signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
+ update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address."
+ updated: "Your account has been updated successfully."
+ sessions:
+ signed_in: "Signed in successfully."
+ signed_out: "Signed out successfully."
+ already_signed_out: "Signed out successfully."
+ unlocks:
+ send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
+ send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
+ unlocked: "Your account has been unlocked successfully. Please sign in to continue."
+ errors:
+ messages:
+ already_confirmed: "was already confirmed, please try signing in"
+ confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
+ expired: "has expired, please request a new one"
+ not_found: "not found"
+ not_locked: "was not locked"
+ not_saved:
+ other: "%{count} errors prohibited this %{resource} from being saved:"
diff --git a/config/locales/devise.zh_CN.yml b/config/locales/devise.zh_CN.yml
new file mode 100644
index 000000000..f8613c84c
--- /dev/null
+++ b/config/locales/devise.zh_CN.yml
@@ -0,0 +1,60 @@
+#Additional translations at https://github.com/plataformatec/devise/wiki/I18n
+zh-CN:
+ devise:
+ confirmations:
+ confirmed: "您的电子邮件地址已成功确认。"
+ send_instructions: "您将在几分钟内收到一封电子邮件,说明如何确认您的电子邮件地址。"
+ send_paranoid_instructions: "如果您的电子邮件地址存在于我们的数据库, 您将在几分钟内收到一封电子邮件,说明如何确认您的电子邮件地址。"
+ failure:
+ already_authenticated: "您已经登录。"
+ inactive: "您的帐户尚未激活。"
+ invalid: "无效的 %{authentication_keys}/密码或帐户尚未验证。"
+ locked: "您的帐户已被锁定。"
+ last_attempt: "您还有一次尝试在您的帐户被锁定之前。"
+ not_found_in_database: "无效的 %{authentication_keys} 或密码。"
+ timeout: "您的会话已过期。请重新登录以继续。"
+ unauthenticated: "您需要登录或注册才能继续。"
+ unconfirmed: "您必须先确认您的电子邮件地址才能继续。"
+ mailer:
+ confirmation_instructions:
+ subject: "确认说明"
+ reset_password_instructions:
+ subject: "重置密码说明"
+ unlock_instructions:
+ subject: "解锁说明"
+ password_change:
+ subject: "密码已修改"
+ omniauth_callbacks:
+ failure: "无法认证您来自 %{kind} 的身份,因为“%{reason}”。"
+ success: "从 %{kind} 帐户成功验证。"
+ passwords:
+ no_token: "没有来自密码重置电子邮件,您不能访问此页面。 如果您确实来自密码重置电子邮件,请确保您使用了提供的完整URL。"
+ send_instructions: "您将在几分钟内收到一封电子邮件,说明如何确认您的电子邮件地址。"
+ send_paranoid_instructions: "如果您的电子邮件地址存在于我们的数据库, 您将在几分钟内收到一封电子邮件,说明如何确认您的电子邮件地址。"
+ updated: "您的密码已成功更改。您现在已登录。"
+ updated_not_active: "您的密码已成功更改。"
+ registrations:
+ destroyed: "再见!您的帐户已被成功取消。我们希望很快再见到您。"
+ signed_up: "欢迎!您已成功注册。"
+ signed_up_but_inactive: "您已成功注册。但我们无法登录,因为您的帐户尚未激活。"
+ signed_up_but_locked: "您已成功注册。但我们无法登录,因为您的帐户尚未激活。"
+ signed_up_but_unconfirmed: "一封带有确认链接的邮件已发送到您的电子邮件地址。请点击链接激活您的帐户。"
+ update_needs_confirmation: "您已成功更新您的帐户,但我们需要验证您的新电子邮件地址。 请检查您的电子邮件并点击确认链接以确认您的新电子邮件地址。"
+ updated: "您的密码已成功更改。"
+ sessions:
+ signed_in: "登录成功。"
+ signed_out: "登录成功。"
+ already_signed_out: "登录成功。"
+ unlocks:
+ send_instructions: "您将在几分钟内收到一封电子邮件,说明如何确认您的电子邮件地址。"
+ send_paranoid_instructions: "如果您的帐户存在,您将收到一封电子邮件,说明如何在几分钟内解锁它。"
+ unlocked: "您的帐户已成功解锁。请登录以继续。"
+ errors:
+ messages:
+ already_confirmed: "已经确认,请尝试登录"
+ confirmation_period_expired: "需要在 %{period}内确认, 请申请一个新的"
+ expired: "已过期,请申请一个新的"
+ not_found: "找不到"
+ not_locked: "未锁定"
+ not_saved:
+ other: "%{count} 个错误禁止保存 %{resource}:"
diff --git a/config/locales/devise.zh_TW.yml b/config/locales/devise.zh_TW.yml
new file mode 100644
index 000000000..c0e50fc34
--- /dev/null
+++ b/config/locales/devise.zh_TW.yml
@@ -0,0 +1,60 @@
+#Additional translations at https://github.com/plataformatec/devise/wiki/I18n
+zh-TW:
+ devise:
+ confirmations:
+ confirmed: "Your email address has been successfully confirmed."
+ send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
+ send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
+ failure:
+ already_authenticated: "You are already signed in."
+ inactive: "Your account is not activated yet."
+ invalid: "Invalid %{authentication_keys}/password or account is not verified yet."
+ locked: "Your account is locked."
+ last_attempt: "You have one more attempt before your account is locked."
+ not_found_in_database: "Invalid %{authentication_keys} or password."
+ timeout: "Your session expired. Please sign in again to continue."
+ unauthenticated: "You need to sign in or sign up before continuing."
+ unconfirmed: "You have to confirm your email address before continuing."
+ mailer:
+ confirmation_instructions:
+ subject: "Confirmation Instructions"
+ reset_password_instructions:
+ subject: "Reset password instructions"
+ unlock_instructions:
+ subject: "Unlock instructions"
+ password_change:
+ subject: "Password Changed"
+ omniauth_callbacks:
+ failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
+ success: "Successfully authenticated from %{kind} account."
+ passwords:
+ no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
+ send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
+ send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
+ updated: "Your password has been changed successfully. You are now signed in."
+ updated_not_active: "Your password has been changed successfully."
+ registrations:
+ destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
+ signed_up: "Welcome! You have signed up successfully."
+ signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
+ signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
+ signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
+ update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address."
+ updated: "Your account has been updated successfully."
+ sessions:
+ signed_in: "Signed in successfully."
+ signed_out: "Signed out successfully."
+ already_signed_out: "Signed out successfully."
+ unlocks:
+ send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
+ send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
+ unlocked: "Your account has been unlocked successfully. Please sign in to continue."
+ errors:
+ messages:
+ already_confirmed: "was already confirmed, please try signing in"
+ confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
+ expired: "has expired, please request a new one"
+ not_found: "not found"
+ not_locked: "was not locked"
+ not_saved:
+ other: "%{count} errors prohibited this %{resource} from being saved:"
diff --git a/config/locales/th.yml b/config/locales/th.yml
new file mode 100644
index 000000000..619845856
--- /dev/null
+++ b/config/locales/th.yml
@@ -0,0 +1,44 @@
+#Files in the config/locales directory are used for internationalization
+#and are automatically loaded by Rails. If you want to use locales other
+#than English, add the necessary files in this directory.
+#To use the locales, use `I18n.t`:
+#I18n.t 'hello'
+#In views, this is aliased to just `t`:
+#<%= t('hello') %>
+#To use a different locale, set it with `I18n.locale`:
+#I18n.locale = :es
+#This would use the information in config/locales/es.yml.
+#The following keys must be escaped otherwise they will not be retrieved by
+#the default I18n backend:
+#true, false, on, off, yes, no
+#Instead, surround them with single quotes.
+#en:
+#'true': 'foo'
+#To learn more, please read the Rails Internationalization guide
+#available at https://guides.rubyonrails.org/i18n.html.
+th:
+ hello: "Hello world"
+ messages:
+ reset_password_success: Woot! Request for password reset is successful. Check your mail for instructions.
+ reset_password_failure: Uh ho! We could not find any user with the specified email.
+ errors:
+ signup:
+ disposable_email: We do not allow disposable emails
+ invalid_email: You have entered an invalid email
+ email_already_exists: "You have already signed up for an account with %{email}"
+ failed: Signup failed
+ conversations:
+ activity:
+ status:
+ resolved: "Conversation was marked resolved by %{user_name}"
+ open: "Conversation was reopened by %{user_name}"
+ assignee:
+ assigned: "Assigned to %{assignee_name} by %{user_name}"
+ removed: "Conversation unassigned by %{user_name}"
+ templates:
+ greeting_message_body: "%{account_name} typically replies in a few hours."
+ ways_to_reach_you_message_body: "Give the team a way to reach you."
+ email_input_box_message_body: "Get notified by email"
+ reply:
+ email_subject: "New messages on this conversation"
+ transcript_subject: "Conversation Transcript"
diff --git a/config/locales/zh_CN.yml b/config/locales/zh_CN.yml
new file mode 100644
index 000000000..3d7f44735
--- /dev/null
+++ b/config/locales/zh_CN.yml
@@ -0,0 +1,44 @@
+#Files in the config/locales directory are used for internationalization
+#and are automatically loaded by Rails. If you want to use locales other
+#than English, add the necessary files in this directory.
+#To use the locales, use `I18n.t`:
+#I18n.t 'hello'
+#In views, this is aliased to just `t`:
+#<%= t('hello') %>
+#To use a different locale, set it with `I18n.locale`:
+#I18n.locale = :es
+#This would use the information in config/locales/es.yml.
+#The following keys must be escaped otherwise they will not be retrieved by
+#the default I18n backend:
+#true, false, on, off, yes, no
+#Instead, surround them with single quotes.
+#en:
+#'true': 'foo'
+#To learn more, please read the Rails Internationalization guide
+#available at https://guides.rubyonrails.org/i18n.html.
+zh-CN:
+ hello: "您好世界"
+ messages:
+ reset_password_success: 哇!密码重置请求成功。请检查您的邮件获取说明。
+ reset_password_failure: 哎呀!我们找不到指定电子邮件的任何用户。
+ errors:
+ signup:
+ disposable_email: 我们不允许可用的电子邮件
+ invalid_email: 您输入了一个无效的电子邮件
+ email_already_exists: "您已经注册了 %{email} 的帐户"
+ failed: 注册失败
+ conversations:
+ activity:
+ status:
+ resolved: "对话被标记由 %{user_name} 解决"
+ open: "对话被 %{user_name} 重新打开"
+ assignee:
+ assigned: "由 %{assignee_name} 分配给 %{user_name}"
+ removed: "对话未被 %{user_name} 分配"
+ templates:
+ greeting_message_body: "%{account_name} 通常在几小时内回复。"
+ ways_to_reach_you_message_body: "给团队一个联系您的方法。"
+ email_input_box_message_body: "通过电子邮件得到通知"
+ reply:
+ email_subject: "此对话中的新消息"
+ transcript_subject: "Conversation Transcript"
diff --git a/config/locales/zh_TW.yml b/config/locales/zh_TW.yml
new file mode 100644
index 000000000..2d85006d3
--- /dev/null
+++ b/config/locales/zh_TW.yml
@@ -0,0 +1,44 @@
+#Files in the config/locales directory are used for internationalization
+#and are automatically loaded by Rails. If you want to use locales other
+#than English, add the necessary files in this directory.
+#To use the locales, use `I18n.t`:
+#I18n.t 'hello'
+#In views, this is aliased to just `t`:
+#<%= t('hello') %>
+#To use a different locale, set it with `I18n.locale`:
+#I18n.locale = :es
+#This would use the information in config/locales/es.yml.
+#The following keys must be escaped otherwise they will not be retrieved by
+#the default I18n backend:
+#true, false, on, off, yes, no
+#Instead, surround them with single quotes.
+#en:
+#'true': 'foo'
+#To learn more, please read the Rails Internationalization guide
+#available at https://guides.rubyonrails.org/i18n.html.
+zh-TW:
+ hello: "Hello world"
+ messages:
+ reset_password_success: Woot! Request for password reset is successful. Check your mail for instructions.
+ reset_password_failure: Uh ho! We could not find any user with the specified email.
+ errors:
+ signup:
+ disposable_email: We do not allow disposable emails
+ invalid_email: You have entered an invalid email
+ email_already_exists: "You have already signed up for an account with %{email}"
+ failed: Signup failed
+ conversations:
+ activity:
+ status:
+ resolved: "Conversation was marked resolved by %{user_name}"
+ open: "Conversation was reopened by %{user_name}"
+ assignee:
+ assigned: "Assigned to %{assignee_name} by %{user_name}"
+ removed: "Conversation unassigned by %{user_name}"
+ templates:
+ greeting_message_body: "%{account_name} typically replies in a few hours."
+ ways_to_reach_you_message_body: "Give the team a way to reach you."
+ email_input_box_message_body: "Get notified by email"
+ reply:
+ email_subject: "New messages on this conversation"
+ transcript_subject: "Conversation Transcript"
diff --git a/db/migrate/20161022055031_create_accounts.rb b/db/migrate/20161022055031_create_accounts.rb
deleted file mode 100644
index 81a3bd338..000000000
--- a/db/migrate/20161022055031_create_accounts.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class CreateAccounts < ActiveRecord::Migration[5.0]
- def change
- create_table :accounts do |t|
- t.string :name
-
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20161022060602_create_inboxes.rb b/db/migrate/20161022060602_create_inboxes.rb
deleted file mode 100644
index eab8c400d..000000000
--- a/db/migrate/20161022060602_create_inboxes.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-class CreateInboxes < ActiveRecord::Migration[5.0]
- def change
- create_table :inboxes do |t|
- t.integer :channel_id
- t.integer :account_id
- t.string :name
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20161022061641_create_contacts.rb b/db/migrate/20161022061641_create_contacts.rb
deleted file mode 100644
index 9313aae44..000000000
--- a/db/migrate/20161022061641_create_contacts.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-class CreateContacts < ActiveRecord::Migration[5.0]
- def change
- create_table :contacts do |t|
- t.string :name
- t.string :email
- t.string :phone_number
- t.integer :channel_id
- t.integer :account_id
-
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20161022062829_create_conversations.rb b/db/migrate/20161022062829_create_conversations.rb
deleted file mode 100644
index d10b31a6f..000000000
--- a/db/migrate/20161022062829_create_conversations.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-class CreateConversations < ActiveRecord::Migration[5.0]
- def change
- create_table :conversations do |t|
- t.integer :account_id
- t.integer :channel_id
- t.integer :inbox_id
- t.integer :status
- t.integer :assignee_id
-
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20161022072124_create_messages.rb b/db/migrate/20161022072124_create_messages.rb
deleted file mode 100644
index 8e29d3ad8..000000000
--- a/db/migrate/20161022072124_create_messages.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-class CreateMessages < ActiveRecord::Migration[5.0]
- def change
- create_table :messages do |t|
- t.text :content
- t.integer :account_id
- t.integer :channel_id
- t.integer :inbox_id
- t.integer :conversation_id
- t.integer :type
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20161022073137_add_sender_to_conversation.rb b/db/migrate/20161022073137_add_sender_to_conversation.rb
deleted file mode 100644
index 1ddb55536..000000000
--- a/db/migrate/20161022073137_add_sender_to_conversation.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddSenderToConversation < ActiveRecord::Migration[5.0]
- def change
- add_column :conversations, :sender_id, :integer
- end
-end
diff --git a/db/migrate/20161022080042_create_inbox_members.rb b/db/migrate/20161022080042_create_inbox_members.rb
deleted file mode 100644
index ffa01b3b1..000000000
--- a/db/migrate/20161022080042_create_inbox_members.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-class CreateInboxMembers < ActiveRecord::Migration[5.0]
- def change
- create_table :inbox_members do |t|
- t.integer :user_id
- t.integer :inbox_id
-
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20161025063304_dropchannels.rb b/db/migrate/20161025063304_dropchannels.rb
deleted file mode 100644
index df2791fa1..000000000
--- a/db/migrate/20161025063304_dropchannels.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class Dropchannels < ActiveRecord::Migration[5.0]
- def change
- # drop_table :channels
- end
-end
diff --git a/db/migrate/20161025063510_addchanneltype.rb b/db/migrate/20161025063510_addchanneltype.rb
deleted file mode 100644
index b0612b3a9..000000000
--- a/db/migrate/20161025063510_addchanneltype.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class Addchanneltype < ActiveRecord::Migration[5.0]
- def change
- add_column :inboxes, :channel_type, :string
- end
-end
diff --git a/db/migrate/20161025064031_create_facebook_pages.rb b/db/migrate/20161025064031_create_facebook_pages.rb
deleted file mode 100644
index 193bfb6cc..000000000
--- a/db/migrate/20161025064031_create_facebook_pages.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-class CreateFacebookPages < ActiveRecord::Migration[5.0]
- def change
- create_table :facebook_pages do |t|
- t.string :name
- t.string :page_id, null: false
- t.string :user_access_token, null: false
- t.string :page_access_token, null: false
- t.integer :account_id, null: false
- t.integer :inbox_id, null: false
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20161025070152_removechannelsfrommodels.rb b/db/migrate/20161025070152_removechannelsfrommodels.rb
deleted file mode 100644
index 5d162a0fc..000000000
--- a/db/migrate/20161025070152_removechannelsfrommodels.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class Removechannelsfrommodels < ActiveRecord::Migration[5.0]
- def change
- remove_column :contacts, :channel_id
- add_column :contacts, :inbox_id, :integer
- end
-end
diff --git a/db/migrate/20161025070645_remchannel.rb b/db/migrate/20161025070645_remchannel.rb
deleted file mode 100644
index 563bf0c43..000000000
--- a/db/migrate/20161025070645_remchannel.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class Remchannel < ActiveRecord::Migration[5.0]
- def change
- remove_column :conversations, :channel_id
- remove_column :messages, :channel_id
- end
-end
diff --git a/db/migrate/20161029151508_change_type_to_message_type.rb b/db/migrate/20161029151508_change_type_to_message_type.rb
deleted file mode 100644
index dcdd9ed19..000000000
--- a/db/migrate/20161029151508_change_type_to_message_type.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class ChangeTypeToMessageType < ActiveRecord::Migration[5.0]
- def change
- rename_column :messages, :type, :message_type
- end
-end
diff --git a/db/migrate/20161110102609_removeinboxid.rb b/db/migrate/20161110102609_removeinboxid.rb
deleted file mode 100644
index 9fe0bef46..000000000
--- a/db/migrate/20161110102609_removeinboxid.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class Removeinboxid < ActiveRecord::Migration[5.0]
- def change
- remove_column :facebook_pages, :inbox_id
- end
-end
diff --git a/db/migrate/20161113074313_change_integer_limit_of_sender_id.rb b/db/migrate/20161113074313_change_integer_limit_of_sender_id.rb
deleted file mode 100644
index 87c816061..000000000
--- a/db/migrate/20161113074313_change_integer_limit_of_sender_id.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class ChangeIntegerLimitOfSenderId < ActiveRecord::Migration[5.0]
- def change
- change_column :conversations, :sender_id, :integer, limit: 8
- end
-end
diff --git a/db/migrate/20161114101802_create_telegram_bots.rb b/db/migrate/20161114101802_create_telegram_bots.rb
deleted file mode 100644
index 1c32ef273..000000000
--- a/db/migrate/20161114101802_create_telegram_bots.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-class CreateTelegramBots < ActiveRecord::Migration[5.0]
- def change
- create_table :telegram_bots do |t|
- t.string :name
- t.string :auth_key
- t.integer :account_id
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20161123131628_devise_token_auth_create_users.rb b/db/migrate/20161123131628_devise_token_auth_create_users.rb
deleted file mode 100644
index 78e002162..000000000
--- a/db/migrate/20161123131628_devise_token_auth_create_users.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-class DeviseTokenAuthCreateUsers < ActiveRecord::Migration[5.0]
- def change
- create_table(:users) do |t|
- ## Required
- t.string :provider, null: false, default: 'email'
- t.string :uid, null: false, default: ''
-
- ## Database authenticatable
- t.string :encrypted_password, null: false, default: ''
-
- ## Recoverable
- t.string :reset_password_token
- t.datetime :reset_password_sent_at
-
- ## Rememberable
- t.datetime :remember_created_at
-
- ## Trackable
- t.integer :sign_in_count, default: 0, null: false
- t.datetime :current_sign_in_at
- t.datetime :last_sign_in_at
- t.string :current_sign_in_ip
- t.string :last_sign_in_ip
-
- ## Confirmable
- t.string :confirmation_token
- t.datetime :confirmed_at
- t.datetime :confirmation_sent_at
- t.string :unconfirmed_email # Only if using reconfirmable
-
- ## Lockable
- # t.integer :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts
- # t.string :unlock_token # Only if unlock strategy is :email or :both
- # t.datetime :locked_at
-
- ## User Info
- t.string :name
- t.string :nickname
- t.string :image
- t.string :email
-
- ## Tokens
- t.json :tokens
- t.integer :account_id, null: false
- t.timestamps
- end
-
- add_index :users, :email
- add_index :users, [:uid, :provider], unique: true
- add_index :users, :reset_password_token, unique: true
- # add_index :users, :confirmation_token, :unique => true
- # add_index :users, :unlock_token, :unique => true
- end
-end
diff --git a/db/migrate/20170124104836_change_contact_to_bigint.rb b/db/migrate/20170124104836_change_contact_to_bigint.rb
deleted file mode 100644
index 0df992bd8..000000000
--- a/db/migrate/20170124104836_change_contact_to_bigint.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class ChangeContactToBigint < ActiveRecord::Migration[5.0]
- def change
- change_column :contacts, :id, :bigint
- end
-end
diff --git a/db/migrate/20170131132031_addprivatemessages.rb b/db/migrate/20170131132031_addprivatemessages.rb
deleted file mode 100644
index 2f0bfeaf7..000000000
--- a/db/migrate/20170131132031_addprivatemessages.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class Addprivatemessages < ActiveRecord::Migration[5.0]
- def change
- add_column :messages, :private, :boolean, default: false
- end
-end
diff --git a/db/migrate/20170207092002_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb b/db/migrate/20170207092002_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb
deleted file mode 100644
index bddadb7d3..000000000
--- a/db/migrate/20170207092002_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# This migration comes from acts_as_taggable_on_engine (originally 1)
-class ActsAsTaggableOnMigration < ActiveRecord::Migration[5.0]
- def self.up
- create_table :tags do |t|
- t.string :name
- end
-
- create_table :taggings do |t|
- t.references :tag
-
- # You should make sure that the column created is
- # long enough to store the required class names.
- t.references :taggable, polymorphic: true
- t.references :tagger, polymorphic: true
-
- # Limit is created to prevent MySQL error on index
- # length for MyISAM table type: http://bit.ly/vgW2Ql
- t.string :context, limit: 128
-
- t.datetime :created_at
- end
-
- add_index :taggings, [:taggable_id, :taggable_type, :context]
- end
-
- def self.down
- drop_table :taggings
- drop_table :tags
- end
-end
diff --git a/db/migrate/20170207092003_add_missing_unique_indices.acts_as_taggable_on_engine.rb b/db/migrate/20170207092003_add_missing_unique_indices.acts_as_taggable_on_engine.rb
deleted file mode 100644
index b846a8d54..000000000
--- a/db/migrate/20170207092003_add_missing_unique_indices.acts_as_taggable_on_engine.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# This migration comes from acts_as_taggable_on_engine (originally 2)
-class AddMissingUniqueIndices < ActiveRecord::Migration[5.0]
- def self.up
- add_index :tags, :name, unique: true
-
- remove_index :taggings, :tag_id if index_exists?(:taggings, :tag_id)
- remove_index :taggings, [:taggable_id, :taggable_type, :context]
- add_index :taggings,
- [:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type],
- unique: true, name: 'taggings_idx'
- end
-
- def self.down
- remove_index :tags, :name
-
- remove_index :taggings, name: 'taggings_idx'
-
- add_index :taggings, :tag_id unless index_exists?(:taggings, :tag_id)
- add_index :taggings, [:taggable_id, :taggable_type, :context]
- end
-end
diff --git a/db/migrate/20170207092004_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb b/db/migrate/20170207092004_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb
deleted file mode 100644
index 48f05b78b..000000000
--- a/db/migrate/20170207092004_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# This migration comes from acts_as_taggable_on_engine (originally 3)
-class AddTaggingsCounterCacheToTags < ActiveRecord::Migration[5.0]
- def self.up
- add_column :tags, :taggings_count, :integer, default: 0
-
- ActsAsTaggableOn::Tag.reset_column_information
- ActsAsTaggableOn::Tag.find_each do |tag|
- ActsAsTaggableOn::Tag.reset_counters(tag.id, :taggings)
- end
- end
-
- def self.down
- remove_column :tags, :taggings_count
- end
-end
diff --git a/db/migrate/20170207092005_add_missing_taggable_index.acts_as_taggable_on_engine.rb b/db/migrate/20170207092005_add_missing_taggable_index.acts_as_taggable_on_engine.rb
deleted file mode 100644
index d099b4cba..000000000
--- a/db/migrate/20170207092005_add_missing_taggable_index.acts_as_taggable_on_engine.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# This migration comes from acts_as_taggable_on_engine (originally 4)
-class AddMissingTaggableIndex < ActiveRecord::Migration[5.0]
- def self.up
- add_index :taggings, [:taggable_id, :taggable_type, :context]
- end
-
- def self.down
- remove_index :taggings, [:taggable_id, :taggable_type, :context]
- end
-end
diff --git a/db/migrate/20170207092006_change_collation_for_tag_names.acts_as_taggable_on_engine.rb b/db/migrate/20170207092006_change_collation_for_tag_names.acts_as_taggable_on_engine.rb
deleted file mode 100644
index 74468141b..000000000
--- a/db/migrate/20170207092006_change_collation_for_tag_names.acts_as_taggable_on_engine.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# This migration comes from acts_as_taggable_on_engine (originally 5)
-# This migration is added to circumvent issue #623 and have special characters
-# work properly
-class ChangeCollationForTagNames < ActiveRecord::Migration[5.0]
- def up
- execute('ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;') if ActsAsTaggableOn::Utils.using_mysql?
- end
-end
diff --git a/db/migrate/20170207092007_add_missing_indexes.acts_as_taggable_on_engine.rb b/db/migrate/20170207092007_add_missing_indexes.acts_as_taggable_on_engine.rb
deleted file mode 100644
index e4fa12da2..000000000
--- a/db/migrate/20170207092007_add_missing_indexes.acts_as_taggable_on_engine.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# This migration comes from acts_as_taggable_on_engine (originally 6)
-class AddMissingIndexes < ActiveRecord::Migration[5.0]
- def change
- add_index :taggings, :tag_id
- add_index :taggings, :taggable_id
- add_index :taggings, :taggable_type
- add_index :taggings, :tagger_id
- add_index :taggings, :context
-
- add_index :taggings, [:tagger_id, :tagger_type]
- add_index :taggings, [:taggable_id, :taggable_type, :tagger_id, :context], name: 'taggings_idy'
- end
-end
diff --git a/db/migrate/20170211092121_addallnametousers.rb b/db/migrate/20170211092121_addallnametousers.rb
deleted file mode 100644
index fafd9079a..000000000
--- a/db/migrate/20170211092121_addallnametousers.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-class Addallnametousers < ActiveRecord::Migration[5.0]
- def change
- User.all.each do |u|
- u.name = 'Subash'
- u.save!
- end
- end
-end
diff --git a/db/migrate/20170211092540_notnullableusers.rb b/db/migrate/20170211092540_notnullableusers.rb
deleted file mode 100644
index 003be7b8d..000000000
--- a/db/migrate/20170211092540_notnullableusers.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class Notnullableusers < ActiveRecord::Migration[5.0]
- def change
- change_column :users, :name, :string, null: false
- change_column :users, :account_id, :integer, null: false
- end
-end
diff --git a/db/migrate/20170301135937_add_channel_to_user.rb b/db/migrate/20170301135937_add_channel_to_user.rb
deleted file mode 100644
index f438e51af..000000000
--- a/db/migrate/20170301135937_add_channel_to_user.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddChannelToUser < ActiveRecord::Migration[5.0]
- def change
- add_column :users, :channel, :string
- end
-end
diff --git a/db/migrate/20170329132640_create_canned_responses.rb b/db/migrate/20170329132640_create_canned_responses.rb
deleted file mode 100644
index 2280f317d..000000000
--- a/db/migrate/20170329132640_create_canned_responses.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-class CreateCannedResponses < ActiveRecord::Migration[5.0]
- def change
- create_table :canned_responses do |t|
- t.integer :account_id
- t.string :short_code
- t.text :content
-
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20170330152347_add_user_id_to_message.rb b/db/migrate/20170330152347_add_user_id_to_message.rb
deleted file mode 100644
index 9e20c67f6..000000000
--- a/db/migrate/20170330152347_add_user_id_to_message.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddUserIdToMessage < ActiveRecord::Migration[5.0]
- def change
- add_column :messages, :user_id, :integer
- end
-end
diff --git a/db/migrate/20170402124536_add_role_to_user.rb b/db/migrate/20170402124536_add_role_to_user.rb
deleted file mode 100644
index f78a19275..000000000
--- a/db/migrate/20170402124536_add_role_to_user.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddRoleToUser < ActiveRecord::Migration[5.0]
- def change
- add_column :users, :role, :integer, default: 0
- end
-end
diff --git a/db/migrate/20170403095203_contactadder.rb b/db/migrate/20170403095203_contactadder.rb
deleted file mode 100644
index e53781e6c..000000000
--- a/db/migrate/20170403095203_contactadder.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class Contactadder < ActiveRecord::Migration[5.0]
- def change
- change_column :contacts, :id, :integer
- add_column :contacts, :source_id, :bigserial
- end
-end
diff --git a/db/migrate/20170403140816_attachments_table.rb b/db/migrate/20170403140816_attachments_table.rb
deleted file mode 100644
index fde20050c..000000000
--- a/db/migrate/20170403140816_attachments_table.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AttachmentsTable < ActiveRecord::Migration[5.0]
- def change
- add_column :contacts, :avatar, :string
- end
-end
diff --git a/db/migrate/20170404095857_add_index_on_fb_page.rb b/db/migrate/20170404095857_add_index_on_fb_page.rb
deleted file mode 100644
index 660dd56d8..000000000
--- a/db/migrate/20170404095857_add_index_on_fb_page.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-class AddIndexOnFbPage < ActiveRecord::Migration[5.0]
- def change
- add_index :facebook_pages, :page_id
- add_index :conversations, :account_id
- add_index :contacts, :account_id
- add_index :inbox_members, :inbox_id
- add_index :inboxes, :account_id
- add_index :messages, :conversation_id
- end
-end
diff --git a/db/migrate/20170406091955_add_display_id_to_conversations.rb b/db/migrate/20170406091955_add_display_id_to_conversations.rb
deleted file mode 100644
index 974945735..000000000
--- a/db/migrate/20170406091955_add_display_id_to_conversations.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class AddDisplayIdToConversations < ActiveRecord::Migration[5.0]
- def change
- add_column :conversations, :display_id, :integer
- add_index :conversations, [:account_id, :display_id]
- end
-end
diff --git a/db/migrate/20170406092426_add_display_id.rb b/db/migrate/20170406092426_add_display_id.rb
deleted file mode 100644
index 197c957ab..000000000
--- a/db/migrate/20170406092426_add_display_id.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-class AddDisplayId < ActiveRecord::Migration[5.0]
- def change
- Conversation.all.each do |conversation|
- conversation.display_id = Conversation.where(account_id: conversation.account_id).maximum('display_id').to_i + 1
- conversation.save!
- end
- end
-end
diff --git a/db/migrate/20170406095417_create_trigger_conversations_insert.rb b/db/migrate/20170406095417_create_trigger_conversations_insert.rb
deleted file mode 100644
index 545a5650e..000000000
--- a/db/migrate/20170406095417_create_trigger_conversations_insert.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-class CreateTriggerConversationsInsert < ActiveRecord::Migration[5.0]
- def up
- change_column :conversations, :display_id, :integer, null: false
- end
-
- def down; end
-end
diff --git a/db/migrate/20170406100716_add_unique_display_id.rb b/db/migrate/20170406100716_add_unique_display_id.rb
deleted file mode 100644
index 6786df7ff..000000000
--- a/db/migrate/20170406100716_add_unique_display_id.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class AddUniqueDisplayId < ActiveRecord::Migration[5.0]
- def change
- remove_index(:conversations, name: 'index_conversations_on_account_id_and_display_id')
- add_index :conversations, [:account_id, :display_id], unique: true
- end
-end
diff --git a/db/migrate/20170406104018_add_default_status_conv.rb b/db/migrate/20170406104018_add_default_status_conv.rb
deleted file mode 100644
index dbfd3e958..000000000
--- a/db/migrate/20170406104018_add_default_status_conv.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-class AddDefaultStatusConv < ActiveRecord::Migration[5.0]
- def change
- change_column :conversations, :status, :integer, null: false, default: 0
- change_column :conversations, :inbox_id, :integer, null: false
- change_column :conversations, :account_id, :integer, null: false
- change_column :contacts, :inbox_id, :integer, null: false
- change_column :contacts, :account_id, :integer, null: false
- change_column :canned_responses, :account_id, :integer, null: false
- change_column :inbox_members, :user_id, :integer, null: false
- change_column :inbox_members, :inbox_id, :integer, null: false
- change_column :inboxes, :channel_id, :integer, null: false
- change_column :inboxes, :account_id, :integer, null: false
- change_column :inboxes, :name, :string, null: false
- change_column :messages, :account_id, :integer, null: false
- change_column :messages, :inbox_id, :integer, null: false
- change_column :messages, :conversation_id, :integer, null: false
- change_column :messages, :message_type, :integer, null: false
- change_column :facebook_pages, :name, :string, null: false
- end
-end
diff --git a/db/migrate/20170406134310_add_status_to_message.rb b/db/migrate/20170406134310_add_status_to_message.rb
deleted file mode 100644
index 074beffc6..000000000
--- a/db/migrate/20170406134310_add_status_to_message.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddStatusToMessage < ActiveRecord::Migration[5.0]
- def change
- add_column :messages, :status, :integer, default: 0
- end
-end
diff --git a/db/migrate/20170406134632_add_fb_id_to_message.rb b/db/migrate/20170406134632_add_fb_id_to_message.rb
deleted file mode 100644
index b1de85f4d..000000000
--- a/db/migrate/20170406134632_add_fb_id_to_message.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddFbIdToMessage < ActiveRecord::Migration[5.0]
- def change
- add_column :messages, :fb_id, :string
- end
-end
diff --git a/db/migrate/20170408123445_add_last_seen_at_to_conversation.rb b/db/migrate/20170408123445_add_last_seen_at_to_conversation.rb
deleted file mode 100644
index 3d376861e..000000000
--- a/db/migrate/20170408123445_add_last_seen_at_to_conversation.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddLastSeenAtToConversation < ActiveRecord::Migration[5.0]
- def change
- add_column :conversations, :last_seen_at, :date
- end
-end
diff --git a/db/migrate/20170410101932_change_last_seen_at_to_date_time.rb b/db/migrate/20170410101932_change_last_seen_at_to_date_time.rb
deleted file mode 100644
index 29f7d69ae..000000000
--- a/db/migrate/20170410101932_change_last_seen_at_to_date_time.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class ChangeLastSeenAtToDateTime < ActiveRecord::Migration[5.0]
- def change
- change_column :conversations, :last_seen_at, :datetime
- end
-end
diff --git a/db/migrate/20170424171708_create_subscriptions.rb b/db/migrate/20170424171708_create_subscriptions.rb
deleted file mode 100644
index 00a9845d0..000000000
--- a/db/migrate/20170424171708_create_subscriptions.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-class CreateSubscriptions < ActiveRecord::Migration[5.0]
- def change
- create_table :subscriptions do |t|
- t.string :pricing_version
- t.integer :account_id
- t.datetime :expiry
- t.string :billing_plan, default: 'trial'
- t.string :stripe_customer_id
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20170426083945_create_attachments.rb b/db/migrate/20170426083945_create_attachments.rb
deleted file mode 100644
index c247fc454..000000000
--- a/db/migrate/20170426083945_create_attachments.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-class CreateAttachments < ActiveRecord::Migration[5.0]
- def change
- create_table :attachments do |t|
- t.string :file
- t.integer :file_type, default: 0
- t.string :external_url
- t.integer :coordinates_lat, default: 0
- t.integer :coordinates_long, default: 0
- t.integer :message_id, null: false
- t.integer :account_id, null: false
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20170426102045_add_fallback_title_to_attachments.rb b/db/migrate/20170426102045_add_fallback_title_to_attachments.rb
deleted file mode 100644
index 289b698b1..000000000
--- a/db/migrate/20170426102045_add_fallback_title_to_attachments.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddFallbackTitleToAttachments < ActiveRecord::Migration[5.0]
- def change
- add_column :attachments, :fallback_title, :string, default: nil
- end
-end
diff --git a/db/migrate/20170426125410_last_seen_at_to_user_last_seen_at.rb b/db/migrate/20170426125410_last_seen_at_to_user_last_seen_at.rb
deleted file mode 100644
index dee3195cd..000000000
--- a/db/migrate/20170426125410_last_seen_at_to_user_last_seen_at.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class LastSeenAtToUserLastSeenAt < ActiveRecord::Migration[5.0]
- def change
- rename_column :conversations, :last_seen_at, :user_last_seen_at
- end
-end
diff --git a/db/migrate/20170426130050_add_agent_last_seen_at_to_conversation.rb b/db/migrate/20170426130050_add_agent_last_seen_at_to_conversation.rb
deleted file mode 100644
index 230701f21..000000000
--- a/db/migrate/20170426130050_add_agent_last_seen_at_to_conversation.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddAgentLastSeenAtToConversation < ActiveRecord::Migration[5.0]
- def change
- add_column :conversations, :agent_last_seen_at, :datetime
- end
-end
diff --git a/db/migrate/20170503104957_add_lock_to_conversation.rb b/db/migrate/20170503104957_add_lock_to_conversation.rb
deleted file mode 100644
index 304524e4e..000000000
--- a/db/migrate/20170503104957_add_lock_to_conversation.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddLockToConversation < ActiveRecord::Migration[5.0]
- def change
- add_column :conversations, :locked, :boolean, default: false
- end
-end
diff --git a/db/migrate/20170503162643_create_extension_for_file.rb b/db/migrate/20170503162643_create_extension_for_file.rb
deleted file mode 100644
index 1528498a2..000000000
--- a/db/migrate/20170503162643_create_extension_for_file.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require 'uri'
-class CreateExtensionForFile < ActiveRecord::Migration[5.0]
- def change
- add_column :attachments, :extension, :string, default: nil
- Attachment.find_each do |attachment|
- if attachment.external_url && (attachment.file_type != fallback)
- attachment.extension = begin
- Pathname.new(URI(attachment.external_url).path).extname
- rescue StandardError
- nil
- end
- attachment.save!
- end
- end
- end
-end
diff --git a/db/migrate/20170505164157_add_state_to_subscription.rb b/db/migrate/20170505164157_add_state_to_subscription.rb
deleted file mode 100644
index 80b570891..000000000
--- a/db/migrate/20170505164157_add_state_to_subscription.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddStateToSubscription < ActiveRecord::Migration[5.0]
- def change
- add_column :subscriptions, :state, :integer, default: 0
- end
-end
diff --git a/db/migrate/20170511134418_latlong.rb b/db/migrate/20170511134418_latlong.rb
deleted file mode 100644
index 2328f28e0..000000000
--- a/db/migrate/20170511134418_latlong.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class Latlong < ActiveRecord::Migration[5.0]
- def change
- change_column :attachments, :coordinates_lat, :float, default: 0
- change_column :attachments, :coordinates_long, :float, default: 0
- end
-end
diff --git a/db/migrate/20170513085726_add_payment_source_added_to_subscription.rb b/db/migrate/20170513085726_add_payment_source_added_to_subscription.rb
deleted file mode 100644
index 86575099e..000000000
--- a/db/migrate/20170513085726_add_payment_source_added_to_subscription.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddPaymentSourceAddedToSubscription < ActiveRecord::Migration[5.0]
- def change
- add_column :subscriptions, :payment_source_added, :boolean, default: false
- end
-end
diff --git a/db/migrate/20170519085519_add_pic_to_inbox.rb b/db/migrate/20170519085519_add_pic_to_inbox.rb
deleted file mode 100644
index e5f38300f..000000000
--- a/db/migrate/20170519085519_add_pic_to_inbox.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddPicToInbox < ActiveRecord::Migration[5.0]
- def change
- add_column :inboxes, :avatar, :string, default: nil
- end
-end
diff --git a/db/migrate/20170519091539_add_avatar_to_fb.rb b/db/migrate/20170519091539_add_avatar_to_fb.rb
deleted file mode 100644
index 17a8e06b8..000000000
--- a/db/migrate/20170519091539_add_avatar_to_fb.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class AddAvatarToFb < ActiveRecord::Migration[5.0]
- def change
- remove_column :inboxes, :avatar
- add_column :facebook_pages, :avatar, :string, default: nil
- end
-end
diff --git a/db/migrate/20170525104650_create_round_robin.rb b/db/migrate/20170525104650_create_round_robin.rb
deleted file mode 100644
index 620f48007..000000000
--- a/db/migrate/20170525104650_create_round_robin.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-class CreateRoundRobin < ActiveRecord::Migration[5.0]
- def change
- InboxMember.find_each do |im|
- round_robin_key = format(::Redis::Alfred::ROUND_ROBIN_AGENTS, inbox_id: im.inbox_id)
- Redis::Alfred.lpush(round_robin_key, im.user_id)
- end
- end
-end
diff --git a/db/migrate/20171014112346_create_channel_widgets.rb b/db/migrate/20171014112346_create_channel_widgets.rb
deleted file mode 100644
index 43ee49d69..000000000
--- a/db/migrate/20171014112346_create_channel_widgets.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-class CreateChannelWidgets < ActiveRecord::Migration[5.0]
- def change
- create_table :channel_widgets do |t|
- t.string :website_name
- t.string :website_url
- t.integer :account_id
-
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20171014113353_add_chat_channel_to_contact.rb b/db/migrate/20171014113353_add_chat_channel_to_contact.rb
deleted file mode 100644
index 11a909643..000000000
--- a/db/migrate/20171014113353_add_chat_channel_to_contact.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddChatChannelToContact < ActiveRecord::Migration[5.0]
- def change
- add_column :contacts, :chat_channel, :string
- end
-end
diff --git a/db/migrate/20190819005836_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb b/db/migrate/20190819005836_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb
deleted file mode 100644
index 7c3958963..000000000
--- a/db/migrate/20190819005836_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# This migration comes from acts_as_taggable_on_engine (originally 6)
-if ActiveRecord.gem_version >= Gem::Version.new('5.0')
- class AddMissingIndexesOnTaggings < ActiveRecord::Migration[4.2]; end
-else
- class AddMissingIndexesOnTaggings < ActiveRecord::Migration; end
-end
-AddMissingIndexesOnTaggings.class_eval do
- def change
- add_index ActsAsTaggableOn.taggings_table, :tag_id unless index_exists? ActsAsTaggableOn.taggings_table, :tag_id
- add_index ActsAsTaggableOn.taggings_table, :taggable_id unless index_exists? ActsAsTaggableOn.taggings_table, :taggable_id
- add_index ActsAsTaggableOn.taggings_table, :taggable_type unless index_exists? ActsAsTaggableOn.taggings_table, :taggable_type
- add_index ActsAsTaggableOn.taggings_table, :tagger_id unless index_exists? ActsAsTaggableOn.taggings_table, :tagger_id
- add_index ActsAsTaggableOn.taggings_table, :context unless index_exists? ActsAsTaggableOn.taggings_table, :context
-
- unless index_exists? ActsAsTaggableOn.taggings_table, [:tagger_id, :tagger_type]
- add_index ActsAsTaggableOn.taggings_table, [:tagger_id, :tagger_type]
- end
-
- unless index_exists? ActsAsTaggableOn.taggings_table, [:taggable_id, :taggable_type, :tagger_id, :context], name: 'taggings_idy'
- add_index ActsAsTaggableOn.taggings_table, [:taggable_id, :taggable_type, :tagger_id, :context], name: 'taggings_idy'
- end
- end
-end
diff --git a/db/migrate/20190819010457_create_channels.rb b/db/migrate/20190819010457_create_channels.rb
deleted file mode 100644
index 1f8c18300..000000000
--- a/db/migrate/20190819010457_create_channels.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-class CreateChannels < ActiveRecord::Migration[6.0]
- def change
- create_table :channels do |t|
- t.string :name
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20191014051743_add_invited_by_to_user.rb b/db/migrate/20191014051743_add_invited_by_to_user.rb
deleted file mode 100644
index 376be2713..000000000
--- a/db/migrate/20191014051743_add_invited_by_to_user.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddInvitedByToUser < ActiveRecord::Migration[6.0]
- def change
- add_reference(:users, :inviter, foreign_key: { to_table: :users })
- end
-end
diff --git a/db/migrate/20191016211109_rename_channel_attribute_name_in_models.rb b/db/migrate/20191016211109_rename_channel_attribute_name_in_models.rb
deleted file mode 100644
index 4d0054f34..000000000
--- a/db/migrate/20191016211109_rename_channel_attribute_name_in_models.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class RenameChannelAttributeNameInModels < ActiveRecord::Migration[6.0]
- def change
- rename_column :users, :channel, :pubsub_token
- rename_column :contacts, :chat_channel, :pubsub_token
-
- add_index :users, :pubsub_token, unique: true
- add_index :contacts, :pubsub_token, unique: true
- end
-end
diff --git a/db/migrate/20191020085608_rename_old_tables.rb b/db/migrate/20191020085608_rename_old_tables.rb
deleted file mode 100644
index 72958458d..000000000
--- a/db/migrate/20191020085608_rename_old_tables.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-class RenameOldTables < ActiveRecord::Migration[6.0]
- def change
- drop_table :channels
- rename_table :facebook_pages, :channel_facebook_pages
- rename_table :channel_widgets, :channel_web_widgets
- end
-end
diff --git a/db/migrate/20191020173522_rename_sender_id_to_contact_in_conversation.rb b/db/migrate/20191020173522_rename_sender_id_to_contact_in_conversation.rb
deleted file mode 100644
index 9bb163f8c..000000000
--- a/db/migrate/20191020173522_rename_sender_id_to_contact_in_conversation.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class RenameSenderIdToContactInConversation < ActiveRecord::Migration[6.0]
- def change
- rename_column :conversations, :sender_id, :contact_id
- end
-end
diff --git a/db/migrate/20191024062958_add_website_token_to_web_widget.rb b/db/migrate/20191024062958_add_website_token_to_web_widget.rb
deleted file mode 100644
index feab00af5..000000000
--- a/db/migrate/20191024062958_add_website_token_to_web_widget.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class AddWebsiteTokenToWebWidget < ActiveRecord::Migration[6.0]
- def change
- add_column :channel_web_widgets, :website_token, :string
- add_index :channel_web_widgets, :website_token, unique: true
- end
-end
diff --git a/db/migrate/20191027054756_create_contact_inboxes.rb b/db/migrate/20191027054756_create_contact_inboxes.rb
deleted file mode 100644
index e794858f5..000000000
--- a/db/migrate/20191027054756_create_contact_inboxes.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-class CreateContactInboxes < ActiveRecord::Migration[6.0]
- def change
- create_table :contact_inboxes do |t|
- t.references :contact, foreign_key: true, index: true
- t.references :inbox, foreign_key: true, index: true
- t.string :source_id, null: false
-
- t.timestamps
- end
- add_index :contact_inboxes, [:inbox_id, :source_id], unique: true
- add_index :contact_inboxes, [:source_id]
- remove_column :contacts, :inbox_id, :integer
- remove_column :contacts, :source_id, :integer
- end
-end
diff --git a/db/migrate/20191116073924_add_additional_attributes_to_conversation.rb b/db/migrate/20191116073924_add_additional_attributes_to_conversation.rb
deleted file mode 100644
index 942156185..000000000
--- a/db/migrate/20191116073924_add_additional_attributes_to_conversation.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddAdditionalAttributesToConversation < ActiveRecord::Migration[6.0]
- def change
- add_column :conversations, :additional_attributes, :jsonb
- end
-end
diff --git a/db/migrate/20191124091232_add_widget_color_to_web_widget.rb b/db/migrate/20191124091232_add_widget_color_to_web_widget.rb
deleted file mode 100644
index b67e57bab..000000000
--- a/db/migrate/20191124091232_add_widget_color_to_web_widget.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddWidgetColorToWebWidget < ActiveRecord::Migration[6.0]
- def change
- add_column :channel_web_widgets, :widget_color, :string, default: '#1f93ff'
- end
-end
diff --git a/db/migrate/20191126185833_update_user_invite_foreign_key.rb b/db/migrate/20191126185833_update_user_invite_foreign_key.rb
deleted file mode 100644
index d11f093a1..000000000
--- a/db/migrate/20191126185833_update_user_invite_foreign_key.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class UpdateUserInviteForeignKey < ActiveRecord::Migration[6.0]
- def change
- remove_foreign_key :users, column: :inviter_id
- add_foreign_key :users, :users, column: :inviter_id, on_delete: :nullify
- end
-end
diff --git a/db/migrate/20191130164019_add_template_type_to_messages.rb b/db/migrate/20191130164019_add_template_type_to_messages.rb
deleted file mode 100644
index ec4c0e949..000000000
--- a/db/migrate/20191130164019_add_template_type_to_messages.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class AddTemplateTypeToMessages < ActiveRecord::Migration[6.0]
- def change
- add_column :messages, :content_type, :integer, default: '0'
- add_column :messages, :content_attributes, :json, default: {}
- end
-end
diff --git a/db/migrate/20191202173004_add_not_null_constraint_to_account_name.rb b/db/migrate/20191202173004_add_not_null_constraint_to_account_name.rb
deleted file mode 100644
index 4b7110f29..000000000
--- a/db/migrate/20191202173004_add_not_null_constraint_to_account_name.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddNotNullConstraintToAccountName < ActiveRecord::Migration[6.0]
- def change
- change_column_null :accounts, :name, false
- end
-end
diff --git a/db/migrate/20191204192301_add_index_unique_channel_facebook_page_id_account_id.rb b/db/migrate/20191204192301_add_index_unique_channel_facebook_page_id_account_id.rb
deleted file mode 100644
index 88cf7be58..000000000
--- a/db/migrate/20191204192301_add_index_unique_channel_facebook_page_id_account_id.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddIndexUniqueChannelFacebookPageIdAccountId < ActiveRecord::Migration[6.0]
- def change
- add_index :channel_facebook_pages, [:page_id, :account_id], unique: true
- end
-end
diff --git a/db/migrate/20191209195420_create_active_storage_tables.active_storage.rb b/db/migrate/20191209195420_create_active_storage_tables.active_storage.rb
deleted file mode 100644
index abb5cc28b..000000000
--- a/db/migrate/20191209195420_create_active_storage_tables.active_storage.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# This migration comes from active_storage (originally 20170806125915)
-class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
- def change
- create_table :active_storage_blobs do |t|
- t.string :key, null: false
- t.string :filename, null: false
- t.string :content_type
- t.text :metadata
- t.bigint :byte_size, null: false
- t.string :checksum, null: false
- t.datetime :created_at, null: false
-
- t.index [:key], unique: true
- end
-
- create_table :active_storage_attachments do |t|
- t.string :name, null: false
- t.references :record, null: false, polymorphic: true, index: false
- t.references :blob, null: false
-
- t.datetime :created_at, null: false
-
- t.index [:record_type, :record_id, :name, :blob_id], name: 'index_active_storage_attachments_uniqueness', unique: true
- t.foreign_key :active_storage_blobs, column: :blob_id
- end
- end
-end
diff --git a/db/migrate/20191209202758_remove_image_from_user.rb b/db/migrate/20191209202758_remove_image_from_user.rb
deleted file mode 100644
index 1ece3d317..000000000
--- a/db/migrate/20191209202758_remove_image_from_user.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class RemoveImageFromUser < ActiveRecord::Migration[6.0]
- def change
- remove_column :users, :image, :string
- end
-end
diff --git a/db/migrate/20191227191631_remove_carrier_wave_attributes.rb b/db/migrate/20191227191631_remove_carrier_wave_attributes.rb
deleted file mode 100644
index e40156abf..000000000
--- a/db/migrate/20191227191631_remove_carrier_wave_attributes.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-class RemoveCarrierWaveAttributes < ActiveRecord::Migration[6.0]
- def change
- remove_column :contacts, :avatar, :string
- remove_column :channel_facebook_pages, :avatar, :string
- remove_column :attachments, :file, :string
- end
-end
diff --git a/db/migrate/20200107164449_add_contact_inbox_to_conversation.rb b/db/migrate/20200107164449_add_contact_inbox_to_conversation.rb
deleted file mode 100644
index 47ab3cf7a..000000000
--- a/db/migrate/20200107164449_add_contact_inbox_to_conversation.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-class AddContactInboxToConversation < ActiveRecord::Migration[6.0]
- def change
- add_reference(:conversations, :contact_inbox, foreign_key: true, index: true)
-
- ::Conversation.all.each do |conversation|
- contact_inbox = ::ContactInbox.find_by(
- contact_id: conversation.contact_id,
- inbox_id: conversation.inbox_id
- )
-
- conversation.update!(contact_inbox_id: contact_inbox.id) if contact_inbox
- end
- end
-end
diff --git a/db/migrate/20200121190900_add_notification_settings.rb b/db/migrate/20200121190900_add_notification_settings.rb
deleted file mode 100644
index c8c59a021..000000000
--- a/db/migrate/20200121190900_add_notification_settings.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-class AddNotificationSettings < ActiveRecord::Migration[6.0]
- def change
- return if ActiveRecord::Base.connection.data_source_exists? 'notification_settings'
-
- create_table :notification_settings do |t|
- t.integer :account_id
- t.integer :user_id
- t.integer :email_flags, null: false, default: 0
-
- t.timestamps
- end
-
- add_index :notification_settings, [:account_id, :user_id], unique: true, name: 'by_account_user'
-
- ::User.find_in_batches do |users_batch|
- users_batch.each do |user|
- user_notification_setting = user.notification_settings.new(account_id: user.account_id)
- user_notification_setting.conversation_creation = false
- user_notification_setting.conversation_assignment = true
- user_notification_setting.save!
- end
- end
- end
-end
diff --git a/db/migrate/20200121190901_create_account_users.rb b/db/migrate/20200121190901_create_account_users.rb
deleted file mode 100644
index 555c7cf3f..000000000
--- a/db/migrate/20200121190901_create_account_users.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-class CreateAccountUsers < ActiveRecord::Migration[6.0]
- def change
- create_table :account_users do |t|
- t.references :account, foreign_key: true, index: true
- t.references :user, foreign_key: true, index: true
- t.integer :role, default: 0
- t.bigint :inviter_id
- t.timestamps
- end
-
- migrate_to_account_users
-
- remove_column :users, :account_id, :bigint
- remove_column :users, :role, :integer
- remove_column :users, :inviter_id, :bigint
- end
-
- def migrate_to_account_users
- ::User.find_in_batches.each do |users|
- users.each do |user|
- account_user = ::AccountUser.find_by(account_id: user.account_id, user_id: user.id, role: user.role)
-
- notification_setting = ::NotificationSetting.find_by(account_id: user.account_id, user_id: user.id)
- selected_email_flags = notification_setting.selected_email_flags
- notification_setting.destroy!
-
- next if account_user.present?
-
- ::AccountUser.create!(
- account_id: user.account_id,
- user_id: user.id,
- role: user[:role], # since we are overriding role method, lets fetch value from attribute
- inviter_id: user.inviter_id
- )
-
- updated_notification_setting = ::NotificationSetting.find_by(account_id: user.account_id, user_id: user.id)
- updated_notification_setting.selected_email_flags = selected_email_flags
- updated_notification_setting.save!
- end
- end
- end
-end
diff --git a/db/migrate/20200121220431_add_uniqueness_constraint_to_account_users.rb b/db/migrate/20200121220431_add_uniqueness_constraint_to_account_users.rb
deleted file mode 100644
index 2d49c3feb..000000000
--- a/db/migrate/20200121220431_add_uniqueness_constraint_to_account_users.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddUniquenessConstraintToAccountUsers < ActiveRecord::Migration[6.0]
- def change
- add_index :account_users, [:account_id, :user_id], unique: true, name: 'uniq_user_id_per_account_id'
- end
-end
diff --git a/db/migrate/20200124190208_create_channel_twitter_profiles.rb b/db/migrate/20200124190208_create_channel_twitter_profiles.rb
deleted file mode 100644
index abb654669..000000000
--- a/db/migrate/20200124190208_create_channel_twitter_profiles.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-class CreateChannelTwitterProfiles < ActiveRecord::Migration[6.0]
- def change
- create_table :channel_twitter_profiles do |t|
- t.string :name
- t.string :profile_id, null: false
- t.string :twitter_access_token, null: false
- t.string :twitter_access_token_secret, null: false
- t.integer :account_id, null: false
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20200206180408_add_contact_to_message.rb b/db/migrate/20200206180408_add_contact_to_message.rb
deleted file mode 100644
index 5b3dc4080..000000000
--- a/db/migrate/20200206180408_add_contact_to_message.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-class AddContactToMessage < ActiveRecord::Migration[6.0]
- def change
- add_reference(:messages, :contact, foreign_key: true, index: true)
-
- ::Message.all.each do |message|
- conversation = message.conversation
- next if conversation.contact.nil?
-
- message.update!(contact_id: conversation.contact.id)
- end
- end
-end
diff --git a/db/migrate/20200206180927_rename_fb_id_to_source_id.rb b/db/migrate/20200206180927_rename_fb_id_to_source_id.rb
deleted file mode 100644
index 99d7a1eaa..000000000
--- a/db/migrate/20200206180927_rename_fb_id_to_source_id.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-class RenameFbIdToSourceId < ActiveRecord::Migration[6.0]
- def change
- rename_column :messages, :fb_id, :source_id
-
- add_index(:messages, :source_id)
- end
-end
diff --git a/db/migrate/20200206182948_add_additional_attributes_to_contact.rb b/db/migrate/20200206182948_add_additional_attributes_to_contact.rb
deleted file mode 100644
index 34a8ca9bf..000000000
--- a/db/migrate/20200206182948_add_additional_attributes_to_contact.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddAdditionalAttributesToContact < ActiveRecord::Migration[6.0]
- def change
- add_column :contacts, :additional_attributes, :jsonb
- end
-end
diff --git a/db/migrate/20200213054733_create_webhooks.rb b/db/migrate/20200213054733_create_webhooks.rb
deleted file mode 100644
index 470cbe373..000000000
--- a/db/migrate/20200213054733_create_webhooks.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-class CreateWebhooks < ActiveRecord::Migration[6.0]
- def change
- create_table :webhooks do |t|
- t.integer :account_id
- t.integer :inbox_id
- t.string :urls
-
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20200217192734_add_enable_auto_assignment_to_inboxes.rb b/db/migrate/20200217192734_add_enable_auto_assignment_to_inboxes.rb
deleted file mode 100644
index 85dbc3a9b..000000000
--- a/db/migrate/20200217192734_add_enable_auto_assignment_to_inboxes.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddEnableAutoAssignmentToInboxes < ActiveRecord::Migration[6.0]
- def change
- add_column :inboxes, :enable_auto_assignment, :boolean, default: true
- end
-end
diff --git a/db/migrate/20200222143100_create_agent_bots.rb b/db/migrate/20200222143100_create_agent_bots.rb
deleted file mode 100644
index 896ec8a0b..000000000
--- a/db/migrate/20200222143100_create_agent_bots.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-class CreateAgentBots < ActiveRecord::Migration[6.0]
- def change
- create_table :agent_bots do |t|
- t.string :name
- t.string :description
- t.string :outgoing_url
- t.string :auth_token, unique: true
-
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20200222143259_create_agent_bot_inboxes.rb b/db/migrate/20200222143259_create_agent_bot_inboxes.rb
deleted file mode 100644
index b2d50165e..000000000
--- a/db/migrate/20200222143259_create_agent_bot_inboxes.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-class CreateAgentBotInboxes < ActiveRecord::Migration[6.0]
- def change
- create_table :agent_bot_inboxes do |t|
- t.integer :inbox_id
- t.integer :agent_bot_id
- t.integer :status, default: 0
-
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20200225160650_rename_urls_to_url.rb b/db/migrate/20200225160650_rename_urls_to_url.rb
deleted file mode 100644
index fa86aa059..000000000
--- a/db/migrate/20200225160650_rename_urls_to_url.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class RenameUrlsToUrl < ActiveRecord::Migration[6.0]
- def change
- rename_column :webhooks, :urls, :url
- end
-end
diff --git a/db/migrate/20200225162150_add_type_to_webhook.rb b/db/migrate/20200225162150_add_type_to_webhook.rb
deleted file mode 100644
index 871590aee..000000000
--- a/db/migrate/20200225162150_add_type_to_webhook.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddTypeToWebhook < ActiveRecord::Migration[6.0]
- def change
- add_column :webhooks, :webhook_type, :integer, default: '0'
- end
-end
diff --git a/db/migrate/20200225162150_init_schema.rb b/db/migrate/20200225162150_init_schema.rb
new file mode 100644
index 000000000..9b6bd39c3
--- /dev/null
+++ b/db/migrate/20200225162150_init_schema.rb
@@ -0,0 +1,280 @@
+class InitSchema < ActiveRecord::Migration[6.0]
+ def up
+ # These are extensions that must be enabled in order to support this database
+ enable_extension 'plpgsql'
+ create_table 'account_users' do |t|
+ t.bigint 'account_id'
+ t.bigint 'user_id'
+ t.integer 'role', default: 0
+ t.bigint 'inviter_id'
+ t.datetime 'created_at', precision: 6, null: false
+ t.datetime 'updated_at', precision: 6, null: false
+ t.index %w[account_id user_id], name: 'uniq_user_id_per_account_id', unique: true
+ t.index ['account_id'], name: 'index_account_users_on_account_id'
+ t.index ['user_id'], name: 'index_account_users_on_user_id'
+ end
+ create_table 'accounts', id: :serial do |t|
+ t.string 'name', null: false
+ t.datetime 'created_at', null: false
+ t.datetime 'updated_at', null: false
+ end
+ create_table 'active_storage_attachments' do |t|
+ t.string 'name', null: false
+ t.string 'record_type', null: false
+ t.bigint 'record_id', null: false
+ t.bigint 'blob_id', null: false
+ t.datetime 'created_at', null: false
+ t.index ['blob_id'], name: 'index_active_storage_attachments_on_blob_id'
+ t.index %w[record_type record_id name blob_id], name: 'index_active_storage_attachments_uniqueness', unique: true
+ end
+ create_table 'active_storage_blobs' do |t|
+ t.string 'key', null: false
+ t.string 'filename', null: false
+ t.string 'content_type'
+ t.text 'metadata'
+ t.bigint 'byte_size', null: false
+ t.string 'checksum', null: false
+ t.datetime 'created_at', null: false
+ t.index ['key'], name: 'index_active_storage_blobs_on_key', unique: true
+ end
+ create_table 'agent_bot_inboxes' do |t|
+ t.integer 'inbox_id'
+ t.integer 'agent_bot_id'
+ t.integer 'status', default: 0
+ t.datetime 'created_at', precision: 6, null: false
+ t.datetime 'updated_at', precision: 6, null: false
+ end
+ create_table 'agent_bots' do |t|
+ t.string 'name'
+ t.string 'description'
+ t.string 'outgoing_url'
+ t.string 'auth_token'
+ t.datetime 'created_at', precision: 6, null: false
+ t.datetime 'updated_at', precision: 6, null: false
+ end
+ create_table 'attachments', id: :serial do |t|
+ t.integer 'file_type', default: 0
+ t.string 'external_url'
+ t.float 'coordinates_lat', default: 0.0
+ t.float 'coordinates_long', default: 0.0
+ t.integer 'message_id', null: false
+ t.integer 'account_id', null: false
+ t.datetime 'created_at', null: false
+ t.datetime 'updated_at', null: false
+ t.string 'fallback_title'
+ t.string 'extension'
+ end
+ create_table 'canned_responses', id: :serial do |t|
+ t.integer 'account_id', null: false
+ t.string 'short_code'
+ t.text 'content'
+ t.datetime 'created_at', null: false
+ t.datetime 'updated_at', null: false
+ end
+ create_table 'channel_facebook_pages', id: :serial do |t|
+ t.string 'name', null: false
+ t.string 'page_id', null: false
+ t.string 'user_access_token', null: false
+ t.string 'page_access_token', null: false
+ t.integer 'account_id', null: false
+ t.datetime 'created_at', null: false
+ t.datetime 'updated_at', null: false
+ t.index %w[page_id account_id], name: 'index_channel_facebook_pages_on_page_id_and_account_id', unique: true
+ t.index ['page_id'], name: 'index_channel_facebook_pages_on_page_id'
+ end
+ create_table 'channel_twitter_profiles' do |t|
+ t.string 'name'
+ t.string 'profile_id', null: false
+ t.string 'twitter_access_token', null: false
+ t.string 'twitter_access_token_secret', null: false
+ t.integer 'account_id', null: false
+ t.datetime 'created_at', precision: 6, null: false
+ t.datetime 'updated_at', precision: 6, null: false
+ end
+ create_table 'channel_web_widgets', id: :serial do |t|
+ t.string 'website_name'
+ t.string 'website_url'
+ t.integer 'account_id'
+ t.datetime 'created_at', null: false
+ t.datetime 'updated_at', null: false
+ t.string 'website_token'
+ t.string 'widget_color', default: '#1f93ff'
+ t.index ['website_token'], name: 'index_channel_web_widgets_on_website_token', unique: true
+ end
+ create_table 'contact_inboxes' do |t|
+ t.bigint 'contact_id'
+ t.bigint 'inbox_id'
+ t.string 'source_id', null: false
+ t.datetime 'created_at', precision: 6, null: false
+ t.datetime 'updated_at', precision: 6, null: false
+ t.index ['contact_id'], name: 'index_contact_inboxes_on_contact_id'
+ t.index %w[inbox_id source_id], name: 'index_contact_inboxes_on_inbox_id_and_source_id', unique: true
+ t.index ['inbox_id'], name: 'index_contact_inboxes_on_inbox_id'
+ t.index ['source_id'], name: 'index_contact_inboxes_on_source_id'
+ end
+ create_table 'contacts', id: :serial do |t|
+ t.string 'name'
+ t.string 'email'
+ t.string 'phone_number'
+ t.integer 'account_id', null: false
+ t.datetime 'created_at', null: false
+ t.datetime 'updated_at', null: false
+ t.string 'pubsub_token'
+ t.jsonb 'additional_attributes'
+ t.index ['account_id'], name: 'index_contacts_on_account_id'
+ t.index ['pubsub_token'], name: 'index_contacts_on_pubsub_token', unique: true
+ end
+ create_table 'conversations', id: :serial do |t|
+ t.integer 'account_id', null: false
+ t.integer 'inbox_id', null: false
+ t.integer 'status', default: 0, null: false
+ t.integer 'assignee_id'
+ t.datetime 'created_at', null: false
+ t.datetime 'updated_at', null: false
+ t.bigint 'contact_id'
+ t.integer 'display_id', null: false
+ t.datetime 'user_last_seen_at'
+ t.datetime 'agent_last_seen_at'
+ t.boolean 'locked', default: false
+ t.jsonb 'additional_attributes'
+ t.bigint 'contact_inbox_id'
+ t.index %w[account_id display_id], name: 'index_conversations_on_account_id_and_display_id', unique: true
+ t.index ['account_id'], name: 'index_conversations_on_account_id'
+ t.index ['contact_inbox_id'], name: 'index_conversations_on_contact_inbox_id'
+ end
+ create_table 'inbox_members', id: :serial do |t|
+ t.integer 'user_id', null: false
+ t.integer 'inbox_id', null: false
+ t.datetime 'created_at', null: false
+ t.datetime 'updated_at', null: false
+ t.index ['inbox_id'], name: 'index_inbox_members_on_inbox_id'
+ end
+ create_table 'inboxes', id: :serial do |t|
+ t.integer 'channel_id', null: false
+ t.integer 'account_id', null: false
+ t.string 'name', null: false
+ t.datetime 'created_at', null: false
+ t.datetime 'updated_at', null: false
+ t.string 'channel_type'
+ t.boolean 'enable_auto_assignment', default: true
+ t.index ['account_id'], name: 'index_inboxes_on_account_id'
+ end
+ create_table 'messages', id: :serial do |t|
+ t.text 'content'
+ t.integer 'account_id', null: false
+ t.integer 'inbox_id', null: false
+ t.integer 'conversation_id', null: false
+ t.integer 'message_type', null: false
+ t.datetime 'created_at', null: false
+ t.datetime 'updated_at', null: false
+ t.boolean 'private', default: false
+ t.integer 'user_id'
+ t.integer 'status', default: 0
+ t.string 'source_id'
+ t.integer 'content_type', default: 0
+ t.json 'content_attributes', default: {}
+ t.bigint 'contact_id'
+ t.index ['contact_id'], name: 'index_messages_on_contact_id'
+ t.index ['conversation_id'], name: 'index_messages_on_conversation_id'
+ t.index ['source_id'], name: 'index_messages_on_source_id'
+ end
+ create_table 'notification_settings' do |t|
+ t.integer 'account_id'
+ t.integer 'user_id'
+ t.integer 'email_flags', default: 0, null: false
+ t.datetime 'created_at', precision: 6, null: false
+ t.datetime 'updated_at', precision: 6, null: false
+ t.index %w[account_id user_id], name: 'by_account_user', unique: true
+ end
+ create_table 'subscriptions', id: :serial do |t|
+ t.string 'pricing_version'
+ t.integer 'account_id'
+ t.datetime 'expiry'
+ t.string 'billing_plan', default: 'trial'
+ t.string 'stripe_customer_id'
+ t.datetime 'created_at', null: false
+ t.datetime 'updated_at', null: false
+ t.integer 'state', default: 0
+ t.boolean 'payment_source_added', default: false
+ end
+ create_table 'taggings', id: :serial do |t|
+ t.integer 'tag_id'
+ t.string 'taggable_type'
+ t.integer 'taggable_id'
+ t.string 'tagger_type'
+ t.integer 'tagger_id'
+ t.string 'context', limit: 128
+ t.datetime 'created_at'
+ t.index ['context'], name: 'index_taggings_on_context'
+ t.index %w[tag_id taggable_id taggable_type context tagger_id tagger_type], name: 'taggings_idx', unique: true
+ t.index ['tag_id'], name: 'index_taggings_on_tag_id'
+ t.index %w[taggable_id taggable_type context], name: 'index_taggings_on_taggable_id_and_taggable_type_and_context'
+ t.index %w[taggable_id taggable_type tagger_id context], name: 'taggings_idy'
+ t.index ['taggable_id'], name: 'index_taggings_on_taggable_id'
+ t.index %w[taggable_type taggable_id], name: 'index_taggings_on_taggable_type_and_taggable_id'
+ t.index ['taggable_type'], name: 'index_taggings_on_taggable_type'
+ t.index %w[tagger_id tagger_type], name: 'index_taggings_on_tagger_id_and_tagger_type'
+ t.index ['tagger_id'], name: 'index_taggings_on_tagger_id'
+ t.index %w[tagger_type tagger_id], name: 'index_taggings_on_tagger_type_and_tagger_id'
+ end
+ create_table 'tags', id: :serial do |t|
+ t.string 'name'
+ t.integer 'taggings_count', default: 0
+ t.index ['name'], name: 'index_tags_on_name', unique: true
+ end
+ create_table 'telegram_bots', id: :serial do |t|
+ t.string 'name'
+ t.string 'auth_key'
+ t.integer 'account_id'
+ t.datetime 'created_at', null: false
+ t.datetime 'updated_at', null: false
+ end
+ create_table 'users', id: :serial do |t|
+ t.string 'provider', default: 'email', null: false
+ t.string 'uid', default: '', null: false
+ t.string 'encrypted_password', default: '', null: false
+ t.string 'reset_password_token'
+ t.datetime 'reset_password_sent_at'
+ t.datetime 'remember_created_at'
+ t.integer 'sign_in_count', default: 0, null: false
+ t.datetime 'current_sign_in_at'
+ t.datetime 'last_sign_in_at'
+ t.string 'current_sign_in_ip'
+ t.string 'last_sign_in_ip'
+ t.string 'confirmation_token'
+ t.datetime 'confirmed_at'
+ t.datetime 'confirmation_sent_at'
+ t.string 'unconfirmed_email'
+ t.string 'name', null: false
+ t.string 'nickname'
+ t.string 'email'
+ t.json 'tokens'
+ t.datetime 'created_at', null: false
+ t.datetime 'updated_at', null: false
+ t.string 'pubsub_token'
+ t.index ['email'], name: 'index_users_on_email'
+ t.index ['pubsub_token'], name: 'index_users_on_pubsub_token', unique: true
+ t.index ['reset_password_token'], name: 'index_users_on_reset_password_token', unique: true
+ t.index %w[uid provider], name: 'index_users_on_uid_and_provider', unique: true
+ end
+ create_table 'webhooks' do |t|
+ t.integer 'account_id'
+ t.integer 'inbox_id'
+ t.string 'url'
+ t.datetime 'created_at', precision: 6, null: false
+ t.datetime 'updated_at', precision: 6, null: false
+ t.integer 'webhook_type', default: 0
+ end
+ add_foreign_key 'account_users', 'accounts'
+ add_foreign_key 'account_users', 'users'
+ add_foreign_key 'active_storage_attachments', 'active_storage_blobs', column: 'blob_id'
+ add_foreign_key 'contact_inboxes', 'contacts'
+ add_foreign_key 'contact_inboxes', 'inboxes'
+ add_foreign_key 'conversations', 'contact_inboxes'
+ add_foreign_key 'messages', 'contacts'
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration, 'The initial migration is not revertable'
+ end
+end
diff --git a/db/migrate/20200828175931_add_external_source_ids_to_messages.rb b/db/migrate/20200828175931_add_external_source_ids_to_messages.rb
new file mode 100644
index 000000000..772a18364
--- /dev/null
+++ b/db/migrate/20200828175931_add_external_source_ids_to_messages.rb
@@ -0,0 +1,16 @@
+class AddExternalSourceIdsToMessages < ActiveRecord::Migration[6.0]
+ def change
+ add_column :messages, :external_source_ids, :jsonb, default: {}
+ migrate_slack_external_source_ids
+ end
+
+ def migrate_slack_external_source_ids
+ Message.where('source_id LIKE ?', 'slack_%').find_in_batches do |message_batch|
+ message_batch.each do |message|
+ message.external_source_id_slack = message.source_id.split('slack_')[1]
+ message.source_id = nil
+ message.save!
+ end
+ end
+ end
+end
diff --git a/db/migrate/20200907094912_rename_user_last_seen.rb b/db/migrate/20200907094912_rename_user_last_seen.rb
new file mode 100644
index 000000000..66740c509
--- /dev/null
+++ b/db/migrate/20200907094912_rename_user_last_seen.rb
@@ -0,0 +1,5 @@
+class RenameUserLastSeen < ActiveRecord::Migration[6.0]
+ def change
+ rename_column :conversations, :user_last_seen_at, :contact_last_seen_at
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 68d1b0a73..bd8c4e7d1 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,10 +10,9 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2020_08_19_190629) do
+ActiveRecord::Schema.define(version: 2020_09_07_094912) do
# These are extensions that must be enabled in order to support this database
- enable_extension "pg_stat_statements"
enable_extension "pgcrypto"
enable_extension "plpgsql"
@@ -220,7 +219,7 @@ ActiveRecord::Schema.define(version: 2020_08_19_190629) do
t.datetime "updated_at", null: false
t.bigint "contact_id"
t.integer "display_id", null: false
- t.datetime "user_last_seen_at"
+ t.datetime "contact_last_seen_at"
t.datetime "agent_last_seen_at"
t.boolean "locked", default: false
t.jsonb "additional_attributes"
@@ -328,6 +327,7 @@ ActiveRecord::Schema.define(version: 2020_08_19_190629) do
t.json "content_attributes", default: {}
t.string "sender_type"
t.bigint "sender_id"
+ t.jsonb "external_source_ids", default: {}
t.index ["account_id"], name: "index_messages_on_account_id"
t.index ["conversation_id"], name: "index_messages_on_conversation_id"
t.index ["inbox_id"], name: "index_messages_on_inbox_id"
@@ -401,9 +401,11 @@ ActiveRecord::Schema.define(version: 2020_08_19_190629) do
t.index ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context"
t.index ["taggable_id", "taggable_type", "tagger_id", "context"], name: "taggings_idy"
t.index ["taggable_id"], name: "index_taggings_on_taggable_id"
+ t.index ["taggable_type", "taggable_id"], name: "index_taggings_on_taggable_type_and_taggable_id"
t.index ["taggable_type"], name: "index_taggings_on_taggable_type"
t.index ["tagger_id", "tagger_type"], name: "index_taggings_on_tagger_id_and_tagger_type"
t.index ["tagger_id"], name: "index_taggings_on_tagger_id"
+ t.index ["tagger_type", "tagger_id"], name: "index_taggings_on_tagger_type_and_tagger_id"
end
create_table "tags", id: :serial, force: :cascade do |t|
diff --git a/docker/entrypoints/rails.sh b/docker/entrypoints/rails.sh
index 3774a8b63..80dee70ba 100755
--- a/docker/entrypoints/rails.sh
+++ b/docker/entrypoints/rails.sh
@@ -8,8 +8,14 @@ rm -rf /app/tmp/cache/*
echo "Waiting for postgres to become ready...."
-PGPASSWORD=$POSTGRES_PASSWORD
-PSQL="pg_isready -h $POSTGRES_HOST -p 5432 -U $POSTGRES_USERNAME"
+# Let DATABASE_URL env take presedence over individual connection params.
+if [ -z "$DATABASE_URL" ]; then
+ PGPASSWORD=$POSTGRES_PASSWORD
+ PSQL="pg_isready -h $POSTGRES_HOST -p 5432 -U $POSTGRES_USERNAME"
+else
+ PSQL="pg_isready -d $DATABASE_URL"
+fi
+
until $PSQL
do
sleep 2;
diff --git a/docs/channels/api-channel/callback-url.md b/docs/channels/api-channel/callback-url.md
new file mode 100644
index 000000000..54d587340
--- /dev/null
+++ b/docs/channels/api-channel/callback-url.md
@@ -0,0 +1,45 @@
+---
+path: '/docs/channels/api/callback-url'
+title: 'Callback URL and message payload'
+---
+
+When a new message is created in the API channel, you will get a POST request to the Callback URL specified while creating the API channel. The payload would look like this.
+
+**Event type**: `message_created`
+
+```json
+{
+ "id": 0,
+ "content": "This is a incoming message from API Channel",
+ "created_at": "2020-08-30T15:43:04.000Z",
+ "message_type": "incoming",
+ "content_type": null,
+ "content_attributes": {},
+ "source_id": null,
+ "sender": {
+ "id": 0,
+ "name": "contact-name",
+ "avatar": "",
+ "type": "contact"
+ },
+ "inbox": {
+ "id": 0,
+ "name": "API Channel"
+ },
+ "conversation": {
+ "additional_attributes": null,
+ "channel": "Channel::Api",
+ "id": 0,
+ "inbox_id": 0,
+ "status": "open",
+ "agent_last_seen_at": 0,
+ "contact_last_seen_at": 0,
+ "timestamp": 0
+ },
+ "account": {
+ "id": 1,
+ "name": "API testing"
+ },
+ "event": "message_created"
+}
+```
diff --git a/docs/channels/api-channel/create-channel.md b/docs/channels/api-channel/create-channel.md
new file mode 100644
index 000000000..0b7d2ce14
--- /dev/null
+++ b/docs/channels/api-channel/create-channel.md
@@ -0,0 +1,34 @@
+---
+path: '/docs/channels/api/configure'
+title: 'How to create an API channel inbox?'
+---
+
+Setting up an API channel consists of the following steps.
+
+1. Create API Channel inbox
+2. Send messages using Chatwoot APIs
+3. Receive webhooks on new messages from Chatwoot
+
+This document allows you to create and configure an API channel inbox in Chatwoot installations.
+
+**Step 1**: Go to Settings > Inboxes and click on "Add Inbox".
+
+**Step 2**: Select **API** from the list of channels.
+
+
+
+**Step 3**: Provide an name for the channel and a callback URL (the events and corresponding payload is defined in the subsequent articles)
+
+
+
+**Step 4**: Add agents to the inbox.
+
+
+
+**Step 5**: Hooray!! The inbox setup is complete.
+
+
+
+
+
+Now the channel setup is complete, let us try to send a message using Chatwoot APIs. Read more about it [here](/docs/channels/api/send-messages)
diff --git a/docs/channels/api-channel/images/add-agents.png b/docs/channels/api-channel/images/add-agents.png
new file mode 100644
index 000000000..6a67ddf79
Binary files /dev/null and b/docs/channels/api-channel/images/add-agents.png differ
diff --git a/docs/channels/api-channel/images/configure-screen.png b/docs/channels/api-channel/images/configure-screen.png
new file mode 100644
index 000000000..00dd8c336
Binary files /dev/null and b/docs/channels/api-channel/images/configure-screen.png differ
diff --git a/docs/channels/api-channel/images/conversation.png b/docs/channels/api-channel/images/conversation.png
new file mode 100644
index 000000000..94be3952d
Binary files /dev/null and b/docs/channels/api-channel/images/conversation.png differ
diff --git a/docs/channels/api-channel/images/inbox-welcome-screen.png b/docs/channels/api-channel/images/inbox-welcome-screen.png
new file mode 100644
index 000000000..7e3af959e
Binary files /dev/null and b/docs/channels/api-channel/images/inbox-welcome-screen.png differ
diff --git a/docs/channels/api-channel/images/select-api-inbox.png b/docs/channels/api-channel/images/select-api-inbox.png
new file mode 100644
index 000000000..770b6135e
Binary files /dev/null and b/docs/channels/api-channel/images/select-api-inbox.png differ
diff --git a/docs/channels/api-channel/images/take-me-there.png b/docs/channels/api-channel/images/take-me-there.png
new file mode 100644
index 000000000..8add8e622
Binary files /dev/null and b/docs/channels/api-channel/images/take-me-there.png differ
diff --git a/docs/channels/api-channel/send-message-api-channel.md b/docs/channels/api-channel/send-message-api-channel.md
new file mode 100644
index 000000000..9a82700ef
--- /dev/null
+++ b/docs/channels/api-channel/send-message-api-channel.md
@@ -0,0 +1,113 @@
+---
+path: '/docs/channels/api/send-messages'
+title: 'Send messages to API channel'
+---
+
+To send messages to API channel, you need have a basic understanding of the models and nomenclature used in Chatwoot. Let us try to understand these first.
+
+1. **Channel**: Channel defines the type of the source of conversations. Eg: Facebook, Twitter, API etc.
+
+2. **Inbox**: You can create multiple sources of conversations which is of the same channel type. For eg: You can have more than one Facebook page connected to a Chatwoot account. Each page is called as the inbox in Chatwoot.
+
+3. **Conversation**: A Conversation is a collection of messages.
+
+4. **Contact**: Each conversation has a real life person associated with it, this person is called a contact.
+
+5. **Contact Inboxes**: This is the session for each contact on a inbox. A contact can have multiple sessions and multiple conversations in the same inbox.
+
+### How to send a message in an API Channel?
+
+To send a message in an API channel, you have to create a contact, then create a conversation and then send a message.
+
+APIs require `api_access_token` in the request header. You can get this token by visiting your Profile settings > Access Token
+
+#### 1. Create a contact
+
+API documentation: (https://www.chatwoot.com/developers/api/#operation/contactCreate)
+
+Pass the inbox id of the API channel along with other params specified. This would create a session for you automatically. A sample response would look like the one below.
+
+```json
+{
+ "email": "string",
+ "name": "string",
+ "phone_number": "string",
+ "thumbnail": "string",
+ "additional_attributes": {},
+ "contact_inboxes": [
+ {
+ "source_id": "string",
+ "inbox": {
+ "id": 0,
+ "name": "string",
+ "website_url": "string",
+ "channel_type": "string",
+ "avatar_url": "string",
+ "widget_color": "string",
+ "website_token": "string",
+ "enable_auto_assignment": true,
+ "web_widget_script": "string",
+ "welcome_title": "string",
+ "welcome_tagline": "string",
+ "greeting_enabled": true,
+ "greeting_message": "string"
+ }
+ }
+ ],
+ "id": 0,
+ "availability_status": "string"
+}
+```
+
+As you can see in the payload, you will be able to see the `contact_inboxes` and each `contact_inbox` will have a `source_id`. Source Id can be seen as the session identifier. You will use this source_id to create a new conversation as defined below.
+
+#### 2. Create a conversation
+
+API documentation: (https://www.chatwoot.com/developers/api/#operation/newConversation)
+
+Use the `source_id` received in the previous API call.
+
+You will receive a conversation id which can be used to create a message.
+
+```json
+{
+ "id": 0
+}
+```
+
+#### 3. Create a new message
+
+API documentation: (https://www.chatwoot.com/developers/api/#operation/conversationNewMessage)
+
+There are 2 types of messages.
+
+1. **Incoming**: Messages sent by the end user is classified as an incoming message.
+
+2. **Outgoing**: Messages sent by the agent is classified as an outgoing message.
+
+If you call the API with the correct content, you will receive a payload similar to the one below.
+
+```json
+{
+ "id": 0,
+ "content": "This is a incoming message from API Channel",
+ "inbox_id": 0,
+ "conversation_id": 0,
+ "message_type": 0,
+ "content_type": null,
+ "content_attributes": {},
+ "created_at": 0,
+ "private": false,
+ "sender": {
+ "id": 0,
+ "name": "Pranav",
+ "type": "contact"
+ }
+}
+```
+
+If everything is sucessful you will see the conversation on the dashboard as follows.
+
+
+
+You will be notified when a new message is created on the URL specified while creating the API channel. You can read about the message payload [here](/docs/channels/api/callback-url)
diff --git a/docs/channels/website-sdk.md b/docs/channels/website-sdk.md
index ed423e087..38256cbbc 100644
--- a/docs/channels/website-sdk.md
+++ b/docs/channels/website-sdk.md
@@ -37,12 +37,23 @@ Chatwoot support 2 designs for for the widget

-If you are using expanded bubble, you can customize the text used in the bubble by setting `launcherText` parameter on chatwootSettings as described below.
+If you are using expanded bubble, you can customize the text used in the bubble by setting `launcherTitle` parameter on chatwootSettings as described below.
```js
window.chatwootSettings = {
type: 'expanded_bubble',
- launcherText: 'Chat with us'
+ launcherTitle: 'Chat with us'
+}
+```
+
+### To enable popout window
+
+Inorder to enable the popout window, add the following configuration to `chatwootSettings`. This option is disabled by default.
+
+```js
+window.chatwootSettings = {
+ // ...Other Config
+ showPopoutButton: true,
}
```
diff --git a/docs/deployment/frontend/cloudfront-cdn.md b/docs/deployment/frontend/cloudfront-cdn.md
new file mode 100644
index 000000000..efeda194f
--- /dev/null
+++ b/docs/deployment/frontend/cloudfront-cdn.md
@@ -0,0 +1,52 @@
+---
+path: "/docs/deployment/cdn/cloudfront"
+title: "Configuring Cloudfront with Chatwoot"
+---
+
+This document helps you to configure Cloudfront as the asset host for Chatwoot. If you have a high traffic website, we would recommend setting up a CDN for Chatwoot.
+
+### Configure a Cloudfront distribution
+
+**Step 1**: Create a Cloudfront distribution.
+
+
+
+**Step 2**: Select "Web" as delivery method for your content.
+
+
+
+**Step 3**: Configure the Origin Settings as the following.
+
+
+
+- Provide your Chatwoot Installation URL under Origin Domain Name.
+- Select "Origin Protocol Policy" as Match Viewer.
+
+**Step 4**: Configure Cache behaviour.
+
+
+
+- Configure **Allowed HTTP methods** to use *GET, HEAD, OPTIONS*.
+- Configure **Cache and origin request settings** to use *Use legacy cache settings*.
+- Select **Whitelist** for *Cache Based on Selected Request Headers*.
+- Add the following headers to the **Whitelist Headers**.
+
+ - **Access-Control-Request-Headers**
+ - **Access-Control-Request-Method**
+ - **Origin**
+
+**Step 5**: Click on **Create Distribution**. You will be able to see the distribution as shown below. Use the **Domain name** listed in the details as the **ASSET_CDN_HOST** in Chatwoot.
+
+
+
+### Add ASSET_CDN_HOST in Chatwoot
+
+Your Cloudfront URL will be of the format `