From 10a17ba33acbf305457473df5bc0247c3b88ff06 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Mon, 30 Nov 2020 15:03:10 +0100
Subject: [PATCH] visibilty of custom fields is linked to tables

---
 smash/web/api_views/subject.py                | 19 +++++++-------
 smash/web/forms/study_subject_list_form.py    | 16 ++++++++++++
 .../web/migrations/0187_auto_20201130_1224.py | 10 ++++++++
 smash/web/models/__init__.py                  |  1 +
 smash/web/models/custom_data/__init__.py      |  3 ++-
 .../custom_study_subject_visibility.py        | 20 +++++++++++++++
 smash/web/models/study_columns.py             | 25 +++++++++++++++++++
 7 files changed, 84 insertions(+), 10 deletions(-)
 create mode 100644 smash/web/models/custom_data/custom_study_subject_visibility.py

diff --git a/smash/web/api_views/subject.py b/smash/web/api_views/subject.py
index 8a3b3b30..ca4f2ba0 100644
--- a/smash/web/api_views/subject.py
+++ b/smash/web/api_views/subject.py
@@ -7,8 +7,8 @@ from django.db.models import Q
 from django.http import JsonResponse
 from django.urls import reverse
 
-from web.api_views.serialization_utils import str_to_yes_no_null, bool_to_yes_no, flying_team_to_str, location_to_str, add_column, \
-    serialize_date, serialize_datetime, get_filters_for_data_table_request, virus_test_to_str, str_to_yes_no
+from web.api_views.serialization_utils import str_to_yes_no_null, bool_to_yes_no, flying_team_to_str, location_to_str, \
+    add_column, serialize_date, serialize_datetime, get_filters_for_data_table_request, virus_test_to_str
 from web.models import ConfigurationItem, StudySubject, Visit, Appointment, Subject, SubjectColumns, StudyColumns, \
     Study, ContactAttempt
 from web.models.constants import SUBJECT_TYPE_CHOICES, GLOBAL_STUDY_ID, VISIT_SHOW_VISIT_NUMBER_FROM_ZERO, \
@@ -123,20 +123,21 @@ def get_subject_columns(request, subject_list_type):
 
     add_column(result, "Type", "type", study_subject_columns, "type_filter", study.columns)
     for custom_study_subject_field in study.customstudysubjectfield_set.all():
+        visible = study_subject_columns.is_custom_field_visible(custom_study_subject_field)
         if custom_study_subject_field.type == CUSTOM_FIELD_TYPE_TEXT:
             add_column(result,
                        custom_study_subject_field.name,
                        get_study_subject_field_id(custom_study_subject_field),
                        study_subject_columns,
                        "string_filter",
-                       visible_param=False)
+                       visible_param=visible)
         elif custom_study_subject_field.type == CUSTOM_FIELD_TYPE_BOOLEAN:
             add_column(result,
                        custom_study_subject_field.name,
                        get_study_subject_field_id(custom_study_subject_field),
                        study_subject_columns,
                        "yes_no_filter",
-                       visible_param=False)
+                       visible_param=visible)
         elif custom_study_subject_field.type == CUSTOM_FIELD_TYPE_INTEGER:
             add_column(result,
                        custom_study_subject_field.name,
@@ -144,7 +145,7 @@ def get_subject_columns(request, subject_list_type):
                        study_subject_columns,
                        None,
                        sortable=False,
-                       visible_param=False)
+                       visible_param=visible)
         elif custom_study_subject_field.type == CUSTOM_FIELD_TYPE_DOUBLE:
             add_column(result,
                        custom_study_subject_field.name,
@@ -152,28 +153,28 @@ def get_subject_columns(request, subject_list_type):
                        study_subject_columns,
                        None,
                        sortable=False,
-                       visible_param=False)
+                       visible_param=visible)
         elif custom_study_subject_field.type == CUSTOM_FIELD_TYPE_DATE:
             add_column(result,
                        custom_study_subject_field.name,
                        get_study_subject_field_id(custom_study_subject_field),
                        study_subject_columns,
                        None,
-                       visible_param=False)
+                       visible_param=visible)
         elif custom_study_subject_field.type == CUSTOM_FIELD_TYPE_SELECT_LIST:
             add_column(result,
                        custom_study_subject_field.name,
                        get_study_subject_field_id(custom_study_subject_field),
                        study_subject_columns,
                        'select_filter:' + custom_study_subject_field.possible_values,
-                       visible_param=False)
+                       visible_param=visible)
         elif custom_study_subject_field.type == CUSTOM_FIELD_TYPE_FILE:
             add_column(result,
                        custom_study_subject_field.name,
                        get_study_subject_field_id(custom_study_subject_field),
                        study_subject_columns,
                        'select_filter:N/A;Available',
-                       visible_param=False)
+                       visible_param=visible)
         else:
             raise NotImplementedError
 
diff --git a/smash/web/forms/study_subject_list_form.py b/smash/web/forms/study_subject_list_form.py
index 71b4c03e..607183dc 100644
--- a/smash/web/forms/study_subject_list_form.py
+++ b/smash/web/forms/study_subject_list_form.py
@@ -1,6 +1,8 @@
+from django import forms
 from django.forms import ModelForm
 
 from web.models import StudySubjectList, SubjectColumns, StudyColumns
+from web.models.custom_data.custom_study_subject_field import get_study_subject_field_id
 
 
 class StudySubjectListEditForm(ModelForm):
