From 679c9528a853238417f726ee6dc0e4fa34256224 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Mon, 30 Nov 2020 13:25:42 +0100
Subject: [PATCH] visible subject columns are editable

---
 smash/web/forms/study_subject_list_form.py    |  30 ++++
 smash/web/models/study_subject_list.py        |   6 +-
 smash/web/templates/study/edit.html           |  36 +++-
 .../study_subject_list/breadcrumb.html        |   3 +
 .../templates/study_subject_list/edit.html    | 168 ++++++++++++++++++
 smash/web/urls.py                             |  22 ++-
 smash/web/views/__init__.py                   |   3 +-
 smash/web/views/study.py                      |  33 +++-
 smash/web/views/study_subject_list.py         |  43 +++++
 9 files changed, 322 insertions(+), 22 deletions(-)
 create mode 100644 smash/web/forms/study_subject_list_form.py
 create mode 100644 smash/web/templates/study_subject_list/breadcrumb.html
 create mode 100644 smash/web/templates/study_subject_list/edit.html
 create mode 100644 smash/web/views/study_subject_list.py

diff --git a/smash/web/forms/study_subject_list_form.py b/smash/web/forms/study_subject_list_form.py
new file mode 100644
index 00000000..71b4c03e
--- /dev/null
+++ b/smash/web/forms/study_subject_list_form.py
@@ -0,0 +1,30 @@
+from django.forms import ModelForm
+
+from web.models import StudySubjectList, SubjectColumns, StudyColumns
+
+
+class StudySubjectListEditForm(ModelForm):
+    class Meta:
+        model = StudySubjectList
+        fields = '__all__'
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+
+
+class SubjectColumnsEditForm(ModelForm):
+    class Meta:
+        model = SubjectColumns
+        fields = '__all__'
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+
+
+class StudySubjectColumnsEditForm(ModelForm):
+    class Meta:
+        model = StudyColumns
+        fields = '__all__'
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
diff --git a/smash/web/models/study_subject_list.py b/smash/web/models/study_subject_list.py
index 1aa9a773..9f4b84ca 100644
--- a/smash/web/models/study_subject_list.py
+++ b/smash/web/models/study_subject_list.py
@@ -24,18 +24,21 @@ class StudySubjectList(models.Model):
         Study,
         on_delete=models.CASCADE,
         null=False,
+        editable=False,
     )
 
     visible_subject_study_columns = models.ForeignKey(
         StudyColumns,
         on_delete=models.CASCADE,
         null=False,
+        editable=False,
     )
 
     visible_subject_columns = models.ForeignKey(
         SubjectColumns,
         on_delete=models.CASCADE,
         null=False,
+        editable=False,
     )
 
     last_contact_attempt = models.BooleanField(
@@ -52,5 +55,6 @@ class StudySubjectList(models.Model):
                             choices=list(SUBJECT_LIST_CHOICES.items()),
                             verbose_name='Type of list',
                             null=True,
-                            blank=True
+                            blank=True,
+                            editable=False,
                             )
