Skip to content

Commit

Permalink
Merge pull request #33438 from dimagi/bmb/b5-notifications-service-js
Browse files Browse the repository at this point in the history
[B5] Initial migration for notifications js (notifications_service)
  • Loading branch information
biyeun authored Sep 8, 2023
2 parents 35703f7 + d83aaf4 commit fbde9e2
Show file tree
Hide file tree
Showing 15 changed files with 283 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ hqDefine("cloudcare/js/formplayer/app", function () {
if (user.environment === Const.WEB_APPS_ENVIRONMENT) {
// This isn't a circular import, but importing it at the top level would
// mean it would need to be faked for tests
hqRequire(["notifications/js/notifications_service_main"], function (Notifications) {
hqRequire(["notifications/js/bootstrap3/notifications_service_main"], function (Notifications) {
Notifications.initNotifications();
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ hqDefine("hqwebapp/js/bootstrap3/base_main", [
'hqwebapp/js/bootstrap3/sticky_tabs',
'hqwebapp/js/bootstrap3/main',
'hqwebapp/js/bootstrap3/inactivity',
'notifications/js/notifications_service_main',
'notifications/js/bootstrap3/notifications_service_main',
'analytix/js/appcues',
'analytix/js/drift',
'analytix/js/google',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ hqDefine("hqwebapp/js/bootstrap5/base_main", [
'hqwebapp/js/bootstrap5/sticky_tabs',
'hqwebapp/js/bootstrap5/main',
'hqwebapp/js/bootstrap5/inactivity',
'notifications/js/notifications_service_main',
'notifications/js/bootstrap5/notifications_service_main',
'analytix/js/appcues',
'analytix/js/drift',
'analytix/js/google',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ requirejs.config({
// This file gets auto-generated during deploy.
// It will add the CDN paths for each JavaScript module, as in the following example.

//'notifications/js/notifications_service': 'https://d2f60qxn5rwjxl.cloudfront.net/static/notifications/js/notifications_service.js?version=e7ee173',
//'notifications/js/bootstrap3/notifications_service': 'https://d2f60qxn5rwjxl.cloudfront.net/static/notifications/js/notifications_service.js?version=e7ee173',
},
});
9 changes: 7 additions & 2 deletions corehq/apps/hqwebapp/templates/hqwebapp/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,13 @@
{# JavaScript Display Logic Libaries #}

{% if request.couch_user and not requirejs_main %}
<script src="{% static 'notifications/js/notifications_service.js' %}"></script>
<script src="{% static 'notifications/js/notifications_service_main.js' %}"></script>
{% if use_bootstrap5 %}
<script src="{% static 'notifications/js/bootstrap5/notifications_service.js' %}"></script>
<script src="{% static 'notifications/js/bootstrap5/notifications_service_main.js' %}"></script>
{% else %}
<script src="{% static 'notifications/js/bootstrap3/notifications_service.js' %}"></script>
<script src="{% static 'notifications/js/bootstrap3/notifications_service_main.js' %}"></script>
{% endif %}
{% endif %}

{% if not requirejs_main %}
Expand Down
8 changes: 8 additions & 0 deletions corehq/apps/hqwebapp/tests/data/bootstrap5_diff_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,5 +109,13 @@
"label": "notifications/partials",
"compare_all_files": true
}
],
"apps/notifications/static/notifications": [
{
"directories": ["js/bootstrap3/", "js/bootstrap5/"],
"file_type": "javascript",
"label": "javascript/notifications",
"compare_all_files": true
}
]
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
+++
@@ -1,12 +1,12 @@
@@ -1,19 +1,19 @@
-hqDefine("hqwebapp/js/bootstrap3/base_main", [
- 'hqwebapp/js/bootstrap3/downgrade_modal',
- 'hqwebapp/js/bootstrap3/prepaid_modal',
Expand All @@ -14,14 +14,15 @@
- 'hqwebapp/js/bootstrap3/sticky_tabs',
- 'hqwebapp/js/bootstrap3/main',
- 'hqwebapp/js/bootstrap3/inactivity',
- 'notifications/js/bootstrap3/notifications_service_main',
+ 'hqwebapp/js/bootstrap5/hq-bug-report',
+ 'hqwebapp/js/bootstrap5/sticky_tabs',
+ 'hqwebapp/js/bootstrap5/main',
+ 'hqwebapp/js/bootstrap5/inactivity',
'notifications/js/notifications_service_main',
+ 'notifications/js/bootstrap5/notifications_service_main',
'analytix/js/appcues',
'analytix/js/drift',
@@ -14,6 +14,6 @@
'analytix/js/google',
'analytix/js/hubspot',
'analytix/js/kissmetrix',
'hqwebapp/js/mobile_experience_warning',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
+++
@@ -4,13 +4,13 @@
*
*/

-hqDefine('notifications/js/bootstrap3/notifications_service', [
+hqDefine('notifications/js/bootstrap5/notifications_service', [
'jquery',
'knockout',
'underscore',
'jquery.rmi/jquery.rmi',
'analytix/js/kissmetrix',
- 'hqwebapp/js/bootstrap3/hq.helpers',
+ 'hqwebapp/js/bootstrap5/hq.helpers',
], function (
$,
ko,
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
+++
@@ -2,10 +2,10 @@
* Document ready handling for pages that use notifications/js/notifications_service.js
*/

-hqDefine('notifications/js/bootstrap3/notifications_service_main', [
+hqDefine('notifications/js/bootstrap5/notifications_service_main', [
'jquery',
'hqwebapp/js/initial_page_data',
- 'notifications/js/bootstrap3/notifications_service',
+ 'notifications/js/bootstrap5/notifications_service',
'analytix/js/google',
], function (
$,
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*
*/

hqDefine('notifications/js/notifications_service', [
hqDefine('notifications/js/bootstrap3/notifications_service', [
'jquery',
'knockout',
'underscore',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
* Document ready handling for pages that use notifications/js/notifications_service.js
*/

hqDefine('notifications/js/notifications_service_main', [
hqDefine('notifications/js/bootstrap3/notifications_service_main', [
'jquery',
'hqwebapp/js/initial_page_data',
'notifications/js/notifications_service',
'notifications/js/bootstrap3/notifications_service',
'analytix/js/google',
], function (
$,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
/**
* NotificationsService communicates with the NotificationsServiceRMIView django view
* to fetch and update notifications for users on CommCare HQ.
*
*/

hqDefine('notifications/js/bootstrap5/notifications_service', [
'jquery',
'knockout',
'underscore',
'jquery.rmi/jquery.rmi',
'analytix/js/kissmetrix',
'hqwebapp/js/bootstrap5/hq.helpers',
], function (
$,
ko,
_,
RMI,
kissmetrics
) {
'use strict';

// Workaround for non-RequireJS pages: when `define` doesn't exist, RMI is just a global variable.
RMI = RMI || window.RMI;

var module = {};
var _private = {};
_private.RMI = function () {};

module.setRMI = function (rmiUrl, csrfToken) {
var _rmi = RMI(rmiUrl, csrfToken);
_private.RMI = function (remoteMethod, data) {
return _rmi("", data, {headers: {"DjNg-Remote-Method": remoteMethod}});
};
};

var Notification = function (data) {
var self = this;
self.id = ko.observable(data.id);
self.isRead = ko.observable(data.isRead);
self.content = ko.observable(data.content);
self.url = ko.observable(data.url);
self.type = ko.observable(data.type);
self.date = ko.observable(data.date);
self.activated = ko.observable(data.activated);

self.isAlert = ko.computed(function () {
return self.type() === 'alert';
});
self.isInfo = ko.computed(function () {
return self.type() === 'info';
});
self.isFeature = ko.computed(function () {
return self.type() === 'feat_basic' || self.type() === 'feat_pro';
});
self.markAsRead = function () {
_private.RMI("mark_as_read", {id: self.id()})
.done(function (data) {
if (self.isFeature()) {
kissmetrics.track.event("Notifications tab - Clicked notifications tab - " +
"Clicked on Case Sharing text link",
{email: data.email, domain: data.domain});
}
});
self.isRead(true);
return true;
};
};

var NotificationsServiceModel = function () {
var self = this;
self.notifications = ko.observableArray();
self.hasError = ko.observable(false);
self.lastSeenNotificationDate = ko.observable();

self.hasUnread = ko.computed(function () {
return _.some(self.notifications(), function (note) {
return !note.isRead();
});
});

self.hasUnreadFeatureNotification = ko.computed(function () {
return _.some(self.notifications(), function (note) {
return !note.isRead() && (note.type() === 'feat_basic' || note.type() === 'feat_pro')
});
})

self.seen = ko.computed(function () {
if (self.hasUnreadFeatureNotification()) {
return false;
}

if (!self.hasUnread()) {
return true;
}

var notifications = self.notifications();
if (notifications.length === 0) {
return true;
}

var newestNotification = notifications[0];
var newestNotificationDate = new Date(newestNotification.activated());
var lastSeenNotificationDate = new Date(self.lastSeenNotificationDate());
return lastSeenNotificationDate >= newestNotificationDate;
});

self.init = function () {
_private.RMI("get_notifications", {'did_it_work': true})
.done(function (data) {
self.lastSeenNotificationDate(data.lastSeenNotificationDate);
_.each(data.notifications, function (data) {
self.notifications.push(new Notification(data));
});
})
.fail(function (jqXHR, textStatus, errorThrown) {
self.hasError(true);
});
};

self.bellClickHandler = function () {
if (self.notifications().length === 0) {
return;
}

_private.RMI("save_last_seen", {"notification_id": self.notifications()[0].id()})
.done(function (data) {
self.lastSeenNotificationDate(data.activated);
if (self.hasUnreadFeatureNotification()) {
kissmetrics.track.event("Notifications tab - Clicked notifications tab",
{email: data.email, domain: data.domain});
}
})
.fail(function (jqXHR, textStatus, errorThrown) {
console.log(errorThrown); // eslint-disable-line no-console
self.hasError(true);
});
};
};

module.serviceModel = {};
module.initService = function (notificationsKoSelector) {
if ($(notificationsKoSelector).length < 1) {
return;
}
module.serviceModel = new NotificationsServiceModel();
module.serviceModel.init();
if (!ko.dataFor($(notificationsKoSelector)[0])) {
// avoid multiple inits
$(notificationsKoSelector).koApplyBindings(module.serviceModel);
}
};

module.relativelyPositionUINotify = function (uiNotifySelector) {
var uiNotifyAlerts = $(uiNotifySelector);
_.each(uiNotifyAlerts, function (elem) {
var $notify = $(elem),
$target = $($notify.data('target'));

$notify.remove();
$target
.css('position', 'relative')
.append($notify);

});
};

// Store dismissed slugs client-side so that alerts that are generated client-side
// don't get re-created after user has dismissed them.
var dismissedSlugs = [];
module.initUINotify = function (uiNotifySelector) {
var uiNotifyAlerts = $(uiNotifySelector);
if (uiNotifyAlerts.length > 0) {
uiNotifyAlerts.on('closed.bs.alert', function () {
var notifySlug = $(this).data('slug');
dismissedSlugs.push(notifySlug);
_private.RMI("dismiss_ui_notify", {
"slug": notifySlug,
});
});
uiNotifyAlerts.each(function () {
if (_.contains(dismissedSlugs, $(this).data('slug'))) {
$(this).addClass("hide");
}
});
}
};

return module;
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Document ready handling for pages that use notifications/js/notifications_service.js
*/

hqDefine('notifications/js/bootstrap5/notifications_service_main', [
'jquery',
'hqwebapp/js/initial_page_data',
'notifications/js/bootstrap5/notifications_service',
'analytix/js/google',
], function (
$,
initialPageData,
notificationsService,
googleAnalytics
) {
var initNotifications = function () {
var csrfToken = $("#csrfTokenContainer").val();
notificationsService.setRMI(initialPageData.reverse('notifications_service'), csrfToken);
notificationsService.initService('#js-settingsmenu-notifications');
notificationsService.relativelyPositionUINotify('.alert-ui-notify-relative');
notificationsService.initUINotify('.alert-ui-notify');

$(document).on('click', '.notification-link', function () {
googleAnalytics.track.event('Notification', 'Opened Message', this.href);
});
googleAnalytics.track.click($('#notification-icon'), 'Notification', 'Clicked Bell Icon');
};
$(document).ready(initNotifications);
return {
'initNotifications': initNotifications,
};
});
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe('NotificationsService Unit Tests', function () {
sinon.stub($, 'ajax', fakePromise.mock);

it('Initialization', function () {
var notifications = hqImport('notifications/js/notifications_service');
var notifications = hqImport('notifications/js/bootstrap3/notifications_service');
var csrfToken = $("#csrfTokenContainer").val();
notifications.setRMI(fakeRMIUrl, csrfToken);
notifications.initService('#js-settingsmenu-notifications');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{% load hq_shared_tags %}

{% block dependencies %}
<script src="{% static 'notifications/js/notifications_service.js' %}"></script>
<script src="{% static 'notifications/js/bootstrap3/notifications_service.js' %}"></script>
{% endblock %}

{% block fixtures %}
Expand Down

0 comments on commit fbde9e2

Please sign in to comment.