mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-31 19:17:48 +00:00 
			
		
		
		
	| @@ -7,7 +7,7 @@ defaults: &defaults | |||||||
|   working_directory: ~/build |   working_directory: ~/build | ||||||
|   docker: |   docker: | ||||||
|     # specify the version you desire here |     # specify the version you desire here | ||||||
|     - image: cimg/ruby:3.1.3-browsers |     - image: cimg/ruby:3.2.2-browsers | ||||||
|  |  | ||||||
|     # Specify service dependencies here if necessary |     # Specify service dependencies here if necessary | ||||||
|     # CircleCI maintains a library of pre-built images |     # CircleCI maintains a library of pre-built images | ||||||
|   | |||||||
| @@ -30,7 +30,7 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ | |||||||
|     npm |     npm | ||||||
|  |  | ||||||
| # Install rbenv and ruby | # Install rbenv and ruby | ||||||
| ARG RUBY_VERSION="3.1.3" | ARG RUBY_VERSION="3.2.2" | ||||||
| RUN git clone https://github.com/rbenv/rbenv.git ~/.rbenv \ | RUN git clone https://github.com/rbenv/rbenv.git ~/.rbenv \ | ||||||
|     &&  echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc \ |     &&  echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc \ | ||||||
|     &&  echo 'eval "$(rbenv init -)"' >> ~/.bashrc |     &&  echo 'eval "$(rbenv init -)"' >> ~/.bashrc | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -67,3 +67,10 @@ test/cypress/videos/* | |||||||
| # yalc for local testing | # yalc for local testing | ||||||
| .yalc | .yalc | ||||||
| yalc.lock | yalc.lock | ||||||
|  |  | ||||||
|  | /public/packs | ||||||
|  | /public/packs-test | ||||||
|  | /node_modules | ||||||
|  | /yarn-error.log | ||||||
|  | yarn-debug.log* | ||||||
|  | .yarn-integrity | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								.rubocop.yml
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								.rubocop.yml
									
									
									
									
									
								
							| @@ -164,6 +164,39 @@ Performance/CollectionLiteralInLoop: | |||||||
|     - 'db/migrate/20210315101919_enable_email_channel.rb' |     - 'db/migrate/20210315101919_enable_email_channel.rb' | ||||||
| RSpec/NamedSubject: | RSpec/NamedSubject: | ||||||
|   Enabled: false |   Enabled: false | ||||||
|  | Style/RedundantConstantBase: | ||||||
|  |   Enabled: false | ||||||
|  | Rails/RootPathnameMethods: | ||||||
|  |   Enabled: false | ||||||
|  | RSpec/Rails/MinitestAssertions: | ||||||
|  |   Enabled: false | ||||||
|  | RSpec/Rails/InferredSpecType: | ||||||
|  |   Enabled: false | ||||||
|  | RSpec/IndexedLet: | ||||||
|  |   Enabled: false | ||||||
|  | RSpec/MatchArray: | ||||||
|  |   Enabled: false | ||||||
|  | Rails/ResponseParsedBody: | ||||||
|  |   Enabled: false | ||||||
|  | RSpec/FactoryBot/ConsistentParenthesesStyle: | ||||||
|  |   Enabled: false | ||||||
|  | Rails/ThreeStateBooleanColumn: | ||||||
|  |   Enabled: false | ||||||
|  | Rails/Pluck: | ||||||
|  |   Enabled: false | ||||||
|  | Rails/TopLevelHashWithIndifferentAccess: | ||||||
|  |   Enabled: false | ||||||
|  | Rails/ActionOrder: | ||||||
|  |   Enabled: false | ||||||
|  | Style/ArrayIntersect: | ||||||
|  |   Enabled: false | ||||||
|  | RSpec/NoExpectationExample: | ||||||
|  |   Enabled: false | ||||||
|  | Style/RedundantReturn: | ||||||
|  |   Enabled: false | ||||||
|  | Rails/I18nLocaleTexts: | ||||||
|  |   Enabled: false | ||||||
|  |  | ||||||
| # we should bring this down | # we should bring this down | ||||||
| RSpec/MultipleMemoizedHelpers: | RSpec/MultipleMemoizedHelpers: | ||||||
|   Max: 14 |   Max: 14 | ||||||
|   | |||||||
| @@ -1 +1 @@ | |||||||
| 3.1.3 | 3.2.2 | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								.slugignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.slugignore
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | /spec | ||||||
							
								
								
									
										46
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								Gemfile
									
									
									
									
									
								
							| @@ -1,10 +1,10 @@ | |||||||
| source 'https://rubygems.org' | source 'https://rubygems.org' | ||||||
|  |  | ||||||
| ruby '3.1.3' | ruby '3.2.2' | ||||||
|  |  | ||||||
| ##-- base gems for rails --## | ##-- base gems for rails --## | ||||||
| gem 'rack-cors', require: 'rack/cors' | gem 'rack-cors', require: 'rack/cors' | ||||||
| gem 'rails', '~> 6.1', '>= 6.1.7.3' | gem 'rails', '~> 7' | ||||||
| # Reduces boot times through caching; required in config/boot.rb | # Reduces boot times through caching; required in config/boot.rb | ||||||
| gem 'bootsnap', require: false | gem 'bootsnap', require: false | ||||||
|  |  | ||||||
| @@ -36,19 +36,19 @@ gem 'json_schemer' | |||||||
| # Rack middleware for blocking & throttling abusive requests | # Rack middleware for blocking & throttling abusive requests | ||||||
| gem 'rack-attack' | gem 'rack-attack' | ||||||
| # a utility tool for streaming, flexible and safe downloading of remote files | # a utility tool for streaming, flexible and safe downloading of remote files | ||||||
| gem 'down', '~> 5.0' | gem 'down' | ||||||
| # authentication type to fetch and send mail over oauth2.0 | # authentication type to fetch and send mail over oauth2.0 | ||||||
| gem 'gmail_xoauth' | gem 'gmail_xoauth' | ||||||
| # Prevent CSV injection | # Prevent CSV injection | ||||||
| gem 'csv-safe' | gem 'csv-safe' | ||||||
| # Support message translation |  | ||||||
| gem 'google-cloud-translate' |  | ||||||
|  |  | ||||||
| ##-- for active storage --## | ##-- for active storage --## | ||||||
| gem 'aws-sdk-s3', require: false | gem 'aws-sdk-s3', require: false | ||||||
| gem 'azure-storage-blob', require: false | # original gem isn't maintained actively | ||||||
|  | # we wanted updated version of faraday which is a dependency for slack-ruby-client | ||||||
|  | gem 'azure-storage-blob', git: 'https://github.com/chatwoot/azure-storage-ruby', branch: 'chatwoot', require: false | ||||||
| gem 'google-cloud-storage', require: false | gem 'google-cloud-storage', require: false | ||||||
| gem 'image_processing', '~> 1.12.2' | gem 'image_processing' | ||||||
|  |  | ||||||
| ##-- gems for database --# | ##-- gems for database --# | ||||||
| gem 'groupdate' | gem 'groupdate' | ||||||
| @@ -62,13 +62,13 @@ gem 'activerecord-import' | |||||||
| gem 'dotenv-rails' | gem 'dotenv-rails' | ||||||
| gem 'foreman' | gem 'foreman' | ||||||
| gem 'puma' | gem 'puma' | ||||||
| gem 'webpacker', '~> 5.4', '>= 5.4.3' | gem 'webpacker' | ||||||
| # metrics on heroku | # metrics on heroku | ||||||
| gem 'barnes' | gem 'barnes' | ||||||
|  |  | ||||||
| ##--- gems for authentication & authorization ---## | ##--- gems for authentication & authorization ---## | ||||||
| gem 'devise' | gem 'devise' | ||||||
| gem 'devise-secure_password', '~> 2.0', git: 'https://github.com/chatwoot/devise-secure_password' | gem 'devise-secure_password', git: 'https://github.com/chatwoot/devise-secure_password', branch: 'chatwoot' | ||||||
| gem 'devise_token_auth' | gem 'devise_token_auth' | ||||||
| # authorization | # authorization | ||||||
| gem 'jwt' | gem 'jwt' | ||||||
| @@ -81,7 +81,6 @@ gem 'administrate' | |||||||
| gem 'wisper', '2.0.0' | gem 'wisper', '2.0.0' | ||||||
|  |  | ||||||
| ##--- gems for channels ---## | ##--- gems for channels ---## | ||||||
| # TODO: bump up gem to 2.0 |  | ||||||
| gem 'facebook-messenger' | gem 'facebook-messenger' | ||||||
| gem 'line-bot-api' | gem 'line-bot-api' | ||||||
| gem 'twilio-ruby', '~> 5.66' | gem 'twilio-ruby', '~> 5.66' | ||||||
| @@ -91,9 +90,14 @@ gem 'twitty', '~> 0.1.5' | |||||||
| # facebook client | # facebook client | ||||||
| gem 'koala' | gem 'koala' | ||||||
| # slack client | # slack client | ||||||
| gem 'slack-ruby-client' | gem 'slack-ruby-client', '~> 2.0.0' | ||||||
| # for dialogflow integrations | # for dialogflow integrations | ||||||
| gem 'google-cloud-dialogflow' | gem 'google-cloud-dialogflow-v2' | ||||||
|  | gem 'grpc' | ||||||
|  | # Translate integrations | ||||||
|  | # 'google-cloud-translate' gem depends on faraday 2.0 version | ||||||
|  | # this dependency breaks the slack-ruby-client gem | ||||||
|  | gem 'google-cloud-translate-v3' | ||||||
|  |  | ||||||
| ##-- apm and error monitoring ---# | ##-- apm and error monitoring ---# | ||||||
| # loaded only when environment variables are set. | # loaded only when environment variables are set. | ||||||
| @@ -108,9 +112,9 @@ gem 'sentry-ruby', require: false | |||||||
| gem 'sentry-sidekiq', require: false | gem 'sentry-sidekiq', require: false | ||||||
|  |  | ||||||
| ##-- background job processing --## | ##-- background job processing --## | ||||||
| gem 'sidekiq', '~> 6.4.2' | gem 'sidekiq' | ||||||
| # We want cron jobs | # We want cron jobs | ||||||
| gem 'sidekiq-cron', '~> 1.6', '>= 1.6.0' | gem 'sidekiq-cron' | ||||||
|  |  | ||||||
| ##-- Push notification service --## | ##-- Push notification service --## | ||||||
| gem 'fcm' | gem 'fcm' | ||||||
| @@ -129,7 +133,10 @@ gem 'procore-sift' | |||||||
|  |  | ||||||
| # parse email | # parse email | ||||||
| gem 'email_reply_trimmer' | gem 'email_reply_trimmer' | ||||||
| gem 'html2text' |  | ||||||
|  | # TODO: we might have to fork this gem since 0.3.1 has hard depency on nokogir 1.10. | ||||||
|  | # and this gem hasn't been updated for a while. | ||||||
|  | gem 'html2text', git: 'https://github.com/chatwoot/html2text_ruby', branch: 'chatwoot' | ||||||
|  |  | ||||||
| # to calculate working hours | # to calculate working hours | ||||||
| gem 'working_hours' | gem 'working_hours' | ||||||
| @@ -144,11 +151,6 @@ gem 'stripe' | |||||||
| ## to populate db with sample data | ## to populate db with sample data | ||||||
| gem 'faker' | gem 'faker' | ||||||
|  |  | ||||||
| # Can remove this in rails 7 |  | ||||||
| gem 'net-imap', require: false |  | ||||||
| gem 'net-pop', require: false |  | ||||||
| gem 'net-smtp', require: false |  | ||||||
|  |  | ||||||
| # Include logrange conditionally in intializer using env variable | # Include logrange conditionally in intializer using env variable | ||||||
| gem 'lograge', '~> 0.12.0', require: false | gem 'lograge', '~> 0.12.0', require: false | ||||||
|  |  | ||||||
| @@ -189,7 +191,7 @@ end | |||||||
|  |  | ||||||
| group :test do | group :test do | ||||||
|   # Cypress in rails. |   # Cypress in rails. | ||||||
|   gem 'cypress-on-rails', '~> 1.13', '>= 1.13.1' |   gem 'cypress-on-rails' | ||||||
|   # fast cleaning of database |   # fast cleaning of database | ||||||
|   gem 'database_cleaner' |   gem 'database_cleaner' | ||||||
|   # mock http calls |   # mock http calls | ||||||
| @@ -211,7 +213,7 @@ group :development, :test do | |||||||
|   gem 'mock_redis' |   gem 'mock_redis' | ||||||
|   gem 'pry-rails' |   gem 'pry-rails' | ||||||
|   gem 'rspec_junit_formatter' |   gem 'rspec_junit_formatter' | ||||||
|   gem 'rspec-rails', '~> 5.0.3' |   gem 'rspec-rails' | ||||||
|   gem 'rubocop', require: false |   gem 'rubocop', require: false | ||||||
|   gem 'rubocop-performance', require: false |   gem 'rubocop-performance', require: false | ||||||
|   gem 'rubocop-rails', require: false |   gem 'rubocop-rails', require: false | ||||||
|   | |||||||
							
								
								
									
										647
									
								
								Gemfile.lock
									
									
									
									
									
								
							
							
						
						
									
										647
									
								
								Gemfile.lock
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -3,7 +3,7 @@ class ApiController < ApplicationController | |||||||
|  |  | ||||||
|   def index |   def index | ||||||
|     render json: { version: Chatwoot.config[:version], |     render json: { version: Chatwoot.config[:version], | ||||||
|                    timestamp: Time.now.utc.to_formatted_s(:db), |                    timestamp: Time.now.utc.to_fs(:db), | ||||||
|                    queue_services: redis_status, |                    queue_services: redis_status, | ||||||
|                    data_services: postgres_status } |                    data_services: postgres_status } | ||||||
|   end |   end | ||||||
|   | |||||||
| @@ -41,7 +41,7 @@ class WidgetsController < ActionController::Base | |||||||
|       source_id: @auth_token_params[:source_id] |       source_id: @auth_token_params[:source_id] | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     @contact = @contact_inbox ? @contact_inbox.contact : nil |     @contact = @contact_inbox&.contact | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   def build_contact |   def build_contact | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| <template> | <template> | ||||||
|   <div v-on-clickaway="onCloseAgentList" class="bulk-action__agents"> |   <div v-on-clickaway="onCloseAgentList" class="bulk-action__agents"> | ||||||
|     <div class="triangle" :style="cssVars"> |     <div class="triangle"> | ||||||
|       <svg height="12" viewBox="0 0 24 12" width="24"> |       <svg height="12" viewBox="0 0 24 12" width="24"> | ||||||
|         <path |         <path | ||||||
|           d="M20 12l-8-8-12 12" |           d="M20 12l-8-8-12 12" | ||||||
| @@ -104,14 +104,13 @@ import { mapGetters } from 'vuex'; | |||||||
| import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue'; | import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue'; | ||||||
| import Spinner from 'shared/components/Spinner'; | import Spinner from 'shared/components/Spinner'; | ||||||
| import { mixin as clickaway } from 'vue-clickaway'; | import { mixin as clickaway } from 'vue-clickaway'; | ||||||
| import bulkActionsMixin from 'dashboard/mixins/bulkActionsMixin.js'; |  | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   components: { |   components: { | ||||||
|     Thumbnail, |     Thumbnail, | ||||||
|     Spinner, |     Spinner, | ||||||
|   }, |   }, | ||||||
|   mixins: [clickaway, bulkActionsMixin], |   mixins: [clickaway], | ||||||
|   props: { |   props: { | ||||||
|     selectedInboxes: { |     selectedInboxes: { | ||||||
|       type: Array, |       type: Array, | ||||||
| @@ -240,7 +239,7 @@ export default { | |||||||
|     display: block; |     display: block; | ||||||
|     z-index: var(--z-index-one); |     z-index: var(--z-index-one); | ||||||
|     position: absolute; |     position: absolute; | ||||||
|     top: calc(var(--space-slab) * -1); |     top: var(--space-minus-slab); | ||||||
|     right: var(--triangle-position); |     right: var(--triangle-position); | ||||||
|     text-align: left; |     text-align: left; | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -58,7 +58,7 @@ | |||||||
|       <transition name="popover-animation"> |       <transition name="popover-animation"> | ||||||
|         <label-actions |         <label-actions | ||||||
|           v-if="showLabelActions" |           v-if="showLabelActions" | ||||||
|           triangle-position="8.5" |           class="label-actions-box" | ||||||
|           @assign="assignLabels" |           @assign="assignLabels" | ||||||
|           @close="showLabelActions = false" |           @close="showLabelActions = false" | ||||||
|         /> |         /> | ||||||
| @@ -66,12 +66,12 @@ | |||||||
|       <transition name="popover-animation"> |       <transition name="popover-animation"> | ||||||
|         <update-actions |         <update-actions | ||||||
|           v-if="showUpdateActions" |           v-if="showUpdateActions" | ||||||
|  |           class="update-actions-box" | ||||||
|           :selected-inboxes="selectedInboxes" |           :selected-inboxes="selectedInboxes" | ||||||
|           :conversation-count="conversations.length" |           :conversation-count="conversations.length" | ||||||
|           :show-resolve="!showResolvedAction" |           :show-resolve="!showResolvedAction" | ||||||
|           :show-reopen="!showOpenAction" |           :show-reopen="!showOpenAction" | ||||||
|           :show-snooze="!showSnoozedAction" |           :show-snooze="!showSnoozedAction" | ||||||
|           triangle-position="5.6" |  | ||||||
|           @update="updateConversations" |           @update="updateConversations" | ||||||
|           @close="showUpdateActions = false" |           @close="showUpdateActions = false" | ||||||
|         /> |         /> | ||||||
| @@ -79,9 +79,9 @@ | |||||||
|       <transition name="popover-animation"> |       <transition name="popover-animation"> | ||||||
|         <agent-selector |         <agent-selector | ||||||
|           v-if="showAgentsList" |           v-if="showAgentsList" | ||||||
|  |           class="agent-actions-box" | ||||||
|           :selected-inboxes="selectedInboxes" |           :selected-inboxes="selectedInboxes" | ||||||
|           :conversation-count="conversations.length" |           :conversation-count="conversations.length" | ||||||
|           triangle-position="2.8" |  | ||||||
|           @select="submit" |           @select="submit" | ||||||
|           @close="showAgentsList = false" |           @close="showAgentsList = false" | ||||||
|         /> |         /> | ||||||
| @@ -89,7 +89,7 @@ | |||||||
|       <transition name="popover-animation"> |       <transition name="popover-animation"> | ||||||
|         <team-actions |         <team-actions | ||||||
|           v-if="showTeamsList" |           v-if="showTeamsList" | ||||||
|           triangle-position="0.2" |           class="team-actions-box" | ||||||
|           @assign-team="assignTeam" |           @assign-team="assignTeam" | ||||||
|           @close="showTeamsList = false" |           @close="showTeamsList = false" | ||||||
|         /> |         /> | ||||||
| @@ -247,4 +247,17 @@ export default { | |||||||
|   opacity: 0; |   opacity: 0; | ||||||
|   transform: scale(0.95); |   transform: scale(0.95); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .label-actions-box { | ||||||
|  |   --triangle-position: 8.5rem; | ||||||
|  | } | ||||||
|  | .update-actions-box { | ||||||
|  |   --triangle-position: 5.6rem; | ||||||
|  | } | ||||||
|  | .agent-actions-box { | ||||||
|  |   --triangle-position: 2.8rem; | ||||||
|  | } | ||||||
|  | .team-actions-box { | ||||||
|  |   --triangle-position: 0.2rem; | ||||||
|  | } | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| <template> | <template> | ||||||
|   <div v-on-clickaway="onClose" class="labels-container"> |   <div v-on-clickaway="onClose" class="labels-container"> | ||||||
|     <div class="triangle" :style="cssVars"> |     <div class="triangle"> | ||||||
|       <svg height="12" viewBox="0 0 24 12" width="24"> |       <svg height="12" viewBox="0 0 24 12" width="24"> | ||||||
|         <path |         <path | ||||||
|           d="M20 12l-8-8-12 12" |           d="M20 12l-8-8-12 12" | ||||||
| @@ -75,10 +75,9 @@ | |||||||
| <script> | <script> | ||||||
| import { mixin as clickaway } from 'vue-clickaway'; | import { mixin as clickaway } from 'vue-clickaway'; | ||||||
| import { mapGetters } from 'vuex'; | import { mapGetters } from 'vuex'; | ||||||
| import bulkActionsMixin from 'dashboard/mixins/bulkActionsMixin.js'; |  | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   mixins: [clickaway, bulkActionsMixin], |   mixins: [clickaway], | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|       query: '', |       query: '', | ||||||
| @@ -207,7 +206,7 @@ export default { | |||||||
|     position: absolute; |     position: absolute; | ||||||
|     right: var(--triangle-position); |     right: var(--triangle-position); | ||||||
|     text-align: left; |     text-align: left; | ||||||
|     top: calc(var(--space-slab) * -1); |     top: var(--space-minus-slab); | ||||||
|     z-index: var(--z-index-one); |     z-index: var(--z-index-one); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| <template> | <template> | ||||||
|   <div v-on-clickaway="onClose" class="bulk-action__teams"> |   <div v-on-clickaway="onClose" class="bulk-action__teams"> | ||||||
|     <div class="triangle" :style="cssVars"> |     <div class="triangle"> | ||||||
|       <svg height="12" viewBox="0 0 24 12" width="24"> |       <svg height="12" viewBox="0 0 24 12" width="24"> | ||||||
|         <path |         <path | ||||||
|           d="M20 12l-8-8-12 12" |           d="M20 12l-8-8-12 12" | ||||||
| @@ -59,9 +59,8 @@ | |||||||
| <script> | <script> | ||||||
| import { mixin as clickaway } from 'vue-clickaway'; | import { mixin as clickaway } from 'vue-clickaway'; | ||||||
| import { mapGetters } from 'vuex'; | import { mapGetters } from 'vuex'; | ||||||
| import bulkActionsMixin from 'dashboard/mixins/bulkActionsMixin.js'; |  | ||||||
| export default { | export default { | ||||||
|   mixins: [clickaway, bulkActionsMixin], |   mixins: [clickaway], | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|       query: '', |       query: '', | ||||||
| @@ -141,7 +140,7 @@ export default { | |||||||
|     display: block; |     display: block; | ||||||
|     z-index: var(--z-index-one); |     z-index: var(--z-index-one); | ||||||
|     position: absolute; |     position: absolute; | ||||||
|     top: calc(var(--space-slab) * -1); |     top: var(--space-minus-slab); | ||||||
|     right: var(--triangle-position); |     right: var(--triangle-position); | ||||||
|     text-align: left; |     text-align: left; | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| <template> | <template> | ||||||
|   <div v-on-clickaway="onClose" class="actions-container"> |   <div v-on-clickaway="onClose" class="actions-container"> | ||||||
|     <div class="triangle" :style="cssVars"> |     <div class="triangle"> | ||||||
|       <svg height="12" viewBox="0 0 24 12" width="24"> |       <svg height="12" viewBox="0 0 24 12" width="24"> | ||||||
|         <path |         <path | ||||||
|           d="M20 12l-8-8-12 12" |           d="M20 12l-8-8-12 12" | ||||||
| @@ -45,14 +45,13 @@ | |||||||
| import { mixin as clickaway } from 'vue-clickaway'; | import { mixin as clickaway } from 'vue-clickaway'; | ||||||
| import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue'; | import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue'; | ||||||
| import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue'; | import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue'; | ||||||
| import bulkActionsMixin from 'dashboard/mixins/bulkActionsMixin.js'; |  | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   components: { |   components: { | ||||||
|     WootDropdownItem, |     WootDropdownItem, | ||||||
|     WootDropdownMenu, |     WootDropdownMenu, | ||||||
|   }, |   }, | ||||||
|   mixins: [clickaway, bulkActionsMixin], |   mixins: [clickaway], | ||||||
|   props: { |   props: { | ||||||
|     selectedInboxes: { |     selectedInboxes: { | ||||||
|       type: Array, |       type: Array, | ||||||
| @@ -156,7 +155,7 @@ export default { | |||||||
|     position: absolute; |     position: absolute; | ||||||
|     right: var(--triangle-position); |     right: var(--triangle-position); | ||||||
|     text-align: left; |     text-align: left; | ||||||
|     top: calc(var(--space-slab) * -1); |     top: var(--space-minus-slab); | ||||||
|     z-index: var(--z-index-one); |     z-index: var(--z-index-one); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ class ApplicationMailbox < ActionMailbox::Base | |||||||
|   # Last part is the regex for the UUID |   # Last part is the regex for the UUID | ||||||
|   # Eg: email should be something like : reply+6bdc3f4d-0bec-4515-a284-5d916fdde489@domain.com |   # Eg: email should be something like : reply+6bdc3f4d-0bec-4515-a284-5d916fdde489@domain.com | ||||||
|   REPLY_EMAIL_UUID_PATTERN = /^reply\+([0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12})$/i |   REPLY_EMAIL_UUID_PATTERN = /^reply\+([0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12})$/i | ||||||
|   CONVERSATION_MESSAGE_ID_PATTERN = %r{conversation/([a-zA-Z0-9\-]*?)/messages/(\d+?)@(\w+\.\w+)} |   CONVERSATION_MESSAGE_ID_PATTERN = %r{conversation/([a-zA-Z0-9-]*?)/messages/(\d+?)@(\w+\.\w+)} | ||||||
|  |  | ||||||
|   # routes as a reply to existing conversations |   # routes as a reply to existing conversations | ||||||
|   routing( |   routing( | ||||||
|   | |||||||
| @@ -62,7 +62,7 @@ class Attachment < ApplicationRecord | |||||||
|  |  | ||||||
|   def thumb_url |   def thumb_url | ||||||
|     if file.attached? && file.representable? |     if file.attached? && file.representable? | ||||||
|       url_for(file.representation(resize: '250x250')) |       url_for(file.representation(resize_to_fill: [250, nil])) | ||||||
|     else |     else | ||||||
|       '' |       '' | ||||||
|     end |     end | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ module Avatarable | |||||||
|   end |   end | ||||||
|  |  | ||||||
|   def avatar_url |   def avatar_url | ||||||
|     return url_for(avatar.representation(resize: '250x250')) if avatar.attached? && avatar.representable? |     return url_for(avatar.representation(resize_to_fill: [250, nil])) if avatar.attached? && avatar.representable? | ||||||
|  |  | ||||||
|     '' |     '' | ||||||
|   end |   end | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ module Pubsubable | |||||||
|  |  | ||||||
|   def pubsub_token |   def pubsub_token | ||||||
|     # backfills tokens for existing records |     # backfills tokens for existing records | ||||||
|     regenerate_pubsub_token if self[:pubsub_token].blank? |     regenerate_pubsub_token if self[:pubsub_token].blank? && persisted? | ||||||
|     self[:pubsub_token] |     self[:pubsub_token] | ||||||
|   end |   end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -1,3 +1,3 @@ | |||||||
| json.identifier @inbox_channel.identifier | json.identifier @inbox_channel.identifier | ||||||
| json.identity_validation_enabled @inbox_channel.hmac_mandatory | json.identity_validation_enabled @inbox_channel.hmac_mandatory | ||||||
| json.partial! 'public/api/v1/models/inbox.json.jbuilder', resource: @inbox_channel.inbox | json.partial! 'public/api/v1/models/inbox', formats: [:json], resource: @inbox_channel.inbox | ||||||
|   | |||||||
| @@ -7,20 +7,20 @@ json.position category.position | |||||||
| json.related_categories do | json.related_categories do | ||||||
|   if category.related_categories.any? |   if category.related_categories.any? | ||||||
|     json.array! category.related_categories.each do |related_category| |     json.array! category.related_categories.each do |related_category| | ||||||
|       json.partial! partial: 'public/api/v1/models/associated_category.json.jbuilder', category: related_category |       json.partial! partial: 'public/api/v1/models/associated_category', formats: [:json], category: related_category | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
| if category.parent_category.present? | if category.parent_category.present? | ||||||
|   json.parent_category do |   json.parent_category do | ||||||
|     json.partial! partial: 'public/api/v1/models/associated_category.json.jbuilder', category: category.parent_category |     json.partial! partial: 'public/api/v1/models/associated_category', formats: [:json], category: category.parent_category | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
| if category.root_category.present? | if category.root_category.present? | ||||||
|   json.root_category do |   json.root_category do | ||||||
|     json.partial! partial: 'public/api/v1/models/associated_category.json.jbuilder', category: category.root_category |     json.partial! partial: 'public/api/v1/models/associated_category', formats: [:json], category: category.root_category | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| json.payload do | json.payload do | ||||||
|   json.array! @articles, partial: 'public/api/v1/models/article.json.jbuilder', as: :article |   json.array! @articles, partial: 'public/api/v1/models/article', formats: [:json], as: :article | ||||||
| end | end | ||||||
|  |  | ||||||
| json.meta do | json.meta do | ||||||
|   | |||||||
| @@ -1,3 +1,3 @@ | |||||||
| json.payload do | json.payload do | ||||||
|   json.array! @categories, partial: 'public/api/v1/models/category.json.jbuilder', as: :category |   json.array! @categories, partial: 'public/api/v1/models/category', formats: [:json], as: :category | ||||||
| end | end | ||||||
|   | |||||||
| @@ -1 +1 @@ | |||||||
| json.array! @portals, partial: 'public/api/v1/models/portal.json.jbuilder', as: :portal | json.array! @portals, partial: 'public/api/v1/models/portal', formats: [:json], as: :portal | ||||||
|   | |||||||
							
								
								
									
										0
									
								
								bin/validate_push
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								bin/validate_push
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -30,7 +30,7 @@ end | |||||||
| module Chatwoot | module Chatwoot | ||||||
|   class Application < Rails::Application |   class Application < Rails::Application | ||||||
|     # Initialize configuration defaults for originally generated Rails version. |     # Initialize configuration defaults for originally generated Rails version. | ||||||
|     config.load_defaults 6.0 |     config.load_defaults 7.0 | ||||||
|  |  | ||||||
|     config.eager_load_paths << Rails.root.join('lib') |     config.eager_load_paths << Rails.root.join('lib') | ||||||
|     config.eager_load_paths << Rails.root.join('enterprise/lib') |     config.eager_load_paths << Rails.root.join('enterprise/lib') | ||||||
| @@ -51,7 +51,7 @@ module Chatwoot | |||||||
|     # https://stackoverflow.com/questions/72970170/upgrading-to-rails-6-1-6-1-causes-psychdisallowedclass-tried-to-load-unspecif |     # https://stackoverflow.com/questions/72970170/upgrading-to-rails-6-1-6-1-causes-psychdisallowedclass-tried-to-load-unspecif | ||||||
|     # https://discuss.rubyonrails.org/t/cve-2022-32224-possible-rce-escalation-bug-with-serialized-columns-in-active-record/81017 |     # https://discuss.rubyonrails.org/t/cve-2022-32224-possible-rce-escalation-bug-with-serialized-columns-in-active-record/81017 | ||||||
|     # FIX ME : fixes breakage of installation config. we need to migrate. |     # FIX ME : fixes breakage of installation config. we need to migrate. | ||||||
|     config.active_record.yaml_column_permitted_classes = [HashWithIndifferentAccess] |     config.active_record.yaml_column_permitted_classes = [ActiveSupport::HashWithIndifferentAccess] | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   def self.config |   def self.config | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ default: &default | |||||||
|   host: <%= ENV.fetch('POSTGRES_HOST', 'localhost') %> |   host: <%= ENV.fetch('POSTGRES_HOST', 'localhost') %> | ||||||
|   port: <%= ENV.fetch('POSTGRES_PORT', '5432') %> |   port: <%= ENV.fetch('POSTGRES_PORT', '5432') %> | ||||||
|    # ref: https://github.com/mperham/sidekiq/issues/2985#issuecomment-531097962 |    # ref: https://github.com/mperham/sidekiq/issues/2985#issuecomment-531097962 | ||||||
|   pool: <%= Sidekiq.server? ? Sidekiq.options[:concurrency] : ENV.fetch('RAILS_MAX_THREADS', 5) %> |   pool: <%= Sidekiq.server? ? ENV.fetch('SIDEKIQ_CONCURRENCY', 10) : ENV.fetch('RAILS_MAX_THREADS', 5) %> | ||||||
|   variables: |   variables: | ||||||
|     # we are setting this value to be close to the racktimeout value. we will iterate and reduce this value going forward |     # we are setting this value to be close to the racktimeout value. we will iterate and reduce this value going forward | ||||||
|     statement_timeout: <%= ENV["POSTGRES_STATEMENT_TIMEOUT"] || "14s" %> |     statement_timeout: <%= ENV["POSTGRES_STATEMENT_TIMEOUT"] || "14s" %> | ||||||
|   | |||||||
| @@ -1,14 +1,14 @@ | |||||||
| # Alfred | # Alfred | ||||||
| # Add here as you use it for more features | # Add here as you use it for more features | ||||||
| # Used for Round Robin, Conversation Emails & Online Presence | # Used for Round Robin, Conversation Emails & Online Presence | ||||||
| $alfred = ConnectionPool.new(size: 5, timeout: 3) do | $alfred = ConnectionPool.new(size: 5, timeout: 1) do | ||||||
|   redis = Rails.env.test? ? MockRedis.new : Redis.new(Redis::Config.app) |   redis = Rails.env.test? ? MockRedis.new : Redis.new(Redis::Config.app) | ||||||
|   Redis::Namespace.new('alfred', redis: redis, warning: true) |   Redis::Namespace.new('alfred', redis: redis, warning: true) | ||||||
| end | end | ||||||
|  |  | ||||||
| # Velma : Determined protector | # Velma : Determined protector | ||||||
| # used in rack attack | # used in rack attack | ||||||
| $velma = ConnectionPool.new(size: 5, timeout: 3) do | $velma = ConnectionPool.new(size: 5, timeout: 1) do | ||||||
|   config = Rails.env.test? ? MockRedis.new : Redis.new(Redis::Config.app) |   config = Rails.env.test? ? MockRedis.new : Redis.new(Redis::Config.app) | ||||||
|   Redis::Namespace.new('velma', redis: config, warning: true) |   Redis::Namespace.new('velma', redis: config, warning: true) | ||||||
| end | end | ||||||
|   | |||||||
| @@ -1,45 +0,0 @@ | |||||||
| # Be sure to restart your server when you modify this file. |  | ||||||
| # |  | ||||||
| # This file contains migration options to ease your Rails 6.0 upgrade. |  | ||||||
| # |  | ||||||
| # Once upgraded flip defaults one by one to migrate to the new default. |  | ||||||
| # |  | ||||||
| # Read the Guide for Upgrading Ruby on Rails for more info on each option. |  | ||||||
|  |  | ||||||
| # Don't force requests from old versions of IE to be UTF-8 encoded. |  | ||||||
| # Rails.application.config.action_view.default_enforce_utf8 = false |  | ||||||
|  |  | ||||||
| # Embed purpose and expiry metadata inside signed and encrypted |  | ||||||
| # cookies for increased security. |  | ||||||
| # |  | ||||||
| # This option is not backwards compatible with earlier Rails versions. |  | ||||||
| # It's best enabled when your entire app is migrated and stable on 6.0. |  | ||||||
| # Rails.application.config.action_dispatch.use_cookies_with_metadata = true |  | ||||||
|  |  | ||||||
| # Change the return value of `ActionDispatch::Response#content_type` to Content-Type header without modification. |  | ||||||
| # Rails.application.config.action_dispatch.return_only_media_type_on_content_type = false |  | ||||||
|  |  | ||||||
| # Return false instead of self when enqueuing is aborted from a callback. |  | ||||||
| # Rails.application.config.active_job.return_false_on_aborted_enqueue = true |  | ||||||
|  |  | ||||||
| # Send Active Storage analysis and purge jobs to dedicated queues. |  | ||||||
| # Rails.application.config.active_storage.queues.analysis = :active_storage_analysis |  | ||||||
| # Rails.application.config.active_storage.queues.purge    = :active_storage_purge |  | ||||||
|  |  | ||||||
| # When assigning to a collection of attachments declared via `has_many_attached`, replace existing |  | ||||||
| # attachments instead of appending. Use #attach to add new attachments without replacing existing ones. |  | ||||||
| # Rails.application.config.active_storage.replace_on_assign_to_many = true |  | ||||||
|  |  | ||||||
| # Use ActionMailer::MailDeliveryJob for sending parameterized and normal mail. |  | ||||||
| # |  | ||||||
| # The default delivery jobs (ActionMailer::Parameterized::DeliveryJob, ActionMailer::DeliveryJob), |  | ||||||
| # will be removed in Rails 6.1. This setting is not backwards compatible with earlier Rails versions. |  | ||||||
| # If you send mail in the background, job workers need to have a copy of |  | ||||||
| # MailDeliveryJob to ensure all delivery jobs are processed properly. |  | ||||||
| # Make sure your entire app is migrated and stable on 6.0 before using this setting. |  | ||||||
| # Rails.application.config.action_mailer.delivery_job = "ActionMailer::MailDeliveryJob" |  | ||||||
|  |  | ||||||
| # Enable the same cache key to be reused when the object being cached of type |  | ||||||
| # `ActiveRecord::Relation` changes by moving the volatile information (max updated at and count) |  | ||||||
| # of the relation's cache key into the cache version to support recycling cache key. |  | ||||||
| # Rails.application.config.active_record.collection_cache_versioning = true |  | ||||||
							
								
								
									
										11
									
								
								config/initializers/permissions_policy.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								config/initializers/permissions_policy.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | # Define an application-wide HTTP permissions policy. For further | ||||||
|  | # information see https://developers.google.com/web/updates/2018/06/feature-policy | ||||||
|  | # | ||||||
|  | # Rails.application.config.permissions_policy do |f| | ||||||
|  | #   f.camera      :none | ||||||
|  | #   f.gyroscope   :none | ||||||
|  | #   f.microphone  :none | ||||||
|  | #   f.usb         :none | ||||||
|  | #   f.fullscreen  :self | ||||||
|  | #   f.payment     :self, "https://secure.example.com" | ||||||
|  | # end | ||||||
| @@ -4,7 +4,7 @@ | |||||||
| # pick it up automatically. | # pick it up automatically. | ||||||
| --- | --- | ||||||
| :verbose: false | :verbose: false | ||||||
| :concurrency: <%= ENV.fetch("SIDEKIQ_CONCURRENCY", 5) %> | :concurrency: <%= ENV.fetch("SIDEKIQ_CONCURRENCY", 10) %> | ||||||
| :timeout: 25 | :timeout: 25 | ||||||
| :max_retries: 3 | :max_retries: 3 | ||||||
|  |  | ||||||
| @@ -32,4 +32,4 @@ | |||||||
| production: | production: | ||||||
|   :concurrency: <%= ENV.fetch("SIDEKIQ_CONCURRENCY", 10) %> |   :concurrency: <%= ENV.fetch("SIDEKIQ_CONCURRENCY", 10) %> | ||||||
| staging: | staging: | ||||||
|   :concurrency: <%= ENV.fetch("SIDEKIQ_CONCURRENCY", 5) %> |   :concurrency: <%= ENV.fetch("SIDEKIQ_CONCURRENCY", 10) %> | ||||||
|   | |||||||
| @@ -0,0 +1,8 @@ | |||||||
|  | # This migration comes from active_storage (originally 20211119233751) | ||||||
|  | class RemoveNotNullOnActiveStorageBlobsChecksum < ActiveRecord::Migration[6.0] | ||||||
|  |   def change | ||||||
|  |     return unless table_exists?(:active_storage_blobs) | ||||||
|  |  | ||||||
|  |     change_column_null(:active_storage_blobs, :checksum, true) | ||||||
|  |   end | ||||||
|  | end | ||||||
							
								
								
									
										283
									
								
								db/schema.rb
									
									
									
									
									
								
							
							
						
						
									
										283
									
								
								db/schema.rb
									
									
									
									
									
								
							| @@ -10,8 +10,7 @@ | |||||||
| # | # | ||||||
| # It's strongly recommended that you check this file into your version control system. | # It's strongly recommended that you check this file into your version control system. | ||||||
|  |  | ||||||
| ActiveRecord::Schema.define(version: 2023_04_26_130150) do | ActiveRecord::Schema[7.0].define(version: 2023_04_26_130150) do | ||||||
|  |  | ||||||
|   # These are extensions that must be enabled in order to support this database |   # These are extensions that must be enabled in order to support this database | ||||||
|   enable_extension "pg_stat_statements" |   enable_extension "pg_stat_statements" | ||||||
|   enable_extension "pg_trgm" |   enable_extension "pg_trgm" | ||||||
| @@ -22,8 +21,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "owner_type" |     t.string "owner_type" | ||||||
|     t.bigint "owner_id" |     t.bigint "owner_id" | ||||||
|     t.string "token" |     t.string "token" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["owner_type", "owner_id"], name: "index_access_tokens_on_owner_type_and_owner_id" |     t.index ["owner_type", "owner_id"], name: "index_access_tokens_on_owner_type_and_owner_id" | ||||||
|     t.index ["token"], name: "index_access_tokens_on_token", unique: true |     t.index ["token"], name: "index_access_tokens_on_token", unique: true | ||||||
|   end |   end | ||||||
| @@ -33,9 +32,9 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.bigint "user_id" |     t.bigint "user_id" | ||||||
|     t.integer "role", default: 0 |     t.integer "role", default: 0 | ||||||
|     t.bigint "inviter_id" |     t.bigint "inviter_id" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.datetime "active_at" |     t.datetime "active_at", precision: nil | ||||||
|     t.integer "availability", default: 0, null: false |     t.integer "availability", default: 0, null: false | ||||||
|     t.boolean "auto_offline", default: true, null: false |     t.boolean "auto_offline", default: true, null: false | ||||||
|     t.index ["account_id", "user_id"], name: "uniq_user_id_per_account_id", unique: true |     t.index ["account_id", "user_id"], name: "uniq_user_id_per_account_id", unique: true | ||||||
| @@ -45,8 +44,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|  |  | ||||||
|   create_table "accounts", id: :serial, force: :cascade do |t| |   create_table "accounts", id: :serial, force: :cascade do |t| | ||||||
|     t.string "name", null: false |     t.string "name", null: false | ||||||
|     t.datetime "created_at", null: false |     t.datetime "created_at", precision: nil, null: false | ||||||
|     t.datetime "updated_at", null: false |     t.datetime "updated_at", precision: nil, null: false | ||||||
|     t.integer "locale", default: 0 |     t.integer "locale", default: 0 | ||||||
|     t.string "domain", limit: 100 |     t.string "domain", limit: 100 | ||||||
|     t.string "support_email", limit: 100 |     t.string "support_email", limit: 100 | ||||||
| @@ -62,8 +61,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.integer "status", default: 0, null: false |     t.integer "status", default: 0, null: false | ||||||
|     t.string "message_id", null: false |     t.string "message_id", null: false | ||||||
|     t.string "message_checksum", null: false |     t.string "message_checksum", null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["message_id", "message_checksum"], name: "index_action_mailbox_inbound_emails_uniqueness", unique: true |     t.index ["message_id", "message_checksum"], name: "index_action_mailbox_inbound_emails_uniqueness", unique: true | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -72,7 +71,7 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "record_type", null: false |     t.string "record_type", null: false | ||||||
|     t.bigint "record_id", null: false |     t.bigint "record_id", null: false | ||||||
|     t.bigint "blob_id", null: false |     t.bigint "blob_id", null: false | ||||||
|     t.datetime "created_at", null: false |     t.datetime "created_at", precision: nil, null: false | ||||||
|     t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" |     t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" | ||||||
|     t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true |     t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true | ||||||
|   end |   end | ||||||
| @@ -83,8 +82,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "content_type" |     t.string "content_type" | ||||||
|     t.text "metadata" |     t.text "metadata" | ||||||
|     t.bigint "byte_size", null: false |     t.bigint "byte_size", null: false | ||||||
|     t.string "checksum", null: false |     t.string "checksum" | ||||||
|     t.datetime "created_at", null: false |     t.datetime "created_at", precision: nil, null: false | ||||||
|     t.string "service_name", null: false |     t.string "service_name", null: false | ||||||
|     t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true |     t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true | ||||||
|   end |   end | ||||||
| @@ -99,8 +98,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.integer "inbox_id" |     t.integer "inbox_id" | ||||||
|     t.integer "agent_bot_id" |     t.integer "agent_bot_id" | ||||||
|     t.integer "status", default: 0 |     t.integer "status", default: 0 | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.integer "account_id" |     t.integer "account_id" | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -108,8 +107,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "name" |     t.string "name" | ||||||
|     t.string "description" |     t.string "description" | ||||||
|     t.string "outgoing_url" |     t.string "outgoing_url" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.bigint "account_id" |     t.bigint "account_id" | ||||||
|     t.integer "bot_type", default: 0 |     t.integer "bot_type", default: 0 | ||||||
|     t.jsonb "bot_config", default: {} |     t.jsonb "bot_config", default: {} | ||||||
| @@ -126,8 +125,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.text "content" |     t.text "content" | ||||||
|     t.integer "status" |     t.integer "status" | ||||||
|     t.integer "views" |     t.integer "views" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.bigint "author_id" |     t.bigint "author_id" | ||||||
|     t.bigint "associated_article_id" |     t.bigint "associated_article_id" | ||||||
|     t.jsonb "meta", default: {} |     t.jsonb "meta", default: {} | ||||||
| @@ -145,8 +144,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.float "coordinates_long", default: 0.0 |     t.float "coordinates_long", default: 0.0 | ||||||
|     t.integer "message_id", null: false |     t.integer "message_id", null: false | ||||||
|     t.integer "account_id", null: false |     t.integer "account_id", null: false | ||||||
|     t.datetime "created_at", null: false |     t.datetime "created_at", precision: nil, null: false | ||||||
|     t.datetime "updated_at", null: false |     t.datetime "updated_at", precision: nil, null: false | ||||||
|     t.string "fallback_title" |     t.string "fallback_title" | ||||||
|     t.string "extension" |     t.string "extension" | ||||||
|     t.index ["account_id"], name: "index_attachments_on_account_id" |     t.index ["account_id"], name: "index_attachments_on_account_id" | ||||||
| @@ -167,7 +166,7 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "comment" |     t.string "comment" | ||||||
|     t.string "remote_address" |     t.string "remote_address" | ||||||
|     t.string "request_uuid" |     t.string "request_uuid" | ||||||
|     t.datetime "created_at" |     t.datetime "created_at", precision: nil | ||||||
|     t.index ["associated_type", "associated_id"], name: "associated_index" |     t.index ["associated_type", "associated_id"], name: "associated_index" | ||||||
|     t.index ["auditable_type", "auditable_id", "version"], name: "auditable_index" |     t.index ["auditable_type", "auditable_id", "version"], name: "auditable_index" | ||||||
|     t.index ["created_at"], name: "index_audits_on_created_at" |     t.index ["created_at"], name: "index_audits_on_created_at" | ||||||
| @@ -182,8 +181,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "event_name", null: false |     t.string "event_name", null: false | ||||||
|     t.jsonb "conditions", default: "{}", null: false |     t.jsonb "conditions", default: "{}", null: false | ||||||
|     t.jsonb "actions", default: "{}", null: false |     t.jsonb "actions", default: "{}", null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.boolean "active", default: true, null: false |     t.boolean "active", default: true, null: false | ||||||
|     t.index ["account_id"], name: "index_automation_rules_on_account_id" |     t.index ["account_id"], name: "index_automation_rules_on_account_id" | ||||||
|   end |   end | ||||||
| @@ -198,12 +197,12 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.bigint "account_id", null: false |     t.bigint "account_id", null: false | ||||||
|     t.bigint "inbox_id", null: false |     t.bigint "inbox_id", null: false | ||||||
|     t.jsonb "trigger_rules", default: {} |     t.jsonb "trigger_rules", default: {} | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.integer "campaign_type", default: 0, null: false |     t.integer "campaign_type", default: 0, null: false | ||||||
|     t.integer "campaign_status", default: 0, null: false |     t.integer "campaign_status", default: 0, null: false | ||||||
|     t.jsonb "audience", default: [] |     t.jsonb "audience", default: [] | ||||||
|     t.datetime "scheduled_at" |     t.datetime "scheduled_at", precision: nil | ||||||
|     t.boolean "trigger_only_during_business_hours", default: false |     t.boolean "trigger_only_during_business_hours", default: false | ||||||
|     t.index ["account_id"], name: "index_campaigns_on_account_id" |     t.index ["account_id"], name: "index_campaigns_on_account_id" | ||||||
|     t.index ["campaign_status"], name: "index_campaigns_on_campaign_status" |     t.index ["campaign_status"], name: "index_campaigns_on_campaign_status" | ||||||
| @@ -216,8 +215,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.integer "account_id", null: false |     t.integer "account_id", null: false | ||||||
|     t.string "short_code" |     t.string "short_code" | ||||||
|     t.text "content" |     t.text "content" | ||||||
|     t.datetime "created_at", null: false |     t.datetime "created_at", precision: nil, null: false | ||||||
|     t.datetime "updated_at", null: false |     t.datetime "updated_at", precision: nil, null: false | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   create_table "categories", force: :cascade do |t| |   create_table "categories", force: :cascade do |t| | ||||||
| @@ -226,8 +225,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "name" |     t.string "name" | ||||||
|     t.text "description" |     t.text "description" | ||||||
|     t.integer "position" |     t.integer "position" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.string "locale", default: "en" |     t.string "locale", default: "en" | ||||||
|     t.string "slug", null: false |     t.string "slug", null: false | ||||||
|     t.bigint "parent_category_id" |     t.bigint "parent_category_id" | ||||||
| @@ -242,8 +241,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|   create_table "channel_api", force: :cascade do |t| |   create_table "channel_api", force: :cascade do |t| | ||||||
|     t.integer "account_id", null: false |     t.integer "account_id", null: false | ||||||
|     t.string "webhook_url" |     t.string "webhook_url" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.string "identifier" |     t.string "identifier" | ||||||
|     t.string "hmac_token" |     t.string "hmac_token" | ||||||
|     t.boolean "hmac_mandatory", default: false |     t.boolean "hmac_mandatory", default: false | ||||||
| @@ -256,15 +255,15 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.integer "account_id", null: false |     t.integer "account_id", null: false | ||||||
|     t.string "email", null: false |     t.string "email", null: false | ||||||
|     t.string "forward_to_email", null: false |     t.string "forward_to_email", null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.boolean "imap_enabled", default: false |     t.boolean "imap_enabled", default: false | ||||||
|     t.string "imap_address", default: "" |     t.string "imap_address", default: "" | ||||||
|     t.integer "imap_port", default: 0 |     t.integer "imap_port", default: 0 | ||||||
|     t.string "imap_login", default: "" |     t.string "imap_login", default: "" | ||||||
|     t.string "imap_password", default: "" |     t.string "imap_password", default: "" | ||||||
|     t.boolean "imap_enable_ssl", default: true |     t.boolean "imap_enable_ssl", default: true | ||||||
|     t.datetime "imap_inbox_synced_at" |     t.datetime "imap_inbox_synced_at", precision: nil | ||||||
|     t.boolean "smtp_enabled", default: false |     t.boolean "smtp_enabled", default: false | ||||||
|     t.string "smtp_address", default: "" |     t.string "smtp_address", default: "" | ||||||
|     t.integer "smtp_port", default: 0 |     t.integer "smtp_port", default: 0 | ||||||
| @@ -286,8 +285,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "user_access_token", null: false |     t.string "user_access_token", null: false | ||||||
|     t.string "page_access_token", null: false |     t.string "page_access_token", null: false | ||||||
|     t.integer "account_id", null: false |     t.integer "account_id", null: false | ||||||
|     t.datetime "created_at", null: false |     t.datetime "created_at", precision: nil, null: false | ||||||
|     t.datetime "updated_at", null: false |     t.datetime "updated_at", precision: nil, null: false | ||||||
|     t.string "instagram_id" |     t.string "instagram_id" | ||||||
|     t.index ["page_id", "account_id"], name: "index_channel_facebook_pages_on_page_id_and_account_id", unique: true |     t.index ["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" |     t.index ["page_id"], name: "index_channel_facebook_pages_on_page_id" | ||||||
| @@ -298,8 +297,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "line_channel_id", null: false |     t.string "line_channel_id", null: false | ||||||
|     t.string "line_channel_secret", null: false |     t.string "line_channel_secret", null: false | ||||||
|     t.string "line_channel_token", null: false |     t.string "line_channel_token", null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["line_channel_id"], name: "index_channel_line_on_line_channel_id", unique: true |     t.index ["line_channel_id"], name: "index_channel_line_on_line_channel_id", unique: true | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -308,8 +307,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "phone_number", null: false |     t.string "phone_number", null: false | ||||||
|     t.string "provider", default: "default" |     t.string "provider", default: "default" | ||||||
|     t.jsonb "provider_config", default: {} |     t.jsonb "provider_config", default: {} | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["phone_number"], name: "index_channel_sms_on_phone_number", unique: true |     t.index ["phone_number"], name: "index_channel_sms_on_phone_number", unique: true | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -317,8 +316,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "bot_name" |     t.string "bot_name" | ||||||
|     t.integer "account_id", null: false |     t.integer "account_id", null: false | ||||||
|     t.string "bot_token", null: false |     t.string "bot_token", null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["bot_token"], name: "index_channel_telegram_on_bot_token", unique: true |     t.index ["bot_token"], name: "index_channel_telegram_on_bot_token", unique: true | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -327,8 +326,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "auth_token", null: false |     t.string "auth_token", null: false | ||||||
|     t.string "account_sid", null: false |     t.string "account_sid", null: false | ||||||
|     t.integer "account_id", null: false |     t.integer "account_id", null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.integer "medium", default: 0 |     t.integer "medium", default: 0 | ||||||
|     t.string "messaging_service_sid" |     t.string "messaging_service_sid" | ||||||
|     t.index ["account_sid", "phone_number"], name: "index_channel_twilio_sms_on_account_sid_and_phone_number", unique: true |     t.index ["account_sid", "phone_number"], name: "index_channel_twilio_sms_on_account_sid_and_phone_number", unique: true | ||||||
| @@ -341,8 +340,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "twitter_access_token", null: false |     t.string "twitter_access_token", null: false | ||||||
|     t.string "twitter_access_token_secret", null: false |     t.string "twitter_access_token_secret", null: false | ||||||
|     t.integer "account_id", null: false |     t.integer "account_id", null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.boolean "tweets_enabled", default: true |     t.boolean "tweets_enabled", default: true | ||||||
|     t.index ["account_id", "profile_id"], name: "index_channel_twitter_profiles_on_account_id_and_profile_id", unique: true |     t.index ["account_id", "profile_id"], name: "index_channel_twitter_profiles_on_account_id_and_profile_id", unique: true | ||||||
|   end |   end | ||||||
| @@ -350,8 +349,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|   create_table "channel_web_widgets", id: :serial, force: :cascade do |t| |   create_table "channel_web_widgets", id: :serial, force: :cascade do |t| | ||||||
|     t.string "website_url" |     t.string "website_url" | ||||||
|     t.integer "account_id" |     t.integer "account_id" | ||||||
|     t.datetime "created_at", null: false |     t.datetime "created_at", precision: nil, null: false | ||||||
|     t.datetime "updated_at", null: false |     t.datetime "updated_at", precision: nil, null: false | ||||||
|     t.string "website_token" |     t.string "website_token" | ||||||
|     t.string "widget_color", default: "#1f93ff" |     t.string "widget_color", default: "#1f93ff" | ||||||
|     t.string "welcome_title" |     t.string "welcome_title" | ||||||
| @@ -372,10 +371,10 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "phone_number", null: false |     t.string "phone_number", null: false | ||||||
|     t.string "provider", default: "default" |     t.string "provider", default: "default" | ||||||
|     t.jsonb "provider_config", default: {} |     t.jsonb "provider_config", default: {} | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.jsonb "message_templates", default: {} |     t.jsonb "message_templates", default: {} | ||||||
|     t.datetime "message_templates_last_updated" |     t.datetime "message_templates_last_updated", precision: nil | ||||||
|     t.index ["phone_number"], name: "index_channel_whatsapp_on_phone_number", unique: true |     t.index ["phone_number"], name: "index_channel_whatsapp_on_phone_number", unique: true | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -383,8 +382,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.bigint "contact_id" |     t.bigint "contact_id" | ||||||
|     t.bigint "inbox_id" |     t.bigint "inbox_id" | ||||||
|     t.string "source_id", null: false |     t.string "source_id", null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.boolean "hmac_verified", default: false |     t.boolean "hmac_verified", default: false | ||||||
|     t.string "pubsub_token" |     t.string "pubsub_token" | ||||||
|     t.index ["contact_id"], name: "index_contact_inboxes_on_contact_id" |     t.index ["contact_id"], name: "index_contact_inboxes_on_contact_id" | ||||||
| @@ -399,12 +398,12 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "email" |     t.string "email" | ||||||
|     t.string "phone_number" |     t.string "phone_number" | ||||||
|     t.integer "account_id", null: false |     t.integer "account_id", null: false | ||||||
|     t.datetime "created_at", null: false |     t.datetime "created_at", precision: nil, null: false | ||||||
|     t.datetime "updated_at", null: false |     t.datetime "updated_at", precision: nil, null: false | ||||||
|     t.jsonb "additional_attributes", default: {} |     t.jsonb "additional_attributes", default: {} | ||||||
|     t.string "identifier" |     t.string "identifier" | ||||||
|     t.jsonb "custom_attributes", default: {} |     t.jsonb "custom_attributes", default: {} | ||||||
|     t.datetime "last_activity_at" |     t.datetime "last_activity_at", precision: nil | ||||||
|     t.index "lower((email)::text), account_id", name: "index_contacts_on_lower_email_account_id" |     t.index "lower((email)::text), account_id", name: "index_contacts_on_lower_email_account_id" | ||||||
|     t.index ["account_id"], name: "index_contacts_on_account_id" |     t.index ["account_id"], name: "index_contacts_on_account_id" | ||||||
|     t.index ["email", "account_id"], name: "uniq_email_per_account_contact", unique: true |     t.index ["email", "account_id"], name: "uniq_email_per_account_contact", unique: true | ||||||
| @@ -417,8 +416,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.bigint "account_id", null: false |     t.bigint "account_id", null: false | ||||||
|     t.bigint "user_id", null: false |     t.bigint "user_id", null: false | ||||||
|     t.bigint "conversation_id", null: false |     t.bigint "conversation_id", null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["account_id"], name: "index_conversation_participants_on_account_id" |     t.index ["account_id"], name: "index_conversation_participants_on_account_id" | ||||||
|     t.index ["conversation_id"], name: "index_conversation_participants_on_conversation_id" |     t.index ["conversation_id"], name: "index_conversation_participants_on_conversation_id" | ||||||
|     t.index ["user_id", "conversation_id"], name: "index_conversation_participants_on_user_id_and_conversation_id", unique: true |     t.index ["user_id", "conversation_id"], name: "index_conversation_participants_on_user_id_and_conversation_id", unique: true | ||||||
| @@ -430,23 +429,23 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.integer "inbox_id", null: false |     t.integer "inbox_id", null: false | ||||||
|     t.integer "status", default: 0, null: false |     t.integer "status", default: 0, null: false | ||||||
|     t.integer "assignee_id" |     t.integer "assignee_id" | ||||||
|     t.datetime "created_at", null: false |     t.datetime "created_at", precision: nil, null: false | ||||||
|     t.datetime "updated_at", null: false |     t.datetime "updated_at", precision: nil, null: false | ||||||
|     t.bigint "contact_id" |     t.bigint "contact_id" | ||||||
|     t.integer "display_id", null: false |     t.integer "display_id", null: false | ||||||
|     t.datetime "contact_last_seen_at" |     t.datetime "contact_last_seen_at", precision: nil | ||||||
|     t.datetime "agent_last_seen_at" |     t.datetime "agent_last_seen_at", precision: nil | ||||||
|     t.jsonb "additional_attributes", default: {} |     t.jsonb "additional_attributes", default: {} | ||||||
|     t.bigint "contact_inbox_id" |     t.bigint "contact_inbox_id" | ||||||
|     t.uuid "uuid", default: -> { "gen_random_uuid()" }, null: false |     t.uuid "uuid", default: -> { "gen_random_uuid()" }, null: false | ||||||
|     t.string "identifier" |     t.string "identifier" | ||||||
|     t.datetime "last_activity_at", default: -> { "CURRENT_TIMESTAMP" }, null: false |     t.datetime "last_activity_at", precision: nil, default: -> { "CURRENT_TIMESTAMP" }, null: false | ||||||
|     t.bigint "team_id" |     t.bigint "team_id" | ||||||
|     t.bigint "campaign_id" |     t.bigint "campaign_id" | ||||||
|     t.datetime "snoozed_until" |     t.datetime "snoozed_until", precision: nil | ||||||
|     t.jsonb "custom_attributes", default: {} |     t.jsonb "custom_attributes", default: {} | ||||||
|     t.datetime "assignee_last_seen_at" |     t.datetime "assignee_last_seen_at", precision: nil | ||||||
|     t.datetime "first_reply_created_at" |     t.datetime "first_reply_created_at", precision: nil | ||||||
|     t.integer "priority" |     t.integer "priority" | ||||||
|     t.index ["account_id", "display_id"], name: "index_conversations_on_account_id_and_display_id", unique: true |     t.index ["account_id", "display_id"], name: "index_conversations_on_account_id_and_display_id", unique: true | ||||||
|     t.index ["account_id", "id"], name: "index_conversations_on_id_and_account_id" |     t.index ["account_id", "id"], name: "index_conversations_on_id_and_account_id" | ||||||
| @@ -474,8 +473,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.text "feedback_message" |     t.text "feedback_message" | ||||||
|     t.bigint "contact_id", null: false |     t.bigint "contact_id", null: false | ||||||
|     t.bigint "assigned_agent_id" |     t.bigint "assigned_agent_id" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["account_id"], name: "index_csat_survey_responses_on_account_id" |     t.index ["account_id"], name: "index_csat_survey_responses_on_account_id" | ||||||
|     t.index ["assigned_agent_id"], name: "index_csat_survey_responses_on_assigned_agent_id" |     t.index ["assigned_agent_id"], name: "index_csat_survey_responses_on_assigned_agent_id" | ||||||
|     t.index ["contact_id"], name: "index_csat_survey_responses_on_contact_id" |     t.index ["contact_id"], name: "index_csat_survey_responses_on_contact_id" | ||||||
| @@ -490,8 +489,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.integer "default_value" |     t.integer "default_value" | ||||||
|     t.integer "attribute_model", default: 0 |     t.integer "attribute_model", default: 0 | ||||||
|     t.bigint "account_id" |     t.bigint "account_id" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.text "attribute_description" |     t.text "attribute_description" | ||||||
|     t.jsonb "attribute_values", default: [] |     t.jsonb "attribute_values", default: [] | ||||||
|     t.index ["account_id"], name: "index_custom_attribute_definitions_on_account_id" |     t.index ["account_id"], name: "index_custom_attribute_definitions_on_account_id" | ||||||
| @@ -504,8 +503,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.jsonb "query", default: "{}", null: false |     t.jsonb "query", default: "{}", null: false | ||||||
|     t.bigint "account_id", null: false |     t.bigint "account_id", null: false | ||||||
|     t.bigint "user_id", null: false |     t.bigint "user_id", null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["account_id"], name: "index_custom_filters_on_account_id" |     t.index ["account_id"], name: "index_custom_filters_on_account_id" | ||||||
|     t.index ["user_id"], name: "index_custom_filters_on_user_id" |     t.index ["user_id"], name: "index_custom_filters_on_user_id" | ||||||
|   end |   end | ||||||
| @@ -515,8 +514,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.jsonb "content", default: [] |     t.jsonb "content", default: [] | ||||||
|     t.bigint "account_id", null: false |     t.bigint "account_id", null: false | ||||||
|     t.bigint "user_id" |     t.bigint "user_id" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["account_id"], name: "index_dashboard_apps_on_account_id" |     t.index ["account_id"], name: "index_dashboard_apps_on_account_id" | ||||||
|     t.index ["user_id"], name: "index_dashboard_apps_on_user_id" |     t.index ["user_id"], name: "index_dashboard_apps_on_user_id" | ||||||
|   end |   end | ||||||
| @@ -528,8 +527,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.text "processing_errors" |     t.text "processing_errors" | ||||||
|     t.integer "total_records" |     t.integer "total_records" | ||||||
|     t.integer "processed_records" |     t.integer "processed_records" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["account_id"], name: "index_data_imports_on_account_id" |     t.index ["account_id"], name: "index_data_imports_on_account_id" | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -539,8 +538,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.integer "account_id" |     t.integer "account_id" | ||||||
|     t.integer "template_type", default: 1 |     t.integer "template_type", default: 1 | ||||||
|     t.integer "locale", default: 0, null: false |     t.integer "locale", default: 0, null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["name", "account_id"], name: "index_email_templates_on_name_and_account_id", unique: true |     t.index ["name", "account_id"], name: "index_email_templates_on_name_and_account_id", unique: true | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -548,15 +547,15 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.integer "account_id", null: false |     t.integer "account_id", null: false | ||||||
|     t.integer "category_id", null: false |     t.integer "category_id", null: false | ||||||
|     t.string "name" |     t.string "name" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   create_table "inbox_members", id: :serial, force: :cascade do |t| |   create_table "inbox_members", id: :serial, force: :cascade do |t| | ||||||
|     t.integer "user_id", null: false |     t.integer "user_id", null: false | ||||||
|     t.integer "inbox_id", null: false |     t.integer "inbox_id", null: false | ||||||
|     t.datetime "created_at", null: false |     t.datetime "created_at", precision: nil, null: false | ||||||
|     t.datetime "updated_at", null: false |     t.datetime "updated_at", precision: nil, null: false | ||||||
|     t.index ["inbox_id", "user_id"], name: "index_inbox_members_on_inbox_id_and_user_id", unique: true |     t.index ["inbox_id", "user_id"], name: "index_inbox_members_on_inbox_id_and_user_id", unique: true | ||||||
|     t.index ["inbox_id"], name: "index_inbox_members_on_inbox_id" |     t.index ["inbox_id"], name: "index_inbox_members_on_inbox_id" | ||||||
|   end |   end | ||||||
| @@ -565,8 +564,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.integer "channel_id", null: false |     t.integer "channel_id", null: false | ||||||
|     t.integer "account_id", null: false |     t.integer "account_id", null: false | ||||||
|     t.string "name", null: false |     t.string "name", null: false | ||||||
|     t.datetime "created_at", null: false |     t.datetime "created_at", precision: nil, null: false | ||||||
|     t.datetime "updated_at", null: false |     t.datetime "updated_at", precision: nil, null: false | ||||||
|     t.string "channel_type" |     t.string "channel_type" | ||||||
|     t.boolean "enable_auto_assignment", default: true |     t.boolean "enable_auto_assignment", default: true | ||||||
|     t.boolean "greeting_enabled", default: false |     t.boolean "greeting_enabled", default: false | ||||||
| @@ -589,8 +588,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|   create_table "installation_configs", force: :cascade do |t| |   create_table "installation_configs", force: :cascade do |t| | ||||||
|     t.string "name", null: false |     t.string "name", null: false | ||||||
|     t.jsonb "serialized_value", default: {}, null: false |     t.jsonb "serialized_value", default: {}, null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.boolean "locked", default: true, null: false |     t.boolean "locked", default: true, null: false | ||||||
|     t.index ["name", "created_at"], name: "index_installation_configs_on_name_and_created_at", unique: true |     t.index ["name", "created_at"], name: "index_installation_configs_on_name_and_created_at", unique: true | ||||||
|     t.index ["name"], name: "index_installation_configs_on_name", unique: true |     t.index ["name"], name: "index_installation_configs_on_name", unique: true | ||||||
| @@ -604,8 +603,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.integer "hook_type", default: 0 |     t.integer "hook_type", default: 0 | ||||||
|     t.string "reference_id" |     t.string "reference_id" | ||||||
|     t.string "access_token" |     t.string "access_token" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.jsonb "settings", default: {} |     t.jsonb "settings", default: {} | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -615,8 +614,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "color", default: "#1f93ff", null: false |     t.string "color", default: "#1f93ff", null: false | ||||||
|     t.boolean "show_on_sidebar" |     t.boolean "show_on_sidebar" | ||||||
|     t.bigint "account_id" |     t.bigint "account_id" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["account_id"], name: "index_labels_on_account_id" |     t.index ["account_id"], name: "index_labels_on_account_id" | ||||||
|     t.index ["title", "account_id"], name: "index_labels_on_title_and_account_id", unique: true |     t.index ["title", "account_id"], name: "index_labels_on_title_and_account_id", unique: true | ||||||
|   end |   end | ||||||
| @@ -628,8 +627,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.bigint "created_by_id" |     t.bigint "created_by_id" | ||||||
|     t.bigint "updated_by_id" |     t.bigint "updated_by_id" | ||||||
|     t.jsonb "actions", default: {}, null: false |     t.jsonb "actions", default: {}, null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["account_id"], name: "index_macros_on_account_id" |     t.index ["account_id"], name: "index_macros_on_account_id" | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -637,9 +636,9 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.bigint "user_id", null: false |     t.bigint "user_id", null: false | ||||||
|     t.bigint "conversation_id", null: false |     t.bigint "conversation_id", null: false | ||||||
|     t.bigint "account_id", null: false |     t.bigint "account_id", null: false | ||||||
|     t.datetime "mentioned_at", null: false |     t.datetime "mentioned_at", precision: nil, null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["account_id"], name: "index_mentions_on_account_id" |     t.index ["account_id"], name: "index_mentions_on_account_id" | ||||||
|     t.index ["conversation_id"], name: "index_mentions_on_conversation_id" |     t.index ["conversation_id"], name: "index_mentions_on_conversation_id" | ||||||
|     t.index ["user_id", "conversation_id"], name: "index_mentions_on_user_id_and_conversation_id", unique: true |     t.index ["user_id", "conversation_id"], name: "index_mentions_on_user_id_and_conversation_id", unique: true | ||||||
| @@ -652,8 +651,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.integer "inbox_id", null: false |     t.integer "inbox_id", null: false | ||||||
|     t.integer "conversation_id", null: false |     t.integer "conversation_id", null: false | ||||||
|     t.integer "message_type", null: false |     t.integer "message_type", null: false | ||||||
|     t.datetime "created_at", null: false |     t.datetime "created_at", precision: nil, null: false | ||||||
|     t.datetime "updated_at", null: false |     t.datetime "updated_at", precision: nil, null: false | ||||||
|     t.boolean "private", default: false |     t.boolean "private", default: false | ||||||
|     t.integer "status", default: 0 |     t.integer "status", default: 0 | ||||||
|     t.string "source_id" |     t.string "source_id" | ||||||
| @@ -678,8 +677,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.bigint "account_id", null: false |     t.bigint "account_id", null: false | ||||||
|     t.bigint "contact_id", null: false |     t.bigint "contact_id", null: false | ||||||
|     t.bigint "user_id" |     t.bigint "user_id" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["account_id"], name: "index_notes_on_account_id" |     t.index ["account_id"], name: "index_notes_on_account_id" | ||||||
|     t.index ["contact_id"], name: "index_notes_on_contact_id" |     t.index ["contact_id"], name: "index_notes_on_contact_id" | ||||||
|     t.index ["user_id"], name: "index_notes_on_user_id" |     t.index ["user_id"], name: "index_notes_on_user_id" | ||||||
| @@ -689,8 +688,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.integer "account_id" |     t.integer "account_id" | ||||||
|     t.integer "user_id" |     t.integer "user_id" | ||||||
|     t.integer "email_flags", default: 0, null: false |     t.integer "email_flags", default: 0, null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.integer "push_flags", default: 0, null: false |     t.integer "push_flags", default: 0, null: false | ||||||
|     t.index ["account_id", "user_id"], name: "by_account_user", unique: true |     t.index ["account_id", "user_id"], name: "by_account_user", unique: true | ||||||
|   end |   end | ||||||
| @@ -699,8 +698,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.bigint "user_id", null: false |     t.bigint "user_id", null: false | ||||||
|     t.integer "subscription_type", null: false |     t.integer "subscription_type", null: false | ||||||
|     t.jsonb "subscription_attributes", default: {}, null: false |     t.jsonb "subscription_attributes", default: {}, null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.string "identifier" |     t.string "identifier" | ||||||
|     t.index ["identifier"], name: "index_notification_subscriptions_on_identifier", unique: true |     t.index ["identifier"], name: "index_notification_subscriptions_on_identifier", unique: true | ||||||
|     t.index ["user_id"], name: "index_notification_subscriptions_on_user_id" |     t.index ["user_id"], name: "index_notification_subscriptions_on_user_id" | ||||||
| @@ -714,9 +713,9 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.bigint "primary_actor_id", null: false |     t.bigint "primary_actor_id", null: false | ||||||
|     t.string "secondary_actor_type" |     t.string "secondary_actor_type" | ||||||
|     t.bigint "secondary_actor_id" |     t.bigint "secondary_actor_id" | ||||||
|     t.datetime "read_at" |     t.datetime "read_at", precision: nil | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["account_id"], name: "index_notifications_on_account_id" |     t.index ["account_id"], name: "index_notifications_on_account_id" | ||||||
|     t.index ["primary_actor_type", "primary_actor_id"], name: "uniq_primary_actor_per_account_notifications" |     t.index ["primary_actor_type", "primary_actor_id"], name: "uniq_primary_actor_per_account_notifications" | ||||||
|     t.index ["secondary_actor_type", "secondary_actor_id"], name: "uniq_secondary_actor_per_account_notifications" |     t.index ["secondary_actor_type", "secondary_actor_id"], name: "uniq_secondary_actor_per_account_notifications" | ||||||
| @@ -727,8 +726,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.bigint "platform_app_id", null: false |     t.bigint "platform_app_id", null: false | ||||||
|     t.string "permissible_type", null: false |     t.string "permissible_type", null: false | ||||||
|     t.bigint "permissible_id", null: false |     t.bigint "permissible_id", null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["permissible_type", "permissible_id"], name: "index_platform_app_permissibles_on_permissibles" |     t.index ["permissible_type", "permissible_id"], name: "index_platform_app_permissibles_on_permissibles" | ||||||
|     t.index ["platform_app_id", "permissible_id", "permissible_type"], name: "unique_permissibles_index", unique: true |     t.index ["platform_app_id", "permissible_id", "permissible_type"], name: "unique_permissibles_index", unique: true | ||||||
|     t.index ["platform_app_id"], name: "index_platform_app_permissibles_on_platform_app_id" |     t.index ["platform_app_id"], name: "index_platform_app_permissibles_on_platform_app_id" | ||||||
| @@ -736,15 +735,15 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|  |  | ||||||
|   create_table "platform_apps", force: :cascade do |t| |   create_table "platform_apps", force: :cascade do |t| | ||||||
|     t.string "name", null: false |     t.string "name", null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   create_table "portal_members", force: :cascade do |t| |   create_table "portal_members", force: :cascade do |t| | ||||||
|     t.bigint "portal_id" |     t.bigint "portal_id" | ||||||
|     t.bigint "user_id" |     t.bigint "user_id" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["portal_id", "user_id"], name: "index_portal_members_on_portal_id_and_user_id", unique: true |     t.index ["portal_id", "user_id"], name: "index_portal_members_on_portal_id_and_user_id", unique: true | ||||||
|     t.index ["user_id", "portal_id"], name: "index_portal_members_on_user_id_and_portal_id", unique: true |     t.index ["user_id", "portal_id"], name: "index_portal_members_on_user_id_and_portal_id", unique: true | ||||||
|   end |   end | ||||||
| @@ -758,8 +757,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "homepage_link" |     t.string "homepage_link" | ||||||
|     t.string "page_title" |     t.string "page_title" | ||||||
|     t.text "header_text" |     t.text "header_text" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.jsonb "config", default: {"allowed_locales"=>["en"]} |     t.jsonb "config", default: {"allowed_locales"=>["en"]} | ||||||
|     t.boolean "archived", default: false |     t.boolean "archived", default: false | ||||||
|     t.index ["custom_domain"], name: "index_portals_on_custom_domain", unique: true |     t.index ["custom_domain"], name: "index_portals_on_custom_domain", unique: true | ||||||
| @@ -777,8 +776,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|   create_table "related_categories", force: :cascade do |t| |   create_table "related_categories", force: :cascade do |t| | ||||||
|     t.bigint "category_id" |     t.bigint "category_id" | ||||||
|     t.bigint "related_category_id" |     t.bigint "related_category_id" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["category_id", "related_category_id"], name: "index_related_categories_on_category_id_and_related_category_id", unique: true |     t.index ["category_id", "related_category_id"], name: "index_related_categories_on_category_id_and_related_category_id", unique: true | ||||||
|     t.index ["related_category_id", "category_id"], name: "index_related_categories_on_related_category_id_and_category_id", unique: true |     t.index ["related_category_id", "category_id"], name: "index_related_categories_on_related_category_id_and_category_id", unique: true | ||||||
|   end |   end | ||||||
| @@ -790,11 +789,11 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.integer "inbox_id" |     t.integer "inbox_id" | ||||||
|     t.integer "user_id" |     t.integer "user_id" | ||||||
|     t.integer "conversation_id" |     t.integer "conversation_id" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.float "value_in_business_hours" |     t.float "value_in_business_hours" | ||||||
|     t.datetime "event_start_time" |     t.datetime "event_start_time", precision: nil | ||||||
|     t.datetime "event_end_time" |     t.datetime "event_end_time", precision: nil | ||||||
|     t.index ["account_id"], name: "index_reporting_events_on_account_id" |     t.index ["account_id"], name: "index_reporting_events_on_account_id" | ||||||
|     t.index ["conversation_id"], name: "index_reporting_events_on_conversation_id" |     t.index ["conversation_id"], name: "index_reporting_events_on_conversation_id" | ||||||
|     t.index ["created_at"], name: "index_reporting_events_on_created_at" |     t.index ["created_at"], name: "index_reporting_events_on_created_at" | ||||||
| @@ -810,7 +809,7 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "tagger_type" |     t.string "tagger_type" | ||||||
|     t.integer "tagger_id" |     t.integer "tagger_id" | ||||||
|     t.string "context", limit: 128 |     t.string "context", limit: 128 | ||||||
|     t.datetime "created_at" |     t.datetime "created_at", precision: nil | ||||||
|     t.index ["context"], name: "index_taggings_on_context" |     t.index ["context"], name: "index_taggings_on_context" | ||||||
|     t.index ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true |     t.index ["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 ["tag_id"], name: "index_taggings_on_tag_id" | ||||||
| @@ -832,8 +831,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|   create_table "team_members", force: :cascade do |t| |   create_table "team_members", force: :cascade do |t| | ||||||
|     t.bigint "team_id", null: false |     t.bigint "team_id", null: false | ||||||
|     t.bigint "user_id", null: false |     t.bigint "user_id", null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["team_id", "user_id"], name: "index_team_members_on_team_id_and_user_id", unique: true |     t.index ["team_id", "user_id"], name: "index_team_members_on_team_id_and_user_id", unique: true | ||||||
|     t.index ["team_id"], name: "index_team_members_on_team_id" |     t.index ["team_id"], name: "index_team_members_on_team_id" | ||||||
|     t.index ["user_id"], name: "index_team_members_on_user_id" |     t.index ["user_id"], name: "index_team_members_on_user_id" | ||||||
| @@ -844,8 +843,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.text "description" |     t.text "description" | ||||||
|     t.boolean "allow_auto_assign", default: true |     t.boolean "allow_auto_assign", default: true | ||||||
|     t.bigint "account_id", null: false |     t.bigint "account_id", null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["account_id"], name: "index_teams_on_account_id" |     t.index ["account_id"], name: "index_teams_on_account_id" | ||||||
|     t.index ["name", "account_id"], name: "index_teams_on_name_and_account_id", unique: true |     t.index ["name", "account_id"], name: "index_teams_on_name_and_account_id", unique: true | ||||||
|   end |   end | ||||||
| @@ -854,8 +853,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "name" |     t.string "name" | ||||||
|     t.string "auth_key" |     t.string "auth_key" | ||||||
|     t.integer "account_id" |     t.integer "account_id" | ||||||
|     t.datetime "created_at", null: false |     t.datetime "created_at", precision: nil, null: false | ||||||
|     t.datetime "updated_at", null: false |     t.datetime "updated_at", precision: nil, null: false | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   create_table "users", id: :serial, force: :cascade do |t| |   create_table "users", id: :serial, force: :cascade do |t| | ||||||
| @@ -863,23 +862,23 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.string "uid", default: "", null: false |     t.string "uid", default: "", null: false | ||||||
|     t.string "encrypted_password", default: "", null: false |     t.string "encrypted_password", default: "", null: false | ||||||
|     t.string "reset_password_token" |     t.string "reset_password_token" | ||||||
|     t.datetime "reset_password_sent_at" |     t.datetime "reset_password_sent_at", precision: nil | ||||||
|     t.datetime "remember_created_at" |     t.datetime "remember_created_at", precision: nil | ||||||
|     t.integer "sign_in_count", default: 0, null: false |     t.integer "sign_in_count", default: 0, null: false | ||||||
|     t.datetime "current_sign_in_at" |     t.datetime "current_sign_in_at", precision: nil | ||||||
|     t.datetime "last_sign_in_at" |     t.datetime "last_sign_in_at", precision: nil | ||||||
|     t.string "current_sign_in_ip" |     t.string "current_sign_in_ip" | ||||||
|     t.string "last_sign_in_ip" |     t.string "last_sign_in_ip" | ||||||
|     t.string "confirmation_token" |     t.string "confirmation_token" | ||||||
|     t.datetime "confirmed_at" |     t.datetime "confirmed_at", precision: nil | ||||||
|     t.datetime "confirmation_sent_at" |     t.datetime "confirmation_sent_at", precision: nil | ||||||
|     t.string "unconfirmed_email" |     t.string "unconfirmed_email" | ||||||
|     t.string "name", null: false |     t.string "name", null: false | ||||||
|     t.string "display_name" |     t.string "display_name" | ||||||
|     t.string "email" |     t.string "email" | ||||||
|     t.json "tokens" |     t.json "tokens" | ||||||
|     t.datetime "created_at", null: false |     t.datetime "created_at", precision: nil, null: false | ||||||
|     t.datetime "updated_at", null: false |     t.datetime "updated_at", precision: nil, null: false | ||||||
|     t.string "pubsub_token" |     t.string "pubsub_token" | ||||||
|     t.integer "availability", default: 0 |     t.integer "availability", default: 0 | ||||||
|     t.jsonb "ui_settings", default: {} |     t.jsonb "ui_settings", default: {} | ||||||
| @@ -896,8 +895,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.integer "account_id" |     t.integer "account_id" | ||||||
|     t.integer "inbox_id" |     t.integer "inbox_id" | ||||||
|     t.string "url" |     t.string "url" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.integer "webhook_type", default: 0 |     t.integer "webhook_type", default: 0 | ||||||
|     t.jsonb "subscriptions", default: ["conversation_status_changed", "conversation_updated", "conversation_created", "contact_created", "contact_updated", "message_created", "message_updated", "webwidget_triggered"] |     t.jsonb "subscriptions", default: ["conversation_status_changed", "conversation_updated", "conversation_created", "contact_created", "contact_updated", "message_created", "message_updated", "webwidget_triggered"] | ||||||
|     t.index ["account_id", "url"], name: "index_webhooks_on_account_id_and_url", unique: true |     t.index ["account_id", "url"], name: "index_webhooks_on_account_id_and_url", unique: true | ||||||
| @@ -912,8 +911,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do | |||||||
|     t.integer "open_minutes" |     t.integer "open_minutes" | ||||||
|     t.integer "close_hour" |     t.integer "close_hour" | ||||||
|     t.integer "close_minutes" |     t.integer "close_minutes" | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", null: false | ||||||
|     t.boolean "open_all_day", default: false |     t.boolean "open_all_day", default: false | ||||||
|     t.index ["account_id"], name: "index_working_hours_on_account_id" |     t.index ["account_id"], name: "index_working_hours_on_account_id" | ||||||
|     t.index ["inbox_id"], name: "index_working_hours_on_inbox_id" |     t.index ["inbox_id"], name: "index_working_hours_on_inbox_id" | ||||||
|   | |||||||
| @@ -16,10 +16,10 @@ KillMode=mixed | |||||||
| StandardInput=null | StandardInput=null | ||||||
| SyslogIdentifier=%p | SyslogIdentifier=%p | ||||||
|  |  | ||||||
| Environment="PATH=/home/chatwoot/.rvm/gems/ruby-3.1.3/bin:/home/chatwoot/.rvm/gems/ruby-3.1.3@global/bin:/home/chatwoot/.rvm/rubies/ruby-3.1.3/bin:/home/chatwoot/.rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/home/chatwoot/.rvm/bin:/home/chatwoot/.rvm/bin" | Environment="PATH=/home/chatwoot/.rvm/gems/ruby-3.2.2/bin:/home/chatwoot/.rvm/gems/ruby-3.2.2@global/bin:/home/chatwoot/.rvm/rubies/ruby-3.2.2/bin:/home/chatwoot/.rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/home/chatwoot/.rvm/bin:/home/chatwoot/.rvm/bin" | ||||||
| Environment="PORT=3000" | Environment="PORT=3000" | ||||||
| Environment="RAILS_ENV=production" | Environment="RAILS_ENV=production" | ||||||
| Environment="NODE_ENV=production" | Environment="NODE_ENV=production" | ||||||
| Environment="RAILS_LOG_TO_STDOUT=true" | Environment="RAILS_LOG_TO_STDOUT=true" | ||||||
| Environment="GEM_HOME=/home/chatwoot/.rvm/gems/ruby-3.1.3" | Environment="GEM_HOME=/home/chatwoot/.rvm/gems/ruby-3.2.2" | ||||||
| Environment="GEM_PATH=/home/chatwoot/.rvm/gems/ruby-3.1.3:/home/chatwoot/.rvm/gems/ruby-3.1.3@global" | Environment="GEM_PATH=/home/chatwoot/.rvm/gems/ruby-3.2.2:/home/chatwoot/.rvm/gems/ruby-3.2.2@global" | ||||||
|   | |||||||
| @@ -16,10 +16,10 @@ KillMode=mixed | |||||||
| StandardInput=null | StandardInput=null | ||||||
| SyslogIdentifier=%p | SyslogIdentifier=%p | ||||||
|  |  | ||||||
| Environment="PATH=/home/chatwoot/.rvm/gems/ruby-3.1.3/bin:/home/chatwoot/.rvm/gems/ruby-3.1.3@global/bin:/home/chatwoot/.rvm/rubies/ruby-3.1.3/bin:/home/chatwoot/.rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/home/chatwoot/.rvm/bin:/home/chatwoot/.rvm/bin" | Environment="PATH=/home/chatwoot/.rvm/gems/ruby-3.2.2/bin:/home/chatwoot/.rvm/gems/ruby-3.2.2@global/bin:/home/chatwoot/.rvm/rubies/ruby-3.2.2/bin:/home/chatwoot/.rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/home/chatwoot/.rvm/bin:/home/chatwoot/.rvm/bin" | ||||||
| Environment="PORT=3000" | Environment="PORT=3000" | ||||||
| Environment="RAILS_ENV=production" | Environment="RAILS_ENV=production" | ||||||
| Environment="NODE_ENV=production" | Environment="NODE_ENV=production" | ||||||
| Environment="RAILS_LOG_TO_STDOUT=true" | Environment="RAILS_LOG_TO_STDOUT=true" | ||||||
| Environment="GEM_HOME=/home/chatwoot/.rvm/gems/ruby-3.1.3" | Environment="GEM_HOME=/home/chatwoot/.rvm/gems/ruby-3.2.2" | ||||||
| Environment="GEM_PATH=/home/chatwoot/.rvm/gems/ruby-3.1.3:/home/chatwoot/.rvm/gems/ruby-3.1.3@global" | Environment="GEM_PATH=/home/chatwoot/.rvm/gems/ruby-3.2.2:/home/chatwoot/.rvm/gems/ruby-3.2.2@global" | ||||||
|   | |||||||
| @@ -328,8 +328,8 @@ function setup_chatwoot() { | |||||||
|   sudo -i -u chatwoot << EOF |   sudo -i -u chatwoot << EOF | ||||||
|   rvm --version |   rvm --version | ||||||
|   rvm autolibs disable |   rvm autolibs disable | ||||||
|   rvm install "ruby-3.1.3" |   rvm install "ruby-3.2.2" | ||||||
|   rvm use 3.1.3 --default |   rvm use 3.2.2 --default | ||||||
|  |  | ||||||
|   git clone https://github.com/chatwoot/chatwoot.git |   git clone https://github.com/chatwoot/chatwoot.git | ||||||
|   cd chatwoot |   cd chatwoot | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| # pre-build stage | # pre-build stage | ||||||
| FROM ruby:3.1.3-alpine3.16 AS pre-builder | FROM ruby:3.2.2-alpine3.16 AS pre-builder | ||||||
|  |  | ||||||
| # ARG default to production settings | # ARG default to production settings | ||||||
| # For development docker-compose file overrides ARGS | # For development docker-compose file overrides ARGS | ||||||
| @@ -64,13 +64,13 @@ RUN if [ "$RAILS_ENV" = "production" ]; then \ | |||||||
| RUN git rev-parse HEAD > /app/.git_sha | RUN git rev-parse HEAD > /app/.git_sha | ||||||
|  |  | ||||||
| # Remove unnecessary files | # Remove unnecessary files | ||||||
| RUN rm -rf /gems/ruby/3.1.0/cache/*.gem \ | RUN rm -rf /gems/ruby/3.2.0/cache/*.gem \ | ||||||
|   && find /gems/ruby/3.1.0/gems/ \( -name "*.c" -o -name "*.o" \) -delete \ |   && find /gems/ruby/3.2.0/gems/ \( -name "*.c" -o -name "*.o" \) -delete \ | ||||||
|   && rm -rf .git \ |   && rm -rf .git \ | ||||||
|   && rm .gitignore |   && rm .gitignore | ||||||
|  |  | ||||||
| # final build stage | # final build stage | ||||||
| FROM ruby:3.1.3-alpine3.16 | FROM ruby:3.2.2-alpine3.16 | ||||||
|  |  | ||||||
|  |  | ||||||
| ARG BUNDLE_WITHOUT="development:test" | ARG BUNDLE_WITHOUT="development:test" | ||||||
|   | |||||||
| @@ -59,7 +59,7 @@ class ConfigLoader | |||||||
|   end |   end | ||||||
|  |  | ||||||
|   def save_as_new_config(latest) |   def save_as_new_config(latest) | ||||||
|     config = InstallationConfig.find_or_create_by(name: latest[:name]) |     config = InstallationConfig.find_or_initialize_by(name: latest[:name]) | ||||||
|     config.value = latest[:value] |     config.value = latest[:value] | ||||||
|     config.locked = latest[:locked] |     config.locked = latest[:locked] | ||||||
|     config.save! |     config.save! | ||||||
|   | |||||||
| @@ -1,3 +1,5 @@ | |||||||
|  | require 'google/cloud/dialogflow/v2' | ||||||
|  |  | ||||||
| class Integrations::Dialogflow::ProcessorService < Integrations::BotProcessorService | class Integrations::Dialogflow::ProcessorService < Integrations::BotProcessorService | ||||||
|   pattr_initialize [:event_name!, :hook!, :event_data!] |   pattr_initialize [:event_name!, :hook!, :event_data!] | ||||||
|  |  | ||||||
| @@ -17,11 +19,15 @@ class Integrations::Dialogflow::ProcessorService < Integrations::BotProcessorSer | |||||||
|       Rails.logger.warn "Account: #{hook.try(:account_id)} Hook: #{hook.id} credentials are not present." && return |       Rails.logger.warn "Account: #{hook.try(:account_id)} Hook: #{hook.id} credentials are not present." && return | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     Google::Cloud::Dialogflow.configure { |config| config.credentials = hook.settings['credentials'] } |     ::Google::Cloud::Dialogflow::V2::Sessions::Client.configure do |config| | ||||||
|     session_client = Google::Cloud::Dialogflow.sessions |       config.timeout = 10.0 | ||||||
|     session = session_client.session_path project: hook.settings['project_id'], session: session_id |       config.credentials = hook.settings['credentials'] | ||||||
|  |     end | ||||||
|  |  | ||||||
|  |     client = ::Google::Cloud::Dialogflow::V2::Sessions::Client.new | ||||||
|  |     session = "projects/#{hook.settings['project_id']}/agent/sessions/#{session_id}" | ||||||
|     query_input = { text: { text: message, language_code: 'en-US' } } |     query_input = { text: { text: message, language_code: 'en-US' } } | ||||||
|     session_client.detect_intent session: session, query_input: query_input |     client.detect_intent session: session, query_input: query_input | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   def process_response(message, response) |   def process_response(message, response) | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | require 'google/cloud/translate/v3' | ||||||
| class Integrations::GoogleTranslate::DetectLanguageService | class Integrations::GoogleTranslate::DetectLanguageService | ||||||
|   pattr_initialize [:hook!, :message!] |   pattr_initialize [:hook!, :message!] | ||||||
|  |  | ||||||
| @@ -33,7 +34,7 @@ class Integrations::GoogleTranslate::DetectLanguageService | |||||||
|   end |   end | ||||||
|  |  | ||||||
|   def client |   def client | ||||||
|     @client ||= Google::Cloud::Translate.translation_service do |config| |     @client ||= ::Google::Cloud::Translate::V3::TranslationService::Client.new do |config| | ||||||
|       config.credentials = hook.settings['credentials'] |       config.credentials = hook.settings['credentials'] | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | require 'google/cloud/translate/v3' | ||||||
| class Integrations::GoogleTranslate::ProcessorService | class Integrations::GoogleTranslate::ProcessorService | ||||||
|   pattr_initialize [:message!, :target_language!] |   pattr_initialize [:message!, :target_language!] | ||||||
|  |  | ||||||
| @@ -23,7 +24,7 @@ class Integrations::GoogleTranslate::ProcessorService | |||||||
|   end |   end | ||||||
|  |  | ||||||
|   def client |   def client | ||||||
|     @client ||= Google::Cloud::Translate.translation_service do |config| |     @client ||= ::Google::Cloud::Translate::V3::TranslationService::Client.new do |config| | ||||||
|       config.credentials = hook.settings['credentials'] |       config.credentials = hook.settings['credentials'] | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ module Redis::Config | |||||||
|         password: ENV.fetch('REDIS_PASSWORD', nil).presence, |         password: ENV.fetch('REDIS_PASSWORD', nil).presence, | ||||||
|         ssl_params: { verify_mode: Chatwoot.redis_ssl_verify_mode }, |         ssl_params: { verify_mode: Chatwoot.redis_ssl_verify_mode }, | ||||||
|         reconnect_attempts: 2, |         reconnect_attempts: 2, | ||||||
|         network_timeout: 5 |         timeout: 1 | ||||||
|       } |       } | ||||||
|     end |     end | ||||||
|  |  | ||||||
|   | |||||||
| @@ -16,8 +16,7 @@ db_namespace = namespace :db do | |||||||
|   desc 'Runs setup if database does not exist, or runs migrations if it does' |   desc 'Runs setup if database does not exist, or runs migrations if it does' | ||||||
|   task chatwoot_prepare: :load_config do |   task chatwoot_prepare: :load_config do | ||||||
|     ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).each do |db_config| |     ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).each do |db_config| | ||||||
|       ActiveRecord::Base.establish_connection(db_config.config) |       ActiveRecord::Base.establish_connection(db_config.configuration_hash) | ||||||
|       # handling case where database was created by the provider, with out running db:setup |  | ||||||
|       unless ActiveRecord::Base.connection.table_exists? 'ar_internal_metadata' |       unless ActiveRecord::Base.connection.table_exists? 'ar_internal_metadata' | ||||||
|         db_namespace['load_config'].invoke if ActiveRecord::Base.schema_format == :ruby |         db_namespace['load_config'].invoke if ActiveRecord::Base.schema_format == :ruby | ||||||
|         ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:ruby, ENV.fetch('SCHEMA', nil)) |         ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:ruby, ENV.fetch('SCHEMA', nil)) | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								lib/tasks/yarn.rake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								lib/tasks/yarn.rake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | # ref: https://github.com/rails/rails/issues/43906#issuecomment-1094380699 | ||||||
|  | # https://github.com/rails/rails/issues/43906#issuecomment-1099992310 | ||||||
|  | task before_assets_precompile: :environment do | ||||||
|  |   # run a command which starts your packaging | ||||||
|  |   system('yarn') | ||||||
|  | end | ||||||
|  |  | ||||||
|  | # every time you execute 'rake assets:precompile' | ||||||
|  | # run 'before_assets_precompile' first | ||||||
|  | Rake::Task['assets:precompile'].enhance ['before_assets_precompile'] | ||||||
| @@ -25,7 +25,7 @@ | |||||||
|     "@june-so/analytics-next": "^1.36.5", |     "@june-so/analytics-next": "^1.36.5", | ||||||
|     "@rails/actioncable": "6.1.3", |     "@rails/actioncable": "6.1.3", | ||||||
|     "@rails/ujs": "^7.0.3-1", |     "@rails/ujs": "^7.0.3-1", | ||||||
|     "@rails/webpacker": "5.3.0", |     "@rails/webpacker": "5.4.4", | ||||||
|     "@sentry/tracing": "^6.19.7", |     "@sentry/tracing": "^6.19.7", | ||||||
|     "@sentry/vue": "^6.19.7", |     "@sentry/vue": "^6.19.7", | ||||||
|     "@tailwindcss/typography": "0.2.0", |     "@tailwindcss/typography": "0.2.0", | ||||||
| @@ -78,7 +78,9 @@ | |||||||
|     "vuelidate": "0.7.7", |     "vuelidate": "0.7.7", | ||||||
|     "vuex": "~2.1.1", |     "vuex": "~2.1.1", | ||||||
|     "vuex-router-sync": "~4.1.2", |     "vuex-router-sync": "~4.1.2", | ||||||
|     "wavesurfer.js": "^6.0.4" |     "wavesurfer.js": "^6.0.4", | ||||||
|  |     "webpack": "^4.46.0", | ||||||
|  |     "webpack-cli": "^3.3.12" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@babel/core": "7.13.16", |     "@babel/core": "7.13.16", | ||||||
| @@ -119,7 +121,7 @@ | |||||||
|     "prettier": "^1.16.4", |     "prettier": "^1.16.4", | ||||||
|     "rimraf": "^3.0.0", |     "rimraf": "^3.0.0", | ||||||
|     "vue-jest": "4", |     "vue-jest": "4", | ||||||
|     "webpack-dev-server": "3.11.2" |     "webpack-dev-server": "^3" | ||||||
|   }, |   }, | ||||||
|   "engines": { |   "engines": { | ||||||
|     "node": ">=10.x", |     "node": ">=10.x", | ||||||
|   | |||||||
| @@ -231,8 +231,8 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do | |||||||
|         json_response = JSON.parse(response.body) |         json_response = JSON.parse(response.body) | ||||||
|  |  | ||||||
|         expect(json_response['payload']['associated_articles'].length).to eq(2) |         expect(json_response['payload']['associated_articles'].length).to eq(2) | ||||||
|         expect(json_response['payload']['associated_articles'][0]['id']).to eq(child_article_1.id) |         associated_articles_ids = json_response['payload']['associated_articles'].map { |article| article['id'] } | ||||||
|         expect(json_response['payload']['associated_articles'][1]['id']).to eq(child_article_2.id) |         expect(associated_articles_ids).to match_array([child_article_1.id, child_article_2.id]) | ||||||
|         expect(json_response['payload']['id']).to eq(root_article.id) |         expect(json_response['payload']['id']).to eq(root_article.id) | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
|   | |||||||
| @@ -150,7 +150,7 @@ describe Integrations::Dialogflow::ProcessorService do | |||||||
|   end |   end | ||||||
|  |  | ||||||
|   describe '#get_response' do |   describe '#get_response' do | ||||||
|     let(:google_dialogflow) { Google::Cloud::Dialogflow } |     let(:google_dialogflow) { ::Google::Cloud::Dialogflow::V2::Sessions::Client } | ||||||
|     let(:session_client) { double } |     let(:session_client) { double } | ||||||
|     let(:session) { double } |     let(:session) { double } | ||||||
|     let(:query_input) { { text: { text: message, language_code: 'en-US' } } } |     let(:query_input) { { text: { text: message, language_code: 'en-US' } } } | ||||||
| @@ -158,8 +158,7 @@ describe Integrations::Dialogflow::ProcessorService do | |||||||
|  |  | ||||||
|     before do |     before do | ||||||
|       hook.update(settings: { 'project_id' => 'test', 'credentials' => 'creds' }) |       hook.update(settings: { 'project_id' => 'test', 'credentials' => 'creds' }) | ||||||
|       allow(google_dialogflow).to receive(:sessions).and_return(session_client) |       allow(google_dialogflow).to receive(:new).and_return(session_client) | ||||||
|       allow(session_client).to receive(:session_path).and_return(session) |  | ||||||
|       allow(session_client).to receive(:detect_intent).and_return({ session: session, query_input: query_input }) |       allow(session_client).to receive(:detect_intent).and_return({ session: session, query_input: query_input }) | ||||||
|     end |     end | ||||||
|  |  | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ describe Integrations::GoogleTranslate::DetectLanguageService do | |||||||
|   let(:translate_client) { double } |   let(:translate_client) { double } | ||||||
|  |  | ||||||
|   before do |   before do | ||||||
|     allow(::Google::Cloud::Translate).to receive(:translation_service).and_return(translate_client) |     allow(::Google::Cloud::Translate::V3::TranslationService::Client).to receive(:new).and_return(translate_client) | ||||||
|     allow(translate_client).to receive(:detect_language).and_return(::Google::Cloud::Translate::V3::DetectLanguageResponse |     allow(translate_client).to receive(:detect_language).and_return(::Google::Cloud::Translate::V3::DetectLanguageResponse | ||||||
|       .new({ languages: [{ language_code: 'es', confidence: 0.71875 }] })) |       .new({ languages: [{ language_code: 'es', confidence: 0.71875 }] })) | ||||||
|   end |   end | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ describe ::Redis::Config do | |||||||
|  |  | ||||||
|     it 'checks for app redis config' do |     it 'checks for app redis config' do | ||||||
|       app_config = described_class.app |       app_config = described_class.app | ||||||
|       expect(app_config.keys).to match_array([:url, :password, :network_timeout, :reconnect_attempts, :ssl_params]) |       expect(app_config.keys).to match_array([:url, :password, :timeout, :reconnect_attempts, :ssl_params]) | ||||||
|       expect(app_config[:url]).to eq(redis_url) |       expect(app_config[:url]).to eq(redis_url) | ||||||
|       expect(app_config[:password]).to eq(redis_pasword) |       expect(app_config[:password]).to eq(redis_pasword) | ||||||
|     end |     end | ||||||
| @@ -43,7 +43,7 @@ describe ::Redis::Config do | |||||||
|     end |     end | ||||||
|  |  | ||||||
|     it 'checks for app redis config' do |     it 'checks for app redis config' do | ||||||
|       expect(described_class.app.keys).to match_array([:url, :password, :sentinels, :network_timeout, :reconnect_attempts, :ssl_params]) |       expect(described_class.app.keys).to match_array([:url, :password, :sentinels, :timeout, :reconnect_attempts, :ssl_params]) | ||||||
|       expect(described_class.app[:url]).to eq("redis://#{redis_master_name}") |       expect(described_class.app[:url]).to eq("redis://#{redis_master_name}") | ||||||
|       expect(described_class.app[:sentinels]).to match_array(expected_sentinels) |       expect(described_class.app[:sentinels]).to match_array(expected_sentinels) | ||||||
|     end |     end | ||||||
| @@ -60,7 +60,7 @@ describe ::Redis::Config do | |||||||
|       end |       end | ||||||
|  |  | ||||||
|       it 'checks for app redis config and sentinel passwords will be empty' do |       it 'checks for app redis config and sentinel passwords will be empty' do | ||||||
|         expect(described_class.app.keys).to match_array([:url, :password, :sentinels, :network_timeout, :reconnect_attempts, :ssl_params]) |         expect(described_class.app.keys).to match_array([:url, :password, :sentinels, :timeout, :reconnect_attempts, :ssl_params]) | ||||||
|         expect(described_class.app[:url]).to eq("redis://#{redis_master_name}") |         expect(described_class.app[:url]).to eq("redis://#{redis_master_name}") | ||||||
|         expect(described_class.app[:sentinels]).to match_array(expected_sentinels.map { |s| s.except(:password) }) |         expect(described_class.app[:sentinels]).to match_array(expected_sentinels.map { |s| s.except(:password) }) | ||||||
|       end |       end | ||||||
| @@ -78,7 +78,7 @@ describe ::Redis::Config do | |||||||
|       end |       end | ||||||
|  |  | ||||||
|       it 'checks for app redis config and redis password is replaced in sentinel config' do |       it 'checks for app redis config and redis password is replaced in sentinel config' do | ||||||
|         expect(described_class.app.keys).to match_array([:url, :password, :sentinels, :network_timeout, :reconnect_attempts, :ssl_params]) |         expect(described_class.app.keys).to match_array([:url, :password, :sentinels, :timeout, :reconnect_attempts, :ssl_params]) | ||||||
|         expect(described_class.app[:url]).to eq("redis://#{redis_master_name}") |         expect(described_class.app[:url]).to eq("redis://#{redis_master_name}") | ||||||
|         expect(described_class.app[:sentinels]).to match_array(expected_sentinels.map { |s| s.merge(password: redis_sentinel_password) }) |         expect(described_class.app[:sentinels]).to match_array(expected_sentinels.map { |s| s.merge(password: redis_sentinel_password) }) | ||||||
|       end |       end | ||||||
|   | |||||||
| @@ -63,10 +63,10 @@ describe ActionCableListener do | |||||||
|         a_collection_containing_exactly( |         a_collection_containing_exactly( | ||||||
|           admin.pubsub_token, conversation.contact_inbox.pubsub_token |           admin.pubsub_token, conversation.contact_inbox.pubsub_token | ||||||
|         ), |         ), | ||||||
|         'conversation.typing_on', conversation: conversation.push_event_data, |         'conversation.typing_on', { conversation: conversation.push_event_data, | ||||||
|                                   user: agent.push_event_data, |                                     user: agent.push_event_data, | ||||||
|                                   account_id: account.id, |                                     account_id: account.id, | ||||||
|                                   is_private: false |                                     is_private: false } | ||||||
|       ) |       ) | ||||||
|       listener.conversation_typing_on(event) |       listener.conversation_typing_on(event) | ||||||
|     end |     end | ||||||
| @@ -83,10 +83,10 @@ describe ActionCableListener do | |||||||
|         a_collection_containing_exactly( |         a_collection_containing_exactly( | ||||||
|           admin.pubsub_token, agent.pubsub_token |           admin.pubsub_token, agent.pubsub_token | ||||||
|         ), |         ), | ||||||
|         'conversation.typing_on', conversation: conversation.push_event_data, |         'conversation.typing_on', { conversation: conversation.push_event_data, | ||||||
|                                   user: conversation.contact.push_event_data, |                                     user: conversation.contact.push_event_data, | ||||||
|                                   account_id: account.id, |                                     account_id: account.id, | ||||||
|                                   is_private: false |                                     is_private: false } | ||||||
|       ) |       ) | ||||||
|       listener.conversation_typing_on(event) |       listener.conversation_typing_on(event) | ||||||
|     end |     end | ||||||
| @@ -103,10 +103,10 @@ describe ActionCableListener do | |||||||
|         a_collection_containing_exactly( |         a_collection_containing_exactly( | ||||||
|           admin.pubsub_token, conversation.contact_inbox.pubsub_token |           admin.pubsub_token, conversation.contact_inbox.pubsub_token | ||||||
|         ), |         ), | ||||||
|         'conversation.typing_off', conversation: conversation.push_event_data, |         'conversation.typing_off', { conversation: conversation.push_event_data, | ||||||
|                                    user: agent.push_event_data, |                                      user: agent.push_event_data, | ||||||
|                                    account_id: account.id, |                                      account_id: account.id, | ||||||
|                                    is_private: false |                                      is_private: false } | ||||||
|       ) |       ) | ||||||
|       listener.conversation_typing_off(event) |       listener.conversation_typing_off(event) | ||||||
|     end |     end | ||||||
|   | |||||||
| @@ -245,6 +245,7 @@ RSpec.describe SupportMailbox, type: :mailbox do | |||||||
|         expect(conversation.messages.last.content_attributes['email']['html_content']['reply']).to include( |         expect(conversation.messages.last.content_attributes['email']['html_content']['reply']).to include( | ||||||
|           <<~BODY.chomp |           <<~BODY.chomp | ||||||
|             Hi, |             Hi, | ||||||
|  |  | ||||||
|             We are providing you platform from here you can sell paid posts on your website. |             We are providing you platform from here you can sell paid posts on your website. | ||||||
|  |  | ||||||
|             Chatwoot | CS team | [C](https://d33wubrfki0l68.cloudfront.net/973467c532160fd8b940300a43fa85fa2d060307/dc9a0/static/brand-73f58cdefae282ae74cebfa74c1d7003.svg) |             Chatwoot | CS team | [C](https://d33wubrfki0l68.cloudfront.net/973467c532160fd8b940300a43fa85fa2d060307/dc9a0/static/brand-73f58cdefae282ae74cebfa74c1d7003.svg) | ||||||
|   | |||||||
| @@ -41,7 +41,7 @@ end | |||||||
| RSpec.configure do |config| | RSpec.configure do |config| | ||||||
|   config.include FactoryBot::Syntax::Methods |   config.include FactoryBot::Syntax::Methods | ||||||
|   # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures |   # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures | ||||||
|   config.fixture_path = "#{::Rails.root}/spec/fixtures" |   config.fixture_path = Rails.root.join('spec/fixtures') | ||||||
|  |  | ||||||
|   # If you're not using ActiveRecord, or you'd prefer not to run each of your |   # If you're not using ActiveRecord, or you'd prefer not to run each of your | ||||||
|   # examples within a transaction, remove the following line or assign false |   # examples within a transaction, remove the following line or assign false | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Sojan Jose
					Sojan Jose