Skip to content

Commit

Permalink
TN-3235 opt-out feature (#4337)
Browse files Browse the repository at this point in the history
Monster PR to implement the opt-out feature.
included front end changes from #4335
reused a migration (by altering the order defined within the migration
files `down_revision` variable), and corrected as the previous
sequential counts we not keeping up. (TN-3274)

includes implementations for:
- TN-3236
- TN-3237
- TN-3238
- TN-3243
- TN-3289
- TN-3240

---------

Co-authored-by: Amy Chen <[email protected]>
Co-authored-by: Amy Chen <[email protected]>
Co-authored-by: Justin McReynolds <[email protected]>
Co-authored-by: Ivan Cvitkovic <[email protected]>
  • Loading branch information
5 people authored Jul 2, 2024
1 parent 07518c5 commit 77e71a4
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 23 deletions.
10 changes: 6 additions & 4 deletions portal/eproms/templates/eproms/assessment_engine/ae_macros.html
Original file line number Diff line number Diff line change
Expand Up @@ -320,9 +320,10 @@ <h2 class="title">
<div class="modal fade" role="dialog" id="emproOptOutModal" data-backdrop="static" tabindex="-1" aria-hidden="true" {% if user and user.current_encounter().auth_method == 'url_authenticated'%}data-url-authenticated="true"{% endif %}>
<div class="modal-dialog modal-lg">
<div class="modal-content">
<button type="button" class="close btn-dismiss" data-dismiss="modal" aria-label="{{_('Close')}}">
<!-- uncomment here if want close button back -->
<!-- <button type="button" class="close btn-dismiss" data-dismiss="modal" aria-label="{{_('Close')}}">
<span aria-hidden="true">&times;</span>
</button>
</button> -->
<div class="modal-body">
<div class="header-section">
<h2 class="title">{{_("We want to check with you ...")}}</h2>
Expand Down Expand Up @@ -369,8 +370,9 @@ <h2 class="title">{{_("We want to check with you ...")}}</h2>
</div>
<div class="modal-footer">
<div>
<button class="btn btn-empro-primary btn-submit">Submit</button>
<button class="btn btn-default btn-dismiss">Dismiss</button>
<button class="btn btn-empro-primary btn-submit btn-large">Submit</button>
<!-- uncomment if want Dismiss button back -->
<!-- <button class="btn btn-default btn-dismiss">Dismiss</button> -->
</div>
<div class="saving-indicator-container hide"><i class="fa fa-spinner fa-spin"></i> {{_("Saving your choices...")}}</div>
<div class="save-success-indicator-container text-success hide"><i class="fa fa-check"></i> {{_("Your choices are saved successfully.")}}</div>
Expand Down
40 changes: 31 additions & 9 deletions portal/static/js/src/empro.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ emproObj.prototype.onAfterSubmitOptoutData = function (data) {
EmproObj.setOptoutButtonsState(false);
EmproObj.setOptoutError(
i18next.t(
"System error: Unable to save your choices.\r\nPlease click 'Submit' to try again. \r\nOtherwise click 'Dismiss' to continue."
"System error: Unable to save your choices.\r\nPlease click 'Submit' to try again."
)
);
return false;
Expand All @@ -198,21 +198,39 @@ emproObj.prototype.onAfterSubmitOptoutData = function (data) {
EmproObj.setOptoutButtonsState(false);
EmproObj.submittedOptOutDomains = EmproObj.selectedOptOutDomains;
EmproObj.populateSelectedOptoutUI();
// TODO different text will appear in thank you modal, waiting for approval before changes
// EmproObj.handleFullOptout();
EmproObj.initOptOutModal(false);
EmproObj.initThankyouModal(true);
}, 1000);
return true;
};
emproObj.prototype.handleSubmitOptoutData = function () {
if (!EmproObj.hasErrorText() && !EmproObj.hasSelectedOptOutDomains()) {
EmproObj.setOptoutError(
i18next.t(
"You didn't select anything. Are you sure?\r\nIf so, click 'Dismiss' to continue."
)
);
return;
emproObj.prototype.handleNoOptOutSelection = function() {
EmproObj.initOptOutModal(false);
EmproObj.initThankyouModal(true);
};
emproObj.prototype.isFullOptout = function() {
return this.submittedOptOutDomains.length > 0 && (
this.submittedOptOutDomains.length === this.hardTriggerDomains.length
);
}
emproObj.prototype.handleFullOptout = function() {
if (this.isFullOptout()) {
$(".full-optout-hide").addClass("hide");
}
}
emproObj.prototype.handleSubmitOptoutData = function () {
// if (!EmproObj.hasErrorText() && !EmproObj.hasSelectedOptOutDomains()) {
// EmproObj.setOptoutError(
// i18next.t(
// "You didn't select anything. Are you sure?\r\nIf so, click 'Dismiss' to continue."
// )
// );
// return;
// }
if (!EmproObj.hasSelectedOptOutDomains()) {
// allow user to continue without selecting any option
EmproObj.handleNoOptOutSelection();
return;
}
EmproObj.onBeforeSubmitOptoutData();
Expand Down Expand Up @@ -300,6 +318,10 @@ emproObj.prototype.initOptOutModal = function (autoShow) {
if (!this.hasOptOutModal()) {
return;
}
$("#emproOptOutModal").modal({
backdrop: "static",
keyboard: false
});
$("#emproOptOutModal").modal(autoShow ? "show" : "hide");
};
emproObj.prototype.onDetectOptOutDomains = function () {
Expand Down
2 changes: 1 addition & 1 deletion portal/templates/profile/profile_macros.html
Original file line number Diff line number Diff line change
Expand Up @@ -875,7 +875,7 @@ <h4 class="text-muted">{% if person and person.username %}{{ _("for") + " " + pe
<div class="item text-warning" v-if="hasSubStudyOptOutDomains()">
<p v-if="hasSubStudyTriggers()">{{_("<b>NOTE</b>: The participant has chosen <em>not</em> to be contacted about some issues.")}}</p>
<p v-else>{{_("<b>NOTE</b>: The participant has chosen <em>not</em> to be contacted.")}}</p>
<p>{{_("High distressed areas ( <em>Do not contact</em> ): ")}} <span v-text="getSubStudyOptoutDomainsDisplay()"></span></p>
<p>{{_("High distress areas ( <em>do not contact</em> ): ")}} <span v-text="getSubStudyOptoutDomainsDisplay()"></span></p>
</div>
{% endmacro %}
{%- macro adminTriggerLinks(person, current_user) %}
Expand Down
14 changes: 6 additions & 8 deletions portal/trigger_states/empro_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def invite_email(user):
db.session.add(msg)


def patient_email(patient, soft_triggers, hard_triggers):
def patient_email(patient, soft_triggers, opted_in_hard_triggers):
"""Prepare email for patient, depending on trigger status"""

# If the user has a pending questionnaire bank, include for due date
Expand All @@ -54,7 +54,7 @@ def patient_email(patient, soft_triggers, hard_triggers):
args = load_template_args(
user=patient, questionnaire_bank_id=qb_id, qb_iteration=qb_iteration)

if hard_triggers:
if opted_in_hard_triggers:
name = 'empro patient both triggers email'
elif soft_triggers:
name = 'empro patient soft triggers email'
Expand Down Expand Up @@ -99,16 +99,13 @@ def staff_emails(patient, hard_triggers, opted_out_domains, initial_notification
if c.id not in staff_list_ids:
staff_list.append(c)

# opt-in holds hard triggers the user did NOT opt-out of
opt_in_domains = hard_triggers

triggered_for_email = hard_triggers
app_text_name = 'empro clinician trigger reminder'
if initial_notification:
app_text_name = 'empro clinician trigger notification'
if not (set(hard_triggers) - set(opted_out_domains)):
# All triggered were opted out of - pick up different email template
app_text_name += " all opted out"
opt_in_domains = []
if not initial_notification:
# seen on test, no idea how - include details in exception
msg = (f"Patient {patient.id} all opted out: {opted_out_domains} "
Expand All @@ -117,7 +114,8 @@ def staff_emails(patient, hard_triggers, opted_out_domains, initial_notification
app_text_name = 'empro clinician trigger notification all opted out'
elif opted_out_domains:
app_text_name += " partially opted out"
opt_in_domains = list(set(hard_triggers) - set(opted_out_domains))
# only include hard triggers the user did NOT opt-out of
triggered_for_email = list(set(hard_triggers) - set(opted_out_domains))

# According to spec, args need at least:
# - study ID
Expand Down Expand Up @@ -145,7 +143,7 @@ def staff_emails(patient, hard_triggers, opted_out_domains, initial_notification
label=_('View Participant Details')))
opted_out = ", ".join(opted_out_domains) if opted_out_domains else ""
opted_out_display = "<b>{opted_out}</b>".format(opted_out=opted_out)
triggered_domains = ", ".join(opt_in_domains) if opt_in_domains else ""
triggered_domains = ", ".join(triggered_for_email) if triggered_for_email else ""
triggered_domains_display = "<b>{triggered_domains}</b>".format(
triggered_domains=triggered_domains)
args = {
Expand Down
2 changes: 1 addition & 1 deletion portal/trigger_states/empro_states.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ def process_processed(ts):
# Patient always gets mail
if patient.email_ready()[0]:
pending_emails.append((
patient_email(patient, soft_triggers, hard_triggers),
patient_email(patient, soft_triggers, actionable_triggers),
"patient thank you"))
else:
current_app.logger.error(
Expand Down

0 comments on commit 77e71a4

Please sign in to comment.