@@ -28,3 +30,17 @@ class StudySubjectColumnsEditForm(ModelForm):
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
+        instance: StudyColumns = kwargs.get('instance')
+        for visibility in instance.custom_fields_visibility:
+            field = visibility.study_subject_field
+            field_id = get_study_subject_field_id(field)
+            self.fields[field_id] = forms.BooleanField(label=field.name, initial=visibility.visible, required=False)
+
+    def save(self, commit=True) -> StudyColumns:
+        instance = super().save(commit)
+        # we can add custom values only after object exists in the database
+        for visibility in instance.custom_fields_visibility:
+            field = self[get_study_subject_field_id(visibility.study_subject_field)]
+            visibility.visible = str(field.value()).lower() == "true"
+            visibility.save()
+        return instance
diff --git a/smash/web/migrations/0187_auto_20201130_1224.py b/smash/web/migrations/0187_auto_20201130_1224.py
index 1fcc8dd6..44d54c08 100644
--- a/smash/web/migrations/0187_auto_20201130_1224.py
+++ b/smash/web/migrations/0187_auto_20201130_1224.py
@@ -31,4 +31,14 @@ class Migration(migrations.Migration):
             name='visible_subject_study_columns',
             field=models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='web.studycolumns'),
         ),
+        migrations.CreateModel(
+            name='CustomStudySubjectVisibility',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('visible', models.BooleanField(default=False)),
+                ('study_subject_field', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='web.customstudysubjectfield', verbose_name='Custom Field')),
+                ('visible_subject_study_columns', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='web.studycolumns', verbose_name='List of visible columns')),
+            ],
+        ),
+
     ]
diff --git a/smash/web/models/__init__.py b/smash/web/models/__init__.py
index d6a3586c..56d7ea62 100644
--- a/smash/web/models/__init__.py
+++ b/smash/web/models/__init__.py
@@ -41,6 +41,7 @@ from .inconsistent_subject import InconsistentSubject, InconsistentField
 from .privacy_notice import PrivacyNotice
 
 from .etl import VisitImportData, SubjectImportData, EtlColumnMapping
+from .custom_data import CustomStudySubjectVisibility
 
 __all__ = [Study, FlyingTeam, Appointment, AppointmentType, Availability, Holiday, Item, Language, Location, Room,
            Subject, StudySubject, StudySubjectList, SubjectColumns, StudyNotificationParameters,
diff --git a/smash/web/models/custom_data/__init__.py b/smash/web/models/custom_data/__init__.py
index e9587ebe..19012a57 100644
--- a/smash/web/models/custom_data/__init__.py
+++ b/smash/web/models/custom_data/__init__.py
@@ -1,4 +1,5 @@
 from .custom_study_subject_field import CustomStudySubjectField
 from .custom_study_subject_value import CustomStudySubjectValue
+from .custom_study_subject_visibility import CustomStudySubjectVisibility
 
-__all__ = [CustomStudySubjectField, CustomStudySubjectValue]
+__all__ = [CustomStudySubjectField, CustomStudySubjectValue, CustomStudySubjectVisibility]
diff --git a/smash/web/models/custom_data/custom_study_subject_visibility.py b/smash/web/models/custom_data/custom_study_subject_visibility.py
new file mode 100644
index 00000000..16aa2f8f
--- /dev/null
+++ b/smash/web/models/custom_data/custom_study_subject_visibility.py
@@ -0,0 +1,20 @@
+# coding=utf-8
+
+from django.db import models
+
+
+class CustomStudySubjectVisibility(models.Model):
+    visible = models.BooleanField(default=False, null=False)
+
+    study_subject_field = models.ForeignKey("web.CustomStudySubjectField",
+                                            verbose_name='Custom Field',
+                                            editable=False,
+                                            null=False,
+                                            on_delete=models.CASCADE
+                                            )
+    visible_subject_study_columns = models.ForeignKey("web.StudyColumns",
+                                                      verbose_name='List of visible columns',
+                                                      editable=False,
+                                                      null=False,
+                                                      on_delete=models.CASCADE
+                                                      )
diff --git a/smash/web/models/study_columns.py b/smash/web/models/study_columns.py
index 858db85a..03f8d30a 100644
--- a/smash/web/models/study_columns.py
+++ b/smash/web/models/study_columns.py
@@ -1,6 +1,8 @@
 # coding=utf-8
 from django.db import models
 
+from web.models.custom_data import CustomStudySubjectField, CustomStudySubjectVisibility
+
 
 class StudyColumns(models.Model):
     class Meta:
@@ -222,3 +224,26 @@ class StudyColumns(models.Model):
         default=False,
         verbose_name='Visit 5 virus IgG status',
     )
+
+    @property
+    def custom_fields_visibility(self):
+        study = self.studysubjectlist_set.all()[0].study
+        values = CustomStudySubjectVisibility.objects.filter(visible_subject_study_columns=self)
+        fields = list(CustomStudySubjectField.objects.filter(study=study))
+        for value in values:
+            fields.remove(value.study_subject_field)
+        for field in fields:
+            CustomStudySubjectVisibility.objects.create(visible_subject_study_columns=self, study_subject_field=field)
+        return CustomStudySubjectVisibility.objects.filter(visible_subject_study_columns=self)
+
+    def set_custom_field_visibility(self, custom_study_subject_field: CustomStudySubjectField, visible: bool):
+        for existing_value in self.custom_fields_visibility.all():
+            if existing_value.study_subject_field == custom_study_subject_field:
+                existing_value.visible = visible
+                existing_value.save()
+
+    def is_custom_field_visible(self, field: CustomStudySubjectField) -> bool:
+        for existing_value in self.custom_fields_visibility.all():
+            if existing_value.study_subject_field == field:
+                return existing_value.visible
+        return False
-- 
GitLab