mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-01 03:27:52 +00:00
fix: Right click Snooze is not working (#9498)
This commit is contained in:
@@ -7,79 +7,17 @@
|
|||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
<div
|
<chat-list-header
|
||||||
class="flex items-center justify-between px-4 py-0"
|
:page-title="pageTitle"
|
||||||
:class="{
|
:has-applied-filters="hasAppliedFilters"
|
||||||
'pb-3 border-b border-slate-75 dark:border-slate-700':
|
:has-active-folders="hasActiveFolders"
|
||||||
hasAppliedFiltersOrActiveFolders,
|
:active-status="activeStatus"
|
||||||
}"
|
@add-folders="onClickOpenAddFoldersModal"
|
||||||
>
|
@delete-folders="onClickOpenDeleteFoldersModal"
|
||||||
<div class="flex max-w-[85%] justify-center items-center">
|
@filters-modal="onToggleAdvanceFiltersModal"
|
||||||
<h1
|
@reset-filters="resetAndFetchData"
|
||||||
class="text-xl font-medium break-words truncate text-black-900 dark:text-slate-100"
|
@basic-filter-change="onBasicFilterChange"
|
||||||
:title="pageTitle"
|
|
||||||
>
|
|
||||||
{{ pageTitle }}
|
|
||||||
</h1>
|
|
||||||
<span
|
|
||||||
v-if="!hasAppliedFiltersOrActiveFolders"
|
|
||||||
class="p-1 my-0.5 mx-1 rounded-md capitalize bg-slate-50 dark:bg-slate-800 text-xxs text-slate-600 dark:text-slate-300"
|
|
||||||
>
|
|
||||||
{{ $t(`CHAT_LIST.CHAT_STATUS_FILTER_ITEMS.${activeStatus}.TEXT`) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center gap-1">
|
|
||||||
<div v-if="hasAppliedFilters && !hasActiveFolders">
|
|
||||||
<woot-button
|
|
||||||
v-tooltip.top-end="$t('FILTER.CUSTOM_VIEWS.ADD.SAVE_BUTTON')"
|
|
||||||
size="tiny"
|
|
||||||
variant="smooth"
|
|
||||||
color-scheme="secondary"
|
|
||||||
icon="save"
|
|
||||||
@click="onClickOpenAddFoldersModal"
|
|
||||||
/>
|
/>
|
||||||
<woot-button
|
|
||||||
v-tooltip.top-end="$t('FILTER.CLEAR_BUTTON_LABEL')"
|
|
||||||
size="tiny"
|
|
||||||
variant="smooth"
|
|
||||||
color-scheme="alert"
|
|
||||||
icon="dismiss-circle"
|
|
||||||
@click="resetAndFetchData"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div v-if="hasActiveFolders">
|
|
||||||
<woot-button
|
|
||||||
v-tooltip.top-end="$t('FILTER.CUSTOM_VIEWS.EDIT.EDIT_BUTTON')"
|
|
||||||
size="tiny"
|
|
||||||
variant="smooth"
|
|
||||||
color-scheme="secondary"
|
|
||||||
icon="edit"
|
|
||||||
@click="onToggleAdvanceFiltersModal"
|
|
||||||
/>
|
|
||||||
<woot-button
|
|
||||||
v-tooltip.top-end="$t('FILTER.CUSTOM_VIEWS.DELETE.DELETE_BUTTON')"
|
|
||||||
size="tiny"
|
|
||||||
variant="smooth"
|
|
||||||
color-scheme="alert"
|
|
||||||
icon="delete"
|
|
||||||
@click="onClickOpenDeleteFoldersModal"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<woot-button
|
|
||||||
v-else
|
|
||||||
v-tooltip.right="$t('FILTER.TOOLTIP_LABEL')"
|
|
||||||
variant="smooth"
|
|
||||||
color-scheme="secondary"
|
|
||||||
icon="filter"
|
|
||||||
size="tiny"
|
|
||||||
@click="onToggleAdvanceFiltersModal"
|
|
||||||
/>
|
|
||||||
<conversation-basic-filter
|
|
||||||
v-if="!hasAppliedFiltersOrActiveFolders"
|
|
||||||
@changeFilter="onBasicFilterChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<add-custom-views
|
<add-custom-views
|
||||||
v-if="showAddFoldersModal"
|
v-if="showAddFoldersModal"
|
||||||
@@ -173,6 +111,15 @@
|
|||||||
@updateFolder="onUpdateSavedFilter"
|
@updateFolder="onUpdateSavedFilter"
|
||||||
/>
|
/>
|
||||||
</woot-modal>
|
</woot-modal>
|
||||||
|
<woot-modal
|
||||||
|
:show.sync="showCustomSnoozeModal"
|
||||||
|
:on-close="hideCustomSnoozeModal"
|
||||||
|
>
|
||||||
|
<custom-snooze-modal
|
||||||
|
@close="hideCustomSnoozeModal"
|
||||||
|
@choose-time="chooseSnoozeTime"
|
||||||
|
/>
|
||||||
|
</woot-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -180,8 +127,8 @@
|
|||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import VirtualList from 'vue-virtual-scroll-list';
|
import VirtualList from 'vue-virtual-scroll-list';
|
||||||
|
|
||||||
|
import ChatListHeader from './ChatListHeader.vue';
|
||||||
import ConversationAdvancedFilter from './widgets/conversation/ConversationAdvancedFilter.vue';
|
import ConversationAdvancedFilter from './widgets/conversation/ConversationAdvancedFilter.vue';
|
||||||
import ConversationBasicFilter from './widgets/conversation/ConversationBasicFilter.vue';
|
|
||||||
import ChatTypeTabs from './widgets/ChatTypeTabs.vue';
|
import ChatTypeTabs from './widgets/ChatTypeTabs.vue';
|
||||||
import ConversationItem from './ConversationItem.vue';
|
import ConversationItem from './ConversationItem.vue';
|
||||||
import timeMixin from '../mixins/time';
|
import timeMixin from '../mixins/time';
|
||||||
@@ -205,10 +152,15 @@ import {
|
|||||||
isOnUnattendedView,
|
isOnUnattendedView,
|
||||||
} from '../store/modules/conversations/helpers/actionHelpers';
|
} from '../store/modules/conversations/helpers/actionHelpers';
|
||||||
import { CONVERSATION_EVENTS } from '../helper/AnalyticsHelper/events';
|
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';
|
import IntersectionObserver from './IntersectionObserver.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
ChatListHeader,
|
||||||
AddCustomViews,
|
AddCustomViews,
|
||||||
ChatTypeTabs,
|
ChatTypeTabs,
|
||||||
// eslint-disable-next-line vue/no-unused-components
|
// eslint-disable-next-line vue/no-unused-components
|
||||||
@@ -216,9 +168,9 @@ export default {
|
|||||||
ConversationAdvancedFilter,
|
ConversationAdvancedFilter,
|
||||||
DeleteCustomViews,
|
DeleteCustomViews,
|
||||||
ConversationBulkActions,
|
ConversationBulkActions,
|
||||||
ConversationBasicFilter,
|
|
||||||
IntersectionObserver,
|
IntersectionObserver,
|
||||||
VirtualList,
|
VirtualList,
|
||||||
|
CustomSnoozeModal,
|
||||||
},
|
},
|
||||||
mixins: [
|
mixins: [
|
||||||
timeMixin,
|
timeMixin,
|
||||||
@@ -295,6 +247,7 @@ export default {
|
|||||||
root: this.$refs.conversationList,
|
root: this.$refs.conversationList,
|
||||||
rootMargin: '100px 0px 100px 0px',
|
rootMargin: '100px 0px 100px 0px',
|
||||||
},
|
},
|
||||||
|
showCustomSnoozeModal: false,
|
||||||
|
|
||||||
itemComponent: ConversationItem,
|
itemComponent: ConversationItem,
|
||||||
// virtualListExtraProps is to pass the props to the conversationItem component.
|
// virtualListExtraProps is to pass the props to the conversationItem component.
|
||||||
@@ -329,12 +282,13 @@ export default {
|
|||||||
campaigns: 'campaigns/getAllCampaigns',
|
campaigns: 'campaigns/getAllCampaigns',
|
||||||
labels: 'labels/getLabels',
|
labels: 'labels/getLabels',
|
||||||
selectedConversations: 'bulkActions/getSelectedConversationIds',
|
selectedConversations: 'bulkActions/getSelectedConversationIds',
|
||||||
|
contextMenuChatId: 'getContextMenuChatId',
|
||||||
}),
|
}),
|
||||||
hasAppliedFilters() {
|
hasAppliedFilters() {
|
||||||
return this.appliedFilters.length !== 0;
|
return this.appliedFilters.length !== 0;
|
||||||
},
|
},
|
||||||
hasActiveFolders() {
|
hasActiveFolders() {
|
||||||
return this.activeFolder && this.foldersId !== 0;
|
return Boolean(this.activeFolder && this.foldersId !== 0);
|
||||||
},
|
},
|
||||||
hasAppliedFiltersOrActiveFolders() {
|
hasAppliedFiltersOrActiveFolders() {
|
||||||
return this.hasAppliedFilters || this.hasActiveFolders;
|
return this.hasAppliedFilters || this.hasActiveFolders;
|
||||||
@@ -558,6 +512,11 @@ export default {
|
|||||||
bus.$on('fetch_conversation_stats', () => {
|
bus.$on('fetch_conversation_stats', () => {
|
||||||
this.$store.dispatch('conversationStats/get', this.conversationFilters);
|
this.$store.dispatch('conversationStats/get', this.conversationFilters);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
bus.$on(CMD_SNOOZE_CONVERSATION, this.onCmdSnoozeConversation);
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
bus.$off(CMD_SNOOZE_CONVERSATION, this.onCmdSnoozeConversation);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateVirtualListProps(key, value) {
|
updateVirtualListProps(key, value) {
|
||||||
@@ -1034,6 +993,43 @@ export default {
|
|||||||
onContextMenuToggle(state) {
|
onContextMenuToggle(state) {
|
||||||
this.isContextMenuOpen = 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;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
115
app/javascript/dashboard/components/ChatListHeader.vue
Normal file
115
app/javascript/dashboard/components/ChatListHeader.vue
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import ConversationBasicFilter from './widgets/conversation/ConversationBasicFilter.vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
pageTitle: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
hasAppliedFilters: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
hasActiveFolders: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
activeStatus: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emits = defineEmits([
|
||||||
|
'add-folders',
|
||||||
|
'delete-folders',
|
||||||
|
'reset-filters',
|
||||||
|
'basic-filter-change',
|
||||||
|
'filters-modal',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const onBasicFilterChange = (value, type) => {
|
||||||
|
emits('basic-filter-change', value, type);
|
||||||
|
};
|
||||||
|
|
||||||
|
const hasAppliedFiltersOrActiveFolders = computed(() => {
|
||||||
|
return props.hasAppliedFilters || props.hasActiveFolders;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="flex items-center justify-between px-4 py-0"
|
||||||
|
:class="{
|
||||||
|
'pb-3 border-b border-slate-75 dark:border-slate-700':
|
||||||
|
hasAppliedFiltersOrActiveFolders,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div class="flex max-w-[85%] justify-center items-center">
|
||||||
|
<h1
|
||||||
|
class="text-xl font-medium break-words truncate text-black-900 dark:text-slate-100"
|
||||||
|
:title="pageTitle"
|
||||||
|
>
|
||||||
|
{{ pageTitle }}
|
||||||
|
</h1>
|
||||||
|
<span
|
||||||
|
v-if="!hasAppliedFiltersOrActiveFolders"
|
||||||
|
class="p-1 my-0.5 mx-1 rounded-md capitalize bg-slate-50 dark:bg-slate-800 text-xxs text-slate-600 dark:text-slate-300"
|
||||||
|
>
|
||||||
|
{{ $t(`CHAT_LIST.CHAT_STATUS_FILTER_ITEMS.${activeStatus}.TEXT`) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-1">
|
||||||
|
<div v-if="hasAppliedFilters && !hasActiveFolders">
|
||||||
|
<woot-button
|
||||||
|
v-tooltip.top-end="$t('FILTER.CUSTOM_VIEWS.ADD.SAVE_BUTTON')"
|
||||||
|
size="tiny"
|
||||||
|
variant="smooth"
|
||||||
|
color-scheme="secondary"
|
||||||
|
icon="save"
|
||||||
|
@click="emits('add-folders')"
|
||||||
|
/>
|
||||||
|
<woot-button
|
||||||
|
v-tooltip.top-end="$t('FILTER.CLEAR_BUTTON_LABEL')"
|
||||||
|
size="tiny"
|
||||||
|
variant="smooth"
|
||||||
|
color-scheme="alert"
|
||||||
|
icon="dismiss-circle"
|
||||||
|
@click="emits('reset-filters')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-if="hasActiveFolders">
|
||||||
|
<woot-button
|
||||||
|
v-tooltip.top-end="$t('FILTER.CUSTOM_VIEWS.EDIT.EDIT_BUTTON')"
|
||||||
|
size="tiny"
|
||||||
|
variant="smooth"
|
||||||
|
color-scheme="secondary"
|
||||||
|
icon="edit"
|
||||||
|
@click="emits('filters-modal')"
|
||||||
|
/>
|
||||||
|
<woot-button
|
||||||
|
v-tooltip.top-end="$t('FILTER.CUSTOM_VIEWS.DELETE.DELETE_BUTTON')"
|
||||||
|
size="tiny"
|
||||||
|
variant="smooth"
|
||||||
|
color-scheme="alert"
|
||||||
|
icon="delete"
|
||||||
|
@click="emits('delete-folders')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<woot-button
|
||||||
|
v-else
|
||||||
|
v-tooltip.right="$t('FILTER.TOOLTIP_LABEL')"
|
||||||
|
variant="smooth"
|
||||||
|
color-scheme="secondary"
|
||||||
|
icon="filter"
|
||||||
|
size="tiny"
|
||||||
|
@click="emits('filters-modal')"
|
||||||
|
/>
|
||||||
|
<conversation-basic-filter
|
||||||
|
v-if="!hasAppliedFiltersOrActiveFolders"
|
||||||
|
@changeFilter="onBasicFilterChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -73,25 +73,13 @@
|
|||||||
</woot-dropdown-item>
|
</woot-dropdown-item>
|
||||||
</woot-dropdown-menu>
|
</woot-dropdown-menu>
|
||||||
</div>
|
</div>
|
||||||
<woot-modal
|
|
||||||
:show.sync="showCustomSnoozeModal"
|
|
||||||
:on-close="hideCustomSnoozeModal"
|
|
||||||
>
|
|
||||||
<custom-snooze-modal
|
|
||||||
@close="hideCustomSnoozeModal"
|
|
||||||
@choose-time="chooseSnoozeTime"
|
|
||||||
/>
|
|
||||||
</woot-modal>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getUnixTime } from 'date-fns';
|
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import CustomSnoozeModal from 'dashboard/components/CustomSnoozeModal.vue';
|
|
||||||
import keyboardEventListenerMixins from 'shared/mixins/keyboardEventListenerMixins';
|
import keyboardEventListenerMixins from 'shared/mixins/keyboardEventListenerMixins';
|
||||||
import { findSnoozeTime } from 'dashboard/helper/snoozeHelpers';
|
|
||||||
import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue';
|
import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue';
|
||||||
import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue';
|
import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue';
|
||||||
|
|
||||||
@@ -99,14 +87,12 @@ import wootConstants from 'dashboard/constants/globals';
|
|||||||
import {
|
import {
|
||||||
CMD_REOPEN_CONVERSATION,
|
CMD_REOPEN_CONVERSATION,
|
||||||
CMD_RESOLVE_CONVERSATION,
|
CMD_RESOLVE_CONVERSATION,
|
||||||
CMD_SNOOZE_CONVERSATION,
|
|
||||||
} from '../../routes/dashboard/commands/commandBarBusEvents';
|
} from '../../routes/dashboard/commands/commandBarBusEvents';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
WootDropdownItem,
|
WootDropdownItem,
|
||||||
WootDropdownMenu,
|
WootDropdownMenu,
|
||||||
CustomSnoozeModal,
|
|
||||||
},
|
},
|
||||||
mixins: [alertMixin, keyboardEventListenerMixins],
|
mixins: [alertMixin, keyboardEventListenerMixins],
|
||||||
props: { conversationId: { type: [String, Number], required: true } },
|
props: { conversationId: { type: [String, Number], required: true } },
|
||||||
@@ -115,7 +101,6 @@ export default {
|
|||||||
isLoading: false,
|
isLoading: false,
|
||||||
showActionsDropdown: false,
|
showActionsDropdown: false,
|
||||||
STATUS_TYPE: wootConstants.STATUS_TYPE,
|
STATUS_TYPE: wootConstants.STATUS_TYPE,
|
||||||
showCustomSnoozeModal: false,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -143,12 +128,10 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
bus.$on(CMD_SNOOZE_CONVERSATION, this.onCmdSnoozeConversation);
|
|
||||||
bus.$on(CMD_REOPEN_CONVERSATION, this.onCmdOpenConversation);
|
bus.$on(CMD_REOPEN_CONVERSATION, this.onCmdOpenConversation);
|
||||||
bus.$on(CMD_RESOLVE_CONVERSATION, this.onCmdResolveConversation);
|
bus.$on(CMD_RESOLVE_CONVERSATION, this.onCmdResolveConversation);
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
bus.$off(CMD_SNOOZE_CONVERSATION, this.onCmdSnoozeConversation);
|
|
||||||
bus.$off(CMD_REOPEN_CONVERSATION, this.onCmdOpenConversation);
|
bus.$off(CMD_REOPEN_CONVERSATION, this.onCmdOpenConversation);
|
||||||
bus.$off(CMD_RESOLVE_CONVERSATION, this.onCmdResolveConversation);
|
bus.$off(CMD_RESOLVE_CONVERSATION, this.onCmdResolveConversation);
|
||||||
},
|
},
|
||||||
@@ -201,28 +184,6 @@ export default {
|
|||||||
// error
|
// error
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onCmdSnoozeConversation(snoozeType) {
|
|
||||||
if (snoozeType === wootConstants.SNOOZE_OPTIONS.UNTIL_CUSTOM_TIME) {
|
|
||||||
this.showCustomSnoozeModal = true;
|
|
||||||
} else {
|
|
||||||
this.toggleStatus(
|
|
||||||
this.STATUS_TYPE.SNOOZED,
|
|
||||||
findSnoozeTime(snoozeType) || null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
chooseSnoozeTime(customSnoozeTime) {
|
|
||||||
this.showCustomSnoozeModal = false;
|
|
||||||
if (customSnoozeTime) {
|
|
||||||
this.toggleStatus(
|
|
||||||
this.STATUS_TYPE.SNOOZED,
|
|
||||||
getUnixTime(customSnoozeTime)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hideCustomSnoozeModal() {
|
|
||||||
this.showCustomSnoozeModal = false;
|
|
||||||
},
|
|
||||||
onCmdOpenConversation() {
|
onCmdOpenConversation() {
|
||||||
this.toggleStatus(this.STATUS_TYPE.OPEN);
|
this.toggleStatus(this.STATUS_TYPE.OPEN);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -103,6 +103,7 @@
|
|||||||
:status="chat.status"
|
:status="chat.status"
|
||||||
:inbox-id="inbox.id"
|
:inbox-id="inbox.id"
|
||||||
:priority="chat.priority"
|
:priority="chat.priority"
|
||||||
|
:chat-id="chat.id"
|
||||||
:has-unread-messages="hasUnread"
|
:has-unread-messages="hasUnread"
|
||||||
@update-conversation="onUpdateConversation"
|
@update-conversation="onUpdateConversation"
|
||||||
@assign-agent="onAssignAgent"
|
@assign-agent="onAssignAgent"
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<menu-item
|
<menu-item
|
||||||
v-if="show(snoozeOption.key)"
|
v-if="showSnooze"
|
||||||
:option="snoozeOption"
|
:option="snoozeOption"
|
||||||
variant="icon"
|
variant="icon"
|
||||||
@click="snoozeConversation()"
|
@click="snoozeConversation()"
|
||||||
@@ -86,6 +86,10 @@ export default {
|
|||||||
},
|
},
|
||||||
mixins: [agentMixin],
|
mixins: [agentMixin],
|
||||||
props: {
|
props: {
|
||||||
|
chatId: {
|
||||||
|
type: Number,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
status: {
|
status: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
@@ -205,6 +209,10 @@ export default {
|
|||||||
...this.filteredAgentOnAvailability,
|
...this.filteredAgentOnAvailability,
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
showSnooze() {
|
||||||
|
// Don't show snooze if the conversation is already snoozed/resolved/pending
|
||||||
|
return this.status === wootConstants.STATUS_TYPE.OPEN;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$store.dispatch('inboxAssignableAgents/fetch', [this.inboxId]);
|
this.$store.dispatch('inboxAssignableAgents/fetch', [this.inboxId]);
|
||||||
@@ -213,7 +221,8 @@ export default {
|
|||||||
toggleStatus(status, snoozedUntil) {
|
toggleStatus(status, snoozedUntil) {
|
||||||
this.$emit('update-conversation', status, snoozedUntil);
|
this.$emit('update-conversation', status, snoozedUntil);
|
||||||
},
|
},
|
||||||
snoozeConversation() {
|
async snoozeConversation() {
|
||||||
|
await this.$store.dispatch('setContextMenuChatId', this.chatId);
|
||||||
const ninja = document.querySelector('ninja-keys');
|
const ninja = document.querySelector('ninja-keys');
|
||||||
ninja.open({ parent: 'snooze_conversation' });
|
ninja.open({ parent: 'snooze_conversation' });
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -52,8 +52,22 @@ export const validateLoggedInRoutes = (to, user, roleWiseRoutes) => {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isAConversationRoute = routeName =>
|
export const isAConversationRoute = (
|
||||||
[
|
routeName,
|
||||||
|
includeBase = false,
|
||||||
|
includeExtended = true
|
||||||
|
) => {
|
||||||
|
const baseRoutes = [
|
||||||
|
'home',
|
||||||
|
'conversation_mentions',
|
||||||
|
'conversation_unattended',
|
||||||
|
'inbox_dashboard',
|
||||||
|
'label_conversations',
|
||||||
|
'team_conversations',
|
||||||
|
'folder_conversations',
|
||||||
|
'conversation_participating',
|
||||||
|
];
|
||||||
|
const extendedRoutes = [
|
||||||
'inbox_conversation',
|
'inbox_conversation',
|
||||||
'conversation_through_mentions',
|
'conversation_through_mentions',
|
||||||
'conversation_through_unattended',
|
'conversation_through_unattended',
|
||||||
@@ -62,7 +76,15 @@ export const isAConversationRoute = routeName =>
|
|||||||
'conversations_through_team',
|
'conversations_through_team',
|
||||||
'conversations_through_folders',
|
'conversations_through_folders',
|
||||||
'conversation_through_participating',
|
'conversation_through_participating',
|
||||||
].includes(routeName);
|
];
|
||||||
|
|
||||||
|
const routes = [
|
||||||
|
...(includeBase ? baseRoutes : []),
|
||||||
|
...(includeExtended ? extendedRoutes : []),
|
||||||
|
];
|
||||||
|
|
||||||
|
return routes.includes(routeName);
|
||||||
|
};
|
||||||
|
|
||||||
export const getConversationDashboardRoute = routeName => {
|
export const getConversationDashboardRoute = routeName => {
|
||||||
switch (routeName) {
|
switch (routeName) {
|
||||||
|
|||||||
@@ -106,6 +106,51 @@ describe('isAConversationRoute', () => {
|
|||||||
expect(isAConversationRoute('conversations_through_team')).toBe(true);
|
expect(isAConversationRoute('conversations_through_team')).toBe(true);
|
||||||
expect(isAConversationRoute('dashboard')).toBe(false);
|
expect(isAConversationRoute('dashboard')).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns true if base conversation route name is provided and includeBase is true', () => {
|
||||||
|
expect(isAConversationRoute('home', true)).toBe(true);
|
||||||
|
expect(isAConversationRoute('conversation_mentions', true)).toBe(true);
|
||||||
|
expect(isAConversationRoute('conversation_unattended', true)).toBe(true);
|
||||||
|
expect(isAConversationRoute('inbox_dashboard', true)).toBe(true);
|
||||||
|
expect(isAConversationRoute('label_conversations', true)).toBe(true);
|
||||||
|
expect(isAConversationRoute('team_conversations', true)).toBe(true);
|
||||||
|
expect(isAConversationRoute('folder_conversations', true)).toBe(true);
|
||||||
|
expect(isAConversationRoute('conversation_participating', true)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false if base conversation route name is provided and includeBase is false', () => {
|
||||||
|
expect(isAConversationRoute('home', false)).toBe(false);
|
||||||
|
expect(isAConversationRoute('conversation_mentions', false)).toBe(false);
|
||||||
|
expect(isAConversationRoute('conversation_unattended', false)).toBe(false);
|
||||||
|
expect(isAConversationRoute('inbox_dashboard', false)).toBe(false);
|
||||||
|
expect(isAConversationRoute('label_conversations', false)).toBe(false);
|
||||||
|
expect(isAConversationRoute('team_conversations', false)).toBe(false);
|
||||||
|
expect(isAConversationRoute('folder_conversations', false)).toBe(false);
|
||||||
|
expect(isAConversationRoute('conversation_participating', false)).toBe(
|
||||||
|
false
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns true if base conversation route name is provided and includeBase and includeExtended is true', () => {
|
||||||
|
expect(isAConversationRoute('home', true, true)).toBe(true);
|
||||||
|
expect(isAConversationRoute('conversation_mentions', true, true)).toBe(
|
||||||
|
true
|
||||||
|
);
|
||||||
|
expect(isAConversationRoute('conversation_unattended', true, true)).toBe(
|
||||||
|
true
|
||||||
|
);
|
||||||
|
expect(isAConversationRoute('inbox_dashboard', true, true)).toBe(true);
|
||||||
|
expect(isAConversationRoute('label_conversations', true, true)).toBe(true);
|
||||||
|
expect(isAConversationRoute('team_conversations', true, true)).toBe(true);
|
||||||
|
expect(isAConversationRoute('folder_conversations', true, true)).toBe(true);
|
||||||
|
expect(isAConversationRoute('conversation_participating', true, true)).toBe(
|
||||||
|
true
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false if base conversation route name is not provided', () => {
|
||||||
|
expect(isAConversationRoute('')).toBe(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getConversationDashboardRoute', () => {
|
describe('getConversationDashboardRoute', () => {
|
||||||
|
|||||||
@@ -154,7 +154,7 @@
|
|||||||
"UNTIL_TOMORROW": "Until tomorrow",
|
"UNTIL_TOMORROW": "Until tomorrow",
|
||||||
"UNTIL_NEXT_MONTH": "Until next month",
|
"UNTIL_NEXT_MONTH": "Until next month",
|
||||||
"AN_HOUR_FROM_NOW": "Until an hour from now",
|
"AN_HOUR_FROM_NOW": "Until an hour from now",
|
||||||
"CUSTOM": "Custom...",
|
"UNTIL_CUSTOM_TIME": "Custom...",
|
||||||
"CHANGE_APPEARANCE": "Change Appearance",
|
"CHANGE_APPEARANCE": "Change Appearance",
|
||||||
"LIGHT_MODE": "Light",
|
"LIGHT_MODE": "Light",
|
||||||
"DARK_MODE": "Dark",
|
"DARK_MODE": "Dark",
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import {
|
|||||||
ICON_RESOLVE_CONVERSATION,
|
ICON_RESOLVE_CONVERSATION,
|
||||||
} from './CommandBarIcons';
|
} from './CommandBarIcons';
|
||||||
|
|
||||||
|
import { createSnoozeHandlers } from './commandBarActions';
|
||||||
|
|
||||||
const SNOOZE_OPTIONS = wootConstants.SNOOZE_OPTIONS;
|
const SNOOZE_OPTIONS = wootConstants.SNOOZE_OPTIONS;
|
||||||
|
|
||||||
export const SNOOZE_CONVERSATION_BULK_ACTIONS = [
|
export const SNOOZE_CONVERSATION_BULK_ACTIONS = [
|
||||||
@@ -22,79 +24,11 @@ export const SNOOZE_CONVERSATION_BULK_ACTIONS = [
|
|||||||
icon: ICON_SNOOZE_CONVERSATION,
|
icon: ICON_SNOOZE_CONVERSATION,
|
||||||
children: Object.values(SNOOZE_OPTIONS),
|
children: Object.values(SNOOZE_OPTIONS),
|
||||||
},
|
},
|
||||||
|
...createSnoozeHandlers(
|
||||||
{
|
|
||||||
id: SNOOZE_OPTIONS.UNTIL_NEXT_REPLY,
|
|
||||||
title: 'COMMAND_BAR.COMMANDS.UNTIL_NEXT_REPLY',
|
|
||||||
parent: 'bulk_action_snooze_conversation',
|
|
||||||
section: 'COMMAND_BAR.SECTIONS.BULK_ACTIONS',
|
|
||||||
icon: ICON_SNOOZE_CONVERSATION,
|
|
||||||
handler: () =>
|
|
||||||
bus.$emit(
|
|
||||||
CMD_BULK_ACTION_SNOOZE_CONVERSATION,
|
CMD_BULK_ACTION_SNOOZE_CONVERSATION,
|
||||||
SNOOZE_OPTIONS.UNTIL_NEXT_REPLY
|
'bulk_action_snooze_conversation',
|
||||||
|
'COMMAND_BAR.SECTIONS.BULK_ACTIONS'
|
||||||
),
|
),
|
||||||
},
|
|
||||||
{
|
|
||||||
id: SNOOZE_OPTIONS.AN_HOUR_FROM_NOW,
|
|
||||||
title: 'COMMAND_BAR.COMMANDS.AN_HOUR_FROM_NOW',
|
|
||||||
parent: 'bulk_action_snooze_conversation',
|
|
||||||
section: 'COMMAND_BAR.SECTIONS.BULK_ACTIONS',
|
|
||||||
icon: ICON_SNOOZE_CONVERSATION,
|
|
||||||
handler: () =>
|
|
||||||
bus.$emit(
|
|
||||||
CMD_BULK_ACTION_SNOOZE_CONVERSATION,
|
|
||||||
SNOOZE_OPTIONS.AN_HOUR_FROM_NOW
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: SNOOZE_OPTIONS.UNTIL_TOMORROW,
|
|
||||||
title: 'COMMAND_BAR.COMMANDS.UNTIL_TOMORROW',
|
|
||||||
section: 'COMMAND_BAR.SECTIONS.BULK_ACTIONS',
|
|
||||||
parent: 'bulk_action_snooze_conversation',
|
|
||||||
icon: ICON_SNOOZE_CONVERSATION,
|
|
||||||
handler: () =>
|
|
||||||
bus.$emit(
|
|
||||||
CMD_BULK_ACTION_SNOOZE_CONVERSATION,
|
|
||||||
SNOOZE_OPTIONS.UNTIL_TOMORROW
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: SNOOZE_OPTIONS.UNTIL_NEXT_WEEK,
|
|
||||||
title: 'COMMAND_BAR.COMMANDS.UNTIL_NEXT_WEEK',
|
|
||||||
section: 'COMMAND_BAR.SECTIONS.BULK_ACTIONS',
|
|
||||||
parent: 'bulk_action_snooze_conversation',
|
|
||||||
icon: ICON_SNOOZE_CONVERSATION,
|
|
||||||
handler: () =>
|
|
||||||
bus.$emit(
|
|
||||||
CMD_BULK_ACTION_SNOOZE_CONVERSATION,
|
|
||||||
SNOOZE_OPTIONS.UNTIL_NEXT_WEEK
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: SNOOZE_OPTIONS.UNTIL_NEXT_MONTH,
|
|
||||||
title: 'COMMAND_BAR.COMMANDS.UNTIL_NEXT_MONTH',
|
|
||||||
section: 'COMMAND_BAR.SECTIONS.BULK_ACTIONS',
|
|
||||||
parent: 'bulk_action_snooze_conversation',
|
|
||||||
icon: ICON_SNOOZE_CONVERSATION,
|
|
||||||
handler: () =>
|
|
||||||
bus.$emit(
|
|
||||||
CMD_BULK_ACTION_SNOOZE_CONVERSATION,
|
|
||||||
SNOOZE_OPTIONS.UNTIL_NEXT_MONTH
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: SNOOZE_OPTIONS.UNTIL_CUSTOM_TIME,
|
|
||||||
title: 'COMMAND_BAR.COMMANDS.CUSTOM',
|
|
||||||
section: 'COMMAND_BAR.SECTIONS.BULK_ACTIONS',
|
|
||||||
parent: 'bulk_action_snooze_conversation',
|
|
||||||
icon: ICON_SNOOZE_CONVERSATION,
|
|
||||||
handler: () =>
|
|
||||||
bus.$emit(
|
|
||||||
CMD_BULK_ACTION_SNOOZE_CONVERSATION,
|
|
||||||
SNOOZE_OPTIONS.UNTIL_CUSTOM_TIME
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export const RESOLVED_CONVERSATION_BULK_ACTIONS = [
|
export const RESOLVED_CONVERSATION_BULK_ACTIONS = [
|
||||||
|
|||||||
@@ -30,6 +30,17 @@ export const OPEN_CONVERSATION_ACTIONS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const createSnoozeHandlers = (busEventName, parentId, section) => {
|
||||||
|
return Object.values(SNOOZE_OPTIONS).map(option => ({
|
||||||
|
id: option,
|
||||||
|
title: `COMMAND_BAR.COMMANDS.${option.toUpperCase()}`,
|
||||||
|
parent: parentId,
|
||||||
|
section: section,
|
||||||
|
icon: ICON_SNOOZE_CONVERSATION,
|
||||||
|
handler: () => bus.$emit(busEventName, option),
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
export const SNOOZE_CONVERSATION_ACTIONS = [
|
export const SNOOZE_CONVERSATION_ACTIONS = [
|
||||||
{
|
{
|
||||||
id: 'snooze_conversation',
|
id: 'snooze_conversation',
|
||||||
@@ -37,61 +48,11 @@ export const SNOOZE_CONVERSATION_ACTIONS = [
|
|||||||
icon: ICON_SNOOZE_CONVERSATION,
|
icon: ICON_SNOOZE_CONVERSATION,
|
||||||
children: Object.values(SNOOZE_OPTIONS),
|
children: Object.values(SNOOZE_OPTIONS),
|
||||||
},
|
},
|
||||||
|
...createSnoozeHandlers(
|
||||||
{
|
CMD_SNOOZE_CONVERSATION,
|
||||||
id: SNOOZE_OPTIONS.UNTIL_NEXT_REPLY,
|
'snooze_conversation',
|
||||||
title: 'COMMAND_BAR.COMMANDS.UNTIL_NEXT_REPLY',
|
'COMMAND_BAR.SECTIONS.SNOOZE_CONVERSATION'
|
||||||
parent: 'snooze_conversation',
|
),
|
||||||
section: 'COMMAND_BAR.SECTIONS.SNOOZE_CONVERSATION',
|
|
||||||
icon: ICON_SNOOZE_CONVERSATION,
|
|
||||||
handler: () =>
|
|
||||||
bus.$emit(CMD_SNOOZE_CONVERSATION, SNOOZE_OPTIONS.UNTIL_NEXT_REPLY),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: SNOOZE_OPTIONS.AN_HOUR_FROM_NOW,
|
|
||||||
title: 'COMMAND_BAR.COMMANDS.AN_HOUR_FROM_NOW',
|
|
||||||
parent: 'snooze_conversation',
|
|
||||||
section: 'COMMAND_BAR.SECTIONS.SNOOZE_CONVERSATION',
|
|
||||||
icon: ICON_SNOOZE_CONVERSATION,
|
|
||||||
handler: () =>
|
|
||||||
bus.$emit(CMD_SNOOZE_CONVERSATION, SNOOZE_OPTIONS.AN_HOUR_FROM_NOW),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: SNOOZE_OPTIONS.UNTIL_TOMORROW,
|
|
||||||
title: 'COMMAND_BAR.COMMANDS.UNTIL_TOMORROW',
|
|
||||||
section: 'COMMAND_BAR.SECTIONS.SNOOZE_CONVERSATION',
|
|
||||||
parent: 'snooze_conversation',
|
|
||||||
icon: ICON_SNOOZE_CONVERSATION,
|
|
||||||
handler: () =>
|
|
||||||
bus.$emit(CMD_SNOOZE_CONVERSATION, SNOOZE_OPTIONS.UNTIL_TOMORROW),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: SNOOZE_OPTIONS.UNTIL_NEXT_WEEK,
|
|
||||||
title: 'COMMAND_BAR.COMMANDS.UNTIL_NEXT_WEEK',
|
|
||||||
section: 'COMMAND_BAR.SECTIONS.SNOOZE_CONVERSATION',
|
|
||||||
parent: 'snooze_conversation',
|
|
||||||
icon: ICON_SNOOZE_CONVERSATION,
|
|
||||||
handler: () =>
|
|
||||||
bus.$emit(CMD_SNOOZE_CONVERSATION, SNOOZE_OPTIONS.UNTIL_NEXT_WEEK),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: SNOOZE_OPTIONS.UNTIL_NEXT_MONTH,
|
|
||||||
title: 'COMMAND_BAR.COMMANDS.UNTIL_NEXT_MONTH',
|
|
||||||
section: 'COMMAND_BAR.SECTIONS.SNOOZE_CONVERSATION',
|
|
||||||
parent: 'snooze_conversation',
|
|
||||||
icon: ICON_SNOOZE_CONVERSATION,
|
|
||||||
handler: () =>
|
|
||||||
bus.$emit(CMD_SNOOZE_CONVERSATION, SNOOZE_OPTIONS.UNTIL_NEXT_MONTH),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: SNOOZE_OPTIONS.UNTIL_CUSTOM_TIME,
|
|
||||||
title: 'COMMAND_BAR.COMMANDS.CUSTOM',
|
|
||||||
section: 'COMMAND_BAR.SECTIONS.SNOOZE_CONVERSATION',
|
|
||||||
parent: 'snooze_conversation',
|
|
||||||
icon: ICON_SNOOZE_CONVERSATION,
|
|
||||||
handler: () =>
|
|
||||||
bus.$emit(CMD_SNOOZE_CONVERSATION, SNOOZE_OPTIONS.UNTIL_CUSTOM_TIME),
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export const RESOLVED_CONVERSATION_ACTIONS = [
|
export const RESOLVED_CONVERSATION_ACTIONS = [
|
||||||
|
|||||||
@@ -6,11 +6,13 @@
|
|||||||
hideBreadcrumbs
|
hideBreadcrumbs
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
@selected="onSelected"
|
@selected="onSelected"
|
||||||
|
@closed="onClosed"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import 'ninja-keys';
|
import '@chatwoot/ninja-keys';
|
||||||
|
import wootConstants from 'dashboard/constants/globals';
|
||||||
import conversationHotKeysMixin from './conversationHotKeys';
|
import conversationHotKeysMixin from './conversationHotKeys';
|
||||||
import bulkActionsHotKeysMixin from './bulkActionsHotKeys';
|
import bulkActionsHotKeysMixin from './bulkActionsHotKeys';
|
||||||
import inboxHotKeysMixin from './inboxHotKeys';
|
import inboxHotKeysMixin from './inboxHotKeys';
|
||||||
@@ -34,6 +36,14 @@ export default {
|
|||||||
appearanceHotKeys,
|
appearanceHotKeys,
|
||||||
goToCommandHotKeys,
|
goToCommandHotKeys,
|
||||||
],
|
],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// Added selectedSnoozeType to track the selected snooze type
|
||||||
|
// So if the selected snooze type is "custom snooze" then we set selectedSnoozeType with the CMD action id
|
||||||
|
// So that we can track the selected snooze type and when we close the command bar
|
||||||
|
selectedSnoozeType: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
placeholder() {
|
placeholder() {
|
||||||
return this.$t('COMMAND_BAR.SEARCH_PLACEHOLDER');
|
return this.$t('COMMAND_BAR.SEARCH_PLACEHOLDER');
|
||||||
@@ -67,14 +77,35 @@ export default {
|
|||||||
this.$refs.ninjakeys.data = this.hotKeys;
|
this.$refs.ninjakeys.data = this.hotKeys;
|
||||||
},
|
},
|
||||||
onSelected(item) {
|
onSelected(item) {
|
||||||
const { detail: { action: { title = null, section = null } = {} } = {} } =
|
const {
|
||||||
item;
|
detail: {
|
||||||
|
action: { title = null, section = null, id = null } = {},
|
||||||
|
} = {},
|
||||||
|
} = item;
|
||||||
|
// Added this condition to prevent setting the selectedSnoozeType to null
|
||||||
|
// When we select the "custom snooze" (CMD bar will close and the custom snooze modal will open)
|
||||||
|
if (id === wootConstants.SNOOZE_OPTIONS.UNTIL_CUSTOM_TIME) {
|
||||||
|
this.selectedSnoozeType =
|
||||||
|
wootConstants.SNOOZE_OPTIONS.UNTIL_CUSTOM_TIME;
|
||||||
|
} else {
|
||||||
|
this.selectedSnoozeType = null;
|
||||||
|
}
|
||||||
this.$track(GENERAL_EVENTS.COMMAND_BAR, {
|
this.$track(GENERAL_EVENTS.COMMAND_BAR, {
|
||||||
section,
|
section,
|
||||||
action: title,
|
action: title,
|
||||||
});
|
});
|
||||||
this.setCommandbarData();
|
this.setCommandbarData();
|
||||||
},
|
},
|
||||||
|
onClosed() {
|
||||||
|
// If the selectedSnoozeType is not "SNOOZE_OPTIONS.UNTIL_CUSTOM_TIME (custom snooze)" then we set the context menu chat id to null
|
||||||
|
// Else we do nothing and its handled in the ChatList.vue hideCustomSnoozeModal() method
|
||||||
|
if (
|
||||||
|
this.selectedSnoozeType !==
|
||||||
|
wootConstants.SNOOZE_OPTIONS.UNTIL_CUSTOM_TIME
|
||||||
|
) {
|
||||||
|
this.$store.dispatch('setContextMenuChatId', null);
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -55,11 +55,15 @@ export default {
|
|||||||
replyMode() {
|
replyMode() {
|
||||||
this.setCommandbarData();
|
this.setCommandbarData();
|
||||||
},
|
},
|
||||||
|
contextMenuChatId() {
|
||||||
|
this.setCommandbarData();
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
currentChat: 'getSelectedChat',
|
currentChat: 'getSelectedChat',
|
||||||
replyMode: 'draftMessages/getReplyEditorMode',
|
replyMode: 'draftMessages/getReplyEditorMode',
|
||||||
|
contextMenuChatId: 'getContextMenuChatId',
|
||||||
}),
|
}),
|
||||||
draftMessage() {
|
draftMessage() {
|
||||||
return this.$store.getters['draftMessages/get'](this.draftKey);
|
return this.$store.getters['draftMessages/get'](this.draftKey);
|
||||||
@@ -93,6 +97,7 @@ export default {
|
|||||||
}
|
}
|
||||||
return this.prepareActions(actions);
|
return this.prepareActions(actions);
|
||||||
},
|
},
|
||||||
|
|
||||||
priorityOptions() {
|
priorityOptions() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -327,11 +332,21 @@ export default {
|
|||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
|
||||||
conversationHotKeys() {
|
isConversationOrInboxRoute() {
|
||||||
if (
|
return (
|
||||||
isAConversationRoute(this.$route.name) ||
|
isAConversationRoute(this.$route.name) ||
|
||||||
isAInboxViewRoute(this.$route.name)
|
isAInboxViewRoute(this.$route.name)
|
||||||
) {
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
shouldShowSnoozeOption() {
|
||||||
|
return (
|
||||||
|
isAConversationRoute(this.$route.name, true, false) &&
|
||||||
|
this.contextMenuChatId
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
getDefaultConversationHotKeys() {
|
||||||
const defaultConversationHotKeys = [
|
const defaultConversationHotKeys = [
|
||||||
...this.statusActions,
|
...this.statusActions,
|
||||||
...this.conversationAdditionalActions,
|
...this.conversationAdditionalActions,
|
||||||
@@ -344,8 +359,15 @@ export default {
|
|||||||
return [...defaultConversationHotKeys, ...this.AIAssistActions];
|
return [...defaultConversationHotKeys, ...this.AIAssistActions];
|
||||||
}
|
}
|
||||||
return defaultConversationHotKeys;
|
return defaultConversationHotKeys;
|
||||||
}
|
},
|
||||||
|
|
||||||
|
conversationHotKeys() {
|
||||||
|
if (this.shouldShowSnoozeOption) {
|
||||||
|
return this.prepareActions(SNOOZE_CONVERSATION_ACTIONS);
|
||||||
|
}
|
||||||
|
if (this.isConversationOrInboxRoute) {
|
||||||
|
return this.getDefaultConversationHotKeys;
|
||||||
|
}
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -466,6 +466,10 @@ const actions = {
|
|||||||
commit(types.ASSIGN_PRIORITY, { priority, conversationId });
|
commit(types.ASSIGN_PRIORITY, { priority, conversationId });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setContextMenuChatId({ commit }, chatId) {
|
||||||
|
commit(types.SET_CONTEXT_MENU_CHAT_ID, chatId);
|
||||||
|
},
|
||||||
|
|
||||||
...messageReadActions,
|
...messageReadActions,
|
||||||
...messageTranslateActions,
|
...messageTranslateActions,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -100,6 +100,10 @@ const getters = {
|
|||||||
getConversationLastSeen: _state => {
|
getConversationLastSeen: _state => {
|
||||||
return _state.conversationLastSeen;
|
return _state.conversationLastSeen;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getContextMenuChatId: _state => {
|
||||||
|
return _state.contextMenuChatId;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default getters;
|
export default getters;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ const state = {
|
|||||||
currentInbox: null,
|
currentInbox: null,
|
||||||
selectedChatId: null,
|
selectedChatId: null,
|
||||||
appliedFilters: [],
|
appliedFilters: [],
|
||||||
|
contextMenuChatId: null,
|
||||||
conversationParticipants: [],
|
conversationParticipants: [],
|
||||||
conversationLastSeen: null,
|
conversationLastSeen: null,
|
||||||
syncConversationsMessages: {},
|
syncConversationsMessages: {},
|
||||||
@@ -281,6 +282,10 @@ export const mutations = {
|
|||||||
) {
|
) {
|
||||||
_state.syncConversationsMessages[conversationId] = messageId;
|
_state.syncConversationsMessages[conversationId] = messageId;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
[types.SET_CONTEXT_MENU_CHAT_ID](_state, chatId) {
|
||||||
|
_state.contextMenuChatId = chatId;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
@@ -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]]);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -403,4 +403,12 @@ describe('#mutations', () => {
|
|||||||
expect(state.allConversations[0].attachments).toHaveLength(1);
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ export default {
|
|||||||
|
|
||||||
SET_CONVERSATION_CAN_REPLY: 'SET_CONVERSATION_CAN_REPLY',
|
SET_CONVERSATION_CAN_REPLY: 'SET_CONVERSATION_CAN_REPLY',
|
||||||
|
|
||||||
|
SET_CONTEXT_MENU_CHAT_ID: 'SET_CONTEXT_MENU_CHAT_ID',
|
||||||
|
|
||||||
// Inboxes
|
// Inboxes
|
||||||
SET_INBOXES_UI_FLAG: 'SET_INBOXES_UI_FLAG',
|
SET_INBOXES_UI_FLAG: 'SET_INBOXES_UI_FLAG',
|
||||||
SET_INBOXES: 'SET_INBOXES',
|
SET_INBOXES: 'SET_INBOXES',
|
||||||
|
|||||||
@@ -67,7 +67,7 @@
|
|||||||
"markdown-it": "^13.0.2",
|
"markdown-it": "^13.0.2",
|
||||||
"markdown-it-link-attributes": "^4.0.1",
|
"markdown-it-link-attributes": "^4.0.1",
|
||||||
"md5": "^2.3.0",
|
"md5": "^2.3.0",
|
||||||
"ninja-keys": "^1.2.2",
|
"@chatwoot/ninja-keys": "1.2.3",
|
||||||
"opus-recorder": "^8.0.5",
|
"opus-recorder": "^8.0.5",
|
||||||
"postcss": "^8.4.31",
|
"postcss": "^8.4.31",
|
||||||
"postcss-loader": "^4.2.0",
|
"postcss-loader": "^4.2.0",
|
||||||
|
|||||||
18
yarn.lock
18
yarn.lock
@@ -3156,6 +3156,15 @@
|
|||||||
"@braid/vue-formulate-i18n" "^1.16.0"
|
"@braid/vue-formulate-i18n" "^1.16.0"
|
||||||
is-plain-object "^3.0.1"
|
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":
|
"@chatwoot/prosemirror-schema@1.0.5":
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/@chatwoot/prosemirror-schema/-/prosemirror-schema-1.0.5.tgz#d6053692beae59d466ac0b04128fa157f59eb176"
|
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"
|
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
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:
|
no-case@^3.0.4:
|
||||||
version "3.0.4"
|
version "3.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"
|
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"
|
||||||
|
|||||||
Reference in New Issue
Block a user