diff --git a/.gitignore b/.gitignore
index dbdd35bcd..017c5c224 100644
--- a/.gitignore
+++ b/.gitignore
@@ -95,6 +95,7 @@ yarn-debug.log*
.claude/settings.local.json
.cursor
.codex/
+.claude/
CLAUDE.local.md
# Histoire deployment
diff --git a/Gemfile.lock b/Gemfile.lock
index 717ec2a02..aad0438cf 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -583,14 +583,14 @@ GEM
newrelic_rpm (9.6.0)
base64
nio4r (2.7.3)
- nokogiri (1.18.9)
+ nokogiri (1.19.1)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
- nokogiri (1.18.9-arm64-darwin)
+ nokogiri (1.19.1-arm64-darwin)
racc (~> 1.4)
- nokogiri (1.18.9-x86_64-darwin)
+ nokogiri (1.19.1-x86_64-darwin)
racc (~> 1.4)
- nokogiri (1.18.9-x86_64-linux-gnu)
+ nokogiri (1.19.1-x86_64-linux-gnu)
racc (~> 1.4)
oauth (1.1.0)
oauth-tty (~> 1.0, >= 1.0.1)
diff --git a/VERSION_CW b/VERSION_CW
index a162ea75a..d782fca8f 100644
--- a/VERSION_CW
+++ b/VERSION_CW
@@ -1 +1 @@
-4.11.0
+4.11.1
diff --git a/app/controllers/api/v1/accounts/conversations_controller.rb b/app/controllers/api/v1/accounts/conversations_controller.rb
index 7c21844f5..ab1cae17d 100644
--- a/app/controllers/api/v1/accounts/conversations_controller.rb
+++ b/app/controllers/api/v1/accounts/conversations_controller.rb
@@ -15,7 +15,7 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro
end
def meta
- result = conversation_finder.perform
+ result = conversation_finder.perform_meta_only
@conversations_count = result[:count]
end
diff --git a/app/finders/conversation_finder.rb b/app/finders/conversation_finder.rb
index d43ed31e7..7821bee49 100644
--- a/app/finders/conversation_finder.rb
+++ b/app/finders/conversation_finder.rb
@@ -55,6 +55,22 @@ class ConversationFinder
}
end
+ def perform_meta_only
+ set_up
+
+ mine_count, unassigned_count, all_count, = set_count_for_all_conversations
+ assigned_count = all_count - unassigned_count
+
+ {
+ count: {
+ mine_count: mine_count,
+ assigned_count: assigned_count,
+ unassigned_count: unassigned_count,
+ all_count: all_count
+ }
+ }
+ end
+
private
def set_up
diff --git a/app/helpers/api/v1/inboxes_helper.rb b/app/helpers/api/v1/inboxes_helper.rb
index d734a346e..3d6b559c8 100644
--- a/app/helpers/api/v1/inboxes_helper.rb
+++ b/app/helpers/api/v1/inboxes_helper.rb
@@ -57,39 +57,35 @@ module Api::V1::InboxesHelper
end
def check_smtp_connection(channel_data, smtp)
+ smtp.open_timeout = 10
smtp.start(channel_data[:smtp_domain], channel_data[:smtp_login], channel_data[:smtp_password],
channel_data[:smtp_authentication]&.to_sym || :login)
smtp.finish
+ rescue Net::SMTPAuthenticationError
+ raise StandardError, I18n.t('errors.inboxes.smtp.authentication_error')
+ rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, Net::OpenTimeout
+ raise StandardError, I18n.t('errors.inboxes.smtp.connection_error')
+ rescue OpenSSL::SSL::SSLError
+ raise StandardError, I18n.t('errors.inboxes.smtp.ssl_error')
+ rescue Net::SMTPServerBusy, Net::SMTPSyntaxError, Net::SMTPFatalError
+ raise StandardError, I18n.t('errors.inboxes.smtp.smtp_error')
+ rescue StandardError => e
+ raise StandardError, e.message
end
def set_smtp_encryption(channel_data, smtp)
if channel_data[:smtp_enable_ssl_tls]
- set_enable_tls(channel_data, smtp)
+ set_smtp_ssl_method(smtp, :enable_tls, channel_data[:smtp_openssl_verify_mode])
elsif channel_data[:smtp_enable_starttls_auto]
- set_enable_starttls_auto(channel_data, smtp)
+ set_smtp_ssl_method(smtp, :enable_starttls_auto, channel_data[:smtp_openssl_verify_mode])
end
end
- def set_enable_starttls_auto(channel_data, smtp)
- return unless smtp.respond_to?(:enable_starttls_auto)
+ def set_smtp_ssl_method(smtp, method, openssl_verify_mode)
+ return unless smtp.respond_to?(method)
- if channel_data[:smtp_openssl_verify_mode]
- context = enable_openssl_mode(channel_data[:smtp_openssl_verify_mode])
- smtp.enable_starttls_auto(context)
- else
- smtp.enable_starttls_auto
- end
- end
-
- def set_enable_tls(channel_data, smtp)
- return unless smtp.respond_to?(:enable_tls)
-
- if channel_data[:smtp_openssl_verify_mode]
- context = enable_openssl_mode(channel_data[:smtp_openssl_verify_mode])
- smtp.enable_tls(context)
- else
- smtp.enable_tls
- end
+ context = enable_openssl_mode(openssl_verify_mode) if openssl_verify_mode
+ context ? smtp.send(method, context) : smtp.send(method)
end
def enable_openssl_mode(smtp_openssl_verify_mode)
diff --git a/app/javascript/dashboard/App.vue b/app/javascript/dashboard/App.vue
index 61d7631e7..8912c03d1 100644
--- a/app/javascript/dashboard/App.vue
+++ b/app/javascript/dashboard/App.vue
@@ -164,10 +164,4 @@ export default {
.v-popper--theme-tooltip .v-popper__arrow-container {
display: none;
}
-
-.multiselect__input {
- margin-bottom: 0px !important;
-}
-
-
diff --git a/app/javascript/dashboard/assets/scss/_base.scss b/app/javascript/dashboard/assets/scss/_base.scss
index 14ae2a9d4..84c8a4b0f 100644
--- a/app/javascript/dashboard/assets/scss/_base.scss
+++ b/app/javascript/dashboard/assets/scss/_base.scss
@@ -66,7 +66,7 @@ textarea {
// Field base styles (Input, TextArea, Select)
@layer components {
.field-base {
- @apply block box-border w-full transition-colors duration-[0.25s] ease-[ease-in-out] focus:outline-n-brand dark:focus:outline-n-brand appearance-none mx-0 mt-0 mb-4 py-2 px-3 rounded-lg text-base font-normal bg-n-alpha-black2 placeholder:text-n-slate-10 dark:placeholder:text-n-slate-10 text-n-slate-12 border-none outline outline-1 outline-n-weak dark:outline-n-weak hover:outline-n-slate-6 dark:hover:outline-n-slate-6;
+ @apply block box-border w-full transition-colors duration-[0.25s] ease-[ease-in-out] focus:outline-n-brand dark:focus:outline-n-brand appearance-none mx-0 mt-0 mb-4 py-2 px-3 rounded-lg text-sm font-normal bg-n-alpha-black2 placeholder:text-n-slate-10 dark:placeholder:text-n-slate-10 text-n-slate-12 border-none outline outline-1 outline-n-weak dark:outline-n-weak hover:outline-n-slate-6 dark:hover:outline-n-slate-6;
}
.field-disabled {
@@ -78,7 +78,7 @@ textarea {
}
}
-$form-input-selector: "input[type]:not([type='file']):not([type='checkbox']):not([type='radio']):not([type='range']):not([type='button']):not([type='submit']):not([type='reset']):not([type='color']):not([type='image']):not([type='hidden']):not(.reset-base):not(.multiselect__input):not(.no-margin)";
+$form-input-selector: "input[type]:not([type='file']):not([type='checkbox']):not([type='radio']):not([type='range']):not([type='button']):not([type='submit']):not([type='reset']):not([type='color']):not([type='image']):not([type='hidden']):not(.reset-base):not(.no-margin)";
#{$form-input-selector} {
@apply field-base h-10;
@@ -92,7 +92,7 @@ $form-input-selector: "input[type]:not([type='file']):not([type='checkbox']):not
}
}
-input[type='file']:not(.multiselect__input) {
+input[type='file'] {
@apply leading-[1.15] mb-4 border-0 bg-transparent text-sm;
}
@@ -126,13 +126,6 @@ label:has(.help-text) {
}
}
-// Error handling
-.has-multi-select-error {
- div.multiselect {
- @apply mb-1;
- }
-}
-
// FormKit support
.formkit-outer[data-invalid='true'] {
#{$form-input-selector},
@@ -150,9 +143,7 @@ label:has(.help-text) {
#{$form-input-selector},
input:not([type]),
textarea,
- select,
- .multiselect > .multiselect__tags,
- .multiselect:not(.no-margin) {
+ select {
@apply field-error;
}
diff --git a/app/javascript/dashboard/assets/scss/_woot.scss b/app/javascript/dashboard/assets/scss/_woot.scss
index 40ca7b436..27764d150 100644
--- a/app/javascript/dashboard/assets/scss/_woot.scss
+++ b/app/javascript/dashboard/assets/scss/_woot.scss
@@ -13,7 +13,6 @@
@import 'base';
// Plugins
-@import 'plugins/multiselect';
@import 'plugins/date-picker';
html,
@@ -66,4 +65,84 @@ body {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
+
+ /**
+ * ============================================================================
+ * TYPOGRAPHY UTILITIES
+ * ============================================================================
+ *
+ * | Class | Use Case |
+ * |--------------------|----------------------------------------------------|
+ * | .text-body-main |
, , general body text |
+ * | .text-body-para | for paragraphs, larger text blocks |
+ * | .text-heading-1 |
, page titles, panel headers |
+ * | .text-heading-2 | , section headings, card titles |
+ * | .text-heading-3 | , card headings, breadcrumbs, subsections |
+ * | .text-label |