diff --git a/smash/web/templates/study/edit.html b/smash/web/templates/study/edit.html
index 8af357b9..fbd02adf 100644
--- a/smash/web/templates/study/edit.html
+++ b/smash/web/templates/study/edit.html
@@ -11,7 +11,7 @@
     <style type="text/css">
         .tooltip-inner {
             max-width: 200px;
-            width: 200px; 
+            width: 200px;
         }
         .privacy-notice-buttons {
             float: right;
@@ -22,7 +22,7 @@
 {% endblock styles %}
 
 {% block ui_active_tab %}'study_conf'{% endblock ui_active_tab %}
-{% block page_header %}Edit subject{% endblock page_header %}
+{% block page_header %}Edit study{% endblock page_header %}
 {% block page_description %}{% endblock page_description %}
 
 {% block title %}{{ block.super }} - Edit subject information{% endblock %}
@@ -60,8 +60,8 @@
                                                    data-placement="bottom" title="{{ field.help_text }}"></i>
                                             {% endif %}
                                         </label>
-                                        
-                                        {% if field.label == 'Study Privacy Note' %} 
+
+                                        {% if field.label == 'Study Privacy Note' %}
                                             <div class="col-sm-7">
                                                 {{ field|add_class:'form-control' }}
                                             </div>
@@ -75,7 +75,7 @@
                                                 </a>
                                                 {% endif %}
                                                 <a title="Add privacy notice" href="{% url 'web.views.privacy_notice_add' %}">
-                                                    <i class="fa fa-plus"></i> 
+                                                    <i class="fa fa-plus"></i>
                                                 </a>
                                             </div>
                                         {% else %}
@@ -177,6 +177,32 @@
                             </table>
                         </div>
 
+                        <div class="box-header with-border">
+                            <h3>Visible columns in subject list</h3>
+                        </div>
+                        <div class="box-body">
+                            <table class="table table-bordered table-striped">
+                                <thead>
+                                <tr>
+                                    <th class="text-center">List Type</th>
+                                    <th class="text-center">Edit</th>
+                                </tr>
+                                </thead>
+                                <tbody>
+                                {% for entry in visible_column_lists %}
+                                    <tr>
+                                        <td class="text-center">{{ entry.type }}</td>
+                                        <td class="text-center"><a
+                                                href="{% url 'web.views.study_subject_list_edit' study_id entry.id %}"
+                                                type="button"
+                                                class="btn btn-block btn-default">EDIT</a>
+                                        </td>
+                                    </tr>
+                                {% endfor %}
+                                </tbody>
+                            </table>
+                        </div>
+
                         {% include 'includes/custom_study_subject_field_box.html' with study=study fields=study.customstudysubjectfield_set.all %}
 
                         <div class="box-header with-border">
diff --git a/smash/web/templates/study_subject_list/breadcrumb.html b/smash/web/templates/study_subject_list/breadcrumb.html
new file mode 100644
index 00000000..f6052818
--- /dev/null
+++ b/smash/web/templates/study_subject_list/breadcrumb.html
@@ -0,0 +1,3 @@
+<li><a href="{% url 'web.views.appointments' %}"><i class="fa fa-dashboard"></i> Dashboard</a></li>
+<li>Configuration</li>
+<li class="active"><a href="{% url 'web.views.edit_study' study_id %}">Study</a></li>
\ No newline at end of file
diff --git a/smash/web/templates/study_subject_list/edit.html b/smash/web/templates/study_subject_list/edit.html
new file mode 100644
index 00000000..e16c82df
--- /dev/null
+++ b/smash/web/templates/study_subject_list/edit.html
@@ -0,0 +1,168 @@
+{% extends "_base.html" %}
+{% load static %}
+{% load filters %}
+
+{% block styles %}
+    {{ block.super }}
+    <!-- DataTables -->
+    <link rel="stylesheet" href="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.css' %}">
+    {% include "includes/datepicker.css.html" %}
+    {% include "includes/datetimepicker.css.html" %}
+    <style type="text/css">
+        .tooltip-inner {
+            max-width: 200px;
+            width: 200px;
+        }
+
+        .privacy-notice-buttons {
+            float: right;
+            padding: 0;
+            margin-top: 7px;
+        }
+    </style>
+{% endblock styles %}
+
+{% block ui_active_tab %}'study_conf'{% endblock ui_active_tab %}
+{% block page_header %}Edit {{ type }}{% endblock page_header %}
+{% block page_description %}{% endblock page_description %}
+
+{% block title %}{{ block.super }} - Edit visible columns in subject list{% endblock %}
+
+{% block breadcrumb %}
+    {% include "study/breadcrumb.html" %}
+{% endblock breadcrumb %}
+
+{% block maincontent %}
+
+    {% block content %}
+        <div class="row">
+            <p class="col-lg-3 pull-left">
+                <a href="javascript:history.back(1)" class="btn btn-block btn-default">Go back (discard changes)</a>
+            </p>
+        </div>
+        <div class="row">
+            <div class="col-md-12">
+                <div class="box box-success">
+                    <form method="post" action="" enctype="multipart/form-data" class="form-horizontal">
+                        {% csrf_token %}
+
+                        <div class="box-body">
+                            <div class="col-md-12">
+
+                                {% for field in list_form %}
+                                    <div class="col-md-6 form-group  {% if field.errors %}has-error{% endif %}">
+                                        <label for="{{ field.id_for_label }}" class="col-sm-4 control-label">
+                                            {{ field.label }}
+                                            {% if field.help_text %}
+                                                <i class="fa fa-info-circle" aria-hidden="true" data-toggle="tooltip"
+                                                   data-placement="bottom" title="{{ field.help_text }}"></i>
+                                            {% endif %}
+                                        </label>
+
+                                        <div class="col-sm-8">
+                                            {{ field|add_class:'form-control' }}
+                                        </div>
+
+                                        {% if field.errors %}
+                                            <span class="help-block"> {{ field.errors }} </span>
+                                        {% endif %}
+                                    </div>
+                                {% endfor %}
+
+                            </div>
+                        </div><!-- /.box-body -->
+                        <div class="box-header with-border">
+                            <h3>Subject columns</h3>
+                        </div>
+                        <div class="box-body">
+                            <div class="col-md-12">
+
+                                {% for field in subject_columns_form %}
+                                    <div class="col-md-6 form-group  {% if field.errors %}has-error{% endif %}">
+                                        <label for="{{ field.id_for_label }}" class="col-sm-4 control-label">
+                                            {{ field.label }}
+                                            {% if field.help_text %}
+                                                <i class="fa fa-info-circle" aria-hidden="true" data-toggle="tooltip"
+                                                   data-placement="bottom" title="{{ field.help_text }}"></i>
+                                            {% endif %}
+                                        </label>
+
+                                        <div class="col-sm-8">
+                                            {{ field|add_class:'form-control' }}
+                                        </div>
+
+                                        {% if field.errors %}
+                                            <span class="help-block"> {{ field.errors }} </span>
+                                        {% endif %}
+                                    </div>
+                                {% endfor %}
+
+                            </div>
+                        </div><!-- /.box-body -->
+                        <div class="box-header with-border">
+                            <h3>Study subject columns</h3>
+                        </div>
+                        <div class="box-body">
+                            <div class="col-md-12">
+
+                                {% for field in study_subject_form %}
+                                    <div class="col-md-6 form-group  {% if field.errors %}has-error{% endif %}">
+                                        <label for="{{ field.id_for_label }}" class="col-sm-4 control-label">
+                                            {{ field.label }}
+                                            {% if field.help_text %}
+                                                <i class="fa fa-info-circle" aria-hidden="true" data-toggle="tooltip"
+                                                   data-placement="bottom" title="{{ field.help_text }}"></i>
+                                            {% endif %}
+                                        </label>
+
+                                        <div class="col-sm-8">
+                                            {{ field|add_class:'form-control' }}
+                                        </div>
+
+                                        {% if field.errors %}
+                                            <span class="help-block"> {{ field.errors }} </span>
+                                        {% endif %}
+                                    </div>
+                                {% endfor %}
+
+                            </div>
+                        </div><!-- /.box-body -->
+                        <div class="box-footer">
+                            <div class="col-sm-4">
+                                <button type="submit" class="btn btn-block btn-success">Save</button>
+                            </div>
+                            <div class="col-sm-4">
+                                <button id="save-and-continue" type="button" class="btn btn-block btn-success">Save and
+                                    Continue
+                                </button>
+                            </div>
+                            <div class="col-sm-4">
+                                <a href="{% url 'web.views.edit_study' study_id %}" class="btn btn-block btn-default"
+                                   onclick="history.back()">Cancel</a>
+                            </div>
+                        </div><!-- /.box-footer -->
+                    </form>
+                </div><!-- /.box -->
+            </div><!-- /.col-md-12 -->
+        </div><!-- /.row -->
+
+    {% endblock %}
+
+
+{% 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>
+
+    {% include "includes/datepicker.js.html" %}
+    {% include "includes/datetimepicker.js.html" %}
+
+    <script>
+        $(function () {
+            $('a[title]').tooltip({container: 'body'})
+        })
+    </script>
+{% endblock scripts %}
diff --git a/smash/web/urls.py b/smash/web/urls.py
index bc1e33e9..79dbc6f4 100644
--- a/smash/web/urls.py
+++ b/smash/web/urls.py
@@ -174,14 +174,17 @@ urlpatterns = [
     ####################
 
     url(r'^privacy_notices$', views.privacy_notice.PrivacyNoticeListView.as_view(), name='web.views.privacy_notices'),
-    
-    url(r'^accept_privacy_notice/(?P<pk>\d+)$', views.privacy_notice.privacy_notice_accept, name='web.views.accept_privacy_notice'),
+
+    url(r'^accept_privacy_notice/(?P<pk>\d+)$', views.privacy_notice.privacy_notice_accept,
+        name='web.views.accept_privacy_notice'),
 
     url(r'^privacy_notices/add$', views.privacy_notice.privacy_notice_add, name='web.views.privacy_notice_add'),
-    url(r'^privacy_notices/(?P<pk>\d+)/edit$', views.privacy_notice.privacy_notice_edit, name='web.views.privacy_notice_edit'),
+    url(r'^privacy_notices/(?P<pk>\d+)/edit$', views.privacy_notice.privacy_notice_edit,
+        name='web.views.privacy_notice_edit'),
+
+    url(r'^privacy_notices/(?P<pk>\d+)/delete$', views.privacy_notice.PrivacyNoticeDeleteView.as_view(),
+        name='web.views.privacy_notice_delete'),
 
-    url(r'^privacy_notices/(?P<pk>\d+)/delete$', views.privacy_notice.PrivacyNoticeDeleteView.as_view(), name='web.views.privacy_notice_delete'),
-   
     ####################
     #       MAIL       #
     ####################
@@ -281,13 +284,18 @@ urlpatterns = [
     url(r'^study/(?P<study_id>\d+)/import_subject_edit/(?P<import_id>\d+)/execute',
         views.etl.import_subject_execute, name='web.views.import_subject_execute'),
 
+    url(r'^study/(?P<study_id>\d+)/subject_list/(?P<study_subject_list_id>\d+)/edit',
+        views.study_subject_list.study_subject_list_edit, name='web.views.study_subject_list_edit'),
+
     ####################
     #       EXPORT     #
     ####################
 
     url(r'^study/(?P<study_id>\d+)export$', views.export.export, name='web.views.export'),
-    url(r'^study/(?P<study_id>\d+)export/csv/(?P<data_type>[A-z]+)$', views.export.export_to_csv, name='web.views.export_to_csv'),
-    url(r'^study/(?P<study_id>\d+)export/xls/(?P<data_type>[A-z]+)$', views.export.export_to_excel, name='web.views.export_to_excel'),
+    url(r'^study/(?P<study_id>\d+)export/csv/(?P<data_type>[A-z]+)$', views.export.export_to_csv,
+        name='web.views.export_to_csv'),
+    url(r'^study/(?P<study_id>\d+)export/xls/(?P<data_type>[A-z]+)$', views.export.export_to_excel,
+        name='web.views.export_to_excel'),
 
     ####################
     #       CONFIGURATION     #
diff --git a/smash/web/views/__init__.py b/smash/web/views/__init__.py
index 0684e2c6..7697fddc 100644
--- a/smash/web/views/__init__.py
+++ b/smash/web/views/__init__.py
@@ -114,4 +114,5 @@ from . import etl
 from . import password
 from . import appointment_type
 from . import provenance
-from . import privacy_notice
\ No newline at end of file
+from . import privacy_notice
+from . import study_subject_list
\ No newline at end of file
diff --git a/smash/web/views/study.py b/smash/web/views/study.py
index 995a1bf5..ca328ad8 100644
--- a/smash/web/views/study.py
+++ b/smash/web/views/study.py
@@ -10,6 +10,7 @@ from web.forms import StudyColumnsEditForm, StudyEditForm, StudyNotificationPara
 from web.forms.custom_study_subject_field_forms import CustomStudySubjectFieldAddForm, CustomStudySubjectFieldEditForm
 from web.models import Study, VisitImportData, SubjectImportData
 from web.models.custom_data import CustomStudySubjectField
+from web.models.study_subject_list import SUBJECT_LIST_CHOICES
 from web.views import wrap_response
 
 logger = logging.getLogger(__name__)
@@ -51,6 +52,19 @@ def study_edit(request, study_id):
         redcap_columns_form = StudyRedCapColumnsEditForm(instance=study.redcap_columns,
                                                          prefix="redcap")
 
+    etl_entries = get_info_about_etl_entries(study)
+    return wrap_response(request, 'study/edit.html', {
+        'study_form': study_form,
+        'privacy_notice': study.study_privacy_notice,
+        'notifications_form': notifications_form,
+        'study_columns_form': study_columns_form,
+        'redcap_columns_form': redcap_columns_form,
+        'etl_entries': etl_entries,
+        'visible_column_lists': get_info_about_visible_columns_subject_list(study),
+    })
+
+
+def get_info_about_etl_entries(study: Study):
     etl_entries = []
     for import_data in VisitImportData.objects.filter(study=study).all():
         etl_entries.append({'type': 'Import visit',
@@ -70,14 +84,17 @@ def study_edit(request, study_id):
                             'available': import_data.filename != '' and import_data.filename is not None,
                             'worker': str(import_data.import_worker)
                             })
-    return wrap_response(request, 'study/edit.html', {
-        'study_form': study_form,
-        'privacy_notice': study.study_privacy_notice,
-        'notifications_form': notifications_form,
-        'study_columns_form': study_columns_form,
-        'redcap_columns_form': redcap_columns_form,
-        'etl_entries': etl_entries
-    })
+    return etl_entries
+
+
+def get_info_about_visible_columns_subject_list(study: Study):
+    result = []
+
+    for entry in study.studysubjectlist_set.all():
+        result.append({'type': SUBJECT_LIST_CHOICES.get(entry.type, entry.type),
+                       'id': entry.id,
+                       })
+    return result
 
 
 @PermissionDecorator('change_study', 'configuration')
diff --git a/smash/web/views/study_subject_list.py b/smash/web/views/study_subject_list.py
new file mode 100644
index 00000000..cdfa219e
--- /dev/null
+++ b/smash/web/views/study_subject_list.py
@@ -0,0 +1,43 @@
+# coding=utf-8
+from django.http import HttpRequest
+from django.shortcuts import redirect, get_object_or_404
+
+from web.decorators import PermissionDecorator
+from web.forms.study_subject_list_form import StudySubjectListEditForm, StudySubjectColumnsEditForm, \
+    SubjectColumnsEditForm
+from web.models import StudySubjectList
+from . import wrap_response
+from ..models.study_subject_list import SUBJECT_LIST_CHOICES
+
+
+@PermissionDecorator('change_study', 'configuration')
+def study_subject_list_edit(request: HttpRequest, study_id: int, study_subject_list_id: int):
+    the_list = get_object_or_404(StudySubjectList, id=study_subject_list_id)
+    if request.method == 'POST':
+        list_form = StudySubjectListEditForm(request.POST, instance=the_list, prefix="list")
+        study_subject_columns_form = StudySubjectColumnsEditForm(request.POST,
+                                                                 instance=the_list.visible_subject_study_columns,
+                                                                 prefix="study_subject")
+        subject_columns_form = SubjectColumnsEditForm(request.POST,
+                                                      instance=the_list.visible_subject_columns,
+                                                      prefix="subject")
+        if list_form.is_valid() and study_subject_columns_form.is_valid() and subject_columns_form.is_valid():
+            list_form.save()
+            study_subject_columns_form.save()
+            subject_columns_form.save()
+            if '_continue' in request.POST:
+                return redirect('web.views.study_subject_list_edit', study_id=study_id,
+                                study_subject_list_id=the_list.id)
+            return redirect('web.views.edit_study', study_id=study_id)
+    else:
+        list_form = StudySubjectListEditForm(instance=the_list, prefix="list")
+        study_subject_columns_form = StudySubjectColumnsEditForm(instance=the_list.visible_subject_study_columns,
+                                                                 prefix="study_subject")
+        subject_columns_form = SubjectColumnsEditForm(instance=the_list.visible_subject_columns,
+                                                      prefix="subject")
+
+    return wrap_response(request, 'study_subject_list/edit.html', {'list_form': list_form,
+                                                                   'study_subject_form': study_subject_columns_form,
+                                                                   'subject_columns_form': subject_columns_form,
+                                                                   'type': SUBJECT_LIST_CHOICES.get(the_list.type,
+                                                                                                    the_list.type)})
-- 
GitLab