Skip to content

Commit

Permalink
Merge pull request #6463 from OCHA-DAP/feature/HDX-10249-implement-mi…
Browse files Browse the repository at this point in the history
…xpanel-tracking

PR notifications to prod
  • Loading branch information
danmihaila authored Oct 28, 2024
2 parents 8144938 + 2d7b9e4 commit 2ebd12a
Show file tree
Hide file tree
Showing 34 changed files with 345 additions and 106 deletions.
23 changes: 23 additions & 0 deletions ckanext-hdx_package/ckanext/hdx_package/helpers/analytics.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

from ckanext.hdx_package.helpers.constants import COD_ENHANCED, COD_STANDARD
from ckanext.hdx_theme.util.analytics import AbstractAnalyticsSender
from ckanext.hdx_users.helpers.notification_platform import check_notifications_enabled_for_dataset

from typing import Any, Dict, Optional

import ckan.lib.helpers as h
import ckan.model as model
Expand Down Expand Up @@ -63,6 +66,22 @@ def dataset_availability(pkg_dict):
return level


def came_from(request_args: Dict[str, str]) -> Optional[str]:
source_mapping = {
'notification_platform_email': 'notification platform email',
}

came_from_arg = request_args.get('came_from')

return source_mapping.get(came_from_arg, '')


def supports_notifications(pkg_dict: dict[str, Any]) -> str:
dataset_supports_notifications = check_notifications_enabled_for_dataset(pkg_dict['id'])

return str(dataset_supports_notifications).lower()


def extract_locations(pkg_dict):
locations = pkg_dict.get('groups', [])
location_names = []
Expand Down Expand Up @@ -121,6 +140,8 @@ def generate_analytics_data(dataset_dict):
analytics_dict['isArchived'] = is_archived(dataset_dict)
analytics_dict['groupNames'], analytics_dict['groupIds'] = extract_locations_in_json(dataset_dict)
analytics_dict['datasetAvailability'] = dataset_availability(dataset_dict)
analytics_dict['cameFrom'] = ''
analytics_dict['supportsNotifications'] = supports_notifications(dataset_dict)
else:
analytics_dict['datasetId'] = ''
analytics_dict['datasetName'] = ''
Expand All @@ -132,6 +153,8 @@ def generate_analytics_data(dataset_dict):
analytics_dict['groupNames'] = '[]'
analytics_dict['groupIds'] = '[]'
analytics_dict['datasetAvailability'] = None
analytics_dict['cameFrom'] = ''
analytics_dict['supportsNotifications'] = 'false'
return analytics_dict


Expand Down
6 changes: 5 additions & 1 deletion ckanext-hdx_package/ckanext/hdx_package/views/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ def read(id):
analytics_is_archived = analytics.is_archived(pkg_dict)
analytics_group_names, analytics_group_ids = analytics.extract_locations_in_json(pkg_dict)
analytics_dataset_availability = analytics.dataset_availability(pkg_dict)
analytics_came_from = analytics.came_from(request.args)
analytics_supports_notifications = analytics.supports_notifications(pkg_dict)

# changes done for indicator
act_data_dict = {'id': pkg_dict['id'], 'limit': 7}
Expand Down Expand Up @@ -189,7 +191,7 @@ def read(id):
unsubscribe_token = request.args.get('unsubscribe_token', None)
if unsubscribe_token:
try:
token_obj = verify_unsubscribe_token(unsubscribe_token, inactivate=False)
unsubscribe_token = verify_unsubscribe_token(unsubscribe_token, inactivate=False)
except Exception as e:
unsubscribe_token = None
h.flash_error('Your token is invalid or has expired.')
Expand All @@ -208,6 +210,8 @@ def read(id):
'analytics_group_names': analytics_group_names,
'analytics_group_ids': analytics_group_ids,
'analytics_dataset_availability': analytics_dataset_availability,
'analytics_came_from': analytics_came_from,
'analytics_supports_notifications': analytics_supports_notifications,
'stats_downloads_last_weeks': stats_downloads_last_weeks,
'user_survey_url': user_survey_url,
'logo_config': logo_config,
Expand Down
21 changes: 13 additions & 8 deletions ckanext-hdx_package/ckanext/hdx_package/views/light_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import ckan.plugins.toolkit as tk

from ckan.common import g
from ckan.types import DataDict, Request
import ckan.logic as logic

import ckanext.hdx_package.helpers.analytics as analytics
Expand Down Expand Up @@ -66,7 +67,7 @@ def read(id):
org_info_dict = _get_org_extras(org_id)
user_survey_url = org_info_dict.get('user_survey_url')
if dataset_dict.get('type') == 'dataset':
analytics_dict = _compute_analytics(dataset_dict)
analytics_dict = _compute_analytics(dataset_dict, tk.request)
dataset_dict['page_list'] = cp_h.hdx_get_page_list_for_dataset(context, dataset_dict)
dataset_dict['link_list'] = get_action('hdx_package_links_by_id_list')(context, {'id': dataset_dict.get('name')})

Expand Down Expand Up @@ -122,13 +123,17 @@ def generic_search(html_template):
return render(html_template, data_dict)


