feat: Inbox item actions (#8838)

* feat: Inbox item actions

* feat: add inbox id in push event data

* Update InboxList.vue

* feat: complete actions

* Update InboxList.vue

* Update InboxView.vue

* chore: code cleanup

* chore: fix specs

---------

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
This commit is contained in:
Muhsin Keloth
2024-02-02 11:58:47 +05:30
committed by GitHub
parent 33e98bf61a
commit d3c1fce761
15 changed files with 242 additions and 54 deletions

View File

@@ -48,14 +48,26 @@ export const actions = {
},
read: async (
{ commit },
{ primaryActorType, primaryActorId, unreadCount }
{ id, primaryActorType, primaryActorId, unreadCount }
) => {
commit(types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: true });
try {
await NotificationsAPI.read(primaryActorType, primaryActorId);
commit(types.SET_NOTIFICATIONS_UNREAD_COUNT, unreadCount - 1);
commit(types.UPDATE_NOTIFICATION, primaryActorId);
commit(types.UPDATE_NOTIFICATION, { id, read_at: new Date() });
commit(types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: false });
} catch (error) {
throw new Error(error);
commit(types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: false });
}
},
unread: async ({ commit }, { id }) => {
commit(types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: true });
try {
await NotificationsAPI.unRead(id);
commit(types.UPDATE_NOTIFICATION, { id, read_at: null });
commit(types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: false });
} catch (error) {
commit(types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: false });
}
},
readAll: async ({ commit }) => {
@@ -71,6 +83,18 @@ export const actions = {
}
},
delete: async ({ commit }, { notification, count, unreadCount }) => {
commit(types.SET_NOTIFICATIONS_UI_FLAG, { isDeleting: true });
try {
await NotificationsAPI.delete(notification.id);
commit(types.SET_NOTIFICATIONS_UNREAD_COUNT, unreadCount - 1);
commit(types.DELETE_NOTIFICATION, { notification, count, unreadCount });
commit(types.SET_NOTIFICATIONS_UI_FLAG, { isDeleting: false });
} catch (error) {
commit(types.SET_NOTIFICATIONS_UI_FLAG, { isDeleting: false });
}
},
addNotification({ commit }, data) {
commit(types.ADD_NOTIFICATION, data);
},

View File

@@ -13,6 +13,7 @@ const state = {
isFetching: false,
isFetchingItem: false,
isUpdating: false,
isDeleting: false,
isUpdatingUnreadCount: false,
isAllNotificationsLoaded: false,
},

View File

@@ -34,12 +34,8 @@ export const mutations = {
});
});
},
[types.UPDATE_NOTIFICATION]: ($state, primaryActorId) => {
Object.values($state.records).forEach(item => {
if (item.primary_actor_id === primaryActorId) {
Vue.set($state.records[item.id], 'read_at', true);
}
});
[types.UPDATE_NOTIFICATION]: ($state, { id, read_at }) => {
Vue.set($state.records[id], 'read_at', read_at);
},
[types.UPDATE_ALL_NOTIFICATIONS]: $state => {
Object.values($state.records).forEach(item => {

View File

@@ -94,18 +94,91 @@ describe('#actions', () => {
describe('#read', () => {
it('sends correct actions if API is success', async () => {
axios.post.mockResolvedValue({});
await actions.read({ commit }, { unreadCount: 2, primaryActorId: 1 });
await actions.read(
{ commit },
{ id: 1, unreadCount: 2, primaryActorId: 1 }
);
expect(commit.mock.calls).toEqual([
[types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: true }],
[types.SET_NOTIFICATIONS_UNREAD_COUNT, 1],
[types.UPDATE_NOTIFICATION, 1],
[types.UPDATE_NOTIFICATION, { id: 1, read_at: expect.any(Date) }],
[types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: false }],
]);
});
it('sends correct actions if API is error', async () => {
axios.post.mockRejectedValue({ message: 'Incorrect header' });
await expect(actions.read({ commit })).rejects.toThrow(Error);
await actions.read(
{ commit },
{ id: 1, unreadCount: 2, primaryActorId: 1 }
);
expect(commit.mock.calls).toEqual([
[types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: true }],
[types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: false }],
]);
});
});
describe('#unread', () => {
it('sends correct actions if API is success', async () => {
axios.post.mockResolvedValue({});
await actions.unread({ commit }, { id: 1 });
expect(commit.mock.calls).toEqual([
['SET_NOTIFICATIONS_UI_FLAG', { isUpdating: true }],
['UPDATE_NOTIFICATION', { id: 1, read_at: null }],
['SET_NOTIFICATIONS_UI_FLAG', { isUpdating: false }],
]);
});
it('sends correct actions if API is error', async () => {
axios.post.mockRejectedValue({ message: 'Incorrect header' });
await expect(actions.unread({ commit })).rejects.toThrow(Error);
await actions.unread({ commit }, { id: 1 });
expect(commit.mock.calls).toEqual([
[types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: true }],
[types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: false }],
]);
});
});
describe('#delete', () => {
it('sends correct actions if API is success', async () => {
axios.delete.mockResolvedValue({});
await actions.delete(
{ commit },
{
notification: { id: 1 },
count: 2,
unreadCount: 1,
}
);
expect(commit.mock.calls).toEqual([
[types.SET_NOTIFICATIONS_UI_FLAG, { isDeleting: true }],
[types.SET_NOTIFICATIONS_UNREAD_COUNT, 0],
[
types.DELETE_NOTIFICATION,
{ notification: { id: 1 }, count: 2, unreadCount: 1 },
],
[types.SET_NOTIFICATIONS_UI_FLAG, { isDeleting: false }],
]);
});
it('sends correct actions if API is error', async () => {
axios.delete.mockRejectedValue({ message: 'Incorrect header' });
await expect(actions.delete({ commit })).rejects.toThrow(Error);
await actions.delete(
{ commit },
{
notification: { id: 1 },
count: 2,
unreadCount: 1,
}
);
expect(commit.mock.calls).toEqual([
[types.SET_NOTIFICATIONS_UI_FLAG, { isDeleting: true }],
[types.SET_NOTIFICATIONS_UI_FLAG, { isDeleting: false }],
]);
});
});
describe('#readAll', () => {
it('sends correct actions if API is success', async () => {
axios.post.mockResolvedValue({ data: 1 });

View File

@@ -75,7 +75,10 @@ describe('#mutations', () => {
1: { id: 1, primary_actor_id: 1 },
},
};
mutations[types.UPDATE_NOTIFICATION](state, 1);
mutations[types.UPDATE_NOTIFICATION](state, {
id: 1,
read_at: true,
});
expect(state.records).toEqual({
1: { id: 1, primary_actor_id: 1, read_at: true },
});