-
+
+
- {{ buttonText }}
+ {{ $t('REPORT.FILTER_ACTIONS.CLEAR_FILTER') }}
diff --git a/app/javascript/dashboard/routes/dashboard/settings/reports/components/Filters/v3/FilterListDropdown.vue b/app/javascript/dashboard/routes/dashboard/settings/reports/components/Filters/v3/FilterListDropdown.vue
index fbb07db77..1a0543af3 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/reports/components/Filters/v3/FilterListDropdown.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/reports/components/Filters/v3/FilterListDropdown.vue
@@ -14,18 +14,18 @@ const props = defineProps({
type: Boolean,
default: false,
},
- inputButtonText: {
- type: String,
- default: '',
- },
- emptyListMessage: {
- type: String,
- default: '',
- },
inputPlaceholder: {
type: String,
default: '',
},
+ activeFilterId: {
+ type: Number,
+ default: null,
+ },
+ showClearFilter: {
+ type: Boolean,
+ default: false,
+ },
});
const searchTerm = ref('');
@@ -42,29 +42,36 @@ const filteredListItems = computed(() => {
const isDropdownListEmpty = computed(() => {
return !filteredListItems.value.length;
});
+
+const isFilterActive = id => {
+ if (!props.activeFilterId) return false;
+ return id === props.activeFilterId;
+};
diff --git a/app/javascript/dashboard/routes/dashboard/settings/reports/components/Filters/v3/FilterListItemButton.vue b/app/javascript/dashboard/routes/dashboard/settings/reports/components/Filters/v3/FilterListItemButton.vue
index 2fb99980a..3566686e1 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/reports/components/Filters/v3/FilterListItemButton.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/reports/components/Filters/v3/FilterListItemButton.vue
@@ -13,7 +13,7 @@ defineProps({
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/settings/reports/components/SLA/SLAReportFilters.vue b/app/javascript/dashboard/routes/dashboard/settings/reports/components/SLA/SLAReportFilters.vue
index 5748366b6..123a921fc 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/reports/components/SLA/SLAReportFilters.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/reports/components/SLA/SLAReportFilters.vue
@@ -1,22 +1,25 @@
-
-
-
-
-
+
+
+
+
-
-
diff --git a/app/javascript/dashboard/routes/dashboard/settings/reports/components/SLA/SLAViewDetails.vue b/app/javascript/dashboard/routes/dashboard/settings/reports/components/SLA/SLAViewDetails.vue
index 72bc4749a..cdeda0af2 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/reports/components/SLA/SLAViewDetails.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/reports/components/SLA/SLAViewDetails.vue
@@ -13,7 +13,7 @@
diff --git a/app/javascript/dashboard/routes/dashboard/settings/reports/components/SLA/helpers/SLAFilterHelpers.js b/app/javascript/dashboard/routes/dashboard/settings/reports/components/SLA/helpers/SLAFilterHelpers.js
new file mode 100644
index 000000000..cac7e93c3
--- /dev/null
+++ b/app/javascript/dashboard/routes/dashboard/settings/reports/components/SLA/helpers/SLAFilterHelpers.js
@@ -0,0 +1,37 @@
+export const buildFilterList = (items, type) =>
+ // Build the filter list for the dropdown
+ items.map(item => ({
+ id: item.id,
+ name: type === 'labels' ? item.title : item.name,
+ type,
+ }));
+
+export const getActiveFilter = (filters, type, key) => {
+ // Method is used to get the active filter from the filter list
+ return filters.find(filterItem =>
+ type === 'labels'
+ ? filterItem.title === key
+ : filterItem.id.toString() === key.toString()
+ );
+};
+
+export const getFilterType = (input, direction) => {
+ // Method is used to map the filter key to the filter type
+ const filterMap = {
+ keyToType: {
+ assigned_agent_id: 'agents',
+ inbox_id: 'inboxes',
+ team_id: 'teams',
+ sla_policy_id: 'sla',
+ label_list: 'labels',
+ },
+ typeToKey: {
+ agents: 'assigned_agent_id',
+ inboxes: 'inbox_id',
+ teams: 'team_id',
+ sla: 'sla_policy_id',
+ labels: 'label_list',
+ },
+ };
+ return filterMap[direction][input];
+};
diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js
index 7c6fb5d93..5029c9e76 100644
--- a/app/javascript/packs/application.js
+++ b/app/javascript/packs/application.js
@@ -31,6 +31,7 @@ import VueDOMPurifyHTML from 'vue-dompurify-html';
import { domPurifyConfig } from '../shared/helpers/HTMLSanitizer';
import AnalyticsPlugin from '../dashboard/helper/AnalyticsHelper/plugin';
import resizeDirective from '../dashboard/helper/directives/resize.js';
+import { directive as onClickaway } from 'vue-clickaway';
Vue.config.env = process.env;
@@ -78,7 +79,9 @@ Vue.component('multiselect', Multiselect);
Vue.component('woot-switch', WootSwitch);
Vue.component('woot-wizard', WootWizard);
Vue.component('fluent-icon', FluentIcon);
+
Vue.directive('resize', resizeDirective);
+Vue.directive('on-clickaway', onClickaway);
const i18nConfig = new VueI18n({
locale: 'en',
diff --git a/app/javascript/sdk/sdk.js b/app/javascript/sdk/sdk.js
index 313bbb88a..95d132258 100644
--- a/app/javascript/sdk/sdk.js
+++ b/app/javascript/sdk/sdk.js
@@ -23,6 +23,7 @@ export const SDK_CSS = `
.woot-widget-holder iframe {
border: 0;
+ color-scheme: normal;
height: 100% !important;
width: 100% !important;
max-height: 100vh !important;
diff --git a/app/services/imap/base_fetch_email_service.rb b/app/services/imap/base_fetch_email_service.rb
index 4f49dc980..1af3bdb5d 100644
--- a/app/services/imap/base_fetch_email_service.rb
+++ b/app/services/imap/base_fetch_email_service.rb
@@ -3,10 +3,17 @@ require 'net/imap'
class Imap::BaseFetchEmailService
pattr_initialize [:channel!]
- def perform
+ def fetch_emails
# Override this method
end
+ def perform
+ inbound_emails = fetch_emails
+ terminate_imap_connection
+
+ inbound_emails
+ end
+
private
def authentication_type
@@ -105,6 +112,13 @@ class Imap::BaseFetchEmailService
imap
end
+ def terminate_imap_connection
+ imap_client.logout
+ rescue Net::IMAP::Error => e
+ Rails.logger.info "Logout failed for #{channel.email} - #{e.message}."
+ imap_client.disconnect
+ end
+
def build_mail_from_string(raw_email_content)
Mail.read_from_string(raw_email_content)
end
diff --git a/app/services/imap/fetch_email_service.rb b/app/services/imap/fetch_email_service.rb
index f6d8de774..f602b3375 100644
--- a/app/services/imap/fetch_email_service.rb
+++ b/app/services/imap/fetch_email_service.rb
@@ -1,5 +1,5 @@
class Imap::FetchEmailService < Imap::BaseFetchEmailService
- def perform
+ def fetch_emails
fetch_mail_for_channel
end
diff --git a/app/services/imap/microsoft_fetch_email_service.rb b/app/services/imap/microsoft_fetch_email_service.rb
index b6d3c03b8..ed3eb20f1 100644
--- a/app/services/imap/microsoft_fetch_email_service.rb
+++ b/app/services/imap/microsoft_fetch_email_service.rb
@@ -1,5 +1,5 @@
class Imap::MicrosoftFetchEmailService < Imap::BaseFetchEmailService
- def perform
+ def fetch_emails
return if channel.provider_config['access_token'].blank?
fetch_mail_for_channel
diff --git a/enterprise/app/models/applied_sla.rb b/enterprise/app/models/applied_sla.rb
index 0ae634536..6adeee036 100644
--- a/enterprise/app/models/applied_sla.rb
+++ b/enterprise/app/models/applied_sla.rb
@@ -30,14 +30,14 @@ class AppliedSla < ApplicationRecord
enum sla_status: { active: 0, hit: 1, missed: 2, active_with_misses: 3 }
scope :filter_by_date_range, ->(range) { where(created_at: range) if range.present? }
- scope :filter_by_inbox_id, ->(inbox_id) { where(inbox_id: inbox_id) if inbox_id.present? }
- scope :filter_by_team_id, ->(team_id) { where(team_id: team_id) if team_id.present? }
+ scope :filter_by_inbox_id, ->(inbox_id) { joins(:conversation).where(conversations: { inbox_id: inbox_id }) if inbox_id.present? }
+ scope :filter_by_team_id, ->(team_id) { joins(:conversation).where(conversations: { team_id: team_id }) if team_id.present? }
scope :filter_by_sla_policy_id, ->(sla_policy_id) { where(sla_policy_id: sla_policy_id) if sla_policy_id.present? }
- scope :filter_by_label_list, ->(label_list) { joins(:conversation).where(conversations: { cached_label_list: label_list }) if label_list.present? }
+ scope :filter_by_label_list, lambda { |label_list|
+ joins(:conversation).where('conversations.cached_label_list LIKE ?', "%#{label_list}%") if label_list.present?
+ }
scope :filter_by_assigned_agent_id, lambda { |assigned_agent_id|
- if assigned_agent_id.present?
- joins(:conversation).where(conversations: { assigned_agent_id: assigned_agent_id })
- end
+ joins(:conversation).where(conversations: { assignee_id: assigned_agent_id }) if assigned_agent_id.present?
}
scope :missed, -> { where(sla_status: %i[missed active_with_misses]) }
diff --git a/spec/enterprise/controllers/api/v1/accounts/applied_slas_controller_spec.rb b/spec/enterprise/controllers/api/v1/accounts/applied_slas_controller_spec.rb
index 34389dad4..423f65711 100644
--- a/spec/enterprise/controllers/api/v1/accounts/applied_slas_controller_spec.rb
+++ b/spec/enterprise/controllers/api/v1/accounts/applied_slas_controller_spec.rb
@@ -92,7 +92,7 @@ RSpec.describe 'Applied SLAs API', type: :request do
create(:applied_sla, sla_policy: sla_policy1, conversation: conversation3, created_at: 3.days.ago)
get "/api/v1/accounts/#{account.id}/applied_slas/metrics",
- params: { label_list: ['label1'] },
+ params: { label_list: 'label1' },
headers: administrator.create_new_auth_token
expect(response).to have_http_status(:success)
body = JSON.parse(response.body)
@@ -205,7 +205,7 @@ RSpec.describe 'Applied SLAs API', type: :request do
create(:applied_sla, sla_policy: sla_policy1, conversation: conversation3, created_at: 3.days.ago, sla_status: 'missed')
get "/api/v1/accounts/#{account.id}/applied_slas",
- params: { label_list: ['label1'] },
+ params: { label_list: 'label1' },
headers: administrator.create_new_auth_token
expect(response).to have_http_status(:success)
body = JSON.parse(response.body)
diff --git a/spec/services/imap/fetch_email_service_spec.rb b/spec/services/imap/fetch_email_service_spec.rb
index 28a173951..46336bf0f 100644
--- a/spec/services/imap/fetch_email_service_spec.rb
+++ b/spec/services/imap/fetch_email_service_spec.rb
@@ -30,6 +30,7 @@ RSpec.describe Imap::FetchEmailService do
allow(imap).to receive(:search).with(%w[SINCE 25-Oct-2020]).and_return([1])
allow(imap).to receive(:fetch).with([1], 'BODY.PEEK[HEADER]').and_return([email_header])
allow(imap).to receive(:fetch).with(1, 'RFC822').and_return([imap_fetch_mail])
+ allow(imap).to receive(:logout)
result = described_class.new(channel: imap_email_channel).perform
@@ -39,6 +40,7 @@ RSpec.describe Imap::FetchEmailService do
expect(imap).to have_received(:fetch).with([1], 'BODY.PEEK[HEADER]')
expect(imap).to have_received(:fetch).with(1, 'RFC822')
expect(logger).to have_received(:info).with("[IMAP::FETCH_EMAIL_SERVICE] Fetching mails from #{imap_email_channel.email}, found 1.")
+ expect(imap).to have_received(:logout)
end
end
@@ -51,6 +53,7 @@ RSpec.describe Imap::FetchEmailService do
allow(imap).to receive(:search).with(%w[SINCE 25-Oct-2020]).and_return([1])
allow(imap).to receive(:fetch).with([1], 'BODY.PEEK[HEADER]').and_return([email_header])
+ allow(imap).to receive(:logout)
result = described_class.new(channel: imap_email_channel).perform
diff --git a/spec/services/imap/microsoft_fetch_email_service_spec.rb b/spec/services/imap/microsoft_fetch_email_service_spec.rb
index 8f79b86b5..3a13ce0c6 100644
--- a/spec/services/imap/microsoft_fetch_email_service_spec.rb
+++ b/spec/services/imap/microsoft_fetch_email_service_spec.rb
@@ -35,6 +35,7 @@ RSpec.describe Imap::MicrosoftFetchEmailService do
allow(imap).to receive(:search).with(%w[SINCE 25-Oct-2020]).and_return([1])
allow(imap).to receive(:fetch).with([1], 'BODY.PEEK[HEADER]').and_return([email_header])
allow(imap).to receive(:fetch).with(1, 'RFC822').and_return([imap_fetch_mail])
+ allow(imap).to receive(:logout)
result = described_class.new(channel: microsoft_channel).perform