def _compute_analytics(dataset_dict):
result = {}
result['is_cod'] = analytics.is_cod(dataset_dict)
result['is_indicator'] = analytics.is_indicator(dataset_dict)
result['is_archived'] = analytics.is_archived(dataset_dict)
result['analytics_group_names'], result['analytics_group_ids'] = analytics.extract_locations_in_json(dataset_dict)
result['analytics_dataset_availability'] = analytics.dataset_availability(dataset_dict)
def _compute_analytics(dataset_dict: DataDict, request: Request):
result = {
'is_cod': analytics.is_cod(dataset_dict),
'is_indicator': analytics.is_indicator(dataset_dict),
'is_archived': analytics.is_archived(dataset_dict),
'analytics_group_names': (analytics.extract_locations_in_json(dataset_dict))[0],
'analytics_group_ids': (analytics.extract_locations_in_json(dataset_dict))[1],
'analytics_dataset_availability': analytics.dataset_availability(dataset_dict),
'analytics_came_from': analytics.came_from(request.args),
'analytics_supports_notifications': analytics.supports_notifications(dataset_dict),
}
return result


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@
var randomIndex = Math.floor(Math.random() * NOTIFICATION_OPTIN_OPTIONS.length);
optinLocation = NOTIFICATION_OPTIN_OPTIONS[randomIndex];
localStorage.setItem(NOTIFICATION_OPTIN_KEY, optinLocation);
hdxUtil.analytics.sendABTestingEvent('notification platform', optinLocation.replace('_', ' '));
}

