-
-
Save shricodev/314fa9f6d90859d6146d49d040eecf4e to your computer and use it in GitHub Desktop.
Chatwoot - Opus 4.6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| From 6ddb34fe2c9ecba3dd8b0b086ba72244d71bcfaa Mon Sep 17 00:00:00 2001 | |
| From: Shrijal Acharya <shrijal.acharya@gmail.com> | |
| Date: Sat, 21 Mar 2026 23:04:31 +0545 | |
| Subject: [PATCH] opus 4.6 | |
| --- | |
| app/finders/conversation_finder.rb | 17 ++++++++++++----- | |
| .../dashboard/components/ChatList.vue | 6 +++++- | |
| app/javascript/dashboard/constants/globals.js | 1 + | |
| .../dashboard/constants/permissions.js | 4 ++++ | |
| .../dashboard/i18n/locale/en/chatlist.json | 1 + | |
| .../store/modules/conversationStats.js | 3 +++ | |
| .../store/modules/conversations/getters.js | 5 +++++ | |
| .../specs/conversationStats/getters.spec.js | 2 ++ | |
| .../specs/conversationStats/mutations.spec.js | 2 ++ | |
| app/listeners/participation_listener.rb | 10 ++++++++++ | |
| .../accounts/conversations/index.json.jbuilder | 1 + | |
| .../accounts/conversations/meta.json.jbuilder | 1 + | |
| docker-compose.yaml | 10 +++++----- | |
| 13 files changed, 52 insertions(+), 11 deletions(-) | |
| diff --git a/app/finders/conversation_finder.rb b/app/finders/conversation_finder.rb | |
| index fa437327d..cc3cf6148 100644 | |
| --- a/app/finders/conversation_finder.rb | |
| +++ b/app/finders/conversation_finder.rb | |
| @@ -40,7 +40,7 @@ class ConversationFinder | |
| def perform | |
| set_up | |
| - mine_count, unassigned_count, all_count, = set_count_for_all_conversations | |
| + mine_count, unassigned_count, all_count, participating_count = set_count_for_all_conversations | |
| assigned_count = all_count - unassigned_count | |
| filter_by_assignee_type | |
| @@ -51,7 +51,8 @@ class ConversationFinder | |
| mine_count: mine_count, | |
| assigned_count: assigned_count, | |
| unassigned_count: unassigned_count, | |
| - all_count: all_count | |
| + all_count: all_count, | |
| + participating_count: participating_count | |
| } | |
| } | |
| end | |
| @@ -59,7 +60,7 @@ class ConversationFinder | |
| def perform_meta_only | |
| set_up | |
| - mine_count, unassigned_count, all_count, = set_count_for_all_conversations | |
| + mine_count, unassigned_count, all_count, participating_count = set_count_for_all_conversations | |
| assigned_count = all_count - unassigned_count | |
| { | |
| @@ -67,7 +68,8 @@ class ConversationFinder | |
| mine_count: mine_count, | |
| assigned_count: assigned_count, | |
| unassigned_count: unassigned_count, | |
| - all_count: all_count | |
| + all_count: all_count, | |
| + participating_count: participating_count | |
| } | |
| } | |
| end | |
| @@ -131,6 +133,10 @@ class ConversationFinder | |
| @conversations = @conversations.unassigned | |
| when 'assigned' | |
| @conversations = @conversations.assigned | |
| + when 'participating' | |
| + @conversations = @conversations.where( | |
| + id: current_user.participating_conversations.select(:id) | |
| + ) | |
| end | |
| @conversations | |
| end | |
| @@ -187,7 +193,8 @@ class ConversationFinder | |
| [ | |
| @conversations.assigned_to(current_user).count, | |
| @conversations.unassigned.count, | |
| - @conversations.count | |
| + @conversations.count, | |
| + @conversations.where(id: current_user.participating_conversations.select(:id)).count | |
| ] | |
| end | |
| diff --git a/app/javascript/dashboard/components/ChatList.vue b/app/javascript/dashboard/components/ChatList.vue | |
| index eeb2ad6e7..460ec2e92 100644 | |
| --- a/app/javascript/dashboard/components/ChatList.vue | |
| +++ b/app/javascript/dashboard/components/ChatList.vue | |
| @@ -111,6 +111,7 @@ const advancedFilterTypes = ref( | |
| const currentUser = useMapGetter('getCurrentUser'); | |
| const chatLists = useMapGetter('getFilteredConversations'); | |
| const mineChatsList = useMapGetter('getMineChats'); | |
| +const participatingChatsList = useMapGetter('getParticipatingChats'); | |
| const allChatList = useMapGetter('getAllStatusChats'); | |
| const unAssignedChatsList = useMapGetter('getUnAssignedChats'); | |
| const chatListLoading = useMapGetter('getChatListLoadingStatus'); | |
| @@ -207,7 +208,8 @@ const assigneeTabItems = computed(() => { | |
| const showAssigneeInConversationCard = computed(() => { | |
| return ( | |
| hasAppliedFiltersOrActiveFolders.value || | |
| - activeAssigneeTab.value === wootConstants.ASSIGNEE_TYPE.ALL | |
| + activeAssigneeTab.value === wootConstants.ASSIGNEE_TYPE.ALL || | |
| + activeAssigneeTab.value === wootConstants.ASSIGNEE_TYPE.PARTICIPATING | |
| ); | |
| }); | |
| @@ -318,6 +320,8 @@ const conversationList = computed(() => { | |
| const filters = conversationFilters.value; | |
| if (activeAssigneeTab.value === 'me') { | |
| localConversationList = [...mineChatsList.value(filters)]; | |
| + } else if (activeAssigneeTab.value === 'participating') { | |
| + localConversationList = [...participatingChatsList.value(filters)]; | |
| } else if (activeAssigneeTab.value === 'unassigned') { | |
| localConversationList = [...unAssignedChatsList.value(filters)]; | |
| } else { | |
| diff --git a/app/javascript/dashboard/constants/globals.js b/app/javascript/dashboard/constants/globals.js | |
| index 21303efcb..fadbcaffd 100644 | |
| --- a/app/javascript/dashboard/constants/globals.js | |
| +++ b/app/javascript/dashboard/constants/globals.js | |
| @@ -2,6 +2,7 @@ export default { | |
| GRAVATAR_URL: 'https://www.gravatar.com/avatar/', | |
| ASSIGNEE_TYPE: { | |
| ME: 'me', | |
| + PARTICIPATING: 'participating', | |
| UNASSIGNED: 'unassigned', | |
| ALL: 'all', | |
| }, | |
| diff --git a/app/javascript/dashboard/constants/permissions.js b/app/javascript/dashboard/constants/permissions.js | |
| index 1ecbd9793..2189215d6 100644 | |
| --- a/app/javascript/dashboard/constants/permissions.js | |
| +++ b/app/javascript/dashboard/constants/permissions.js | |
| @@ -34,6 +34,10 @@ export const ASSIGNEE_TYPE_TAB_PERMISSIONS = { | |
| count: 'mineCount', | |
| permissions: [...ROLES, ...CONVERSATION_PERMISSIONS], | |
| }, | |
| + participating: { | |
| + count: 'participatingCount', | |
| + permissions: [...ROLES, ...CONVERSATION_PERMISSIONS], | |
| + }, | |
| unassigned: { | |
| count: 'unAssignedCount', | |
| permissions: [ | |
| diff --git a/app/javascript/dashboard/i18n/locale/en/chatlist.json b/app/javascript/dashboard/i18n/locale/en/chatlist.json | |
| index 0e8e87a04..c652797d8 100644 | |
| --- a/app/javascript/dashboard/i18n/locale/en/chatlist.json | |
| +++ b/app/javascript/dashboard/i18n/locale/en/chatlist.json | |
| @@ -16,6 +16,7 @@ | |
| "FILTER_ALL": "All", | |
| "ASSIGNEE_TYPE_TABS": { | |
| "me": "Mine", | |
| + "participating": "Participating", | |
| "unassigned": "Unassigned", | |
| "all": "All" | |
| }, | |
| diff --git a/app/javascript/dashboard/store/modules/conversationStats.js b/app/javascript/dashboard/store/modules/conversationStats.js | |
| index ba3e5c455..2d85d9f08 100644 | |
| --- a/app/javascript/dashboard/store/modules/conversationStats.js | |
| +++ b/app/javascript/dashboard/store/modules/conversationStats.js | |
| @@ -4,6 +4,7 @@ import { debounce } from '@chatwoot/utils'; | |
| const state = { | |
| mineCount: 0, | |
| + participatingCount: 0, | |
| unAssignedCount: 0, | |
| allCount: 0, | |
| }; | |
| @@ -54,11 +55,13 @@ export const mutations = { | |
| $state, | |
| { | |
| mine_count: mineCount, | |
| + participating_count: participatingCount, | |
| unassigned_count: unAssignedCount, | |
| all_count: allCount, | |
| } = {} | |
| ) { | |
| $state.mineCount = mineCount; | |
| + $state.participatingCount = participatingCount; | |
| $state.allCount = allCount; | |
| $state.unAssignedCount = unAssignedCount; | |
| $state.updatedOn = new Date(); | |
| diff --git a/app/javascript/dashboard/store/modules/conversations/getters.js b/app/javascript/dashboard/store/modules/conversations/getters.js | |
| index 9f5744fbb..11b9a296f 100644 | |
| --- a/app/javascript/dashboard/store/modules/conversations/getters.js | |
| +++ b/app/javascript/dashboard/store/modules/conversations/getters.js | |
| @@ -102,6 +102,11 @@ const getters = { | |
| return isUnAssigned && shouldFilter; | |
| }); | |
| }, | |
| + getParticipatingChats: _state => activeFilters => { | |
| + return _state.allConversations.filter(conversation => { | |
| + return applyPageFilters(conversation, activeFilters); | |
| + }); | |
| + }, | |
| getAllStatusChats: (_state, _, __, rootGetters) => activeFilters => { | |
| const currentUser = rootGetters.getCurrentUser; | |
| const currentUserId = rootGetters.getCurrentUser.id; | |
| diff --git a/app/javascript/dashboard/store/modules/specs/conversationStats/getters.spec.js b/app/javascript/dashboard/store/modules/specs/conversationStats/getters.spec.js | |
| index 38b7a88bc..feb19e888 100644 | |
| --- a/app/javascript/dashboard/store/modules/specs/conversationStats/getters.spec.js | |
| +++ b/app/javascript/dashboard/store/modules/specs/conversationStats/getters.spec.js | |
| @@ -4,11 +4,13 @@ describe('#getters', () => { | |
| it('getCurrentPage', () => { | |
| const state = { | |
| mineCount: 1, | |
| + participatingCount: 1, | |
| unAssignedCount: 1, | |
| allCount: 2, | |
| }; | |
| expect(getters.getStats(state)).toEqual({ | |
| mineCount: 1, | |
| + participatingCount: 1, | |
| unAssignedCount: 1, | |
| allCount: 2, | |
| }); | |
| diff --git a/app/javascript/dashboard/store/modules/specs/conversationStats/mutations.spec.js b/app/javascript/dashboard/store/modules/specs/conversationStats/mutations.spec.js | |
| index e625eb13c..22b702861 100644 | |
| --- a/app/javascript/dashboard/store/modules/specs/conversationStats/mutations.spec.js | |
| +++ b/app/javascript/dashboard/store/modules/specs/conversationStats/mutations.spec.js | |
| @@ -7,11 +7,13 @@ describe('#mutations', () => { | |
| const state = {}; | |
| mutations[types.SET_CONV_TAB_META](state, { | |
| mine_count: 1, | |
| + participating_count: 1, | |
| unassigned_count: 1, | |
| all_count: 2, | |
| }); | |
| expect(state).toEqual({ | |
| mineCount: 1, | |
| + participatingCount: 1, | |
| unAssignedCount: 1, | |
| allCount: 2, | |
| updatedOn: expect.any(Date), | |
| diff --git a/app/listeners/participation_listener.rb b/app/listeners/participation_listener.rb | |
| index b9f94e252..e7d08aa5e 100644 | |
| --- a/app/listeners/participation_listener.rb | |
| +++ b/app/listeners/participation_listener.rb | |
| @@ -12,4 +12,14 @@ class ParticipationListener < BaseListener | |
| Rails.logger.warn "Failed to create conversation participant for account #{conversation.account.id} " \ | |
| ": user #{conversation.assignee_id} : conversation #{conversation.id}" | |
| end | |
| + | |
| + def message_created(event) | |
| + message = extract_message_and_account(event)[0] | |
| + return unless message.sender_type == 'User' | |
| + return unless message.outgoing? || message.private? | |
| + | |
| + message.conversation.conversation_participants.find_or_create_by!(user_id: message.sender_id) | |
| + rescue ActiveRecord::RecordNotUnique, ActiveRecord::RecordInvalid | |
| + # Ignore race conditions | |
| + end | |
| end | |
| diff --git a/app/views/api/v1/accounts/conversations/index.json.jbuilder b/app/views/api/v1/accounts/conversations/index.json.jbuilder | |
| index 670899f38..9ab045316 100644 | |
| --- a/app/views/api/v1/accounts/conversations/index.json.jbuilder | |
| +++ b/app/views/api/v1/accounts/conversations/index.json.jbuilder | |
| @@ -4,6 +4,7 @@ json.data do | |
| json.assigned_count @conversations_count[:assigned_count] | |
| json.unassigned_count @conversations_count[:unassigned_count] | |
| json.all_count @conversations_count[:all_count] | |
| + json.participating_count @conversations_count[:participating_count] | |
| end | |
| json.payload do | |
| json.array! @conversations do |conversation| | |
| diff --git a/app/views/api/v1/accounts/conversations/meta.json.jbuilder b/app/views/api/v1/accounts/conversations/meta.json.jbuilder | |
| index 0326ad52f..84cca79e6 100644 | |
| --- a/app/views/api/v1/accounts/conversations/meta.json.jbuilder | |
| +++ b/app/views/api/v1/accounts/conversations/meta.json.jbuilder | |
| @@ -3,4 +3,5 @@ json.meta do | |
| json.assigned_count @conversations_count[:assigned_count] | |
| json.unassigned_count @conversations_count[:unassigned_count] | |
| json.all_count @conversations_count[:all_count] | |
| + json.participating_count @conversations_count[:participating_count] | |
| end | |
| diff --git a/docker-compose.yaml b/docker-compose.yaml | |
| index facac830f..9ea7ff85c 100644 | |
| --- a/docker-compose.yaml | |
| +++ b/docker-compose.yaml | |
| @@ -41,7 +41,7 @@ services: | |
| - NODE_ENV=development | |
| - RAILS_ENV=development | |
| entrypoint: docker/entrypoints/rails.sh | |
| - command: ["bundle", "exec", "rails", "s", "-p", "3000", "-b", "0.0.0.0"] | |
| + command: ['bundle', 'exec', 'rails', 's', '-p', '3000', '-b', '0.0.0.0'] | |
| sidekiq: | |
| <<: *base | |
| @@ -59,7 +59,7 @@ services: | |
| environment: | |
| - NODE_ENV=development | |
| - RAILS_ENV=development | |
| - command: ["bundle", "exec", "sidekiq", "-C", "config/sidekiq.yml"] | |
| + command: ['bundle', 'exec', 'sidekiq', '-C', 'config/sidekiq.yml'] | |
| vite: | |
| <<: *base | |
| @@ -74,7 +74,7 @@ services: | |
| - cache:/app/tmp/cache | |
| - bundle:/usr/local/bundle | |
| ports: | |
| - - "3036:3036" # Vite dev server | |
| + - '3036:3036' # Vite dev server | |
| environment: | |
| - VITE_DEV_SERVER_HOST=0.0.0.0 | |
| - NODE_ENV=development | |
| @@ -92,12 +92,12 @@ services: | |
| environment: | |
| - POSTGRES_DB=chatwoot | |
| - POSTGRES_USER=postgres | |
| - - POSTGRES_PASSWORD= | |
| + - POSTGRES_PASSWORD=chatwootpass | |
| redis: | |
| image: redis:alpine | |
| restart: always | |
| - command: ["sh", "-c", "redis-server --requirepass \"$REDIS_PASSWORD\""] | |
| + command: ['sh', '-c', 'redis-server --requirepass "$REDIS_PASSWORD"'] | |
| env_file: .env | |
| volumes: | |
| - redis:/data/redis | |
| -- | |
| 2.53.0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment