From ecd88318264884d79b7c90277b80579e96ed4ce8 Mon Sep 17 00:00:00 2001 From: Piotr Gawron <piotr.gawron@uni.lu> Date: Wed, 13 Sep 2017 18:40:06 +0200 Subject: [PATCH] redcap notifications in the web client --- smash/web/redcap_connector.py | 9 +-- .../redcap/inconsistent_subjects.html | 71 +++++++++++++++++++ .../templates/redcap/missing_subjects.html | 71 +++++++++++++++++++ smash/web/urls.py | 7 ++ smash/web/views/__init__.py | 1 + smash/web/views/notifications.py | 30 +++++++- smash/web/views/redcap.py | 33 +++++++++ 7 files changed, 217 insertions(+), 5 deletions(-) create mode 100644 smash/web/templates/redcap/inconsistent_subjects.html create mode 100644 smash/web/templates/redcap/missing_subjects.html create mode 100644 smash/web/views/redcap.py diff --git a/smash/web/redcap_connector.py b/smash/web/redcap_connector.py index 959c56aa..706c4e19 100644 --- a/smash/web/redcap_connector.py +++ b/smash/web/redcap_connector.py @@ -83,12 +83,12 @@ class RedcapConnector(object): result = [] for subject in red_cap_subjects: - if getattr(smash_subject_by_nd, subject.nd_number, None) is None: + if smash_subject_by_nd.get(subject.nd_number) is None: url = self.create_redcap_link(pid, redcap_version, subject) result.append(MissingSubject.create(red_cap_subject=subject, smash_subject=None, url=url)) for subject in smash_subjects: - if getattr(red_cap_subject_by_nd, subject.nd_number, None) is None: + if red_cap_subject_by_nd.get(subject.nd_number) is None: result.append(MissingSubject.create(red_cap_subject=None, smash_subject=subject)) return result @@ -137,8 +137,8 @@ class RedcapConnector(object): self.add_missing(missing) def refresh_inconsistent(self): - missing = self.find_inconsistent() - self.add_inconsistent(missing) + inconsistent = self.find_inconsistent() + self.add_inconsistent(inconsistent) def find_inconsistent(self): pid = self.get_project_id() @@ -154,6 +154,7 @@ class RedcapConnector(object): result = [] for subject in smash_subjects: red_cap_subject = red_cap_subject_by_nd.get(subject.nd_number) + if red_cap_subject is not None: url = self.create_redcap_link(pid, redcap_version, subject) subject = self.create_inconsistency_subject(red_cap_subject, subject, url) diff --git a/smash/web/templates/redcap/inconsistent_subjects.html b/smash/web/templates/redcap/inconsistent_subjects.html new file mode 100644 index 00000000..e436c11e --- /dev/null +++ b/smash/web/templates/redcap/inconsistent_subjects.html @@ -0,0 +1,71 @@ +{% extends "_base.html" %} +{% load static %} + +{% block styles %} + {{ block.super }} + <!-- DataTables --> + <link rel="stylesheet" href="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.css' %}"> +{% endblock styles %} + +{% block ui_active_tab %}'subjects'{% endblock ui_active_tab %} +{% block page_header %}Missing subjects{% endblock page_header %} +{% block page_description %}{% endblock page_description %} + +{% block breadcrumb %} + {% include "subjects/breadcrumb.html" %} +{% endblock breadcrumb %} + +{% block maincontent %} + + <div class="box-body"> + <table id="table" class="table table-bordered table-striped"> + <thead> + <tr> + <th>Smash subject</th> + <th>RED Cap subject</th> + <th>Differences</th> + </tr> + </thead> + <tbody> + {% for inconsistent_subject in inconsistent_subjects %} + <tr> + <td> + <a href="{% url 'web.views.subject_edit' inconsistent_subject.subject.id %}">{{ inconsistent_subject.subject }}</a> + </td> + <td> + <a href="{{ inconsistent_subject.redcap_url }}" + target="_redcap">{{ inconsistent_subject.subject.nd_number }}</a> + </td> + <td> + <ul> + {% for field in inconsistent_subject.inconsistentfield_set.all %} + <li>{{ field.name }}: {{ field.smash_value }} - {{ field.redcap_value }}</li> + {% endfor %} + </ul> + </td> + </tr> + {% endfor %} + + </tbody> + </table> + </div> +{% endblock maincontent %} + +{% block scripts %} + {{ block.super }} + + <script src="{% static 'AdminLTE/plugins/datatables/jquery.dataTables.min.js' %}"></script> + <script src="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.min.js' %}"></script> + <script> + $(function () { + $('#table').DataTable({ + "paging": true, + "lengthChange": false, + "searching": true, + "ordering": true, + "info": true, + "autoWidth": false + }); + }); + </script> +{% endblock scripts %} diff --git a/smash/web/templates/redcap/missing_subjects.html b/smash/web/templates/redcap/missing_subjects.html new file mode 100644 index 00000000..855df575 --- /dev/null +++ b/smash/web/templates/redcap/missing_subjects.html @@ -0,0 +1,71 @@ +{% extends "_base.html" %} +{% load static %} + +{% block styles %} + {{ block.super }} + <!-- DataTables --> + <link rel="stylesheet" href="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.css' %}"> +{% endblock styles %} + +{% block ui_active_tab %}'subjects'{% endblock ui_active_tab %} +{% block page_header %}Missing subjects{% endblock page_header %} +{% block page_description %}{% endblock page_description %} + +{% block breadcrumb %} + {% include "subjects/breadcrumb.html" %} +{% endblock breadcrumb %} + +{% block maincontent %} + + <div class="box-body"> + <table id="table" class="table table-bordered table-striped"> + <thead> + <tr> + <th>ND number</th> + <th>Smash subject</th> + <th>RED Cap subject</th> + <th>Ignored</th> + </tr> + </thead> + <tbody> + {% for missing_subject in missing_subjects %} + <tr> + <td>{% if missing_subject.subject %} + {{ missing_subject.subject.nd_number }} {% elif missing_subject.redcap_id %} + {{ missing_subject.redcap_id }} {% endif %}</td> + <td>{% if missing_subject.subject %} + <a href="{% url 'web.views.subject_edit' missing_subject.subject.id %}">{{ missing_subject.subject }}</a> + {% endif %} + </td> + <td>{% if missing_subject.redcap_id %} + <a href="{{ missing_subject.redcap_url }}" target="_redcap">{{ missing_subject.redcap_id }}</a> {% endif %} + </td> + <td> + {% if missing_subject.ignore %}YES{% else %}NO{% endif %} + </td> + </tr> + {% endfor %} + + </tbody> + </table> + </div> +{% endblock maincontent %} + +{% block scripts %} + {{ block.super }} + + <script src="{% static 'AdminLTE/plugins/datatables/jquery.dataTables.min.js' %}"></script> + <script src="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.min.js' %}"></script> + <script> + $(function () { + $('#table').DataTable({ + "paging": true, + "lengthChange": false, + "searching": true, + "ordering": true, + "info": true, + "autoWidth": false + }); + }); + </script> +{% endblock scripts %} diff --git a/smash/web/urls.py b/smash/web/urls.py index 6247a094..55216a04 100644 --- a/smash/web/urls.py +++ b/smash/web/urls.py @@ -76,6 +76,13 @@ urlpatterns = [ name='web.views.subject_visit_details'), url(r'^subjects/edit/(?P<id>\d+)$', views.subject.subject_edit, name='web.views.subject_edit'), + ######################### + # RED CAP NOTIFICATIONS # + ######################### + + url(r'^redcap/missing_subjects$', views.redcap.missing_subjects, name='web.views.missing_redcap_subject'), + url(r'^redcap/inconsistent_subjects$', views.redcap.inconsistent_subjects, name='web.views.inconsistent_redcap_subject'), + #################### # CONTACTS # #################### diff --git a/smash/web/views/__init__.py b/smash/web/views/__init__.py index 49fc1dce..0afadd68 100644 --- a/smash/web/views/__init__.py +++ b/smash/web/views/__init__.py @@ -72,3 +72,4 @@ import export import contact_attempt import configuration_item import language +import redcap diff --git a/smash/web/views/notifications.py b/smash/web/views/notifications.py index 6a580bc5..8dd49b02 100644 --- a/smash/web/views/notifications.py +++ b/smash/web/views/notifications.py @@ -5,7 +5,7 @@ from django.utils import timezone from django.contrib.auth.models import User, AnonymousUser from django.db.models import Count, Case, When -from ..models import Worker, Subject, Visit, Appointment, Location +from ..models import Worker, Subject, Visit, Appointment, Location, MissingSubject, InconsistentSubject class NotificationCount(object): @@ -30,6 +30,24 @@ def get_exceeded_visit_notifications_count(user): return notification +def get_missing_redcap_subject_notification_count(user): + notification = NotificationCount( + title="missing RED Cap subject", + count=get_missing_redcap_subjects(user).count(), + style="fa fa-user text-yellow", + type='web.views.missing_redcap_subject') + return notification + + +def get_inconsistent_redcap_subject_notification_count(user): + notification = NotificationCount( + title="inconsistent RED Cap subject", + count=get_inconsistent_redcap_subjects(user).count(), + style="fa fa-user-circle text-yellow", + type='web.views.inconsistent_redcap_subject') + return notification + + def get_subjects_with_reminder_count(user): notification = NotificationCount( title="subject required contact", @@ -105,6 +123,8 @@ def get_notifications(the_user): notifications.append(get_subject_with_no_visit_notifications_count(worker)) notifications.append(get_approaching_visits_for_mail_contact_count(worker)) notifications.append(get_subjects_with_reminder_count(worker)) + notifications.append(get_missing_redcap_subject_notification_count(worker)) + notifications.append(get_inconsistent_redcap_subject_notification_count(worker)) for notification in notifications: count += notification.count @@ -184,6 +204,14 @@ def get_exceeded_visits(user): ).order_by('datetime_begin') +def get_missing_redcap_subjects(user): + return MissingSubject.objects.all().order_by("ignore") + + +def get_inconsistent_redcap_subjects(user): + return InconsistentSubject.objects.all() + + def get_unfinished_appointments(user): return Appointment.objects.filter( datetime_when__lt=get_today_midnight_date(), diff --git a/smash/web/views/redcap.py b/smash/web/views/redcap.py new file mode 100644 index 00000000..60e57dd8 --- /dev/null +++ b/smash/web/views/redcap.py @@ -0,0 +1,33 @@ +# coding=utf-8 + +from django.contrib import messages + +from notifications import get_missing_redcap_subjects, get_inconsistent_redcap_subjects +from . import wrap_response +from ..redcap_connector import RedcapConnector + + +def missing_subjects(request): + connector = RedcapConnector() + if connector.is_valid(): + connector.refresh_missing() + else: + messages.add_message(request, messages.ERROR, 'There is a problem with RED Cap connection') + + context = { + 'missing_subjects': get_missing_redcap_subjects(request.user) + } + return wrap_response(request, 'redcap/missing_subjects.html', context) + + +def inconsistent_subjects(request): + connector = RedcapConnector() + if connector.is_valid(): + connector.refresh_inconsistent() + else: + messages.add_message(request, messages.ERROR, 'There is a problem with RED Cap connection') + + context = { + 'inconsistent_subjects': get_inconsistent_redcap_subjects(request.user) + } + return wrap_response(request, 'redcap/inconsistent_subjects.html', context) -- GitLab