Files
chatwoot/app/javascript/dashboard/store/modules/notifications/mutations.js
Shivam Mishra e0ef007047 fix: Fix Sentry issues from Vite migration (#10262)
Fixes the following issues

- https://chatwoot-p3.sentry.io/issues/5966466083
- https://chatwoot-p3.sentry.io/issues/5966497518
- https://chatwoot-p3.sentry.io/issues/5966555379

For the first one, I am not sure if the fix is 100% correct, since I was
not able to reproduce, but I am confident it will work.

For both, 1st and 2nd issues, the problem came from the fact that we set
individual records to `undefined` when the intent was to remove it,
explicitly using delete fixes the issue.

### Whats up with the store changes?

Glad you asked, this comes down to Vue reactivity, previously Vue didn't
track undefined strictly, it just kinda ignored it, in Vue 3, the
reactivity changed significantly when they introduced ES6 proxies. The
Proxy tracks all property changes, including those set to undefined, so
properties remain enumerable.

So to delete a record, we actually have to the delete it using the
delete keyword, or replace the parent object with a new object splicing
the object to be deleted out.

I am assuming it worked earlier because VueX 3 reactivity was using
Object.defineProperty. Setting it to undefined might have "deleted" it
earlier

---------

Co-authored-by: Pranav <pranav@chatwoot.com>
2024-10-14 10:44:59 -07:00

108 lines
3.4 KiB
JavaScript

import types from '../../mutation-types';
export const mutations = {
[types.SET_NOTIFICATIONS_UI_FLAG]($state, data) {
$state.uiFlags = {
...$state.uiFlags,
...data,
};
},
[types.CLEAR_NOTIFICATIONS]: $state => {
$state.records = {};
$state.uiFlags.isAllNotificationsLoaded = false;
},
[types.SET_NOTIFICATIONS_META]: ($state, data) => {
const {
count,
current_page: currentPage,
unread_count: unreadCount,
} = data;
$state.meta = { ...$state.meta, count, currentPage, unreadCount };
},
[types.SET_NOTIFICATIONS_UNREAD_COUNT]: ($state, count) => {
$state.meta.unreadCount = count < 0 ? 0 : count;
},
[types.SET_NOTIFICATIONS]: ($state, data) => {
data.forEach(notification => {
// Find existing notification with same primary_actor_id (primary_actor_id is unique)
const existingNotification = Object.values($state.records).find(
record => record.primary_actor_id === notification.primary_actor_id
);
// This is to handle the case where the same notification is received multiple times
// On reconnect, if there is existing notification with same primary_actor_id,
// it will be deleted and the new one will be added. So it will solve with duplicate notification
if (existingNotification) {
delete $state.records[existingNotification.id];
}
$state.records[notification.id] = {
...($state.records[notification.id] || {}),
...notification,
};
});
},
[types.READ_NOTIFICATION]: ($state, { id, read_at }) => {
$state.records[id].read_at = read_at;
},
[types.UPDATE_ALL_NOTIFICATIONS]: $state => {
Object.values($state.records).forEach(item => {
$state.records[item.id].read_at = true;
});
},
[types.ADD_NOTIFICATION]($state, data) {
const { notification, unread_count: unreadCount, count } = data;
$state.records[notification.id] = {
...($state.records[notification.id] || {}),
...notification,
};
$state.meta.unreadCount = unreadCount;
$state.meta.count = count;
},
[types.UPDATE_NOTIFICATION]($state, data) {
const { notification, unread_count: unreadCount, count } = data;
$state.records[notification.id] = {
...($state.records[notification.id] || {}),
...notification,
};
$state.meta.unreadCount = unreadCount;
$state.meta.count = count;
},
[types.DELETE_NOTIFICATION]($state, data) {
const { notification, unread_count: unreadCount, count } = data;
delete $state.records[notification.id];
$state.meta.unreadCount = unreadCount;
$state.meta.count = count;
},
[types.SET_ALL_NOTIFICATIONS_LOADED]: $state => {
$state.uiFlags.isAllNotificationsLoaded = true;
},
[types.DELETE_READ_NOTIFICATIONS]: $state => {
Object.values($state.records).forEach(item => {
if (item.read_at) {
delete $state.records[item.id];
}
});
},
[types.DELETE_ALL_NOTIFICATIONS]: $state => {
$state.records = {};
},
[types.SNOOZE_NOTIFICATION]: ($state, { id, snoozed_until }) => {
$state.records[id].snoozed_until = snoozed_until;
},
[types.SET_NOTIFICATION_FILTERS]: ($state, filters) => {
$state.notificationFilters = filters;
},
[types.UPDATE_NOTIFICATION_FILTERS]: ($state, filters) => {
$state.notificationFilters = {
...$state.notificationFilters,
...filters,
};
},
};