From 0af7dd8057a6dfb5a489096e3eb3065f152dffea Mon Sep 17 00:00:00 2001 From: Tobias Bengfort Date: Mon, 25 Jun 2018 12:39:34 +0200 Subject: [PATCH 1/5] use context_object_name for subject detail view --- .../templates/recruitment/subject_detail_view.html | 14 +++++++------- castellum_core/castellum_core/recruitment/views.py | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/castellum_core/castellum_core/recruitment/templates/recruitment/subject_detail_view.html b/castellum_core/castellum_core/recruitment/templates/recruitment/subject_detail_view.html index 687f04812..0736b8852 100644 --- a/castellum_core/castellum_core/recruitment/templates/recruitment/subject_detail_view.html +++ b/castellum_core/castellum_core/recruitment/templates/recruitment/subject_detail_view.html @@ -5,33 +5,33 @@ -

{{ object.first_name|default:_('not provided') }} {{ object.last_name|default:_('not provided') }}

+

{{ subject.first_name|default:_('not provided') }} {{ subject.last_name|default:_('not provided') }}

- + - + - + - + - + - +
{% trans 'Gender:' %}{{ object.gender|default:_('not provided') }}{{ subject.gender|default:_('not provided') }}
{% trans 'Birthday:' %}{{ object.birthday|default:_('not provided') }}{{ subject.birthday|default:_('not provided') }}
{% trans 'Address:' %}{{ object.address|default:_('not provided') }}{{ subject.address|default:_('not provided') }}
{% trans 'Email:' %}{{ object.email|default:_('not provided') }}{{ subject.email|default:_('not provided') }}
{% trans 'Phone number:' %}{{ object.phone_number|default:_('not provided') }}{{ subject.phone_number|default:_('not provided') }}
{% trans 'Second phone number:' %}{{ object.phone_number_alternative|default:_('not provided') }}{{ subject.phone_number_alternative|default:_('not provided') }}
diff --git a/castellum_core/castellum_core/recruitment/views.py b/castellum_core/castellum_core/recruitment/views.py index a8bb69621..77eb0c90b 100644 --- a/castellum_core/castellum_core/recruitment/views.py +++ b/castellum_core/castellum_core/recruitment/views.py @@ -55,6 +55,7 @@ class SubjectDetailsView(LoginRequiredMixin, DetailView): model = Subject slug_field = 'id' slug_url_kwarg = 'subject_pk' + context_object_name = 'subject' template_name = 'recruitment/subject_detail_view.html' def get_context_data(self, **kwargs): -- GitLab From a2b5c2fff134f7bc5705923b178fa299cd8da570 Mon Sep 17 00:00:00 2001 From: Tobias Bengfort Date: Mon, 25 Jun 2018 12:42:02 +0200 Subject: [PATCH 2/5] rename subject detail view to contact --- .../recruitment/{subject_detail_view.html => contact.html} | 0 .../recruitment/templates/recruitment/subjects_list.html | 2 +- castellum_core/castellum_core/recruitment/urls.py | 2 +- castellum_core/castellum_core/recruitment/views.py | 4 ++-- .../{test_subject_details_view.py => test_contact_view.py} | 0 5 files changed, 4 insertions(+), 4 deletions(-) rename castellum_core/castellum_core/recruitment/templates/recruitment/{subject_detail_view.html => contact.html} (100%) rename castellum_core/tests/recruitment/views/{test_subject_details_view.py => test_contact_view.py} (100%) diff --git a/castellum_core/castellum_core/recruitment/templates/recruitment/subject_detail_view.html b/castellum_core/castellum_core/recruitment/templates/recruitment/contact.html similarity index 100% rename from castellum_core/castellum_core/recruitment/templates/recruitment/subject_detail_view.html rename to castellum_core/castellum_core/recruitment/templates/recruitment/contact.html diff --git a/castellum_core/castellum_core/recruitment/templates/recruitment/subjects_list.html b/castellum_core/castellum_core/recruitment/templates/recruitment/subjects_list.html index b5e3c6316..29e8cabb1 100644 --- a/castellum_core/castellum_core/recruitment/templates/recruitment/subjects_list.html +++ b/castellum_core/castellum_core/recruitment/templates/recruitment/subjects_list.html @@ -34,7 +34,7 @@ {{ subject.first_name|default:_('not provided') }} {{ subject.last_name|default:_('not provided') }} - {% trans 'Call' %} + {% trans 'Call' %} {% endfor %} diff --git a/castellum_core/castellum_core/recruitment/urls.py b/castellum_core/castellum_core/recruitment/urls.py index 293678129..a310cd47b 100644 --- a/castellum_core/castellum_core/recruitment/urls.py +++ b/castellum_core/castellum_core/recruitment/urls.py @@ -27,5 +27,5 @@ app_name = 'recruitment' urlpatterns = [ path('', views.StudyChoiceView.as_view(), name='select_study'), path('/', views.SubjectChoiceView.as_view(), name='select_subject'), - path('//', views.SubjectDetailsView.as_view(), name='detail_subject'), + path('//', views.ContactView.as_view(), name='contact'), ] diff --git a/castellum_core/castellum_core/recruitment/views.py b/castellum_core/castellum_core/recruitment/views.py index 77eb0c90b..5ea72875d 100644 --- a/castellum_core/castellum_core/recruitment/views.py +++ b/castellum_core/castellum_core/recruitment/views.py @@ -51,12 +51,12 @@ class SubjectChoiceView(LoginRequiredMixin, ListView): return context -class SubjectDetailsView(LoginRequiredMixin, DetailView): +class ContactView(LoginRequiredMixin, DetailView): model = Subject slug_field = 'id' slug_url_kwarg = 'subject_pk' context_object_name = 'subject' - template_name = 'recruitment/subject_detail_view.html' + template_name = 'recruitment/contact.html' def get_context_data(self, **kwargs): context = super(DetailView, self).get_context_data(**kwargs) diff --git a/castellum_core/tests/recruitment/views/test_subject_details_view.py b/castellum_core/tests/recruitment/views/test_contact_view.py similarity index 100% rename from castellum_core/tests/recruitment/views/test_subject_details_view.py rename to castellum_core/tests/recruitment/views/test_contact_view.py -- GitLab From 4991b0b7f60728ab9bbba2a02574789a84e944d7 Mon Sep 17 00:00:00 2001 From: Tobias Bengfort Date: Mon, 25 Jun 2018 12:46:21 +0200 Subject: [PATCH 3/5] model participation --- .../castellum_core/recruitment/admin.py | 2 ++ .../migrations/0002_participation.py | 25 +++++++++++++++++++ .../castellum_core/recruitment/models.py | 20 +++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 castellum_core/castellum_core/recruitment/migrations/0002_participation.py diff --git a/castellum_core/castellum_core/recruitment/admin.py b/castellum_core/castellum_core/recruitment/admin.py index 87e5ca310..627d221ae 100644 --- a/castellum_core/castellum_core/recruitment/admin.py +++ b/castellum_core/castellum_core/recruitment/admin.py @@ -22,5 +22,7 @@ from django.contrib import admin from .models import AttributeSet +from .models import Participation admin.site.register(AttributeSet) +admin.site.register(Participation) diff --git a/castellum_core/castellum_core/recruitment/migrations/0002_participation.py b/castellum_core/castellum_core/recruitment/migrations/0002_participation.py new file mode 100644 index 000000000..383997f33 --- /dev/null +++ b/castellum_core/castellum_core/recruitment/migrations/0002_participation.py @@ -0,0 +1,25 @@ +# Generated by Django 2.0.4 on 2018-06-25 14:13 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('studies', '0001_initial'), + ('recruitment', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Participation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('subject_pk', models.CharField(max_length=128)), + ('status', models.IntegerField(choices=[(0, 'missed call'), (1, 'unsuitable'), (2, 'invited')], default=2, verbose_name='status of participation')), + ('updated_at', models.DateTimeField(blank=True, null=True, verbose_name='last updated at')), + ('study', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='studies.Study', verbose_name='study')), + ], + ), + ] diff --git a/castellum_core/castellum_core/recruitment/models.py b/castellum_core/castellum_core/recruitment/models.py index f0f967069..c74491192 100644 --- a/castellum_core/castellum_core/recruitment/models.py +++ b/castellum_core/castellum_core/recruitment/models.py @@ -22,6 +22,8 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ +from studies.models import Study + class AttributeSet(models.Model): handedness = models.CharField(_('Handedness'), blank=True, max_length=10, choices=( @@ -30,3 +32,21 @@ class AttributeSet(models.Model): )) first_language = models.CharField(_('First Language'), blank=True, max_length=5) date_of_birth = models.DateField(_('Date of birth'), null=True, blank=True) + + +class Participation(models.Model): + MISSED_CALL = 0 + UNSUITABLE = 1 + INVITED = 2 + STATUS_OPTIONS = ( + (MISSED_CALL, _('missed call')), + (UNSUITABLE, _('unsuitable')), + (INVITED, _('invited')), + ) + + study = models.ForeignKey(Study, verbose_name=_('study'), on_delete=models.CASCADE) + # just a placeholder until proper pseudonyms are available + subject_pk = models.CharField(max_length=128) + status = models.IntegerField( + _('status of participation'), choices=STATUS_OPTIONS, default=INVITED) + updated_at = models.DateTimeField(_('last updated at'), blank=True, null=True) -- GitLab From d7abddf21d28be9427009d639c6f19b13f62babf Mon Sep 17 00:00:00 2001 From: Tobias Bengfort Date: Mon, 25 Jun 2018 12:46:35 +0200 Subject: [PATCH 4/5] adjust contact view --- .../templates/recruitment/contact.html | 16 +++++++- .../castellum_core/recruitment/views.py | 38 ++++++++++++++----- .../recruitment/views/test_contact_view.py | 20 ++++++++++ 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/castellum_core/castellum_core/recruitment/templates/recruitment/contact.html b/castellum_core/castellum_core/recruitment/templates/recruitment/contact.html index 0736b8852..2e86fce53 100644 --- a/castellum_core/castellum_core/recruitment/templates/recruitment/contact.html +++ b/castellum_core/castellum_core/recruitment/templates/recruitment/contact.html @@ -1,5 +1,5 @@ {% extends "base.html" %} -{% load i18n %} +{% load i18n bootstrap4 %} {% block content %} @@ -35,5 +35,17 @@
- {% trans "Back" %} + +
+ {% for error in form.non_field_errors %} + + {% endfor %} + + {% csrf_token %} + {% bootstrap_field form.status %} + + + {% trans "Back" %} +
+ {% endblock %} \ No newline at end of file diff --git a/castellum_core/castellum_core/recruitment/views.py b/castellum_core/castellum_core/recruitment/views.py index 5ea72875d..a54e7fd6e 100644 --- a/castellum_core/castellum_core/recruitment/views.py +++ b/castellum_core/castellum_core/recruitment/views.py @@ -21,12 +21,16 @@ from django.contrib.auth.mixins import LoginRequiredMixin from django.shortcuts import get_object_or_404 -from django.views.generic import DetailView +from django.urls import reverse +from django.utils import timezone from django.views.generic import ListView +from django.views.generic import UpdateView from studies.models import Study from subject_management.models import Subject +from .models import Participation + class StudyChoiceView(LoginRequiredMixin, ListView): model = Study @@ -51,15 +55,31 @@ class SubjectChoiceView(LoginRequiredMixin, ListView): return context -class ContactView(LoginRequiredMixin, DetailView): - model = Subject - slug_field = 'id' - slug_url_kwarg = 'subject_pk' - context_object_name = 'subject' +class ContactView(LoginRequiredMixin, UpdateView): + model = Participation + fields = ['status'] template_name = 'recruitment/contact.html' - def get_context_data(self, **kwargs): - context = super(DetailView, self).get_context_data(**kwargs) + def get_object(self, queryset=None): + if queryset is None: + queryset = self.get_queryset() + study = get_object_or_404(Study, pk=self.kwargs['study_pk']) - context['study'] = study + subject_pk = self.kwargs['subject_pk'] + + participation, __ = queryset.get_or_create(study=study, subject_pk=subject_pk) + return participation + + def get_success_url(self): + return reverse('recruitment:select_subject', args=[self.object.study.pk]) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['study'] = self.object.study + context['subject'] = get_object_or_404(Subject, pk=self.object.subject_pk) return context + + def form_valid(self, form): + instance = form.save(commit=False) + instance.updated_at = timezone.now() + return super(ContactView, self).form_valid(form) diff --git a/castellum_core/tests/recruitment/views/test_contact_view.py b/castellum_core/tests/recruitment/views/test_contact_view.py index 519456bc0..c55cb214e 100644 --- a/castellum_core/tests/recruitment/views/test_contact_view.py +++ b/castellum_core/tests/recruitment/views/test_contact_view.py @@ -1,3 +1,6 @@ +from freezegun import freeze_time + +from recruitment.models import Participation def test_404_page_returned_if_study_is_not_provided(client, user, subject): @@ -12,3 +15,20 @@ def test_200_page_returned_if_study_is_provided(client, user, study, subject): url = '/recruitment/{}/{}/'.format(study.pk, subject.pk) response = client.get(url) assert response.status_code == 200 + + +def test_post_redirect(client, user, study, subject): + client.force_login(user) + url = '/recruitment/{}/{}/'.format(study.pk, subject.pk) + response = client.post(url, {'status': 2}) + assert response.status_code == 302 + assert response.url == '/recruitment/{}/'.format(study.pk) + + +@freeze_time('2018-01-01') +def test_post_updated_at(client, user, study, subject): + client.force_login(user) + url = '/recruitment/{}/{}/'.format(study.pk, subject.pk) + client.post(url, {'status': 2}) + participation = Participation.objects.get() + assert participation.updated_at.strftime('%Y-%m-%d') == '2018-01-01' -- GitLab From fc38fb4edc3db41620c92658f1b049fba12abba6 Mon Sep 17 00:00:00 2001 From: Tobias Bengfort Date: Tue, 26 Jun 2018 09:56:40 +0200 Subject: [PATCH 5/5] adjust to !80 --- .../recruitment/migrations/0002_participation.py | 2 +- castellum_core/castellum_core/recruitment/models.py | 4 +++- .../recruitment/templates/recruitment/contact.html | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/castellum_core/castellum_core/recruitment/migrations/0002_participation.py b/castellum_core/castellum_core/recruitment/migrations/0002_participation.py index 383997f33..61c6dc337 100644 --- a/castellum_core/castellum_core/recruitment/migrations/0002_participation.py +++ b/castellum_core/castellum_core/recruitment/migrations/0002_participation.py @@ -17,7 +17,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('subject_pk', models.CharField(max_length=128)), - ('status', models.IntegerField(choices=[(0, 'missed call'), (1, 'unsuitable'), (2, 'invited')], default=2, verbose_name='status of participation')), + ('status', models.IntegerField(choices=[(0, 'missed call'), (1, 'unsuitable'), (2, 'invited')], default=1, verbose_name='status of participation')), ('updated_at', models.DateTimeField(blank=True, null=True, verbose_name='last updated at')), ('study', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='studies.Study', verbose_name='study')), ], diff --git a/castellum_core/castellum_core/recruitment/models.py b/castellum_core/castellum_core/recruitment/models.py index c74491192..bc6e3fc87 100644 --- a/castellum_core/castellum_core/recruitment/models.py +++ b/castellum_core/castellum_core/recruitment/models.py @@ -45,8 +45,10 @@ class Participation(models.Model): ) study = models.ForeignKey(Study, verbose_name=_('study'), on_delete=models.CASCADE) + # just a placeholder until proper pseudonyms are available subject_pk = models.CharField(max_length=128) + status = models.IntegerField( - _('status of participation'), choices=STATUS_OPTIONS, default=INVITED) + _('status of participation'), choices=STATUS_OPTIONS, default=UNSUITABLE) updated_at = models.DateTimeField(_('last updated at'), blank=True, null=True) diff --git a/castellum_core/castellum_core/recruitment/templates/recruitment/contact.html b/castellum_core/castellum_core/recruitment/templates/recruitment/contact.html index 2e86fce53..21e2f5042 100644 --- a/castellum_core/castellum_core/recruitment/templates/recruitment/contact.html +++ b/castellum_core/castellum_core/recruitment/templates/recruitment/contact.html @@ -44,8 +44,8 @@ {% csrf_token %} {% bootstrap_field form.status %} - {% trans "Back" %} + -{% endblock %} \ No newline at end of file +{% endblock %} -- GitLab