diff --git a/app/javascript/dashboard/components/ChatList.vue b/app/javascript/dashboard/components/ChatList.vue
index 348d8572a..60966b476 100644
--- a/app/javascript/dashboard/components/ChatList.vue
+++ b/app/javascript/dashboard/components/ChatList.vue
@@ -7,79 +7,17 @@
]"
>
-
-
-
- {{ pageTitle }}
-
-
- {{ $t(`CHAT_LIST.CHAT_STATUS_FILTER_ITEMS.${activeStatus}.TEXT`) }}
-
-
-
-
+
+
+
+
@@ -180,8 +127,8 @@
import { mapGetters } from 'vuex';
import VirtualList from 'vue-virtual-scroll-list';
+import ChatListHeader from './ChatListHeader.vue';
import ConversationAdvancedFilter from './widgets/conversation/ConversationAdvancedFilter.vue';
-import ConversationBasicFilter from './widgets/conversation/ConversationBasicFilter.vue';
import ChatTypeTabs from './widgets/ChatTypeTabs.vue';
import ConversationItem from './ConversationItem.vue';
import timeMixin from '../mixins/time';
@@ -205,10 +152,15 @@ import {
isOnUnattendedView,
} from '../store/modules/conversations/helpers/actionHelpers';
import { CONVERSATION_EVENTS } from '../helper/AnalyticsHelper/events';
+import { CMD_SNOOZE_CONVERSATION } from 'dashboard/routes/dashboard/commands/commandBarBusEvents';
+import { findSnoozeTime } from 'dashboard/helper/snoozeHelpers';
+import { getUnixTime } from 'date-fns';
+import CustomSnoozeModal from 'dashboard/components/CustomSnoozeModal.vue';
import IntersectionObserver from './IntersectionObserver.vue';
export default {
components: {
+ ChatListHeader,
AddCustomViews,
ChatTypeTabs,
// eslint-disable-next-line vue/no-unused-components
@@ -216,9 +168,9 @@ export default {
ConversationAdvancedFilter,
DeleteCustomViews,
ConversationBulkActions,
- ConversationBasicFilter,
IntersectionObserver,
VirtualList,
+ CustomSnoozeModal,
},
mixins: [
timeMixin,
@@ -295,6 +247,7 @@ export default {
root: this.$refs.conversationList,
rootMargin: '100px 0px 100px 0px',
},
+ showCustomSnoozeModal: false,
itemComponent: ConversationItem,
// virtualListExtraProps is to pass the props to the conversationItem component.
@@ -329,12 +282,13 @@ export default {
campaigns: 'campaigns/getAllCampaigns',
labels: 'labels/getLabels',
selectedConversations: 'bulkActions/getSelectedConversationIds',
+ contextMenuChatId: 'getContextMenuChatId',
}),
hasAppliedFilters() {
return this.appliedFilters.length !== 0;
},
hasActiveFolders() {
- return this.activeFolder && this.foldersId !== 0;
+ return Boolean(this.activeFolder && this.foldersId !== 0);
},
hasAppliedFiltersOrActiveFolders() {
return this.hasAppliedFilters || this.hasActiveFolders;
@@ -558,6 +512,11 @@ export default {
bus.$on('fetch_conversation_stats', () => {
this.$store.dispatch('conversationStats/get', this.conversationFilters);
});
+
+ bus.$on(CMD_SNOOZE_CONVERSATION, this.onCmdSnoozeConversation);
+ },
+ beforeDestroy() {
+ bus.$off(CMD_SNOOZE_CONVERSATION, this.onCmdSnoozeConversation);
},
methods: {
updateVirtualListProps(key, value) {
@@ -1034,6 +993,43 @@ export default {
onContextMenuToggle(state) {
this.isContextMenuOpen = state;
},
+ onCmdSnoozeConversation(snoozeType) {
+ if (snoozeType === wootConstants.SNOOZE_OPTIONS.UNTIL_CUSTOM_TIME) {
+ this.showCustomSnoozeModal = true;
+ } else {
+ this.toggleStatus(
+ wootConstants.STATUS_TYPE.SNOOZED,
+ findSnoozeTime(snoozeType) || null
+ );
+ }
+ },
+ chooseSnoozeTime(customSnoozeTime) {
+ this.showCustomSnoozeModal = false;
+ if (customSnoozeTime) {
+ this.toggleStatus(
+ wootConstants.STATUS_TYPE.SNOOZED,
+ getUnixTime(customSnoozeTime)
+ );
+ }
+ },
+ toggleStatus(status, snoozedUntil) {
+ this.$store
+ .dispatch('toggleStatus', {
+ conversationId: this.currentChat?.id || this.contextMenuChatId,
+ status,
+ snoozedUntil,
+ })
+ .then(() => {
+ this.$store.dispatch('setContextMenuChatId', null);
+ this.showAlert(this.$t('CONVERSATION.CHANGE_STATUS'));
+ });
+ },
+ hideCustomSnoozeModal() {
+ // if we select custom snooze and then the custom snooze modal is open
+ // Then if the custom snooze modal is closed and set the context menu chat id to null
+ this.$store.dispatch('setContextMenuChatId', null);
+ this.showCustomSnoozeModal = false;
+ },
},
};
diff --git a/app/javascript/dashboard/components/ChatListHeader.vue b/app/javascript/dashboard/components/ChatListHeader.vue
new file mode 100644
index 000000000..d2df2bea3
--- /dev/null
+++ b/app/javascript/dashboard/components/ChatListHeader.vue
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+ {{ pageTitle }}
+
+
+ {{ $t(`CHAT_LIST.CHAT_STATUS_FILTER_ITEMS.${activeStatus}.TEXT`) }}
+
+
+
+
+
diff --git a/app/javascript/dashboard/components/buttons/ResolveAction.vue b/app/javascript/dashboard/components/buttons/ResolveAction.vue
index 61375dc21..c56f27e14 100644
--- a/app/javascript/dashboard/components/buttons/ResolveAction.vue
+++ b/app/javascript/dashboard/components/buttons/ResolveAction.vue
@@ -73,25 +73,13 @@
-
-
-
diff --git a/app/javascript/dashboard/routes/dashboard/commands/conversationHotKeys.js b/app/javascript/dashboard/routes/dashboard/commands/conversationHotKeys.js
index 5d0b1960d..aaa73c5d4 100644
--- a/app/javascript/dashboard/routes/dashboard/commands/conversationHotKeys.js
+++ b/app/javascript/dashboard/routes/dashboard/commands/conversationHotKeys.js
@@ -55,11 +55,15 @@ export default {
replyMode() {
this.setCommandbarData();
},
+ contextMenuChatId() {
+ this.setCommandbarData();
+ },
},
computed: {
...mapGetters({
currentChat: 'getSelectedChat',
replyMode: 'draftMessages/getReplyEditorMode',
+ contextMenuChatId: 'getContextMenuChatId',
}),
draftMessage() {
return this.$store.getters['draftMessages/get'](this.draftKey);
@@ -93,6 +97,7 @@ export default {
}
return this.prepareActions(actions);
},
+
priorityOptions() {
return [
{
@@ -327,25 +332,42 @@ export default {
];
},
- conversationHotKeys() {
- if (
+ isConversationOrInboxRoute() {
+ return (
isAConversationRoute(this.$route.name) ||
isAInboxViewRoute(this.$route.name)
- ) {
- const defaultConversationHotKeys = [
- ...this.statusActions,
- ...this.conversationAdditionalActions,
- ...this.assignAgentActions,
- ...this.assignTeamActions,
- ...this.labelActions,
- ...this.assignPriorityActions,
- ];
- if (this.isAIIntegrationEnabled) {
- return [...defaultConversationHotKeys, ...this.AIAssistActions];
- }
- return defaultConversationHotKeys;
- }
+ );
+ },
+ shouldShowSnoozeOption() {
+ return (
+ isAConversationRoute(this.$route.name, true, false) &&
+ this.contextMenuChatId
+ );
+ },
+
+ getDefaultConversationHotKeys() {
+ const defaultConversationHotKeys = [
+ ...this.statusActions,
+ ...this.conversationAdditionalActions,
+ ...this.assignAgentActions,
+ ...this.assignTeamActions,
+ ...this.labelActions,
+ ...this.assignPriorityActions,
+ ];
+ if (this.isAIIntegrationEnabled) {
+ return [...defaultConversationHotKeys, ...this.AIAssistActions];
+ }
+ return defaultConversationHotKeys;
+ },
+
+ conversationHotKeys() {
+ if (this.shouldShowSnoozeOption) {
+ return this.prepareActions(SNOOZE_CONVERSATION_ACTIONS);
+ }
+ if (this.isConversationOrInboxRoute) {
+ return this.getDefaultConversationHotKeys;
+ }
return [];
},
},
diff --git a/app/javascript/dashboard/store/modules/conversations/actions.js b/app/javascript/dashboard/store/modules/conversations/actions.js
index 0a9d23c6b..12877078a 100644
--- a/app/javascript/dashboard/store/modules/conversations/actions.js
+++ b/app/javascript/dashboard/store/modules/conversations/actions.js
@@ -466,6 +466,10 @@ const actions = {
commit(types.ASSIGN_PRIORITY, { priority, conversationId });
},
+ setContextMenuChatId({ commit }, chatId) {
+ commit(types.SET_CONTEXT_MENU_CHAT_ID, chatId);
+ },
+
...messageReadActions,
...messageTranslateActions,
};
diff --git a/app/javascript/dashboard/store/modules/conversations/getters.js b/app/javascript/dashboard/store/modules/conversations/getters.js
index 62e9ef4ef..4ba517616 100644
--- a/app/javascript/dashboard/store/modules/conversations/getters.js
+++ b/app/javascript/dashboard/store/modules/conversations/getters.js
@@ -100,6 +100,10 @@ const getters = {
getConversationLastSeen: _state => {
return _state.conversationLastSeen;
},
+
+ getContextMenuChatId: _state => {
+ return _state.contextMenuChatId;
+ },
};
export default getters;
diff --git a/app/javascript/dashboard/store/modules/conversations/index.js b/app/javascript/dashboard/store/modules/conversations/index.js
index 6bce92e02..83250fa38 100644
--- a/app/javascript/dashboard/store/modules/conversations/index.js
+++ b/app/javascript/dashboard/store/modules/conversations/index.js
@@ -15,6 +15,7 @@ const state = {
currentInbox: null,
selectedChatId: null,
appliedFilters: [],
+ contextMenuChatId: null,
conversationParticipants: [],
conversationLastSeen: null,
syncConversationsMessages: {},
@@ -281,6 +282,10 @@ export const mutations = {
) {
_state.syncConversationsMessages[conversationId] = messageId;
},
+
+ [types.SET_CONTEXT_MENU_CHAT_ID](_state, chatId) {
+ _state.contextMenuChatId = chatId;
+ },
};
export default {
diff --git a/app/javascript/dashboard/store/modules/specs/conversations/actions.spec.js b/app/javascript/dashboard/store/modules/specs/conversations/actions.spec.js
index 648ab2a46..ad42d24f7 100644
--- a/app/javascript/dashboard/store/modules/specs/conversations/actions.spec.js
+++ b/app/javascript/dashboard/store/modules/specs/conversations/actions.spec.js
@@ -652,4 +652,11 @@ describe('#addMentions', () => {
]);
});
});
+
+ describe('#setContextMenuChatId', () => {
+ it('sets the context menu chat id', () => {
+ actions.setContextMenuChatId({ commit }, 1);
+ expect(commit.mock.calls).toEqual([[types.SET_CONTEXT_MENU_CHAT_ID, 1]]);
+ });
+ });
});
diff --git a/app/javascript/dashboard/store/modules/specs/conversations/getters.spec.js b/app/javascript/dashboard/store/modules/specs/conversations/getters.spec.js
index 1a2225da6..6126692e3 100644
--- a/app/javascript/dashboard/store/modules/specs/conversations/getters.spec.js
+++ b/app/javascript/dashboard/store/modules/specs/conversations/getters.spec.js
@@ -272,4 +272,11 @@ describe('#getters', () => {
]);
});
});
+
+ describe('#getContextMenuChatId', () => {
+ it('returns the context menu chat id', () => {
+ const state = { contextMenuChatId: 1 };
+ expect(getters.getContextMenuChatId(state)).toEqual(1);
+ });
+ });
});
diff --git a/app/javascript/dashboard/store/modules/specs/conversations/mutations.spec.js b/app/javascript/dashboard/store/modules/specs/conversations/mutations.spec.js
index 279b36872..93a617ddd 100644
--- a/app/javascript/dashboard/store/modules/specs/conversations/mutations.spec.js
+++ b/app/javascript/dashboard/store/modules/specs/conversations/mutations.spec.js
@@ -403,4 +403,12 @@ describe('#mutations', () => {
expect(state.allConversations[0].attachments).toHaveLength(1);
});
});
+
+ describe('#SET_CONTEXT_MENU_CHAT_ID', () => {
+ it('sets the context menu chat id', () => {
+ const state = { contextMenuChatId: 1 };
+ mutations[types.SET_CONTEXT_MENU_CHAT_ID](state, 2);
+ expect(state.contextMenuChatId).toEqual(2);
+ });
+ });
});
diff --git a/app/javascript/dashboard/store/mutation-types.js b/app/javascript/dashboard/store/mutation-types.js
index 40db99212..e424d56b8 100644
--- a/app/javascript/dashboard/store/mutation-types.js
+++ b/app/javascript/dashboard/store/mutation-types.js
@@ -58,6 +58,8 @@ export default {
SET_CONVERSATION_CAN_REPLY: 'SET_CONVERSATION_CAN_REPLY',
+ SET_CONTEXT_MENU_CHAT_ID: 'SET_CONTEXT_MENU_CHAT_ID',
+
// Inboxes
SET_INBOXES_UI_FLAG: 'SET_INBOXES_UI_FLAG',
SET_INBOXES: 'SET_INBOXES',
diff --git a/package.json b/package.json
index 1063ddf16..78fb2fed1 100644
--- a/package.json
+++ b/package.json
@@ -67,7 +67,7 @@
"markdown-it": "^13.0.2",
"markdown-it-link-attributes": "^4.0.1",
"md5": "^2.3.0",
- "ninja-keys": "^1.2.2",
+ "@chatwoot/ninja-keys": "1.2.3",
"opus-recorder": "^8.0.5",
"postcss": "^8.4.31",
"postcss-loader": "^4.2.0",
diff --git a/yarn.lock b/yarn.lock
index 0aefd8413..daecee4b6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3156,6 +3156,15 @@
"@braid/vue-formulate-i18n" "^1.16.0"
is-plain-object "^3.0.1"
+"@chatwoot/ninja-keys@1.2.3":
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/@chatwoot/ninja-keys/-/ninja-keys-1.2.3.tgz#3c3f2b505f091ef4707fd1da39bb2ec6d12e7824"
+ integrity sha512-xM8d9P5ikDMZm2WbaCTk/TW5HFauylrU3cJ75fq5je6ixKwyhl/0kZbVN/vbbZN4+AUX/OaSIn6IJbtCgIF67g==
+ dependencies:
+ "@material/mwc-icon" "0.25.3"
+ hotkeys-js "3.8.7"
+ lit "2.2.6"
+
"@chatwoot/prosemirror-schema@1.0.5":
version "1.0.5"
resolved "https://registry.yarnpkg.com/@chatwoot/prosemirror-schema/-/prosemirror-schema-1.0.5.tgz#d6053692beae59d466ac0b04128fa157f59eb176"
@@ -15083,15 +15092,6 @@ nice-try@^1.0.4:
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
-ninja-keys@^1.2.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/ninja-keys/-/ninja-keys-1.2.2.tgz#c1e1ec1a98aee3a977ee77157ac4aa865348be88"
- integrity sha512-ylo8jzKowi3XBHkgHRjBJaKQkl32WRLr7kRiA0ajiku11vHRDJ2xANtTScR5C7XlDwKEOYvUPesCKacUeeLAYw==
- dependencies:
- "@material/mwc-icon" "0.25.3"
- hotkeys-js "3.8.7"
- lit "2.2.6"
-
no-case@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"