diff --git a/.env.example b/.env.example
index 177cb7fc8..55b998f19 100644
--- a/.env.example
+++ b/.env.example
@@ -180,8 +180,6 @@ ANDROID_SHA256_CERT_FINGERPRINT=AC:73:8E:DE:EB:56:EA:CC:10:87:02:A7:65:37:7B:38:
## Sentry
# SENTRY_DSN=
-## LogRocket
-# LOG_ROCKET_PROJECT_ID=xxxxx/some-project
# MICROSOFT CLARITY
# MS_CLARITY_TOKEN=xxxxxxxxx
@@ -251,9 +249,6 @@ AZURE_APP_SECRET=
## OpenAI key
# OPENAI_API_KEY=
-# Sentiment analysis model file path
-SENTIMENT_FILE_PATH=
-
# Housekeeping/Performance related configurations
# Set to true if you want to remove stale contact inboxes
# contact_inboxes with no conversation older than 90 days will be removed
diff --git a/Gemfile b/Gemfile
index 0dac6e95f..f39655a5c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -113,10 +113,10 @@ gem 'newrelic-sidekiq-metrics', '>= 1.6.2', require: false
gem 'scout_apm', require: false
gem 'sentry-rails', '>= 5.14.0', require: false
gem 'sentry-ruby', require: false
-gem 'sentry-sidekiq', '>= 5.14.0', require: false
+gem 'sentry-sidekiq', '>= 5.15.0', require: false
##-- background job processing --##
-gem 'sidekiq', '>= 7.2.1'
+gem 'sidekiq', '>= 7.2.4'
# We want cron jobs
gem 'sidekiq-cron', '>= 1.12.0'
@@ -175,9 +175,6 @@ gem 'pgvector'
# Convert Website HTML to Markdown
gem 'reverse_markdown'
-# Sentiment analysis
-gem 'informers'
-
### Gems required only in specific deployment environments ###
##############################################################
diff --git a/Gemfile.lock b/Gemfile.lock
index 55021a04b..b5ad38993 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -150,8 +150,8 @@ GEM
statsd-ruby (~> 1.1)
base64 (0.1.1)
bcrypt (3.1.20)
+ bigdecimal (3.1.7)
bindex (0.8.1)
- blingfire (0.1.8)
bootsnap (1.16.0)
msgpack (~> 1.2)
brakeman (5.4.1)
@@ -316,15 +316,15 @@ GEM
google-cloud-translate-v3 (0.6.0)
gapic-common (>= 0.17.1, < 2.a)
google-cloud-errors (~> 1.0)
- google-protobuf (3.25.2)
- google-protobuf (3.25.2-arm64-darwin)
- google-protobuf (3.25.2-x86_64-darwin)
- google-protobuf (3.25.2-x86_64-linux)
+ google-protobuf (3.25.3)
+ google-protobuf (3.25.3-arm64-darwin)
+ google-protobuf (3.25.3-x86_64-darwin)
+ google-protobuf (3.25.3-x86_64-linux)
googleapis-common-protos (1.4.0)
google-protobuf (~> 3.14)
googleapis-common-protos-types (~> 1.2)
grpc (~> 1.27)
- googleapis-common-protos-types (1.11.0)
+ googleapis-common-protos-types (1.14.0)
google-protobuf (~> 3.18)
googleauth (1.5.2)
faraday (>= 0.17.3, < 3.a)
@@ -335,14 +335,17 @@ GEM
signet (>= 0.16, < 2.a)
groupdate (6.2.1)
activesupport (>= 5.2)
- grpc (1.54.3)
- google-protobuf (~> 3.21)
+ grpc (1.62.0)
+ google-protobuf (~> 3.25)
googleapis-common-protos-types (~> 1.0)
- grpc (1.54.3-x86_64-darwin)
- google-protobuf (~> 3.21)
+ grpc (1.62.0-arm64-darwin)
+ google-protobuf (~> 3.25)
googleapis-common-protos-types (~> 1.0)
- grpc (1.54.3-x86_64-linux)
- google-protobuf (~> 3.21)
+ grpc (1.62.0-x86_64-darwin)
+ google-protobuf (~> 3.25)
+ googleapis-common-protos-types (~> 1.0)
+ grpc (1.62.0-x86_64-linux)
+ google-protobuf (~> 3.25)
googleapis-common-protos-types (~> 1.0)
haikunator (1.1.1)
hairtrigger (1.0.0)
@@ -371,10 +374,6 @@ GEM
image_processing (1.12.2)
mini_magick (>= 4.9.5, < 5)
ruby-vips (>= 2.0.17, < 3)
- informers (0.2.0)
- blingfire (>= 0.1.7)
- numo-narray
- onnxruntime (>= 0.5.1)
io-console (0.6.0)
irb (1.7.2)
reline (>= 0.3.6)
@@ -500,7 +499,6 @@ GEM
racc (~> 1.4)
nokogiri (1.16.4-x86_64-linux)
racc (~> 1.4)
- numo-narray (0.9.2.1)
oauth (1.1.0)
oauth-tty (~> 1.0, >= 1.0.1)
snaky_hash (~> 2.0)
@@ -529,14 +527,6 @@ GEM
omniauth-rails_csrf_protection (1.0.1)
actionpack (>= 4.2)
omniauth (~> 2.0)
- onnxruntime (0.7.6)
- ffi
- onnxruntime (0.7.6-arm64-darwin)
- ffi
- onnxruntime (0.7.6-x86_64-darwin)
- ffi
- onnxruntime (0.7.6-x86_64-linux)
- ffi
openssl (3.1.0)
orm_adapter (0.5.0)
os (1.1.4)
@@ -614,7 +604,7 @@ GEM
ffi (~> 1.0)
redis (5.0.6)
redis-client (>= 0.9.0)
- redis-client (0.19.1)
+ redis-client (0.22.1)
connection_pool
redis-namespace (1.10.0)
redis (>= 4)
@@ -713,18 +703,19 @@ GEM
activesupport (>= 4)
selectize-rails (0.12.6)
semantic_range (3.0.0)
- sentry-rails (5.14.0)
+ sentry-rails (5.17.3)
railties (>= 5.0)
- sentry-ruby (~> 5.14.0)
- sentry-ruby (5.14.0)
+ sentry-ruby (~> 5.17.3)
+ sentry-ruby (5.17.3)
+ bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
- sentry-sidekiq (5.14.0)
- sentry-ruby (~> 5.14.0)
+ sentry-sidekiq (5.17.3)
+ sentry-ruby (~> 5.17.3)
sidekiq (>= 3.0)
sexp_processor (4.17.0)
shoulda-matchers (5.3.0)
activesupport (>= 5.2.0)
- sidekiq (7.2.1)
+ sidekiq (7.2.4)
concurrent-ruby (< 2)
connection_pool (>= 2.3.0)
rack (>= 2.2.4)
@@ -892,7 +883,6 @@ DEPENDENCIES
hashie
html2text!
image_processing
- informers
jbuilder
json_refs
json_schemer
@@ -943,9 +933,9 @@ DEPENDENCIES
seed_dump
sentry-rails (>= 5.14.0)
sentry-ruby
- sentry-sidekiq (>= 5.14.0)
+ sentry-sidekiq (>= 5.15.0)
shoulda-matchers
- sidekiq (>= 7.2.1)
+ sidekiq (>= 7.2.4)
sidekiq-cron (>= 1.12.0)
simplecov (= 0.17.1)
slack-ruby-client (~> 2.2.0)
diff --git a/app/controllers/public/api/v1/portals_controller.rb b/app/controllers/public/api/v1/portals_controller.rb
index fe51ed161..e8fb867cb 100644
--- a/app/controllers/public/api/v1/portals_controller.rb
+++ b/app/controllers/public/api/v1/portals_controller.rb
@@ -6,6 +6,12 @@ class Public::Api::V1::PortalsController < Public::Api::V1::Portals::BaseControl
def show; end
+ def sitemap
+ @help_center_url = @portal.custom_domain || ChatwootApp.help_center_root
+ # if help_center_url does not contain a protocol, prepend it with https
+ @help_center_url = "https://#{@help_center_url}" unless @help_center_url.include?('://')
+ end
+
private
def portal
diff --git a/app/javascript/dashboard/assets/scss/_woot.scss b/app/javascript/dashboard/assets/scss/_woot.scss
index 06dabb7cb..4b33d5b10 100644
--- a/app/javascript/dashboard/assets/scss/_woot.scss
+++ b/app/javascript/dashboard/assets/scss/_woot.scss
@@ -42,19 +42,20 @@
}
@layer base {
+ // scss-lint:disable PropertySortOrder
:root {
- --color-amber-100: 255 243 208;
- --color-amber-200: 255 236 183;
--color-amber-25: 254 253 251;
- --color-amber-300: 255 224 161;
- --color-amber-400: 245 208 140;
--color-amber-50: 255 249 237;
- --color-amber-500: 228 187 120;
+ --color-amber-75: 255 243 208;
+ --color-amber-100: 255 236 183;
+ --color-amber-200: 255 224 161;
+ --color-amber-300: 245 208 140;
+ --color-amber-400: 228 187 120;
+ --color-amber-500: 214 163 92;
--color-amber-600: 214 163 92;
- --color-amber-700: 214 163 92;
- --color-amber-800: 255 186 26;
- --color-amber-900: 145 89 48;
- --color-amber-950: 79 52 34;
+ --color-amber-700: 255 186 26;
+ --color-amber-800: 145 89 48;
+ --color-amber-900: 79 52 34;
--color-ash-100: 235 235 239;
--color-ash-200: 228 228 233;
@@ -69,18 +70,18 @@
--color-ash-800: 96 100 108;
--color-ash-900: 28 32 36;
- --color-primary-100: 222 234 255;
- --color-primary-200: 206 223 255;
- --color-primary-25: 252 253 254;
- --color-primary-300: 186 209 255;
- --color-primary-400: 163 190 255;
- --color-primary-50: 246 249 255;
- --color-primary-500: 131 164 250;
- --color-primary-600: 69 110 255;
- --color-primary-700: 57 95 241;
- --color-primary-75: 236 242 255;
- --color-primary-800: 53 88 217;
- --color-primary-900: 27 44 99;
+ --color-primary-25: 251 253 255;
+ --color-primary-50: 245 249 255;
+ --color-primary-75: 233 243 255;
+ --color-primary-100: 218 236 255;
+ --color-primary-200: 201 226 255;
+ --color-primary-300: 181 213 255;
+ --color-primary-400: 155 195 252;
+ --color-primary-500: 117 171 247;
+ --color-primary-600: 39 129 246;
+ --color-primary-700: 16 115 233;
+ --color-primary-800: 8 109 224;
+ --color-primary-900: 11 50 101;
--color-ruby-100: 255 220 225;
--color-ruby-200: 255 206 214;
@@ -107,21 +108,125 @@
--color-teal-75: 236 249 255;
--color-teal-800: 0 133 115;
--color-teal-900: 13 61 56;
+
+ --color-green-25: 251 254 252;
+ --color-green-50: 244 251 246;
+ --color-green-75: 230 246 235;
+ --color-green-100: 214 241 223;
+ --color-green-200: 196 232 209;
+ --color-green-300: 173 221 192;
+ --color-green-400: 142 206 170;
+ --color-green-500: 91 185 139;
+ --color-green-600: 48 164 108;
+ --color-green-700: 43 154 102;
+ --color-green-800: 33 131 88;
+ --color-green-900: 25 59 45;
+
+ --color-mint-25: 249 254 253;
+ --color-mint-50: 242 251 249;
+ --color-mint-75: 221 249 242;
+ --color-mint-100: 200 244 233;
+ --color-mint-200: 179 236 222;
+ --color-mint-300: 156 224 208;
+ --color-mint-400: 126 207 189;
+ --color-mint-500: 76 187 165;
+ --color-mint-600: 134 234 212;
+ --color-mint-700: 125 224 203;
+ --color-mint-800: 2 120 100;
+ --color-mint-900: 22 67 60;
+
+ --color-sky-25: 249 254 255;
+ --color-sky-50: 241 250 253;
+ --color-sky-75: 225 246 253;
+ --color-sky-100: 209 240 250;
+ --color-sky-200: 190 231 245;
+ --color-sky-300: 169 218 237;
+ --color-sky-400: 141 202 227;
+ --color-sky-500: 96 179 215;
+ --color-sky-600: 124 226 254;
+ --color-sky-700: 116 218 248;
+ --color-sky-800: 0 116 158;
+ --color-sky-900: 29 62 86;
+
+ --color-indigo-25: 253 253 254;
+ --color-indigo-50: 247 249 255;
+ --color-indigo-75: 237 242 254;
+ --color-indigo-100: 225 233 255;
+ --color-indigo-200: 210 222 255;
+ --color-indigo-300: 193 208 255;
+ --color-indigo-400: 171 189 249;
+ --color-indigo-500: 141 164 239;
+ --color-indigo-600: 62 99 221;
+ --color-indigo-700: 51 88 212;
+ --color-indigo-800: 58 91 199;
+ --color-indigo-900: 31 45 92;
+
+ --color-iris-25: 253 253 255;
+ --color-iris-50: 248 248 255;
+ --color-iris-75: 240 241 254;
+ --color-iris-100: 230 231 255;
+ --color-iris-200: 218 220 255;
+ --color-iris-300: 203 205 255;
+ --color-iris-400: 184 186 248;
+ --color-iris-500: 155 158 240;
+ --color-iris-600: 91 91 214;
+ --color-iris-700: 81 81 205;
+ --color-iris-800: 87 83 198;
+ --color-iris-900: 39 41 98;
+
+ --color-violet-25: 253 252 254;
+ --color-violet-50: 250 248 255;
+ --color-violet-75: 244 240 254;
+ --color-violet-100: 235 228 255;
+ --color-violet-200: 225 217 255;
+ --color-violet-300: 212 202 254;
+ --color-violet-400: 194 181 245;
+ --color-violet-500: 170 153 236;
+ --color-violet-600: 110 86 207;
+ --color-violet-700: 101 77 196;
+ --color-violet-800: 101 80 185;
+ --color-violet-900: 47 38 95;
+
+ --color-pink-25: 255 252 254;
+ --color-pink-50: 254 247 251;
+ --color-pink-75: 254 233 245;
+ --color-pink-100: 251 220 239;
+ --color-pink-200: 246 206 231;
+ --color-pink-300: 239 191 221;
+ --color-pink-400: 231 172 208;
+ --color-pink-500: 221 147 194;
+ --color-pink-600: 214 64 159;
+ --color-pink-700: 207 56 151;
+ --color-pink-800: 194 41 138;
+ --color-pink-900: 101 18 73;
+
+ --color-orange-25: 254 252 251;
+ --color-orange-50: 255 247 237;
+ --color-orange-75: 255 239 214;
+ --color-orange-100: 255 223 181;
+ --color-orange-200: 255 209 154;
+ --color-orange-300: 255 193 130;
+ --color-orange-400: 245 174 115;
+ --color-orange-500: 236 148 85;
+ --color-orange-600: 247 107 21;
+ --color-orange-700: 239 95 0;
+ --color-orange-800: 204 78 0;
+ --color-orange-900: 88 45 29;
}
// scss-lint:disable QualifyingElement
body.dark {
+ --color-amber-25: 31 19 0;
+ --color-amber-50: 37 24 4;
+ --color-amber-75: 48 32 11;
--color-amber-100: 57 39 15;
--color-amber-200: 67 46 18;
- --color-amber-25: 31 19 0;
--color-amber-300: 83 57 22;
--color-amber-400: 111 77 29;
- --color-amber-50: 37 24 4;
--color-amber-500: 169 118 42;
--color-amber-600: 169 118 42;
--color-amber-700: 255 203 71;
--color-amber-800: 255 204 77;
--color-amber-900: 255 231 179;
- --color-amber-950: 255 231 179;
--color-ash-100: 46 48 53;
--color-ash-200: 53 55 60;
@@ -136,18 +241,18 @@
--color-ash-800: 173 177 184;
--color-ash-900: 237 238 240;
- --color-primary-100: 24 43 109;
- --color-primary-200: 31 53 129;
- --color-primary-25: 11 16 31;
- --color-primary-300: 40 64 146;
- --color-primary-400: 48 76 168;
- --color-primary-50: 16 23 41;
- --color-primary-500: 57 89 196;
- --color-primary-600: 69 110 255;
- --color-primary-700: 58 96 240;
- --color-primary-75: 20 34 81;
- --color-primary-800: 140 177 255;
- --color-primary-900: 210 225 255;
+ --color-primary-25: 10 17 28;
+ --color-primary-50: 15 24 38;
+ --color-primary-75: 15 39 72;
+ --color-primary-100: 10 49 99;
+ --color-primary-200: 18 61 117;
+ --color-primary-300: 29 74 134;
+ --color-primary-400: 40 89 156;
+ --color-primary-500: 48 106 186;
+ --color-primary-600: 39 129 246;
+ --color-primary-700: 21 116 231;
+ --color-primary-800: 126 182 255;
+ --color-primary-900: 205 227 255;
--color-ruby-100: 78 19 37;
--color-ruby-200: 94 26 46;
@@ -174,5 +279,108 @@
--color-teal-75: 13 45 42;
--color-teal-800: 11 216 182;
--color-teal-900: 173 240 221;
+
+ --color-green-25: 14 21 18;
+ --color-green-50: 18 27 23;
+ --color-green-75: 19 45 33;
+ --color-green-100: 17 59 41;
+ --color-green-200: 23 73 51;
+ --color-green-300: 32 87 62;
+ --color-green-400: 40 104 74;
+ --color-green-500: 47 124 87;
+ --color-green-600: 48 164 108;
+ --color-green-700: 51 176 116;
+ --color-green-800: 61 214 140;
+ --color-green-900: 177 241 203;
+
+ --color-mint-25: 14 21 21;
+ --color-mint-50: 15 27 27;
+ --color-mint-75: 9 44 43;
+ --color-mint-100: 0 58 56;
+ --color-mint-200: 0 71 68;
+ --color-mint-300: 16 86 80;
+ --color-mint-400: 30 104 95;
+ --color-mint-500: 39 127 112;
+ --color-mint-600: 134 234 212;
+ --color-mint-700: 168 245 229;
+ --color-mint-800: 88 213 186;
+ --color-mint-900: 196 245 225;
+
+ --color-sky-25: 14 21 21;
+ --color-sky-50: 15 27 27;
+ --color-sky-75: 9 44 43;
+ --color-sky-100: 0 58 56;
+ --color-sky-200: 0 71 68;
+ --color-sky-300: 16 86 80;
+ --color-sky-400: 30 104 95;
+ --color-sky-500: 39 127 112;
+ --color-sky-600: 134 234 212;
+ --color-sky-700: 168 245 229;
+ --color-sky-800: 88 213 186;
+ --color-sky-900: 196 245 225;
+
+ --color-indigo-25: 17 19 31;
+ --color-indigo-50: 20 23 38;
+ --color-indigo-75: 24 36 73;
+ --color-indigo-100: 29 46 98;
+ --color-indigo-200: 37 57 116;
+ --color-indigo-300: 48 67 132;
+ --color-indigo-400: 58 79 151;
+ --color-indigo-500: 67 93 177;
+ --color-indigo-600: 62 99 221;
+ --color-indigo-700: 84 114 228;
+ --color-indigo-800: 158 177 255;
+ --color-indigo-900: 214 225 255;
+
+ --color-iris-25: 19 19 30;
+ --color-iris-50: 23 22 37;
+ --color-iris-75: 32 34 72;
+ --color-iris-100: 38 42 101;
+ --color-iris-200: 48 51 116;
+ --color-iris-300: 61 62 130;
+ --color-iris-400: 74 74 149;
+ --color-iris-500: 89 88 177;
+ --color-iris-600: 91 91 214;
+ --color-iris-700: 110 106 222;
+ --color-iris-800: 177 169 255;
+ --color-iris-900: 224 223 254;
+
+ --color-violet-25: 20 18 31;
+ --color-violet-50: 27 21 37;
+ --color-violet-75: 41 31 67;
+ --color-violet-100: 51 37 91;
+ --color-violet-200: 60 46 105;
+ --color-violet-300: 71 56 118;
+ --color-violet-400: 86 70 139;
+ --color-violet-500: 105 88 173;
+ --color-violet-600: 110 86 207;
+ --color-violet-700: 125 102 217;
+ --color-violet-800: 186 167 255;
+ --color-violet-900: 226 221 254;
+
+ --color-pink-25: 25 17 23;
+ --color-pink-50: 33 18 29;
+ --color-pink-75: 55 23 47;
+ --color-pink-100: 75 20 61;
+ --color-pink-200: 89 28 71;
+ --color-pink-300: 105 41 85;
+ --color-pink-400: 131 56 105;
+ --color-pink-500: 168 72 133;
+ --color-pink-600: 214 64 159;
+ --color-pink-700: 222 81 168;
+ --color-pink-800: 255 141 204;
+ --color-pink-900: 253 209 234;
+ --color-orange-25: 23 18 14;
+ --color-orange-50: 30 22 15;
+ --color-orange-75: 51 30 11;
+ --color-orange-100: 70 33 0;
+ --color-orange-200: 86 40 0;
+ --color-orange-300: 102 53 12;
+ --color-orange-400: 126 69 29;
+ --color-orange-500: 163 88 41;
+ --color-orange-600: 247 107 21;
+ --color-orange-700: 255 128 31;
+ --color-orange-800: 255 160 87;
+ --color-orange-900: 255 224 194;
}
}
diff --git a/app/javascript/dashboard/components/ChatList.vue b/app/javascript/dashboard/components/ChatList.vue
index 26c057f98..e7fae6e01 100644
--- a/app/javascript/dashboard/components/ChatList.vue
+++ b/app/javascript/dashboard/components/ChatList.vue
@@ -185,7 +185,7 @@ import ConversationBasicFilter from './widgets/conversation/ConversationBasicFil
import ChatTypeTabs from './widgets/ChatTypeTabs.vue';
import ConversationItem from './ConversationItem.vue';
import timeMixin from '../mixins/time';
-import eventListenerMixins from 'shared/mixins/eventListenerMixins';
+import keyboardEventListenerMixins from 'shared/mixins/keyboardEventListenerMixins';
import conversationMixin from '../mixins/conversations';
import wootConstants from 'dashboard/constants/globals';
import advancedFilterTypes from './widgets/conversation/advancedFilterItems';
@@ -199,11 +199,6 @@ import uiSettingsMixin from 'dashboard/mixins/uiSettings';
import languages from 'dashboard/components/widgets/conversation/advancedFilterItems/languages';
import countries from 'shared/constants/countries';
import { generateValuesForEditCustomViews } from 'dashboard/helper/customViewsHelper';
-
-import {
- hasPressedAltAndJKey,
- hasPressedAltAndKKey,
-} from 'shared/helpers/KeyboardHelpers';
import { conversationListPageURL } from '../helper/URLHelper';
import {
isOnMentionsView,
@@ -228,7 +223,7 @@ export default {
mixins: [
timeMixin,
conversationMixin,
- eventListenerMixins,
+ keyboardEventListenerMixins,
alertMixin,
filterMixin,
uiSettingsMixin,
@@ -691,30 +686,40 @@ export default {
lastConversationIndex,
};
},
- handleKeyEvents(e) {
- if (hasPressedAltAndJKey(e)) {
- const { allConversations, activeConversationIndex } =
- this.getKeyboardListenerParams();
- if (activeConversationIndex === -1) {
- allConversations[0].click();
- }
- if (activeConversationIndex >= 1) {
- allConversations[activeConversationIndex - 1].click();
- }
+ handlePreviousConversation() {
+ const { allConversations, activeConversationIndex } =
+ this.getKeyboardListenerParams();
+ if (activeConversationIndex === -1) {
+ allConversations[0].click();
}
- if (hasPressedAltAndKKey(e)) {
- const {
- allConversations,
- activeConversationIndex,
- lastConversationIndex,
- } = this.getKeyboardListenerParams();
- if (activeConversationIndex === -1) {
- allConversations[lastConversationIndex].click();
- } else if (activeConversationIndex < lastConversationIndex) {
- allConversations[activeConversationIndex + 1].click();
- }
+ if (activeConversationIndex >= 1) {
+ allConversations[activeConversationIndex - 1].click();
}
},
+ handleNextConversation() {
+ const {
+ allConversations,
+ activeConversationIndex,
+ lastConversationIndex,
+ } = this.getKeyboardListenerParams();
+ if (activeConversationIndex === -1) {
+ allConversations[lastConversationIndex].click();
+ } else if (activeConversationIndex < lastConversationIndex) {
+ allConversations[activeConversationIndex + 1].click();
+ }
+ },
+ getKeyboardEvents() {
+ return {
+ 'Alt+KeyJ': {
+ action: () => this.handlePreviousConversation(),
+ allowOnFocusedInput: true,
+ },
+ 'Alt+KeyK': {
+ action: () => this.handleNextConversation(),
+ allowOnFocusedInput: true,
+ },
+ };
+ },
resetAndFetchData() {
this.appliedFilter = [];
this.resetBulkActions();
diff --git a/app/javascript/dashboard/components/CustomAttribute.vue b/app/javascript/dashboard/components/CustomAttribute.vue
index b50ad54cb..2c0fb48f7 100644
--- a/app/javascript/dashboard/components/CustomAttribute.vue
+++ b/app/javascript/dashboard/components/CustomAttribute.vue
@@ -12,7 +12,7 @@
{{ label }}
+
diff --git a/app/javascript/dashboard/components/buttons/ResolveAction.vue b/app/javascript/dashboard/components/buttons/ResolveAction.vue
index 84e33cc42..9a70a7f19 100644
--- a/app/javascript/dashboard/components/buttons/ResolveAction.vue
+++ b/app/javascript/dashboard/components/buttons/ResolveAction.vue
@@ -91,12 +91,7 @@ import { mapGetters } from 'vuex';
import { mixin as clickaway } from 'vue-clickaway';
import alertMixin from 'shared/mixins/alertMixin';
import CustomSnoozeModal from 'dashboard/components/CustomSnoozeModal.vue';
-import eventListenerMixins from 'shared/mixins/eventListenerMixins';
-import {
- hasPressedAltAndEKey,
- hasPressedCommandPlusAltAndEKey,
- hasPressedAltAndMKey,
-} from 'shared/helpers/KeyboardHelpers';
+import keyboardEventListenerMixins from 'shared/mixins/keyboardEventListenerMixins';
import { findSnoozeTime } from 'dashboard/helper/snoozeHelpers';
import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue';
import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue';
@@ -114,7 +109,7 @@ export default {
WootDropdownMenu,
CustomSnoozeModal,
},
- mixins: [clickaway, alertMixin, eventListenerMixins],
+ mixins: [clickaway, alertMixin, keyboardEventListenerMixins],
props: { conversationId: { type: [String, Number], required: true } },
data() {
return {
@@ -159,37 +154,52 @@ export default {
bus.$off(CMD_RESOLVE_CONVERSATION, this.onCmdResolveConversation);
},
methods: {
- async handleKeyEvents(e) {
+ getKeyboardEvents() {
+ return {
+ 'Alt+KeyM': {
+ action: () => this.$refs.arrowDownButton?.$el.click(),
+ allowOnFocusedInput: true,
+ },
+ 'Alt+KeyE': this.resolveOrToast,
+ '$mod+Alt+KeyE': async event => {
+ const { all, activeIndex, lastIndex } = this.getConversationParams();
+ await this.resolveOrToast();
+
+ if (activeIndex < lastIndex) {
+ all[activeIndex + 1].click();
+ } else if (all.length > 1) {
+ all[0].click();
+ document.querySelector('.conversations-list').scrollTop = 0;
+ }
+
+ event.preventDefault();
+ },
+ };
+ },
+ getConversationParams() {
const allConversations = document.querySelectorAll(
'.conversations-list .conversation'
);
- if (hasPressedAltAndMKey(e)) {
- if (this.$refs.arrowDownButton) {
- this.$refs.arrowDownButton.$el.click();
- }
- }
- if (hasPressedAltAndEKey(e)) {
- const activeConversation = document.querySelector(
- 'div.conversations-list div.conversation.active'
- );
- const activeConversationIndex = [...allConversations].indexOf(
- activeConversation
- );
- const lastConversationIndex = allConversations.length - 1;
- try {
- await this.toggleStatus(wootConstants.STATUS_TYPE.RESOLVED);
- } catch (error) {
- // error
- }
- if (hasPressedCommandPlusAltAndEKey(e)) {
- if (activeConversationIndex < lastConversationIndex) {
- allConversations[activeConversationIndex + 1].click();
- } else if (allConversations.length > 1) {
- allConversations[0].click();
- document.querySelector('.conversations-list').scrollTop = 0;
- }
- e.preventDefault();
- }
+
+ const activeConversation = document.querySelector(
+ 'div.conversations-list div.conversation.active'
+ );
+ const activeConversationIndex = [...allConversations].indexOf(
+ activeConversation
+ );
+ const lastConversationIndex = allConversations.length - 1;
+
+ return {
+ all: allConversations,
+ activeIndex: activeConversationIndex,
+ lastIndex: lastConversationIndex,
+ };
+ },
+ async resolveOrToast() {
+ try {
+ await this.toggleStatus(wootConstants.STATUS_TYPE.RESOLVED);
+ } catch (error) {
+ // error
}
},
onCmdSnoozeConversation(snoozeType) {
diff --git a/app/javascript/dashboard/components/index.js b/app/javascript/dashboard/components/index.js
index bc515cfdf..2b624b6d9 100644
--- a/app/javascript/dashboard/components/index.js
+++ b/app/javascript/dashboard/components/index.js
@@ -24,6 +24,7 @@ import SubmitButton from './buttons/FormSubmitButton';
import Tabs from './ui/Tabs/Tabs';
import TabsItem from './ui/Tabs/TabsItem';
import Thumbnail from './widgets/Thumbnail.vue';
+import DatePicker from './ui/DatePicker/DatePicker.vue';
const WootUIKit = {
AvatarUploader,
@@ -51,6 +52,7 @@ const WootUIKit = {
Tabs,
TabsItem,
Thumbnail,
+ DatePicker,
install(Vue) {
const keys = Object.keys(this);
keys.pop(); // remove 'install' from keys
diff --git a/app/javascript/dashboard/components/layout/Sidebar.vue b/app/javascript/dashboard/components/layout/Sidebar.vue
index 1290ea602..0f3a1a857 100644
--- a/app/javascript/dashboard/components/layout/Sidebar.vue
+++ b/app/javascript/dashboard/components/layout/Sidebar.vue
@@ -1,5 +1,5 @@
-
diff --git a/app/javascript/dashboard/routes/dashboard/settings/personal/MessageSignature.vue b/app/javascript/dashboard/routes/dashboard/settings/personal/MessageSignature.vue
new file mode 100644
index 000000000..7639465be
--- /dev/null
+++ b/app/javascript/dashboard/routes/dashboard/settings/personal/MessageSignature.vue
@@ -0,0 +1,50 @@
+
+
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/settings/personal/UserBasicDetails.vue b/app/javascript/dashboard/routes/dashboard/settings/personal/UserBasicDetails.vue
new file mode 100644
index 000000000..1a0fb2eae
--- /dev/null
+++ b/app/javascript/dashboard/routes/dashboard/settings/personal/UserBasicDetails.vue
@@ -0,0 +1,135 @@
+
+
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/settings/personal/UserProfilePicture.vue b/app/javascript/dashboard/routes/dashboard/settings/personal/UserProfilePicture.vue
new file mode 100644
index 000000000..d4ab08bc1
--- /dev/null
+++ b/app/javascript/dashboard/routes/dashboard/settings/personal/UserProfilePicture.vue
@@ -0,0 +1,40 @@
+
+
+
+ {{ $t('PROFILE_SETTINGS.FORM.PICTURE') }}
+
+
+
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/settings/personal/personal.routes.js b/app/javascript/dashboard/routes/dashboard/settings/personal/personal.routes.js
new file mode 100644
index 000000000..66aaf0a11
--- /dev/null
+++ b/app/javascript/dashboard/routes/dashboard/settings/personal/personal.routes.js
@@ -0,0 +1,20 @@
+import { frontendURL } from 'dashboard/helper/URLHelper';
+
+const Index = () => import('./Index.vue');
+
+export default {
+ routes: [
+ {
+ path: frontendURL('accounts/:accountId/personal'),
+ name: 'personal_settings',
+ roles: ['administrator', 'agent'],
+ component: Index,
+ props: {
+ headerTitle: 'PROFILE_SETTINGS.TITLE',
+ icon: 'edit',
+ showNewButton: false,
+ showSidemenuIcon: false,
+ },
+ },
+ ],
+};
diff --git a/app/javascript/dashboard/routes/dashboard/settings/reports/components/Heatmap.vue b/app/javascript/dashboard/routes/dashboard/settings/reports/components/Heatmap.vue
index fb7e7b5eb..6f28dabb5 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/reports/components/Heatmap.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/reports/components/Heatmap.vue
@@ -1,308 +1,173 @@
+
+
-