return optinLocation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
.floating-button__paragraph {
font-size: 18px;
color: #FFF;
max-width: 250px;
max-width: 300px;
padding-left: 10px;
padding-right: 10px;
}
14 changes: 10 additions & 4 deletions ckanext-hdx_theme/ckanext/hdx_theme/fanstatic/datasets/dataset.css
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,19 @@
.wrapper-secondary .form-check .form-check-input {
box-shadow: none;
}
.notification-platform-opt-in-action-menu i {
.notification-platform-opt-in-action-menu {
margin-top: -25px;
margin-bottom: 15px;
}
.notification-platform-opt-in-action-menu a {
background-color: #007CE1;
color: #fff;
padding: 5px 10px 5px 5px;
display: inline-block;
border-radius: 5px;
}
.notification-platform-opt-in-action-menu a i {
width: 22px;
height: 22px;
line-height: 22px;
border-radius: 11px;
font-size: 10px;
text-align: center;
}
Original file line number Diff line number Diff line change
@@ -1,41 +1,70 @@
var $notificationsSignupModal = $('#notificationsSignupBemModal');
var notificationsSignupModal = bootstrap.Modal.getOrCreateInstance($notificationsSignupModal.get(0));
var $signupSubmitButton = $notificationsSignupModal.find('button[type="submit"]');
var $signupDangerAlert = $notificationsSignupModal.find('.alert-danger');
var $signupForm = $notificationsSignupModal.find('#notification-platform-form');
var $signupFormPopupSourceInput = $signupForm.find('input[name="popup_source"]');

var $verificationModal = $('#notificationsVerificationBemModal');
var verificationModal = bootstrap.Modal.getOrCreateInstance($verificationModal.get(0));

var $unsubscribeModal = $('#notificationsUnsubscribeBemModal');
var unsubscribeModal = bootstrap.Modal.getOrCreateInstance($unsubscribeModal.get(0));

var $unsubscribedModal = $('#notificationsUnsubscribedBemModal');
var unsubscribedModal = bootstrap.Modal.getOrCreateInstance($unsubscribedModal.get(0));

var $unsubscribeSubmitButton = $unsubscribeModal.find('button[type="submit"]');
var $unsubscribeDangerAlert = $unsubscribeModal.find('.alert-danger');

var $actionMenuButton = $('.notification-platform-opt-in-action-menu');
var $floatingButton = $('.notification-platform-opt-in-floating-button');

var $unsubscribeToken = $('#unsubscribe_token');
var unsubscribeToken = null;
if($unsubscribeToken.length > 0 && $unsubscribeToken.data('token').toLowerCase() !== 'none') {
unsubscribeToken = $unsubscribeToken.data('token');
}

$(document).ready(function () {
var $verificationModal = $('#notificationsVerificationBemModal');
var verificationModal = bootstrap.Modal.getOrCreateInstance($verificationModal.get(0));
var $unsubscribeModal = $('#notificationsUnsubscribeBemModal');
var unsubscribeModal = bootstrap.Modal.getOrCreateInstance($unsubscribeModal.get(0));
var $unsubscribedModal = $('#notificationsUnsubscribedBemModal');
var unsubscribedModal = bootstrap.Modal.getOrCreateInstance($unsubscribedModal.get(0));

var $signupForm = $notificationsSignupModal.find('#notification-platform-form');
var $signupSubmitButton = $notificationsSignupModal.find('button[type="submit"]');
var $signupDangerAlert = $notificationsSignupModal.find('.alert-danger');

var $unsubscribeSubmitButton = $unsubscribeModal.find('button[type="submit"]');
var $unsubscribeDangerAlert = $unsubscribeModal.find('.alert-danger');

var $unsubscribeToken = $('#unsubscribe_token');
var unsubscribeToken = null;
if($unsubscribeToken.length > 0 && $unsubscribeToken.data('token').toLowerCase() !== 'none') {
unsubscribeToken = $unsubscribeToken.data('token');
}

var onSignupSubmit = function (e) {
e.preventDefault();

var formDataArray = $signupForm.serializeArray(), formData = {};
$(formDataArray).each(function (i, field) {
formData[field.name] = field.value;
});

var datasetId = formData.dataset_id;
var email = formData.email;

$.ajax({
url: '/notifications/subscription-confirmation',
method: 'POST',
headers: hdxUtil.net.getCsrfTokenAsObject(),
data: $signupForm.serialize(),
data: {
'email': email,
'dataset_id': datasetId,
'g-recaptcha-response': formData['g-recaptcha-response'],
},
success: function (data) {
grecaptcha.reset();
if (data.success) {
hideAlert($signupDangerAlert);
hideNotificationsSignupModal();
notificationsSignupModal.hide();

verificationModal.show();

hdxUtil.analytics.sendNotificationPlatformPopupInteractionEvent(
'confirm popup',
'subscribe to notifications',
formData.popup_source,
datasetId,
formData.dataset_name,
hdxUtil.compute.strHash(email, 'notification_platform')
);

}
else {
showAlert($signupDangerAlert, data.error.message);
Expand All @@ -53,6 +82,10 @@ $(document).ready(function () {
var onUnsubscribeSubmit = function (e) {
e.preventDefault();

var unsubscribeToken = $unsubscribeModal.data('token');
var email = $unsubscribeModal.data('email');
var datasetId = $unsubscribeModal.data('dataset-id');
var datasetName = $unsubscribeModal.data('dataset-name');
$.ajax({
url: '/notifications/unsubscribe-confirmation',
method: 'POST',
Expand All @@ -65,6 +98,15 @@ $(document).ready(function () {
hideAlert($unsubscribeDangerAlert);
unsubscribeModal.hide();
unsubscribedModal.show();

hdxUtil.analytics.sendNotificationPlatformPopupInteractionEvent(
'confirm popup',
'unsubscribe from notifications',
null,
datasetId,
datasetName,
hdxUtil.compute.strHash(email, 'notification_platform')
);
}
else {
showAlert($unsubscribeDangerAlert, data.error.message);
Expand All @@ -90,10 +132,10 @@ $(document).ready(function () {
var optinLocation = hdxUtil.net.getNotificationOptinLocation();

if (optinLocation === 'action_menu') {
$('.notification-platform-opt-in-action-menu').removeClass('d-none');
$actionMenuButton.removeClass('d-none');
}
else if (optinLocation === 'floating_button') {
$('.notification-platform-opt-in-floating-button').removeClass('d-none');
$floatingButton.removeClass('d-none');
}
};

Expand All @@ -102,26 +144,64 @@ $(document).ready(function () {

$unsubscribeSubmitButton.on('click', onUnsubscribeSubmit);

$actionMenuButton.find('a').on('click', function(e) {
e.preventDefault();
var datasetId = $(this).data('dataset-id');
var datasetName = $(this).data('dataset-name');
showNotificationsSignupModal('action menu', datasetId, datasetName);
return false;
});

$floatingButton.on('click', function(e) {
e.preventDefault();
var datasetId = $(this).data('dataset-id');
var datasetName = $(this).data('dataset-name');
showNotificationsSignupModal('floating button', datasetId, datasetName);
return false;
});

if(unsubscribeToken) {
unsubscribeModal.show();
var datasetId = $unsubscribeModal.data('dataset-id');
var datasetName = $unsubscribeModal.data('dataset-name');

hdxUtil.analytics.sendNotificationPlatformPopupInteractionEvent(
'show popup',
'unsubscribe from notifications',
null,
datasetId,
datasetName,
null
);
}
else {
displayNotificationOptinOption();
}
});

var showNotificationsSignupModal = function (datasetId) {
var showNotificationsSignupModal = function (popupSource, datasetId, datasetName) {
var modalShownData = hdxUtil.net.getNotificationModalData() || {};

if (!modalShownData[datasetId]) {
if (!modalShownData[datasetId] || popupSource !== 'download') {
notificationsSignupModal.show();

var newData = {};
newData[datasetId] = true;
hdxUtil.net.updateNotificationModalData(newData);
$signupFormPopupSourceInput.val(popupSource);
hdxUtil.analytics.sendNotificationPlatformPopupInteractionEvent(
'show popup',
'subscribe to notifications',
popupSource,
datasetId,
datasetName,
null
);

if(popupSource === 'download') {
var newData = {};
newData[datasetId] = true;
hdxUtil.net.updateNotificationModalData(newData);
}
}
};

var hideNotificationsSignupModal = function () {
notificationsSignupModal.hide();
};
$notificationsSignupModal.on('hide.bs.modal', function () {
$signupFormPopupSourceInput.val('');
});
Loading

0 comments on commit 2ebd12a

Please sign in to comment.