From e2dd2ccb42420a70eb17f760d504234749c96f96 Mon Sep 17 00:00:00 2001 From: Pranav Date: Wed, 25 Feb 2026 18:22:41 -0800 Subject: [PATCH] feat: Add a priority + created at sort for conversations (#13658) - Add a new conversation sort option "Priority: Highest first, Created: Oldest first" that sorts by priority descending (urgent > high > medium > low > none) with created_at ascending as the tiebreaker --- app/finders/conversation_finder.rb | 1 + .../widgets/conversation/ConversationBasicFilter.vue | 4 ++++ app/javascript/dashboard/constants/globals.js | 1 + app/javascript/dashboard/i18n/locale/en/chatlist.json | 3 +++ .../dashboard/store/modules/conversations/helpers.js | 9 +++++++++ app/models/concerns/sort_handler.rb | 4 ++++ 6 files changed, 22 insertions(+) diff --git a/app/finders/conversation_finder.rb b/app/finders/conversation_finder.rb index 7821bee49..fa437327d 100644 --- a/app/finders/conversation_finder.rb +++ b/app/finders/conversation_finder.rb @@ -11,6 +11,7 @@ class ConversationFinder 'priority_desc' => %w[sort_on_priority desc], 'waiting_since_asc' => %w[sort_on_waiting_since asc], 'waiting_since_desc' => %w[sort_on_waiting_since desc], + 'priority_desc_created_at_asc' => %w[sort_on_priority_created_at desc], # To be removed in v3.5.0 'latest' => %w[sort_on_last_activity_at desc], diff --git a/app/javascript/dashboard/components/widgets/conversation/ConversationBasicFilter.vue b/app/javascript/dashboard/components/widgets/conversation/ConversationBasicFilter.vue index d699923f5..fa1563ed8 100644 --- a/app/javascript/dashboard/components/widgets/conversation/ConversationBasicFilter.vue +++ b/app/javascript/dashboard/components/widgets/conversation/ConversationBasicFilter.vue @@ -86,6 +86,10 @@ const chatSortOptions = computed(() => [ label: t('CHAT_LIST.SORT_ORDER_ITEMS.priority_asc.TEXT'), value: 'priority_asc', }, + { + label: t('CHAT_LIST.SORT_ORDER_ITEMS.priority_desc_created_at_asc.TEXT'), + value: 'priority_desc_created_at_asc', + }, { label: t('CHAT_LIST.SORT_ORDER_ITEMS.waiting_since_asc.TEXT'), value: 'waiting_since_asc', diff --git a/app/javascript/dashboard/constants/globals.js b/app/javascript/dashboard/constants/globals.js index eb42a270f..21303efcb 100644 --- a/app/javascript/dashboard/constants/globals.js +++ b/app/javascript/dashboard/constants/globals.js @@ -21,6 +21,7 @@ export default { PRIORITY_DESC: 'priority_desc', WAITING_SINCE_ASC: 'waiting_since_asc', WAITING_SINCE_DESC: 'waiting_since_desc', + PRIORITY_DESC_CREATED_AT_ASC: 'priority_desc_created_at_asc', }, ARTICLE_STATUS_TYPES: { DRAFT: 0, diff --git a/app/javascript/dashboard/i18n/locale/en/chatlist.json b/app/javascript/dashboard/i18n/locale/en/chatlist.json index 92e67635b..0e8e87a04 100644 --- a/app/javascript/dashboard/i18n/locale/en/chatlist.json +++ b/app/javascript/dashboard/i18n/locale/en/chatlist.json @@ -76,6 +76,9 @@ }, "waiting_since_desc": { "TEXT": "Pending Response: Shortest first" + }, + "priority_desc_created_at_asc": { + "TEXT": "Priority: Highest first, Created: Oldest first" } }, "ATTACHMENTS": { diff --git a/app/javascript/dashboard/store/modules/conversations/helpers.js b/app/javascript/dashboard/store/modules/conversations/helpers.js index ebbdcbe64..af6b16023 100644 --- a/app/javascript/dashboard/store/modules/conversations/helpers.js +++ b/app/javascript/dashboard/store/modules/conversations/helpers.js @@ -116,6 +116,7 @@ const SORT_OPTIONS = { priority_desc: ['sortOnPriority', 'desc'], waiting_since_asc: ['sortOnWaitingSince', 'asc'], waiting_since_desc: ['sortOnWaitingSince', 'desc'], + priority_desc_created_at_asc: ['sortOnPriorityCreatedAt', 'desc'], }; const sortAscending = (valueA, valueB) => valueA - valueB; const sortDescending = (valueA, valueB) => valueB - valueA; @@ -139,6 +140,14 @@ const sortConfig = { return getSortOrderFunction(sortDirection)(p1, p2); }, + sortOnPriorityCreatedAt: (a, b) => { + const DEFAULT_FOR_NULL = 0; + const p1 = CONVERSATION_PRIORITY_ORDER[a.priority] || DEFAULT_FOR_NULL; + const p2 = CONVERSATION_PRIORITY_ORDER[b.priority] || DEFAULT_FOR_NULL; + if (p1 !== p2) return p2 - p1; + return a.created_at - b.created_at; + }, + sortOnWaitingSince: (a, b, sortDirection) => { const sortFunc = getSortOrderFunction(sortDirection); if (!a.waiting_since || !b.waiting_since) { diff --git a/app/models/concerns/sort_handler.rb b/app/models/concerns/sort_handler.rb index 00eb73717..065fa7fea 100644 --- a/app/models/concerns/sort_handler.rb +++ b/app/models/concerns/sort_handler.rb @@ -14,6 +14,10 @@ module SortHandler order(generate_sql_query("priority #{sort_direction.to_s.upcase} NULLS LAST, last_activity_at DESC")) end + def sort_on_priority_created_at(sort_direction = :desc) + order(generate_sql_query("priority #{sort_direction.to_s.upcase} NULLS LAST, created_at ASC")) + end + def sort_on_waiting_since(sort_direction = :asc) order(generate_sql_query("waiting_since #{sort_direction.to_s.upcase} NULLS LAST, created_at ASC")) end