Skip to content

Commit

Permalink
Merge pull request #12644 from iamshobhraj/v1
Browse files Browse the repository at this point in the history
Moved core notifications handling into NotificationsRoot component
  • Loading branch information
nucleogenesis authored Oct 9, 2024
2 parents a580655 + 094e8e7 commit 8a0029f
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 50 deletions.
1 change: 0 additions & 1 deletion kolibri/core/assets/src/kolibri_app.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ export default class KolibriApp extends KolibriModule {
ready() {
this.setupVue();
return heartbeat.startPolling().then(() => {
this.store.dispatch('getNotifications');
return Promise.all([
// Invoke each of the state setters before initializing the app.
...this.stateSetters.map(setter => setter(this.store)),
Expand Down
44 changes: 0 additions & 44 deletions kolibri/core/assets/src/state/modules/core/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,13 @@ import {
FacilityResource,
FacilityDatasetResource,
UserSyncStatusResource,
PingbackNotificationResource,
PingbackNotificationDismissedResource,
} from 'kolibri.resources';
import { setServerTime } from 'kolibri.utils.serverClock';
import urls from 'kolibri.urls';
import redirectBrowser from 'kolibri.utils.redirectBrowser';
import CatchErrors from 'kolibri.utils.CatchErrors';
import Vue from 'kolibri.lib.vue';
import Lockr from 'lockr';
import { get } from '@vueuse/core';
import useUser from 'kolibri.coreVue.composables.useUser';
import {
DisconnectionErrorCodes,
LoginErrors,
Expand All @@ -36,16 +32,6 @@ const logging = logger.getLogger(__filename);
* the API to state in the Vuex store
*/

function _notificationListState(data) {
return data.map(notification => ({
id: notification.id,
version_range: notification.version_range,
timestamp: notification.timestamp,
link_url: notification.link_url,
i18n: notification.i18n,
}));
}

/**
* Actions
*
Expand Down Expand Up @@ -179,36 +165,6 @@ export function setPageVisibility(store) {
_setPageVisibility(store, document.visibilityState === 'visible');
}

export function getNotifications(store) {
const { isAdmin, isSuperuser } = useUser();
if (get(isAdmin) || get(isSuperuser)) {
return PingbackNotificationResource.fetchCollection()
.then(notifications => {
logging.info('Notifications set.');
store.commit('CORE_SET_NOTIFICATIONS', _notificationListState(notifications));
})
.catch(error => {
store.dispatch('handleApiError', { error });
});
}
return Promise.resolve();
}

export function saveDismissedNotification(store, notification_id) {
const { user_id } = useUser();
const dismissedNotificationData = {
user: get(user_id),
notification: notification_id,
};
return PingbackNotificationDismissedResource.saveModel({ data: dismissedNotificationData })
.then(() => {
store.commit('CORE_REMOVE_NOTIFICATION', notification_id);
})
.catch(error => {
store.dispatch('handleApiError', { error });
});
}

export function getFacilities(store) {
return FacilityResource.fetchCollection({ force: true }).then(facilities => {
store.commit('CORE_SET_FACILITIES', [...facilities]);
Expand Down
61 changes: 59 additions & 2 deletions kolibri/core/assets/src/views/NotificationsRoot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
import { mapState } from 'vuex';
import Lockr from 'lockr';
import {
PingbackNotificationResource,
PingbackNotificationDismissedResource,
} from 'kolibri.resources';
import { UPDATE_MODAL_DISMISSED } from 'kolibri.coreVue.vuex.constants';
import { currentLanguage, defaultLanguage } from 'kolibri.utils.i18n';
import AuthMessage from 'kolibri.coreVue.components.AuthMessage';
Expand All @@ -63,11 +67,12 @@
UpdateNotification,
},
setup() {
const { isAdmin, isSuperuser } = useUser();
const { isAdmin, isSuperuser, user_id } = useUser();
return {
isAdmin,
isSuperuser,
user_id,
};
},
props: {
Expand Down Expand Up @@ -95,13 +100,13 @@
},
data() {
return {
notifications: [],
notificationModalShown: true,
};
},
computed: {
...mapState({
error: state => state.core.error,
notifications: state => state.core.notifications,
}),
notAuthorized() {
// catch "not authorized" error, display AuthMessage
Expand All @@ -127,6 +132,9 @@
return false;
},
mostRecentNotification() {
if (this.notifications.length === 0) {
return null;
}
let languageCode = defaultLanguage.id;
// notifications should already be ordered by timestamp
const notification = this.notifications[0];
Expand All @@ -147,16 +155,65 @@
return null;
},
},
created() {
this.getNotifications();
},
methods: {
async getNotifications() {
const { isAdmin, isSuperuser } = useUser();
if (isAdmin || isSuperuser) {
try {
const notifications = await PingbackNotificationResource.fetchCollection();
this.notifications = _notificationListState(notifications);
} catch (error) {
this.dispatchError(error);
}
}
},
async saveDismissedNotification(notificationId) {
try {
await PingbackNotificationDismissedResource.saveModel({
data: {
user: this.user_id,
notification: notificationId,
},
});
this.removeNotification(notificationId);
} catch (error) {
this.dispatchError(error);
}
},
dismissUpdateModal() {
if (this.notifications.length === 0) {
this.notificationModalShown = false;
Lockr.set(UPDATE_MODAL_DISMISSED, true);
} else {
this.saveDismissedNotification(this.mostRecentNotification.id);
}
},
dispatchError(error) {
this.$store.dispatch('handleApiError', { error });
},
removeNotification(notificationId) {
this.notifications = this.notifications.filter(n => n.id !== notificationId);
},
},
};
function _notificationListState(data) {
if (!data || data.length === 0) {
return [];
}
return data.map(notification => ({
id: notification.id,
version_range: notification.version_range,
timestamp: notification.timestamp,
link_url: notification.link_url,
i18n: notification.i18n,
}));
}
</script>


Expand Down
1 change: 0 additions & 1 deletion kolibri/core/assets/test/kolibri_app.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ describe('KolibriApp', function () {
core: {
actions: {
getCurrentSession: jest.fn().mockResolvedValue(),
getNotifications: jest.fn().mockResolvedValue(),
},
},
},
Expand Down
5 changes: 3 additions & 2 deletions kolibri/core/assets/test/views/NotificationsRoot.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { coreStoreFactory as makeStore } from '../../src/state/store';
import coreModule from '../../src/state/modules/core';

jest.mock('kolibri.coreVue.composables.useUser');
jest.mock('kolibri.resources');

function makeWrapper(useUserMockObj = null) {
const store = makeStore();
Expand Down Expand Up @@ -72,7 +73,7 @@ describe('NotificationsRoot', function () {
it('notification modal should be rendered if the user is an admin/superuser, a notification exists, and there is a recent notification', async () => {
const { wrapper, store } = makeWrapper({ isAdmin: true, isSuperuser: true });
store.state.core.loading = false;
store.state.core.notifications = [
wrapper.vm.notifications = [
{
id: 2,
title: 'title',
Expand All @@ -90,7 +91,7 @@ describe('NotificationsRoot', function () {
const { wrapper, store } = makeWrapper();
store.commit('CORE_SET_SESSION', { kind: [UserKinds.ADMIN] });
store.state.core.loading = false;
store.state.core.notifications = [];
wrapper.vm.notifications = [];
await wrapper.vm.$nextTick();

expect(wrapper.findComponent({ name: 'UpdateNotification' }).exists()).toBeFalsy();
Expand Down

0 comments on commit 8a0029f

Please sign in to comment.