Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e22897f8f | ||
|
|
84ab32f571 | ||
|
|
ccf90b030b | ||
|
|
82441b99fb | ||
|
|
d46c0cfed2 | ||
|
|
79764724a5 | ||
|
|
c8d0d06d45 | ||
|
|
681373a248 | ||
|
|
f8a0e950f5 | ||
|
|
018dfc4428 | ||
|
|
d0cb1e006a | ||
|
|
4796ee46cf | ||
|
|
685e5c615b | ||
|
|
2f67de0f82 | ||
|
|
e87a7d90bf | ||
|
|
4574f4203b |
@@ -4,7 +4,6 @@
|
||||
"TITLE": "Inbox",
|
||||
"DISPLAY_DROPDOWN": "Display",
|
||||
"LOADING": "Fetching notifications",
|
||||
"EOF": "All notifications loaded 🎉",
|
||||
"404": "There are no active notifications in this group.",
|
||||
"NO_NOTIFICATIONS": "No notifications",
|
||||
"NOTE": "Notifications from all subscribed inboxes",
|
||||
|
||||
@@ -18,3 +18,4 @@ export const CMD_AI_ASSIST = 'CMD_AI_ASSIST';
|
||||
|
||||
// Inbox Commands (Notifications)
|
||||
export const CMD_SNOOZE_NOTIFICATION = 'CMD_SNOOZE_NOTIFICATION';
|
||||
export const CMD_TOGGLE_SNOOZE_NOTIFICATION = 'CMD_TOGGLE_SNOOZE_NOTIFICATION';
|
||||
|
||||
@@ -6,11 +6,12 @@
|
||||
hideBreadcrumbs
|
||||
:placeholder="placeholder"
|
||||
@selected="onSelected"
|
||||
@closed="onClosed"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import 'ninja-keys';
|
||||
import '@chatwoot/ninja-keys';
|
||||
import conversationHotKeysMixin from './conversationHotKeys';
|
||||
import inboxHotKeysMixin from './inboxHotKeys';
|
||||
import goToCommandHotKeys from './goToCommandHotKeys';
|
||||
@@ -55,6 +56,10 @@ export default {
|
||||
routeName() {
|
||||
this.setCommandbarData();
|
||||
},
|
||||
hotKeys() {
|
||||
// This is to update the command bar data when the hot keys are updated dynamically
|
||||
this.setCommandbarData();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.setCommandbarData();
|
||||
@@ -72,6 +77,9 @@ export default {
|
||||
});
|
||||
this.setCommandbarData();
|
||||
},
|
||||
onClosed() {
|
||||
this.showSnoozeNotificationItems = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import wootConstants from 'dashboard/constants/globals';
|
||||
|
||||
import { CMD_SNOOZE_NOTIFICATION } from './commandBarBusEvents';
|
||||
import {
|
||||
CMD_SNOOZE_NOTIFICATION,
|
||||
CMD_TOGGLE_SNOOZE_NOTIFICATION,
|
||||
} from './commandBarBusEvents';
|
||||
import { ICON_SNOOZE_NOTIFICATION } from './CommandBarIcons';
|
||||
|
||||
import { isAInboxViewRoute } from 'dashboard/helper/routeHelpers';
|
||||
@@ -61,14 +64,29 @@ const INBOX_SNOOZE_EVENTS = [
|
||||
},
|
||||
];
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
showSnoozeNotificationItems: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
inboxHotKeys() {
|
||||
if (isAInboxViewRoute(this.$route.name)) {
|
||||
if (
|
||||
isAInboxViewRoute(this.$route.name) ||
|
||||
this.showSnoozeNotificationItems
|
||||
) {
|
||||
return this.prepareActions(INBOX_SNOOZE_EVENTS);
|
||||
}
|
||||
return [];
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
bus.$on(CMD_TOGGLE_SNOOZE_NOTIFICATION, this.toggleSnoozeOptions);
|
||||
},
|
||||
destroyed() {
|
||||
bus.$off(CMD_TOGGLE_SNOOZE_NOTIFICATION, this.toggleSnoozeOptions);
|
||||
this.showSnoozeNotificationItems = false;
|
||||
},
|
||||
methods: {
|
||||
prepareActions(actions) {
|
||||
return actions.map(action => ({
|
||||
@@ -77,5 +95,9 @@ export default {
|
||||
section: this.$t(action.section),
|
||||
}));
|
||||
},
|
||||
toggleSnoozeOptions() {
|
||||
// Used to show/hide snooze notification items in cmd bar dynamically
|
||||
this.showSnoozeNotificationItems = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -15,12 +15,12 @@ export default {
|
||||
},
|
||||
},
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/inbox-view/:conversation_id'),
|
||||
path: frontendURL('accounts/:accountId/inbox-view/:notification_id'),
|
||||
name: 'inbox_view_conversation',
|
||||
roles: ['administrator', 'agent'],
|
||||
component: InboxView,
|
||||
props: route => {
|
||||
return { inboxId: 0, conversationId: route.params.conversation_id };
|
||||
return { inboxId: 0, notificationId: route.params.notification_id };
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
class="flex flex-col h-full w-full ltr:border-r border-slate-50 dark:border-slate-800/50"
|
||||
:class="isOnExpandedLayout ? '' : 'min-w-[360px] max-w-[360px]'"
|
||||
>
|
||||
<inbox-list-header @filter="onFilterChange" />
|
||||
<inbox-list-header
|
||||
:is-context-menu-open="isInboxContextMenuOpen"
|
||||
@filter="onFilterChange"
|
||||
@redirect="redirectToInbox"
|
||||
/>
|
||||
<div
|
||||
ref="notificationList"
|
||||
class="flex flex-col w-full h-[calc(100%-56px)] overflow-x-hidden overflow-y-auto"
|
||||
@@ -15,6 +19,9 @@
|
||||
@mark-notification-as-read="markNotificationAsRead"
|
||||
@mark-notification-as-unread="markNotificationAsUnRead"
|
||||
@delete-notification="deleteNotification"
|
||||
@snooze-notification="openSnoozeNotificationModal"
|
||||
@context-menu-open="isInboxContextMenuOpen = true"
|
||||
@context-menu-close="isInboxContextMenuOpen = false"
|
||||
/>
|
||||
<div v-if="uiFlags.isFetching" class="text-center">
|
||||
<span class="spinner mt-4 mb-4" />
|
||||
@@ -25,18 +32,21 @@
|
||||
>
|
||||
{{ $t('INBOX.LIST.NO_NOTIFICATIONS') }}
|
||||
</p>
|
||||
<p
|
||||
v-if="showEndOfListMessage"
|
||||
class="text-center text-slate-400 dark:text-slate-400 p-4"
|
||||
>
|
||||
{{ $t('INBOX.LIST.EOF') }}
|
||||
</p>
|
||||
<intersection-observer
|
||||
v-if="!showEndOfList && !uiFlags.isFetching"
|
||||
:options="infiniteLoaderOptions"
|
||||
@observed="loadMoreNotifications"
|
||||
/>
|
||||
</div>
|
||||
<woot-modal
|
||||
:show.sync="showCustomSnoozeModal"
|
||||
:on-close="hideCustomSnoozeModal"
|
||||
>
|
||||
<custom-snooze-modal
|
||||
@close="hideCustomSnoozeModal"
|
||||
@choose-time="scheduleCustomSnooze"
|
||||
/>
|
||||
</woot-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -46,18 +56,26 @@ import wootConstants from 'dashboard/constants/globals';
|
||||
import InboxCard from './components/InboxCard.vue';
|
||||
import InboxListHeader from './components/InboxListHeader.vue';
|
||||
import { INBOX_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
|
||||
import {
|
||||
CMD_TOGGLE_SNOOZE_NOTIFICATION,
|
||||
CMD_SNOOZE_NOTIFICATION,
|
||||
} from 'dashboard/routes/dashboard/commands/commandBarBusEvents';
|
||||
import { getUnixTime } from 'date-fns';
|
||||
import { findSnoozeTime } from 'dashboard/helper/snoozeHelpers';
|
||||
import IntersectionObserver from 'dashboard/components/IntersectionObserver.vue';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||
import CustomSnoozeModal from 'dashboard/components/CustomSnoozeModal.vue';
|
||||
export default {
|
||||
components: {
|
||||
InboxCard,
|
||||
InboxListHeader,
|
||||
IntersectionObserver,
|
||||
CustomSnoozeModal,
|
||||
},
|
||||
mixins: [alertMixin, uiSettingsMixin],
|
||||
props: {
|
||||
conversationId: {
|
||||
notificationId: {
|
||||
type: [String, Number],
|
||||
default: 0,
|
||||
},
|
||||
@@ -76,6 +94,9 @@ export default {
|
||||
status: '',
|
||||
type: '',
|
||||
sortOrder: wootConstants.INBOX_SORT_BY.NEWEST,
|
||||
isInboxContextMenuOpen: false,
|
||||
showCustomSnoozeModal: false,
|
||||
notificationIdToSnooze: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -102,13 +123,14 @@ export default {
|
||||
showEmptyState() {
|
||||
return !this.uiFlags.isFetching && !this.notifications.length;
|
||||
},
|
||||
showEndOfListMessage() {
|
||||
return this.showEndOfList && this.notifications.length;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.setSavedFilter();
|
||||
this.fetchNotifications();
|
||||
bus.$on(CMD_SNOOZE_NOTIFICATION, this.onCmdSnoozeNotification);
|
||||
},
|
||||
destroyed() {
|
||||
bus.$off(CMD_SNOOZE_NOTIFICATION, this.onCmdSnoozeNotification);
|
||||
},
|
||||
methods: {
|
||||
fetchNotifications() {
|
||||
@@ -119,7 +141,7 @@ export default {
|
||||
this.$store.dispatch('notifications/index', filter);
|
||||
},
|
||||
redirectToInbox() {
|
||||
if (!this.conversationId) return;
|
||||
if (!this.notificationId) return;
|
||||
if (this.$route.name === 'inbox_view') return;
|
||||
this.$router.push({ name: 'inbox_view' });
|
||||
},
|
||||
@@ -195,6 +217,48 @@ export default {
|
||||
this.type = type;
|
||||
this.sortOrder = sortBy || wootConstants.INBOX_SORT_BY.NEWEST;
|
||||
},
|
||||
openSnoozeNotificationModal(notificationItem) {
|
||||
this.notificationIdToSnooze = notificationItem.id;
|
||||
// There is an bus event to toggle snooze modal, because
|
||||
// We need to show the snooze notification items in the command bar Dynamically
|
||||
// If cmd + k is pressed from inbox view (In list screen) and search snooze notification items then we no need to show,
|
||||
// snooze notification because we don't get notification id.
|
||||
// Only show when the snooze button is clicked from the notification item card context menu
|
||||
if (!this.notificationId) bus.$emit(CMD_TOGGLE_SNOOZE_NOTIFICATION);
|
||||
this.$nextTick(() => {
|
||||
const ninja = document.querySelector('ninja-keys');
|
||||
ninja.open({ parent: 'snooze_notification' });
|
||||
});
|
||||
},
|
||||
hideCustomSnoozeModal() {
|
||||
this.showCustomSnoozeModal = false;
|
||||
},
|
||||
snoozeNotification(snoozedUntil) {
|
||||
this.$store
|
||||
.dispatch('notifications/snooze', {
|
||||
id: this.notificationIdToSnooze || this.notificationId,
|
||||
snoozedUntil,
|
||||
})
|
||||
.then(() => {
|
||||
this.showAlert(this.$t('INBOX.ALERTS.SNOOZE'));
|
||||
});
|
||||
this.notificationIdToSnooze = null;
|
||||
},
|
||||
onCmdSnoozeNotification(snoozeType) {
|
||||
if (snoozeType === wootConstants.SNOOZE_OPTIONS.UNTIL_CUSTOM_TIME) {
|
||||
this.showCustomSnoozeModal = true;
|
||||
} else {
|
||||
const snoozedUntil = findSnoozeTime(snoozeType) || null;
|
||||
this.snoozeNotification(snoozedUntil);
|
||||
}
|
||||
},
|
||||
scheduleCustomSnooze(customSnoozeTime) {
|
||||
this.showCustomSnoozeModal = false;
|
||||
if (customSnoozeTime) {
|
||||
const snoozedUntil = getUnixTime(customSnoozeTime) || null;
|
||||
this.snoozeNotification(snoozedUntil);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<section class="flex w-full h-full bg-white dark:bg-slate-900">
|
||||
<inbox-list
|
||||
v-show="showConversationList"
|
||||
:conversation-id="conversationId"
|
||||
:notification-id="notificationId"
|
||||
:is-on-expanded-layout="isOnExpandedLayout"
|
||||
/>
|
||||
<div
|
||||
@@ -68,7 +68,7 @@ export default {
|
||||
type: [String, Number],
|
||||
default: 0,
|
||||
},
|
||||
conversationId: {
|
||||
notificationId: {
|
||||
type: [String, Number],
|
||||
default: 0,
|
||||
},
|
||||
@@ -78,13 +78,15 @@ export default {
|
||||
currentAccountId: 'getCurrentAccountId',
|
||||
notifications: 'notifications/getNotifications',
|
||||
currentChat: 'getSelectedChat',
|
||||
allConversation: 'getAllConversations',
|
||||
activeNotificationById: 'notifications/getActiveNotificationById',
|
||||
conversationById: 'getConversationById',
|
||||
uiFlags: 'notifications/getUIFlags',
|
||||
}),
|
||||
activeNotification() {
|
||||
return this.notifications.find(
|
||||
n => n.primary_actor.id === Number(this.conversationId)
|
||||
);
|
||||
return this.activeNotificationById(this.notificationId);
|
||||
},
|
||||
conversationId() {
|
||||
return this.activeNotification?.primary_actor?.id;
|
||||
},
|
||||
isInboxViewEnabled() {
|
||||
return this.$store.getters['accounts/isFeatureEnabledGlobally'](
|
||||
@@ -99,11 +101,7 @@ export default {
|
||||
return this.uiFlags.isFetching && !this.notifications.length;
|
||||
},
|
||||
showInboxMessageView() {
|
||||
return (
|
||||
Boolean(this.conversationId) &&
|
||||
Boolean(this.currentChat.id) &&
|
||||
!this.isFetchingInitialData
|
||||
);
|
||||
return Boolean(this.conversationId) && !this.isFetchingInitialData;
|
||||
},
|
||||
totalNotifications() {
|
||||
return this.notifications?.length ?? 0;
|
||||
@@ -135,8 +133,10 @@ export default {
|
||||
watch: {
|
||||
conversationId: {
|
||||
immediate: true,
|
||||
handler() {
|
||||
this.fetchConversationById();
|
||||
handler(newVal, oldVal) {
|
||||
if (newVal !== oldVal) {
|
||||
this.fetchConversationById();
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -152,11 +152,14 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
async fetchConversationById() {
|
||||
if (!this.conversationId) return;
|
||||
const chat = this.findConversation();
|
||||
if (!chat) {
|
||||
await this.$store.dispatch('getConversation', this.conversationId);
|
||||
if (!this.notificationId || !this.conversationId) return;
|
||||
this.$store.dispatch('clearSelectedState');
|
||||
const existingChat = this.findConversation();
|
||||
if (existingChat) {
|
||||
this.setActiveChat(existingChat);
|
||||
return;
|
||||
}
|
||||
await this.$store.dispatch('getConversation', this.conversationId);
|
||||
this.setActiveChat();
|
||||
},
|
||||
setActiveChat() {
|
||||
@@ -169,8 +172,7 @@ export default {
|
||||
});
|
||||
},
|
||||
findConversation() {
|
||||
const conversationId = Number(this.conversationId);
|
||||
return this.allConversation.find(c => c.id === conversationId);
|
||||
return this.conversationById(this.conversationId);
|
||||
},
|
||||
navigateToConversation(activeIndex, direction) {
|
||||
const indexOffset = direction === 'next' ? 0 : -2;
|
||||
@@ -180,7 +182,7 @@ export default {
|
||||
id,
|
||||
primary_actor_id: primaryActorId,
|
||||
primary_actor_type: primaryActorType,
|
||||
primary_actor: { id: conversationId, meta: { unreadCount } = {} },
|
||||
primary_actor: { meta: { unreadCount } = {} },
|
||||
notification_type: notificationType,
|
||||
} = targetNotification;
|
||||
|
||||
@@ -197,7 +199,7 @@ export default {
|
||||
|
||||
this.$router.push({
|
||||
name: 'inbox_view_conversation',
|
||||
params: { conversation_id: conversationId },
|
||||
params: { notification_id: id },
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -89,6 +89,7 @@ export default {
|
||||
return {
|
||||
isContextMenuOpen: false,
|
||||
contextMenuPosition: { x: null, y: null },
|
||||
activeNotificationId: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -96,7 +97,9 @@ export default {
|
||||
return this.notificationItem?.primary_actor;
|
||||
},
|
||||
isInboxCardActive() {
|
||||
return this.$route.params.conversation_id === this.primaryActor?.id;
|
||||
return (
|
||||
Number(this.activeNotificationId) === Number(this.notificationItem?.id)
|
||||
);
|
||||
},
|
||||
inbox() {
|
||||
return this.$store.getters['inboxes/getInbox'](
|
||||
@@ -109,6 +112,9 @@ export default {
|
||||
meta() {
|
||||
return this.primaryActor?.meta;
|
||||
},
|
||||
isNotSnoozed() {
|
||||
return !this.notificationItem?.snoozed_until;
|
||||
},
|
||||
assigneeMeta() {
|
||||
return this.meta?.assignee;
|
||||
},
|
||||
@@ -131,6 +137,13 @@ export default {
|
||||
},
|
||||
];
|
||||
|
||||
if (this.isNotSnoozed) {
|
||||
items.push({
|
||||
key: 'snooze',
|
||||
label: this.$t('INBOX.MENU_ITEM.SNOOZE'),
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.isUnread) {
|
||||
items.push({
|
||||
key: 'mark_as_unread',
|
||||
@@ -157,6 +170,14 @@ export default {
|
||||
return '';
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'$route.params.notification_id': {
|
||||
immediate: true,
|
||||
handler(newVal) {
|
||||
this.activeNotificationId = newVal;
|
||||
},
|
||||
},
|
||||
},
|
||||
unmounted() {
|
||||
this.closeContextMenu();
|
||||
},
|
||||
@@ -166,11 +187,11 @@ export default {
|
||||
id,
|
||||
primary_actor_id: primaryActorId,
|
||||
primary_actor_type: primaryActorType,
|
||||
primary_actor: { id: conversationId, inbox_id: inboxId },
|
||||
primary_actor: { inbox_id: inboxId },
|
||||
notification_type: notificationType,
|
||||
} = notification;
|
||||
|
||||
if (this.$route.params.conversation_id !== conversationId) {
|
||||
if (this.$route.params.notification_id !== id) {
|
||||
this.$track(INBOX_EVENTS.OPEN_CONVERSATION_VIA_INBOX, {
|
||||
notificationType,
|
||||
});
|
||||
@@ -184,13 +205,14 @@ export default {
|
||||
|
||||
this.$router.push({
|
||||
name: 'inbox_view_conversation',
|
||||
params: { inboxId, conversation_id: conversationId },
|
||||
params: { inboxId, notification_id: id },
|
||||
});
|
||||
}
|
||||
},
|
||||
closeContextMenu() {
|
||||
this.isContextMenuOpen = false;
|
||||
this.contextMenuPosition = { x: null, y: null };
|
||||
this.$emit('context-menu-close');
|
||||
},
|
||||
openContextMenu(e) {
|
||||
this.closeContextMenu();
|
||||
@@ -200,6 +222,7 @@ export default {
|
||||
y: e.pageY || e.clientY,
|
||||
};
|
||||
this.isContextMenuOpen = true;
|
||||
this.$emit('context-menu-open');
|
||||
},
|
||||
handleAction(key) {
|
||||
switch (key) {
|
||||
@@ -212,6 +235,9 @@ export default {
|
||||
case 'delete':
|
||||
this.$emit('delete-notification', this.notificationItem);
|
||||
break;
|
||||
case 'snooze':
|
||||
this.$emit('snooze-notification', this.notificationItem);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
},
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
<div v-else />
|
||||
<div class="flex items-center gap-2">
|
||||
<woot-button
|
||||
v-if="!isNotificationAlreadySnoozed"
|
||||
variant="hollow"
|
||||
size="small"
|
||||
color-scheme="secondary"
|
||||
@@ -30,32 +31,17 @@
|
||||
{{ $t('INBOX.ACTION_HEADER.DELETE') }}
|
||||
</woot-button>
|
||||
</div>
|
||||
<woot-modal
|
||||
:show.sync="showCustomSnoozeModal"
|
||||
:on-close="hideCustomSnoozeModal"
|
||||
>
|
||||
<custom-snooze-modal
|
||||
@close="hideCustomSnoozeModal"
|
||||
@choose-time="scheduleCustomSnooze"
|
||||
/>
|
||||
</woot-modal>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { getUnixTime } from 'date-fns';
|
||||
import { CMD_SNOOZE_NOTIFICATION } from 'dashboard/routes/dashboard/commands/commandBarBusEvents';
|
||||
import wootConstants from 'dashboard/constants/globals';
|
||||
import { findSnoozeTime } from 'dashboard/helper/snoozeHelpers';
|
||||
import { INBOX_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
|
||||
import PaginationButton from './PaginationButton.vue';
|
||||
import CustomSnoozeModal from 'dashboard/components/CustomSnoozeModal.vue';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
PaginationButton,
|
||||
CustomSnoozeModal,
|
||||
},
|
||||
mixins: [alertMixin],
|
||||
props: {
|
||||
@@ -81,46 +67,15 @@ export default {
|
||||
...mapGetters({
|
||||
meta: 'notifications/getMeta',
|
||||
}),
|
||||
},
|
||||
mounted() {
|
||||
bus.$on(CMD_SNOOZE_NOTIFICATION, this.onCmdSnoozeNotification);
|
||||
},
|
||||
destroyed() {
|
||||
bus.$off(CMD_SNOOZE_NOTIFICATION, this.onCmdSnoozeNotification);
|
||||
isNotificationAlreadySnoozed() {
|
||||
return this.activeNotification?.snoozed_until;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
openSnoozeNotificationModal() {
|
||||
const ninja = document.querySelector('ninja-keys');
|
||||
ninja.open({ parent: 'snooze_notification' });
|
||||
},
|
||||
hideCustomSnoozeModal() {
|
||||
this.showCustomSnoozeModal = false;
|
||||
},
|
||||
snoozeNotification(snoozedUntil) {
|
||||
this.$store
|
||||
.dispatch('notifications/snooze', {
|
||||
id: this.activeNotification?.id,
|
||||
snoozedUntil,
|
||||
})
|
||||
.then(() => {
|
||||
this.showAlert(this.$t('INBOX.ALERTS.SNOOZE'));
|
||||
});
|
||||
},
|
||||
onCmdSnoozeNotification(snoozeType) {
|
||||
if (snoozeType === wootConstants.SNOOZE_OPTIONS.UNTIL_CUSTOM_TIME) {
|
||||
this.showCustomSnoozeModal = true;
|
||||
} else {
|
||||
const snoozedUntil = findSnoozeTime(snoozeType) || null;
|
||||
this.snoozeNotification(snoozedUntil);
|
||||
}
|
||||
},
|
||||
scheduleCustomSnooze(customSnoozeTime) {
|
||||
this.showCustomSnoozeModal = false;
|
||||
if (customSnoozeTime) {
|
||||
const snoozedUntil = getUnixTime(customSnoozeTime) || null;
|
||||
this.snoozeNotification(snoozedUntil);
|
||||
}
|
||||
},
|
||||
deleteNotification() {
|
||||
this.$track(INBOX_EVENTS.DELETE_NOTIFICATION);
|
||||
this.$store
|
||||
|
||||
@@ -69,12 +69,29 @@ export default {
|
||||
InboxDisplayMenu,
|
||||
},
|
||||
mixins: [clickaway, alertMixin],
|
||||
props: {
|
||||
isContextMenuOpen: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showInboxDisplayMenu: false,
|
||||
showInboxOptionMenu: false,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
isContextMenuOpen: {
|
||||
handler(val) {
|
||||
if (val) {
|
||||
this.showInboxDisplayMenu = false;
|
||||
this.showInboxOptionMenu = false;
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
markAllRead() {
|
||||
this.$track(INBOX_EVENTS.MARK_ALL_NOTIFICATIONS_AS_READ);
|
||||
@@ -99,22 +116,19 @@ export default {
|
||||
this.showInboxOptionMenu = !this.showInboxOptionMenu;
|
||||
},
|
||||
onInboxOptionMenuClick(key) {
|
||||
this.showInboxOptionMenu = false;
|
||||
if (key === 'mark_all_read') {
|
||||
this.markAllRead();
|
||||
}
|
||||
if (key === 'delete_all') {
|
||||
this.deleteAll();
|
||||
}
|
||||
if (key === 'delete_all_read') {
|
||||
this.deleteAllRead();
|
||||
}
|
||||
const actions = {
|
||||
mark_all_read: () => this.markAllRead(),
|
||||
delete_all: () => this.deleteAll(),
|
||||
delete_all_read: () => this.deleteAllRead(),
|
||||
};
|
||||
const action = actions[key];
|
||||
if (action) action();
|
||||
this.$emit('redirect');
|
||||
},
|
||||
onFilterChange(option) {
|
||||
this.$emit('filter', option);
|
||||
this.showInboxDisplayMenu = false;
|
||||
if (this.$route.name === 'inbox_view') return;
|
||||
this.$router.push({ name: 'inbox_view' });
|
||||
this.$emit('redirect');
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -11,6 +11,9 @@ export const getters = {
|
||||
);
|
||||
return sortedNotifications;
|
||||
},
|
||||
getActiveNotificationById: $state => id => {
|
||||
return $state.records[id] || {};
|
||||
},
|
||||
getUIFlags($state) {
|
||||
return $state.uiFlags;
|
||||
},
|
||||
|
||||
@@ -44,6 +44,16 @@ describe('#getters', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('getActiveNotificationById', () => {
|
||||
const state = {
|
||||
records: {
|
||||
1: { id: 1 },
|
||||
},
|
||||
};
|
||||
expect(getters.getActiveNotificationById(state)(1)).toEqual({ id: 1 });
|
||||
expect(getters.getActiveNotificationById(state)(2)).toEqual({});
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@
|
||||
"markdown-it": "^13.0.1",
|
||||
"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",
|
||||
|
||||
@@ -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"
|
||||
@@ -15072,15 +15081,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"
|
||||
|
||||
Reference in New Issue
Block a user