From 4cca9c147a88763a6a30ea5aecd698ec1bd5e706 Mon Sep 17 00:00:00 2001 From: Edo Storm Date: Thu, 24 Oct 2024 15:24:00 +0200 Subject: [PATCH 01/22] feat: create all InformationLetter kinds --- attachments/kinds.py | 51 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/attachments/kinds.py b/attachments/kinds.py index 05112c00..41633a41 100644 --- a/attachments/kinds.py +++ b/attachments/kinds.py @@ -19,14 +19,53 @@ class StudyAttachmentKind(AttachmentKind): attached_object = Study attachment_class = StudyAttachment +##################### +# Information letters +##################### + +class InformationLetterAnonymous(StudyAttachmentKind): + + db_name = "information_letter_anonymous" + name = _("Informatiebrief anoniem onderzoek") + description = _("Je verzamelt en verwerkt de gegevens van je deelnemers" + " anoniem. Je moet je deelnemers dan wél informeren op" + " ethische gronden (zodat ze kunnen beslissen of ze" + " vrijwillig willen meedoen), maar omdat de AVG niet" + " van toepassing is op anonieme gegevens, hoef je geen" + " informatie te verstrekken over de verwerking van" + " persoonsgegevens.") + desiredness = desiredness.REQUIRED -class InformationLetter(StudyAttachmentKind): +class InformationLetterPublicInterest(StudyAttachmentKind): - db_name = "information_letter" - name = _("Informatiebrief") - description = _("Omschrijving informatiebrief") + db_name = "information_letter_public_interest" + name = _("Informatiebrief algemeen belang") + description = _("Je kiest ervoor om de verwerking van persoonsgegevens te" + " baseren op het algemeen belang. In beginsel is dit" + " de standaardwerkwijze. \n" + "Let op! Voor bepaalde aspecten van je onderzoek kan het" + " desondanks nodig zijn om toestemming te vragen.") desiredness = desiredness.REQUIRED +class InformationLetterConsent(StudyAttachmentKind): + + db_name = "information_letter_consent" + name = _("Informatiebrief toestemming") + description = _("Er zijn redenen om de verwerking van persoonsgegevens" + " te baseren op toestemming van de deelnemers." + " Bijvoorbeeld als er gevoelige data wordt verzameld of" + " er met minderjarigen wordt gewerkt.") + desiredness = desiredness.REQUIRED + +LEGAL_BASIS_KIND_DICT = { + Study.LegalBases.ANONYMOUS: InformationLetterAnonymous, + Study.LegalBases.CONSENT: InformationLetterConsent, + Study.LegalBases.PUBLIC_INTEREST: InformationLetterPublicInterest, +} + +############### +# Consent forms +############### class ConsentForm(AttachmentKind): @@ -61,7 +100,9 @@ def num_suggested(self): STUDY_ATTACHMENTS = [ - InformationLetter, + InformationLetterAnonymous, + InformationLetterPublicInterest, + InformationLetterConsent, ConsentForm, ] From 91831756928b069982d3258d4ce49c65ccf66744 Mon Sep 17 00:00:00 2001 From: Edo Storm Date: Thu, 24 Oct 2024 15:27:22 +0200 Subject: [PATCH 02/22] feat: add correct informationletter in checker --- proposals/utils/checkers.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/proposals/utils/checkers.py b/proposals/utils/checkers.py index 4b6ed212..f066182d 100644 --- a/proposals/utils/checkers.py +++ b/proposals/utils/checkers.py @@ -12,7 +12,7 @@ from tasks.models import Task, Session from attachments.utils import AttachmentSlot, desiredness -from attachments.kinds import InformationLetter, DataManagementPlan +from attachments.kinds import DataManagementPlan, LEGAL_BASIS_KIND_DICT from .stepper_helpers import ( Checker, @@ -472,12 +472,13 @@ def __init__( def check( self, ): - kind = InformationLetter - info_slot = AttachmentSlot( - self.study, - kind=kind, - ) - self.stepper.add_slot(info_slot) + if self.study.legal_basis is not None: + kind = LEGAL_BASIS_KIND_DICT[self.study.legal_basis] + info_slot = AttachmentSlot( + self.study, + kind=kind, + ) + self.stepper.add_slot(info_slot) return [] From 29a9d1cd7352bd116100e3ab259e632208bae9f0 Mon Sep 17 00:00:00 2001 From: Edo Storm Date: Thu, 24 Oct 2024 15:27:49 +0200 Subject: [PATCH 03/22] feat: check if Study has AV registration --- proposals/utils/checkers.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/proposals/utils/checkers.py b/proposals/utils/checkers.py index f066182d..5c0b86d2 100644 --- a/proposals/utils/checkers.py +++ b/proposals/utils/checkers.py @@ -4,9 +4,12 @@ from proposals import forms as proposal_forms from proposals.models import Wmo from studies import forms as study_forms +from studies.models import Study from interventions import forms as intervention_forms from observations import forms as observation_forms +from observations.models import Registration as observation_registration from tasks import forms as tasks_forms +from tasks.models import Registration as task_registration from tasks.views import task_views, session_views from tasks.models import Task, Session @@ -479,7 +482,40 @@ def check( kind=kind, ) self.stepper.add_slot(info_slot) + + if self.check_has_AV_registration: + # Add "agreement video/audio recordings" slot or "script for verbal consent recordings" + # Maybe if one has been fulfilled, change the orther's desiredness + pass return [] + + def check_has_AV_registration(self): + """ + A function that checks whether a study features audio or video + registration. + """ + if self.study.legal_basis == Study.LegalBases.CONSENT: + has_AV_registration = False + if self.study.has_observation: + #gather all AV observation_registraions + AV_registrations = observation_registration.objects.filter( + description__in=["audio-opname", "video-opname"] + ) + if self.study.observation.registration in AV_registrations: + has_AV_registration = True + if self.study.has_sessions: + # gather all the tasks + all_tasks = [ + session.task_set.all() for session in self.study.session_set.all() + ] + #gather all AV task_registrations + AV_registrations = task_registration.objects.filter( + description__in=["audio-opname", "video-opname"] + ) + if all_tasks.filter(registration__in=AV_registrations): + has_AV_registration = True + return has_AV_registration + class ParticipantsChecker( From d3717ce35f181417a5fe62361fa98d7e5061edf5 Mon Sep 17 00:00:00 2001 From: Edo Storm Date: Thu, 24 Oct 2024 15:28:31 +0200 Subject: [PATCH 04/22] fix: bug, where legal basis can be 0 ... woopsie --- studies/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/studies/forms.py b/studies/forms.py index 16cd20c7..1259916e 100644 --- a/studies/forms.py +++ b/studies/forms.py @@ -221,7 +221,7 @@ def clean(self): if cleaned_data["has_special_details"] is None: self.add_error("has_special_details", _("Dit veld is verplicht.")) - if not cleaned_data["legal_basis"]: + if cleaned_data["legal_basis"] is None: self.add_error("legal_basis", _("Selecteer een van de opties.")) self.check_dependency_multiple( From 6654c4a42259e739f5f5a84af57af6091447d93e Mon Sep 17 00:00:00 2001 From: Edo Storm Date: Thu, 7 Nov 2024 10:30:06 +0100 Subject: [PATCH 05/22] feature: add all possible kinds --- attachments/kinds.py | 165 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 146 insertions(+), 19 deletions(-) diff --git a/attachments/kinds.py b/attachments/kinds.py index 41633a41..4b90c127 100644 --- a/attachments/kinds.py +++ b/attachments/kinds.py @@ -19,6 +19,7 @@ class StudyAttachmentKind(AttachmentKind): attached_object = Study attachment_class = StudyAttachment + ##################### # Information letters ##################### @@ -27,52 +28,171 @@ class InformationLetterAnonymous(StudyAttachmentKind): db_name = "information_letter_anonymous" name = _("Informatiebrief anoniem onderzoek") - description = _("Je verzamelt en verwerkt de gegevens van je deelnemers" - " anoniem. Je moet je deelnemers dan wél informeren op" - " ethische gronden (zodat ze kunnen beslissen of ze" - " vrijwillig willen meedoen), maar omdat de AVG niet" - " van toepassing is op anonieme gegevens, hoef je geen" - " informatie te verstrekken over de verwerking van" - " persoonsgegevens.") + description = _( + "Je verzamelt en verwerkt de gegevens van je deelnemers" + " anoniem. Je moet je deelnemers dan wél informeren op" + " ethische gronden (zodat ze kunnen beslissen of ze" + " vrijwillig willen meedoen), maar omdat de AVG niet" + " van toepassing is op anonieme gegevens, hoef je geen" + " informatie te verstrekken over de verwerking van" + " persoonsgegevens." + ) desiredness = desiredness.REQUIRED + class InformationLetterPublicInterest(StudyAttachmentKind): db_name = "information_letter_public_interest" name = _("Informatiebrief algemeen belang") - description = _("Je kiest ervoor om de verwerking van persoonsgegevens te" - " baseren op het algemeen belang. In beginsel is dit" - " de standaardwerkwijze. \n" - "Let op! Voor bepaalde aspecten van je onderzoek kan het" - " desondanks nodig zijn om toestemming te vragen.") + description = _( + "Je kiest ervoor om de verwerking van persoonsgegevens te" + " baseren op het algemeen belang. In beginsel is dit" + " de standaardwerkwijze. \n" + "Let op! Voor bepaalde aspecten van je onderzoek kan het" + " desondanks nodig zijn om toestemming te vragen." + ) desiredness = desiredness.REQUIRED + class InformationLetterConsent(StudyAttachmentKind): db_name = "information_letter_consent" name = _("Informatiebrief toestemming") - description = _("Er zijn redenen om de verwerking van persoonsgegevens" - " te baseren op toestemming van de deelnemers." - " Bijvoorbeeld als er gevoelige data wordt verzameld of" - " er met minderjarigen wordt gewerkt.") + description = _( + "Er zijn redenen om de verwerking van persoonsgegevens" + " te baseren op toestemming van de deelnemers." + " Bijvoorbeeld als er gevoelige data wordt verzameld of" + " er met minderjarigen wordt gewerkt." + ) desiredness = desiredness.REQUIRED + LEGAL_BASIS_KIND_DICT = { Study.LegalBases.ANONYMOUS: InformationLetterAnonymous, Study.LegalBases.CONSENT: InformationLetterConsent, - Study.LegalBases.PUBLIC_INTEREST: InformationLetterPublicInterest, + Study.LegalBases.PUBLIC_INTEREST: InformationLetterPublicInterest, } + ############### # Consent forms ############### -class ConsentForm(AttachmentKind): +class ConsentForm(StudyAttachmentKind): db_name = "consent_form" name = _("Toestemmingsverklaring") - description = _("Omschrijving toestemmingsverklaring") + description = _( + "Je baseert de verwerking van persoonsgegevens binnen je onderzoek op" + " de wettelijke grondslag toestemming. De deelnemers zijn volwassenen" + " (16 jaar en ouder)." + ) + desiredness = desiredness.REQUIRED + +class ConsentPublicInterestSpecialDetails(StudyAttachmentKind): + + db_name = "consent_public_interest_special_details" + name = _("Toestemmingsverklaring algemeen belang bijzondere persoonsgegevens") + description = _( + "Je baseert de verwerking van persoonsgegevens binnen je onderzoek" + " weliswaar op de wettelijke grondslag algemeen belang, maar je" + " verzamelt zgn. bijzondere persoonsgegevens externe link en daarvoor" + " heb je toestemming nodig." + ) + desiredness = desiredness.REQUIRED + + +class ConsentChildrenParents(StudyAttachmentKind): + + db_name = "consent_children_w_parents" + name = _("Toestemmingsverklaring kinderen tot 16 jaar, ouders of voogden aanwezig") + description = _( + "Je baseert de verwerking van persoonsgegevens binnen je" + " onderzoek op de wettelijke grondslag toestemming. De" + " deelnemers zijn kinderen jonger dan 16 jaar en minimaal" + " één van de ouders of voogden is bij het onderzoek aanwezig." + ) + desiredness = desiredness.REQUIRED + + +class ConsentChildrenNoParents(StudyAttachmentKind): + + db_name = "consent_children_no_parents" + name = _("Toestemmingsverklaring kinderen tot 16 jaar, ouders of voogden afwezig") + description = _( + "Je baseert de verwerking van persoonsgegevens binnen je" + " onderzoek op de wettelijke grondslag toestemming. De" + " deelnemers zijn kinderen jonger dan 16 jaar en er zijn" + " geen ouders of voodgen aanwezig." + ) + desiredness = desiredness.REQUIRED + + +#################### +# Recordings consent +#################### + +class AgreementRecordingsPublicInterest(StudyAttachmentKind): + + db_name = "agreement_av_recordings" + name = _("Akkoordverklaring beeld- en geluidsopnames algemeen belang") + description = _( + "Je baseert de verwerking van persoonsgegevens weliswaar op de" + " wettelijke grondslag algemeen belang, maar je maakt beeld- en/of" + " geluidsopnames en daar moeten je deelnemers op ethische gronden" + " mee instemmen. Ook voor het verdere gebruik van die opnames kun" + " je de afspraken schriftelijk vastleggen." + ) + desiredness = desiredness.REQUIRED + + +class ScriptVerbalConsentRecordings(StudyAttachmentKind): + + db_name = "script_verbal_consent_recordings" + name = _("Script voor mondelinge toestemming opnames") + description = _( + "Je interviewt deelnemers en je maakt daarvan beeld- en/of" + " geluidsopnames. De toestemming daarvoor, en de eventuele" + " toestemming en afspraken met betrekking tot andere aspecten van" + " de verwerking van persoonsgegevens, leg je vast in een aparte opname." + ) + desiredness = desiredness.REQUIRED + + +############## +# School stuff +############## + +class SchoolInformationLetter(ProposalAttachmentKind): + + db_name = "school_information_letter" + name = _("Informatiebrief gatekeeper/schoolleiding") + description = _( + "Je wilt onderzoek gaan doen binnen een bepaalde instelling (bijv." + " een school) en je verzoekt de leiding van die instelling om" + " medewerking. Voor het maken van een geïnformeerde keuze moet de" + " leiding van de instelling op de hoogte zijn van de opzet van je" + " onderzoek en van allerlei praktische aspecten." + ) + desiredness = desiredness.REQUIRED + + +class SchoolConsentForm(ProposalAttachmentKind): + + db_name = "school_consent_form" + name = _("Akkoordverklaring gatekeeper/schoolleiding") + description = _( + "Je wilt onderzoek gaan doen binnen een bepaalde instelling (bijv." + " een school) en je verzoekt de leiding van die instelling om" + " medewerking. De schoolleiding moet, na goed geïnformeerd te zijn" + "toestemming geven voor het onderzoek." + ) + desiredness = desiredness.REQUIRED + +############# +# Other stuff +############# class DataManagementPlan(ProposalAttachmentKind): @@ -103,10 +223,17 @@ def num_suggested(self): InformationLetterAnonymous, InformationLetterPublicInterest, InformationLetterConsent, + AgreementRecordingsPublicInterest, + ScriptVerbalConsentRecordings, + ConsentPublicInterestSpecialDetails, + ConsentChildrenParents, + ConsentChildrenNoParents, ConsentForm, ] PROPOSAL_ATTACHMENTS = [ + SchoolInformationLetter, + SchoolConsentForm, DataManagementPlan, OtherProposalAttachment, ] From ba2ddfdd3181e1aacddb07f9e546b1b4b5febec9 Mon Sep 17 00:00:00 2001 From: Edo Storm Date: Thu, 7 Nov 2024 10:30:29 +0100 Subject: [PATCH 06/22] feature: add all slots, through checkers --- proposals/utils/checkers.py | 165 ++++++++++++++++++++++++++++++------ 1 file changed, 137 insertions(+), 28 deletions(-) diff --git a/proposals/utils/checkers.py b/proposals/utils/checkers.py index 5c0b86d2..f6d464d5 100644 --- a/proposals/utils/checkers.py +++ b/proposals/utils/checkers.py @@ -15,7 +15,18 @@ from tasks.models import Task, Session from attachments.utils import AttachmentSlot, desiredness -from attachments.kinds import DataManagementPlan, LEGAL_BASIS_KIND_DICT +from attachments.kinds import ( + DataManagementPlan, + LEGAL_BASIS_KIND_DICT, + ConsentForm, + AgreementRecordingsPublicInterest, + ScriptVerbalConsentRecordings, + ConsentPublicInterestSpecialDetails, + ConsentChildrenParents, + ConsentChildrenNoParents, + SchoolConsentForm, + SchoolInformationLetter, +) from .stepper_helpers import ( Checker, @@ -483,39 +494,116 @@ def check( ) self.stepper.add_slot(info_slot) - if self.check_has_AV_registration: - # Add "agreement video/audio recordings" slot or "script for verbal consent recordings" - # Maybe if one has been fulfilled, change the orther's desiredness - pass + if self.study.legal_basis == Study.LegalBases.PUBLIC_INTEREST: + + fulfilled_recording_slot = None + + if self.check_has_recordings(): + # if a study features registration, add two slots + recordings_slots = [ + AttachmentSlot( + self.study, + kind=AgreementRecordingsPublicInterest, + ), + AttachmentSlot( + self.study, + kind=ScriptVerbalConsentRecordings, + ), + ] + # if one of them has been fulfilled, this becomes the fulfilled slot + fulfilled_recording_slot = self.at_least_one_fulfilled(recordings_slots) + + for slot in recordings_slots: + # if there is at least one, make the other one optional + if ( + fulfilled_recording_slot + and slot is not fulfilled_recording_slot + ): + slot.force_desiredness = desiredness.OPTIONAL + self.stepper.add_slot(slot) + + if self.study.has_special_details and not fulfilled_recording_slot: + self.stepper.add_slot( + AttachmentSlot( + self.study, + kind=ConsentPublicInterestSpecialDetails, + ) + ) + + if self.study.legal_basis == Study.LegalBases.CONSENT: + fulfilled_children_slot = None + if self.study.has_children(): + children_slots = [ + AttachmentSlot( + self.study, + kind=ConsentChildrenParents, + ), + AttachmentSlot( + self.study, + kind=ConsentChildrenNoParents, + ), + ] + + # if one of them has been fulfilled, this becomes the fulfilled slot + fulfilled_children_slot = self.at_least_one_fulfilled(children_slots) + for slot in children_slots: + # if there is at least one, make the other one optional + if fulfilled_children_slot and slot is not fulfilled_children_slot: + slot.force_desiredness = desiredness.OPTIONAL + self.stepper.add_slot(slot) + + # Add a slot for a normal ConsentForm + self.stepper.add_slot( + AttachmentSlot( + self.study, + kind=ConsentForm, + force_desiredness=( + desiredness.REQUIRED + if not fulfilled_children_slot + else desiredness.OPTIONAL + ), + ) + ) + return [] - - def check_has_AV_registration(self): + + def check_has_recordings(self): """ A function that checks whether a study features audio or video registration. """ - if self.study.legal_basis == Study.LegalBases.CONSENT: - has_AV_registration = False - if self.study.has_observation: - #gather all AV observation_registraions - AV_registrations = observation_registration.objects.filter( - description__in=["audio-opname", "video-opname"] - ) - if self.study.observation.registration in AV_registrations: - has_AV_registration = True - if self.study.has_sessions: - # gather all the tasks - all_tasks = [ - session.task_set.all() for session in self.study.session_set.all() - ] - #gather all AV task_registrations - AV_registrations = task_registration.objects.filter( - description__in=["audio-opname", "video-opname"] - ) - if all_tasks.filter(registration__in=AV_registrations): - has_AV_registration = True - return has_AV_registration + has_recordings = False + if self.study.get_observation: + # gather all AV observation_registraions + recordings_observation = observation_registration.objects.filter( + description__in=["audio recording", "video recording"] + ) + # check if there is an overlap between these two QS's + if self.study.observation.registrations.all() & recordings_observation: + has_recordings = True + if self.study.get_sessions: + # gather all the tasks + all_tasks = Task.objects.filter(session__study=self.study) + # gather all AV task_registrations + recordings_sessions = task_registration.objects.filter( + description__in=["audio recording", "video recording"] + ) + if all_tasks.filter(registrations__in=recordings_sessions): + has_recordings = True + return has_recordings + def at_least_one_fulfilled(self, slots): + """ + Function which receives a list of slots and checks if at least one has + been fullfilled. It returns None, or the fullfiled slot + """ + fullfilled_slot = None + for slot in slots: + # check if any of these slots have been fullfilled yet using match() + slot.match(exclude=[]) + if slot.attachment: + fullfilled_slot = slot + return fullfilled_slot class ParticipantsChecker( @@ -904,6 +992,7 @@ def check( self, ): self.add_dmp_slot() + self.add_school_slots() item = self.make_stepper_item() self.stepper.items.append(item) return [ @@ -920,6 +1009,26 @@ def add_dmp_slot(self): ) self.stepper.add_slot(slot) + def add_school_slots(self): + studies_with_schools = [ + study + for study in self.proposal.study_set.all() + if study.research_settings_contains_schools() + ] + if studies_with_schools: + self.stepper.add_slot( + AttachmentSlot( + self.stepper.proposal, + kind=SchoolInformationLetter, + ) + ) + self.stepper.add_slot( + AttachmentSlot( + self.stepper.proposal, + kind=SchoolConsentForm, + ) + ) + def make_stepper_item(self): url = reverse( "proposals:attachments", From 4b27c6df550e51816e4a5fc4f1f102b9074aa68f Mon Sep 17 00:00:00 2001 From: Edo Storm Date: Thu, 7 Nov 2024 10:32:02 +0100 Subject: [PATCH 07/22] feat: implement navigation buttons for ProposalsAttachmentsView --- proposals/views/attachment_views.py | 21 ++++++++++++++++++++- proposals/views/proposal_views.py | 4 ++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/proposals/views/attachment_views.py b/proposals/views/attachment_views.py index 48d00160..7cfc9b18 100644 --- a/proposals/views/attachment_views.py +++ b/proposals/views/attachment_views.py @@ -2,6 +2,7 @@ from django import forms from django.urls import reverse from django import forms +from main.views import UpdateView from proposals.mixins import ProposalContextMixin from proposals.models import Proposal from studies.models import Study @@ -218,14 +219,26 @@ class AttachmentDetailView( template_name = "proposals/attachment_detail.html" model = Attachment +class ProposalAttachmentsForm( + forms.ModelForm, +): + """ + An empty form, needed to make the navigation work. + """ + class Meta: + model = Proposal + fields = [] + class ProposalAttachmentsView( ProposalContextMixin, - generic.DetailView, + UpdateView, ): template_name = "proposals/attachments.html" model = Proposal + #this form does not do anything, it's just here to make navigation work + form_class = ProposalAttachmentsForm def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) @@ -242,6 +255,12 @@ def get_context_data(self, **kwargs): context["study_slots"] = study_slots context["proposal_slots"] = proposal_slots return context + + def get_next_url(self): + return reverse("proposals:translated", args=(self.object.pk,)) + + def get_back_url(self): + return reverse("proposals:knowledge_security", args=(self.object.pk,)) class ProposalAttachmentDownloadView( diff --git a/proposals/views/proposal_views.py b/proposals/views/proposal_views.py index 4b27bdde..f3f48adf 100644 --- a/proposals/views/proposal_views.py +++ b/proposals/views/proposal_views.py @@ -491,7 +491,7 @@ class ProposalKnowledgeSecurity( template_name = "proposals/knowledge_security_form.html" def get_next_url(self): - return reverse("proposals:consent", args=(self.object.pk,)) + return reverse("proposals:attachments", args=(self.object.pk,)) def get_back_url(self): return reverse("studies:design_end", args=(self.object.last_study().pk,)) @@ -508,7 +508,7 @@ def get_next_url(self): def get_back_url(self): """Return to the overview of the last Study""" - return reverse("proposals:consent", args=(self.object.pk,)) + return reverse("proposals:attachments", args=(self.object.pk,)) class ProposalDataManagement(ProposalContextMixin, UpdateView): From fc848fcb2aca6c4e00c029891d74d5a4d9b7d190 Mon Sep 17 00:00:00 2001 From: Edo Storm Date: Thu, 7 Nov 2024 11:03:41 +0100 Subject: [PATCH 08/22] feature: a lotta translations --- locale/en/LC_MESSAGES/django.po | 459 ++++++++++++++++++++++++++------ 1 file changed, 383 insertions(+), 76 deletions(-) diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po index 6c714ad2..b63070b3 100644 --- a/locale/en/LC_MESSAGES/django.po +++ b/locale/en/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-22 09:51+0200\n" +"POT-Creation-Date: 2024-11-07 10:32+0100\n" "PO-Revision-Date: 2024-04-03 12:32+0200\n" "Last-Translator: Anna Asbury \n" "Language-Team: \n" @@ -17,6 +17,241 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.4.1\n" +#: attachments/kinds.py:30 +msgid "Informatiebrief anoniem onderzoek" +msgstr "Information letter anonymous research" + +#: attachments/kinds.py:32 +msgid "" +"Je verzamelt en verwerkt de gegevens van je deelnemers anoniem. Je moet je " +"deelnemers dan wél informeren op ethische gronden (zodat ze kunnen beslissen " +"of ze vrijwillig willen meedoen), maar omdat de AVG niet van toepassing is " +"op anonieme gegevens, hoef je geen informatie te verstrekken over de " +"verwerking van persoonsgegevens." +msgstr "" +"You collect and process your participants' data anonymously. You do have " +"to inform your participants on ethical grounds (so they can decide if they " +"want to participate voluntarily), but because the GDPR does not apply to " +"anonymous data, you do not have to provide information about the processing " +"of personal data." + +#: attachments/kinds.py:46 +msgid "Informatiebrief algemeen belang" +msgstr "Information letter public interest" + +#: attachments/kinds.py:48 +msgid "" +"Je kiest ervoor om de verwerking van persoonsgegevens te baseren op het " +"algemeen belang. In beginsel is dit de standaardwerkwijze. \n" +"Let op! Voor bepaalde aspecten van je onderzoek kan het desondanks nodig " +"zijn om toestemming te vragen." +msgstr "" +"You choose to process personal data on the legal basis public interest. " +"In principle, this is the standard operating procedure. \n" +"Please note! Certain aspects of your research may nevertheless require you " +"to obtain consent. Whether this is the case is indicated in the information letter below." + +#: attachments/kinds.py:60 +msgid "Informatiebrief toestemming" +msgstr "Information letter consent" + +#: attachments/kinds.py:62 +msgid "" +"Er zijn redenen om de verwerking van persoonsgegevens te baseren op " +"toestemming van de deelnemers. Bijvoorbeeld als er gevoelige data wordt " +"verzameld of er met minderjarigen wordt gewerkt." +msgstr "There are reasons to base the processing of personal data on " +"participant consent. Such reasons could be if you are processing sensitive " +"data, or are working with minors." + +#: attachments/kinds.py:84 +msgid "Toestemmingsverklaring" +msgstr "Declaration of consent" + +#: attachments/kinds.py:86 +msgid "" +"Je baseert de verwerking van persoonsgegevens binnen je onderzoek op de " +"wettelijke grondslag toestemming. De deelnemers zijn volwassenen (16 jaar en " +"ouder)." +msgstr "" +"You base the processing of personal data within your research on the legal " +"basis consent. Participants are adults (16 years and older)." + +#: attachments/kinds.py:95 +msgid "Toestemmingsverklaring algemeen belang bijzondere persoonsgegevens" +msgstr "Declaration of consent public interest special categories of data" + +#: attachments/kinds.py:97 +msgid "" +"Je baseert de verwerking van persoonsgegevens binnen je onderzoek weliswaar " +"op de wettelijke grondslag algemeen belang, maar je verzamelt zgn. " +"bijzondere persoonsgegevens externe link en daarvoor heb je toestemming " +"nodig." +msgstr "" +"Although you base the processing of personal data within your research on " +"the legal basis public interest, you collect so-called special categories " +"of personal data external link and for that you need consent." + +#: attachments/kinds.py:108 +msgid "Toestemmingsverklaring kinderen tot 16 jaar, ouders of voogden aanwezig" +msgstr "Declaration of consent children up to the age of 16, parents or caregivers present" + +#: attachments/kinds.py:110 +msgid "" +"Je baseert de verwerking van persoonsgegevens binnen je onderzoek op de " +"wettelijke grondslag toestemming. De deelnemers zijn kinderen jonger dan 16 " +"jaar en minimaal één van de ouders of voogden is bij het onderzoek aanwezig." +msgstr "" +"You base the processing of personal data within your research on the legal " +"basis consent. Your participants are children under the age of 16 and at " +"least one of the parents or guardians is present during the research." + +#: attachments/kinds.py:121 +msgid "Toestemmingsverklaring kinderen tot 16 jaar, ouders of voogden afwezig" +msgstr "Declaration of consent children up to the age of 16, no parents or caregivers present" + + +#: attachments/kinds.py:123 +msgid "" +"Je baseert de verwerking van persoonsgegevens binnen je onderzoek op de " +"wettelijke grondslag toestemming. De deelnemers zijn kinderen jonger dan 16 " +"jaar en er zijn geen ouders of voodgen aanwezig." +msgstr "" +"You base the processing of personal data within your research on the legal " +"basis consent. Your participants are children under the age of 16 and no " +"parents or guardians are present during the research." + +#: attachments/kinds.py:138 +msgid "Akkoordverklaring beeld- en geluidsopnames algemeen belang" +msgstr "Agreement video- or audiorecordings public interest" + +#: attachments/kinds.py:140 +msgid "" +"Je baseert de verwerking van persoonsgegevens weliswaar op de wettelijke " +"grondslag algemeen belang, maar je maakt beeld- en/of geluidsopnames en daar " +"moeten je deelnemers op ethische gronden mee instemmen. Ook voor het verdere " +"gebruik van die opnames kun je de afspraken schriftelijk vastleggen." +msgstr "" +"Although you base the processing of personal data on the legal basis " +"public interest, you make video and/or audio recordings and for that you " +"need consent. For the further use of those recordings, you can also put agreements in writing." + +#: attachments/kinds.py:152 +msgid "Script voor mondelinge toestemming opnames" +msgstr "Script for verbal consent recordings" + +#: attachments/kinds.py:154 +msgid "" +"Je interviewt deelnemers en je maakt daarvan beeld- en/of geluidsopnames. De " +"toestemming daarvoor, en de eventuele toestemming en afspraken met " +"betrekking tot andere aspecten van de verwerking van persoonsgegevens, leg " +"je vast in een aparte opname." +msgstr "" +"You interview participants and make video and/or audio recordings of them. " +"You record consent for this, and any consent and agreements regarding other " +"aspects of the processing of personal data, in a separate recording." + +#: attachments/kinds.py:169 +msgid "Informatiebrief gatekeeper/schoolleiding" +msgstr "Information letter gatekeeper/schoolmanagement" + +#: attachments/kinds.py:171 +msgid "" +"Je wilt onderzoek gaan doen binnen een bepaalde instelling (bijv. een " +"school) en je verzoekt de leiding van die instelling om medewerking. Voor " +"het maken van een geïnformeerde keuze moet de leiding van de instelling op " +"de hoogte zijn van de opzet van je onderzoek en van allerlei praktische " +"aspecten." +msgstr "" +"You want to conduct research within a particular institution (e.g., a school) " +"and you request the cooperation of the management of that institution. " +"To make an informed choice, the management of that institution must be aware " +"of the design of your research and a variety of practical aspects. " + +#: attachments/kinds.py:183 +msgid "Akkoordverklaring gatekeeper/schoolleiding" +msgstr "Declaration of cooperation gatekeeper/schoolmanagement" + +#: attachments/kinds.py:185 +msgid "" +"Je wilt onderzoek gaan doen binnen een bepaalde instelling (bijv. een " +"school) en je verzoekt de leiding van die instelling om medewerking. De " +"schoolleiding moet, na goed geïnformeerd te zijntoestemming geven voor het " +"onderzoek." +msgstr "" +"You want to conduct research within a particular institution (e.g., a school) " +"and you request the cooperation of the management of that institution. " +"The school management must, after having been properly informed, give consent" +"to the students' participation in the research." + +#: attachments/kinds.py:200 +#: proposals/templates/proposals/proposal_data_management.html:17 +#: proposals/utils/pdf_diff_logic.py:980 +#: reviews/templatetags/documents_list.py:224 +msgid "Data Management Plan" +msgstr "Data Management Plan" + +#: attachments/kinds.py:201 +msgid "Omschrijving DMP" +msgstr "description DMP" + +#: attachments/kinds.py:210 +msgid "Overige bestanden" +msgstr "Other attachments" + +#: attachments/kinds.py:211 +msgid "Voor alle overige soorten bestanden" +msgstr "For all other attachments" + +#: attachments/models.py:22 +msgid "Bestand" +msgstr "File" + +#: attachments/models.py:23 +msgid "Selecteer hier het bestand om toe te voegen." +msgstr "Select a file to upload." + +#: attachments/models.py:40 +msgid "Gelieve selecteren" +msgstr "Please select" + +#: attachments/models.py:46 +msgid "Geef je bestand een omschrijvende naam, het liefst maar enkele woorden." +msgstr "Give your file a descriptive name, preferably a short one." + +#: attachments/models.py:53 +msgid "" +"Geef hier optioneel je motivatie om dit bestand toe te voegen en waar je het " +"voor gaat gebruiken tijdens je onderzoek. Eventuele opmerkingen voor de FETC " +"kun je hier ook kwijt." +msgstr "" +"Optionally, provide your motivation for uploading this file and what you " +"will be using it for. Other remarks for the FETC can also be provided here." + +#: attachments/templates/attachments/slot.html:16 +msgid "Wijzig" +msgstr "Edit" + +#: attachments/templates/attachments/slot.html:18 +msgid "Voeg toe" +msgstr "Upload" + +#: attachments/utils.py:11 +msgid "Verplicht" +msgstr "Required" + +#: attachments/utils.py:12 +msgid "Aangeraden" +msgstr "Recommended" + +#: attachments/utils.py:13 +msgid "Optioneel" +msgstr "Optional" + +#: attachments/utils.py:14 +msgid "Extra" +msgstr "Extra" + #: faqs/menus.py:7 main/templates/main/index.html:130 msgid "FETC-GW website" msgstr "FEtC-H website" @@ -63,11 +298,11 @@ msgstr "FAQ" msgid "Frequently Asked Questions" msgstr "Frequently Asked Questions" -#: fetc/settings.py:135 +#: fetc/settings.py:137 msgid "Nederlands" msgstr "Dutch" -#: fetc/settings.py:136 +#: fetc/settings.py:138 msgid "Engels" msgstr "English" @@ -612,7 +847,7 @@ msgid "Nieuw amendement starten" msgstr "Create new amendment" #: main/templates/main/index.html:90 proposals/menus.py:112 -#: proposals/views/proposal_views.py:190 +#: proposals/views/proposal_views.py:189 msgid "Archief" msgstr "Archive" @@ -1271,23 +1506,23 @@ msgstr "New application" msgid "Al mijn aanvragen" msgstr "All my applications" -#: proposals/menus.py:58 proposals/views/proposal_views.py:103 +#: proposals/menus.py:58 proposals/views/proposal_views.py:102 msgid "Mijn conceptaanvragen" msgstr "My draft applications" -#: proposals/menus.py:62 proposals/views/proposal_views.py:162 +#: proposals/menus.py:62 proposals/views/proposal_views.py:161 msgid "Mijn oefenaanvragen" msgstr "My practice applications" -#: proposals/menus.py:66 proposals/views/proposal_views.py:117 +#: proposals/menus.py:66 proposals/views/proposal_views.py:116 msgid "Mijn ingediende aanvragen" msgstr "My submitted applications" -#: proposals/menus.py:70 proposals/views/proposal_views.py:131 +#: proposals/menus.py:70 proposals/views/proposal_views.py:130 msgid "Mijn afgehandelde aanvragen" msgstr "My processed applications" -#: proposals/menus.py:74 proposals/views/proposal_views.py:145 +#: proposals/menus.py:74 proposals/views/proposal_views.py:144 msgid "Mijn aanvragen als eindverantwoordelijke" msgstr "My supervised applications" @@ -1818,6 +2053,79 @@ msgstr "Please upload the decision of METC (in .pdf or .doc(x)-format) here" msgid "WMO {title}, status {status}" msgstr "WMO {title}, status {status}" +#: proposals/templates/proposals/attach_form.html:7 +msgid "Voeg een bestand toe" +msgstr "Upload a file" + +#: proposals/templates/proposals/attach_form.html:11 +msgid "Maak of wijzig een bestand" +msgstr "Create of edit a file" + +#: proposals/templates/proposals/attach_form.html:14 +msgid "Je voegt een bestand toe aan het volgende:" +msgstr "You are adding an attachment to the following:" + +#: proposals/templates/proposals/attach_form.html:18 +msgid "Je bewerkt het volgende bestand:" +msgstr "You are editing the following attachment:" + +#: proposals/templates/proposals/attach_form.html:22 +msgid "Dit bestand is gekoppeld aan het volgende:" +msgstr "This file is attached to the following:" + +#: proposals/templates/proposals/attach_form.html:29 +msgid "Traject %(order)s: %(name)s van" +msgstr "Trajectory %(order)s (%(name)s)" + +#: proposals/templates/proposals/attach_form.html:33 +msgid "de aanvraag" +msgstr "the application" + +#: proposals/templates/proposals/attach_form.html:36 +#, python-format +msgid "" +"Je gaat hier een %(name)s aan toevoegen. Wil je een ander soort bestand " +"toevoegen? Ga dan terug naar de vorige pagina." +msgstr "" +"You are about to add a %(name)s. If you are looking to upload a different " +"type of attachment, please return to the previous page." + +#: proposals/templates/proposals/attach_form.html:47 +#: proposals/templates/proposals/detach_form.html:29 +msgid "<< Ga terug" +msgstr "<< Go back" + +#: proposals/templates/proposals/attach_form.html:52 +msgid "Bestand verwijderen" +msgstr "Delete file" + +#: proposals/templates/proposals/attach_form.html:58 +msgid "Opslaan" +msgstr "Save" + +#: proposals/templates/proposals/attachments.html:7 +#: proposals/templates/proposals/other_researchers_form.html:7 +#: proposals/templates/proposals/other_researchers_form.html:21 +#: proposals/utils/proposal_utils.py:60 +msgid "Informatie over betrokken onderzoekers" +msgstr "Information about other researchers" + +#: proposals/templates/proposals/attachments.html:11 +#: proposals/utils/checkers.py:1039 proposals/utils/stepper.py:226 +#: reviews/templates/reviews/review_detail_sidebar.html:124 +msgid "Documenten" +msgstr "Documents" + +#: proposals/templates/proposals/attachments.html:12 +msgid "Algemeen" +msgstr "General" + +#: proposals/templates/proposals/attachments.html:19 +#: proposals/utils/pdf_diff_logic.py:319 proposals/utils/pdf_diff_logic.py:346 +#: proposals/utils/pdf_diff_logic.py:355 proposals/utils/pdf_diff_logic.py:379 +msgid "Traject " +msgstr "Trajectory " + #: proposals/templates/proposals/compare_documents.html:8 #: proposals/templates/proposals/compare_documents.html:50 msgid "Vergelijk documenten" @@ -1865,6 +2173,34 @@ msgstr "Old" msgid "Nieuw" msgstr "New" +#: proposals/templates/proposals/detach_form.html:7 +#: proposals/templates/proposals/detach_form.html:11 +msgid "Verwijder een bestand" +msgstr "Delete a file" + +#: proposals/templates/proposals/detach_form.html:13 +msgid "Je verwijdert het volgende bestand:" +msgstr "You are deleting the following file:" + +#: proposals/templates/proposals/detach_form.html:19 +msgid "" +"Als je een nieuwe versie van dit document wil aanleveren, verwijder het dan " +"niet, maar ga dan terug naar de vorige pagina en wijzig het daar. Zo blijft " +"de geschiedenis van het document bewaard, en dat vergemakkelijkt het " +"beoordeelproces aanzienlijk." +msgstr "" +"If you would like to upload a new version of this file, do not delete it, but" +"return to the previous page and edit it. This ensures the document's history" +"will persist and significantly eases the review process." + +#: proposals/templates/proposals/detach_form.html:34 +#: proposals/templates/proposals/proposal_confirm_delete.html:22 +#: proposals/templates/proposals/vue_templates/proposal_list.html:66 +#: tasks/templates/tasks/session_confirm_delete.html:22 +#: tasks/templates/tasks/task_confirm_delete.html:22 +msgid "Verwijderen" +msgstr "Delete" + #: proposals/templates/proposals/funding_form.html:7 #: proposals/templates/proposals/funding_form.html:21 #: proposals/utils/proposal_utils.py:68 @@ -1876,12 +2212,6 @@ msgstr "Funding information" msgid "Afronding trajecten" msgstr "Trajectories conclusion" -#: proposals/templates/proposals/other_researchers_form.html:7 -#: proposals/templates/proposals/other_researchers_form.html:21 -#: proposals/utils/proposal_utils.py:60 -msgid "Informatie over betrokken onderzoekers" -msgstr "Information about other researchers" - #: proposals/templates/proposals/practice_or_supervisor_warning.html:7 msgid "" "Je past nu een aanvraag aan van een student/PhD kandidaat onder jouw " @@ -1919,13 +2249,6 @@ msgstr "Delete application" msgid "Weet je zeker dat je de aanvraag %(title)s wilt verwijderen?" msgstr "Are you sure you want to delete the application %(title)s?" -#: proposals/templates/proposals/proposal_confirm_delete.html:22 -#: proposals/templates/proposals/vue_templates/proposal_list.html:66 -#: tasks/templates/tasks/session_confirm_delete.html:22 -#: tasks/templates/tasks/task_confirm_delete.html:22 -msgid "Verwijderen" -msgstr "Delete" - #: proposals/templates/proposals/proposal_confirm_delete.html:23 #: proposals/templates/proposals/proposal_copy.html:93 #: tasks/templates/tasks/session_confirm_delete.html:23 @@ -2049,7 +2372,7 @@ msgid "Kopiëren" msgstr "Copy" #: proposals/templates/proposals/proposal_data_management.html:7 -#: proposals/utils/proposal_utils.py:136 proposals/utils/stepper.py:216 +#: proposals/utils/proposal_utils.py:136 proposals/utils/stepper.py:227 msgid "Datamanagement" msgstr "Data management" @@ -2069,12 +2392,6 @@ msgstr "" "introduction of the GDPR there are clear rules which researchers should " "follow with regard to data." -#: proposals/templates/proposals/proposal_data_management.html:17 -#: proposals/utils/pdf_diff_logic.py:980 -#: reviews/templatetags/documents_list.py:224 -msgid "Data Management Plan" -msgstr "Data Management Plan" - #: proposals/templates/proposals/proposal_data_management.html:20 msgid "" "Een data management plan is sinds 2020 Date: Thu, 7 Nov 2024 11:24:55 +0100 Subject: [PATCH 09/22] style: black sabbath --- attachments/kinds.py | 6 ++++++ proposals/views/attachment_views.py | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/attachments/kinds.py b/attachments/kinds.py index 4b90c127..4d6a570a 100644 --- a/attachments/kinds.py +++ b/attachments/kinds.py @@ -24,6 +24,7 @@ class StudyAttachmentKind(AttachmentKind): # Information letters ##################### + class InformationLetterAnonymous(StudyAttachmentKind): db_name = "information_letter_anonymous" @@ -78,6 +79,7 @@ class InformationLetterConsent(StudyAttachmentKind): # Consent forms ############### + class ConsentForm(StudyAttachmentKind): db_name = "consent_form" @@ -89,6 +91,7 @@ class ConsentForm(StudyAttachmentKind): ) desiredness = desiredness.REQUIRED + class ConsentPublicInterestSpecialDetails(StudyAttachmentKind): db_name = "consent_public_interest_special_details" @@ -132,6 +135,7 @@ class ConsentChildrenNoParents(StudyAttachmentKind): # Recordings consent #################### + class AgreementRecordingsPublicInterest(StudyAttachmentKind): db_name = "agreement_av_recordings" @@ -163,6 +167,7 @@ class ScriptVerbalConsentRecordings(StudyAttachmentKind): # School stuff ############## + class SchoolInformationLetter(ProposalAttachmentKind): db_name = "school_information_letter" @@ -194,6 +199,7 @@ class SchoolConsentForm(ProposalAttachmentKind): # Other stuff ############# + class DataManagementPlan(ProposalAttachmentKind): db_name = "dmp" diff --git a/proposals/views/attachment_views.py b/proposals/views/attachment_views.py index 7c0bb8e9..ac9f5b1c 100644 --- a/proposals/views/attachment_views.py +++ b/proposals/views/attachment_views.py @@ -221,12 +221,14 @@ class AttachmentDetailView( template_name = "proposals/attachment_detail.html" model = Attachment + class ProposalAttachmentsForm( forms.ModelForm, ): """ An empty form, needed to make the navigation work. """ + class Meta: model = Proposal fields = [] @@ -239,7 +241,7 @@ class ProposalAttachmentsView( template_name = "proposals/attachments.html" model = Proposal - #this form does not do anything, it's just here to make navigation work + # this form does not do anything, it's just here to make navigation work form_class = ProposalAttachmentsForm def get_context_data(self, **kwargs): @@ -257,7 +259,7 @@ def get_context_data(self, **kwargs): context["study_slots"] = study_slots context["proposal_slots"] = proposal_slots return context - + def get_next_url(self): return reverse("proposals:translated", args=(self.object.pk,)) From 91d56d0059976e30d8c089b966a411df22569dfd Mon Sep 17 00:00:00 2001 From: Michael Villeneuve Date: Wed, 13 Nov 2024 10:01:46 +0100 Subject: [PATCH 10/22] fix: Make get_kind_from_str resilient to unknown kinds --- attachments/utils.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/attachments/utils.py b/attachments/utils.py index 769c94aa..8242a9c3 100644 --- a/attachments/utils.py +++ b/attachments/utils.py @@ -142,7 +142,10 @@ def get_edit_url( def get_kind_from_str(db_name): - from attachments.kinds import ATTACHMENTS + from attachments.kinds import ATTACHMENTS, OtherProposalAttachment kinds = {kind.db_name: kind for kind in ATTACHMENTS} - return kinds[db_name] + try: + return kinds[db_name] + except KeyError: + return OtherProposalAttachment From 004491ae7abc283287a85954e7e880c2d6f0571e Mon Sep 17 00:00:00 2001 From: Michael Villeneuve Date: Wed, 13 Nov 2024 10:19:53 +0100 Subject: [PATCH 11/22] feat: Rename OtherProposalAttachment --- attachments/kinds.py | 4 ++-- attachments/utils.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/attachments/kinds.py b/attachments/kinds.py index 96c001e7..7f27fa8d 100644 --- a/attachments/kinds.py +++ b/attachments/kinds.py @@ -210,7 +210,7 @@ def num_recommended(self): return 1 -class OtherProposalAttachment(ProposalAttachmentKind): +class OtherAttachment(ProposalAttachmentKind): db_name = "other" name = _("Overig bestand") @@ -241,7 +241,7 @@ def num_suggested(self): SchoolInformationLetter, SchoolConsentForm, DataManagementPlan, - OtherProposalAttachment, + OtherAttachment, ] ATTACHMENTS = PROPOSAL_ATTACHMENTS + STUDY_ATTACHMENTS diff --git a/attachments/utils.py b/attachments/utils.py index 8242a9c3..2a5ead23 100644 --- a/attachments/utils.py +++ b/attachments/utils.py @@ -142,10 +142,10 @@ def get_edit_url( def get_kind_from_str(db_name): - from attachments.kinds import ATTACHMENTS, OtherProposalAttachment + from attachments.kinds import ATTACHMENTS, OtherAttachment kinds = {kind.db_name: kind for kind in ATTACHMENTS} try: return kinds[db_name] except KeyError: - return OtherProposalAttachment + return OtherAttachment From 9a94224f1a5026ce507e73619745534a1b63778a Mon Sep 17 00:00:00 2001 From: Michael Villeneuve Date: Wed, 13 Nov 2024 12:56:27 +0100 Subject: [PATCH 12/22] feat: Optionality groups for attachment slots --- .../attachments/optionality_group.html | 11 +++++ attachments/utils.py | 49 +++++++++++++++++++ proposals/utils/checkers.py | 8 ++- proposals/views/attachment_views.py | 7 ++- 4 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 attachments/templates/attachments/optionality_group.html diff --git a/attachments/templates/attachments/optionality_group.html b/attachments/templates/attachments/optionality_group.html new file mode 100644 index 00000000..763d4355 --- /dev/null +++ b/attachments/templates/attachments/optionality_group.html @@ -0,0 +1,11 @@ +{% load i18n %} + +
+
{% blocktrans trimmed with count=group.count%} + Een van deze {{ count }} documenten is voldoende + {% endblocktrans %} +
+ {% for slot in group.members %} + {% include slot %} + {% endfor %} +
diff --git a/attachments/utils.py b/attachments/utils.py index 2a5ead23..c3dae8b1 100644 --- a/attachments/utils.py +++ b/attachments/utils.py @@ -35,11 +35,15 @@ def __init__( attachment=None, kind=None, force_desiredness=None, + optionality_group=None, ): self.attachment = attachment self.attached_object = attached_object self.kind = kind self.force_desiredness = force_desiredness + self.optionality_group = optionality_group + if self.optionality_group: + self.optionality_group.members.add(self) def match(self, exclude): """ @@ -140,6 +144,51 @@ def get_edit_url( }, ) +class OptionalityGroup(renderable): + + template_name = "attachments/optionality_group.html" + + def __init__(self, members=set()): + self.members = set(members) + + @property + def count(self,): + return len(self.members) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["group"] = self + return context + +def merge_groups(slots): + """ + Takes a list of slots and merges slots that belong to the same + optionality group together. This results in a mixed output list + of bare slots and optionality groups. + """ + grouped = [] + for slot in slots: + if not slot.optionality_group: + # No group, so we just append it + grouped.append(slot) + continue + if slot.optionality_group not in grouped: + # We only append the group if it's not already in the + # output list to avoid duplication + grouped.append(slot.optionality_group) + # Final pass to remove single-member groups + out = [] + for item in grouped: + if type(item) is OptionalityGroup: + if item.count < 2: + # If we have fewer than two members, we just append + # the members. Addition allows for the empty list edge + # case to work. + out += item.members + continue + out.append(item) + return out + def get_kind_from_str(db_name): from attachments.kinds import ATTACHMENTS, OtherAttachment diff --git a/proposals/utils/checkers.py b/proposals/utils/checkers.py index 92d05efd..e87c4e28 100644 --- a/proposals/utils/checkers.py +++ b/proposals/utils/checkers.py @@ -14,7 +14,7 @@ from tasks.views import task_views, session_views from tasks.models import Task, Session -from attachments.utils import AttachmentSlot, desiredness +from attachments.utils import AttachmentSlot, desiredness, OptionalityGroup from attachments.kinds import ( DataManagementPlan, LEGAL_BASIS_KIND_DICT, @@ -500,14 +500,17 @@ def check( if self.check_has_recordings(): # if a study features registration, add two slots + recording_group = OptionalityGroup() recordings_slots = [ AttachmentSlot( self.study, kind=AgreementRecordingsPublicInterest, + optionality_group=recording_group, ), AttachmentSlot( self.study, kind=ScriptVerbalConsentRecordings, + optionality_group=recording_group, ), ] # if one of them has been fulfilled, this becomes the fulfilled slot @@ -533,14 +536,17 @@ def check( if self.study.legal_basis == Study.LegalBases.CONSENT: fulfilled_children_slot = None if self.study.has_children(): + child_group = OptionalityGroup() children_slots = [ AttachmentSlot( self.study, kind=ConsentChildrenParents, + optionality_group=child_group, ), AttachmentSlot( self.study, kind=ConsentChildrenNoParents, + optionality_group=child_group, ), ] diff --git a/proposals/views/attachment_views.py b/proposals/views/attachment_views.py index 91acabe8..2a00f695 100644 --- a/proposals/views/attachment_views.py +++ b/proposals/views/attachment_views.py @@ -13,7 +13,7 @@ from cdh.core import forms as cdh_forms from django.http import FileResponse from attachments.kinds import ATTACHMENTS, KIND_CHOICES -from attachments.utils import AttachmentKind +from attachments.utils import AttachmentKind, merge_groups from cdh.core import forms as cdh_forms from django.utils.translation import gettext as _ from reviews.mixins import UsersOrGroupsAllowedMixin @@ -299,8 +299,11 @@ def get_context_data(self, **kwargs): for slot in all_slots: if type(slot.attached_object) is Study: study_slots[slot.attached_object].append(slot) + # Final step to merge optionality groups + for obj, slots in study_slots.items(): + study_slots[obj] = merge_groups(slots) context["study_slots"] = study_slots - context["proposal_slots"] = proposal_slots + context["proposal_slots"] = merge_groups(proposal_slots) return context def get_next_url(self): From 465d10f18166ad58cbe41a9909a9c4e8a45c9058 Mon Sep 17 00:00:00 2001 From: Michael Villeneuve Date: Wed, 13 Nov 2024 12:56:48 +0100 Subject: [PATCH 13/22] feat: Render help texts next to slots --- attachments/kinds.py | 1 + attachments/templates/attachments/slot.html | 40 ++++++++++------- .../templates/proposals/attachments.html | 45 ++++++++++--------- 3 files changed, 49 insertions(+), 37 deletions(-) diff --git a/attachments/kinds.py b/attachments/kinds.py index 7f27fa8d..582624b1 100644 --- a/attachments/kinds.py +++ b/attachments/kinds.py @@ -205,6 +205,7 @@ class DataManagementPlan(ProposalAttachmentKind): db_name = "dmp" name = _("Data Management Plan") description = _("Omschrijving DMP") + desiredness = desiredness.RECOMMENDED def num_recommended(self): return 1 diff --git a/attachments/templates/attachments/slot.html b/attachments/templates/attachments/slot.html index d78ecafa..12d20809 100644 --- a/attachments/templates/attachments/slot.html +++ b/attachments/templates/attachments/slot.html @@ -1,21 +1,27 @@ {% load i18n %} -
-
{{ slot.desiredness }}
-
-
{{ slot.kind.name }}
- {% if slot.attachment %} - {% include slot.attachment with proposal=proposal %} - {% else %} - {% trans "Nog toe te voegen" %} - {% endif %} - {{ kind.reason }} -
-
- {% if slot.attachment %} - {% trans "Wijzig" %} - {% else %} - {% trans "Voeg toe" %} - {% endif %} +
+
+
+
{{ slot.desiredness }}
+
+
{{ slot.kind.name }}
+ {% if slot.attachment %} + {% include slot.attachment with proposal=proposal %} + {% else %} + {% trans "Nog toe te voegen" %} + {% endif %} + {{ kind.reason }} +
+
+ {% if slot.attachment %} + {% trans "Wijzig" %} + {% else %} + {% trans "Voeg toe" %} + {% endif %} +
+
+
+
Meer info{{ slot.kind.description }}
diff --git a/proposals/templates/proposals/attachments.html b/proposals/templates/proposals/attachments.html index 391d6bf8..3799d58e 100644 --- a/proposals/templates/proposals/attachments.html +++ b/proposals/templates/proposals/attachments.html @@ -9,32 +9,37 @@ {% block pre-form-text %}

{% trans "Documenten" %}

-

{% trans "Algemeen" %}

- {% for slot in proposal_slots %} - {% include slot %} - {% endfor %} -
+ {% endblock %} + {% block auto-form-render %} +

{% trans "Algemeen" %}

+ {% for slot in proposal_slots %} + {% include slot %} + {% endfor %} + {% for study, slots in study_slots.items %} -

- {% trans "Traject " %} {{ study.order }} - {% if study.name %}: {{ study.name }}{% endif %} -

- {% for slot in slots %} - {% include slot with manager=manager %} +

+ {% trans "Traject " %} {{ study.order }} + {% if study.name %}: {{ study.name }}{% endif %} +

+ {% for slot in slots %} + {% include slot with manager=manager %} + {% endfor %} + {% endfor %} - - {% endfor %} - {% block auto-form-render %}{% endblock %} {% endblock %} From 661b418ef9948e33c5054c3ee0f55db21e72f2af Mon Sep 17 00:00:00 2001 From: Michael Villeneuve Date: Wed, 13 Nov 2024 13:36:30 +0100 Subject: [PATCH 14/22] style: Black and djlint --- .../attachments/optionality_group.html | 5 +- attachments/templates/attachments/slot.html | 8 ++- attachments/utils.py | 6 +- .../templates/proposals/attach_form.html | 2 +- .../templates/proposals/attachments.html | 55 ++++++++++--------- 5 files changed, 45 insertions(+), 31 deletions(-) diff --git a/attachments/templates/attachments/optionality_group.html b/attachments/templates/attachments/optionality_group.html index 763d4355..3bf33072 100644 --- a/attachments/templates/attachments/optionality_group.html +++ b/attachments/templates/attachments/optionality_group.html @@ -1,8 +1,9 @@ {% load i18n %}
-
{% blocktrans trimmed with count=group.count%} - Een van deze {{ count }} documenten is voldoende +
+ {% blocktrans trimmed with count=group.count %} + Een van deze {{ count }} documenten is voldoende {% endblocktrans %}
{% for slot in group.members %} diff --git a/attachments/templates/attachments/slot.html b/attachments/templates/attachments/slot.html index 12d20809..1767d83d 100644 --- a/attachments/templates/attachments/slot.html +++ b/attachments/templates/attachments/slot.html @@ -2,7 +2,7 @@
-
+
{{ slot.desiredness }}
{{ slot.kind.name }}
@@ -23,5 +23,9 @@
{{ slot.kind.name }}
-
Meer info{{ slot.kind.description }}
+
+ Meer info + {{ slot.kind.description }} +
+
diff --git a/attachments/utils.py b/attachments/utils.py index c3dae8b1..a235c992 100644 --- a/attachments/utils.py +++ b/attachments/utils.py @@ -144,6 +144,7 @@ def get_edit_url( }, ) + class OptionalityGroup(renderable): template_name = "attachments/optionality_group.html" @@ -152,7 +153,9 @@ def __init__(self, members=set()): self.members = set(members) @property - def count(self,): + def count( + self, + ): return len(self.members) def get_context_data(self, **kwargs): @@ -160,6 +163,7 @@ def get_context_data(self, **kwargs): context["group"] = self return context + def merge_groups(slots): """ Takes a list of slots and merges slots that belong to the same diff --git a/proposals/templates/proposals/attach_form.html b/proposals/templates/proposals/attach_form.html index 297e0ae0..c9285e30 100644 --- a/proposals/templates/proposals/attach_form.html +++ b/proposals/templates/proposals/attach_form.html @@ -39,7 +39,7 @@

{% trans "Maak of wijzig een bestand" %}

{% endblocktrans %} {% endif %} {% endif %} -

+

{% endblock %} {% block form-buttons %} diff --git a/proposals/templates/proposals/attachments.html b/proposals/templates/proposals/attachments.html index 3799d58e..7f51d46e 100644 --- a/proposals/templates/proposals/attachments.html +++ b/proposals/templates/proposals/attachments.html @@ -9,37 +9,42 @@ {% block pre-form-text %}

{% trans "Documenten" %}

- {% endblock %} - {% block auto-form-render %} -

{% trans "Algemeen" %}

- {% for slot in proposal_slots %} - {% include slot %} - {% endfor %} -
-
- - {% trans "Algemeen" %} + {% for slot in proposal_slots %} + {% include slot %} + {% endfor %} + - {% for study, slots in study_slots.items %} -

- {% trans "Traject " %} {{ study.order }} - {% if study.name %}: {{ study.name }}{% endif %} -

- {% for slot in slots %} - {% include slot with manager=manager %} - {% endfor %} -
+
+ {% for study, slots in study_slots.items %} +

+ {% trans "Traject " %} {{ study.order }} + {% if study.name %}: {{ study.name }}{% endif %} +

+ {% for slot in slots %} + {% include slot with manager=manager %} + {% endfor %} + - {% endfor %} +
+ {% endfor %} {% endblock %} From a95755e43e8d29fd12e53ecc6104cf60944704ea Mon Sep 17 00:00:00 2001 From: Edo Storm Date: Wed, 13 Nov 2024 14:48:56 +0100 Subject: [PATCH 15/22] fix: logic of slots --- proposals/utils/checkers.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/proposals/utils/checkers.py b/proposals/utils/checkers.py index e87c4e28..f36dc4fb 100644 --- a/proposals/utils/checkers.py +++ b/proposals/utils/checkers.py @@ -525,7 +525,7 @@ def check( slot.force_desiredness = desiredness.OPTIONAL self.stepper.add_slot(slot) - if self.study.has_special_details and not fulfilled_recording_slot: + elif self.study.has_special_details: self.stepper.add_slot( AttachmentSlot( self.study, @@ -557,19 +557,15 @@ def check( if fulfilled_children_slot and slot is not fulfilled_children_slot: slot.force_desiredness = desiredness.OPTIONAL self.stepper.add_slot(slot) - - # Add a slot for a normal ConsentForm - self.stepper.add_slot( - AttachmentSlot( - self.study, - kind=ConsentForm, - force_desiredness=( - desiredness.REQUIRED - if not fulfilled_children_slot - else desiredness.OPTIONAL - ), + + #if there is no children, make the normal consentform required + else: + self.stepper.add_slot( + AttachmentSlot( + self.study, + kind=ConsentForm, + ) ) - ) return [] From 4920ba3f3d64e553b4ec4e8526a95163594be040 Mon Sep 17 00:00:00 2001 From: Edo Storm Date: Wed, 13 Nov 2024 15:49:26 +0100 Subject: [PATCH 16/22] feature: implement match + match_and_set --- attachments/utils.py | 22 +++++++++++++++------- proposals/utils/checkers.py | 3 +-- proposals/utils/stepper.py | 4 ++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/attachments/utils.py b/attachments/utils.py index a235c992..1c3b0c21 100644 --- a/attachments/utils.py +++ b/attachments/utils.py @@ -45,18 +45,26 @@ def __init__( if self.optionality_group: self.optionality_group.members.add(self) - def match(self, exclude): + def match(self, exclude=[]): """ - Tries to fill this slot with an existing attachment that is not - in the exclusion set of already matched attachments. Returns True - or False depending on if the slot was succesfully matched. + Tries to find a matching attachment for this slot. If it finds one, + it returns the attachment, otherwise it returns False. """ for instance in self.get_instances_for_slot(): if instance not in exclude: - self.attachment = instance - self.kind = get_kind_from_str(instance.kind) - return True + return instance return False + + def match_and_set(self, exclude): + """ + Uses self.match() to find a matching attachment. If it finds one, it + sets self.attachment and self.kind + """ + matched_attachment = self.match(exclude=exclude) + if matched_attachment: + self.attachment = matched_attachment + self.kind = get_kind_from_str(matched_attachment.kind) + @property def classes(self): diff --git a/proposals/utils/checkers.py b/proposals/utils/checkers.py index f36dc4fb..d7a7a761 100644 --- a/proposals/utils/checkers.py +++ b/proposals/utils/checkers.py @@ -602,8 +602,7 @@ def at_least_one_fulfilled(self, slots): fullfilled_slot = None for slot in slots: # check if any of these slots have been fullfilled yet using match() - slot.match(exclude=[]) - if slot.attachment: + if slot.match(): fullfilled_slot = slot return fullfilled_slot diff --git a/proposals/utils/stepper.py b/proposals/utils/stepper.py index ff78d98c..9e4fdf79 100644 --- a/proposals/utils/stepper.py +++ b/proposals/utils/stepper.py @@ -66,7 +66,7 @@ def attachment_slots( obj, force_desiredness=desiredness.EXTRA, ) - success = empty_slot.match(exclude=exclude) + success = empty_slot.match_and_set(exclude=exclude) if success: extra_slots.append(empty_slot) return self._attachment_slots + extra_slots @@ -199,7 +199,7 @@ def add_slot(self, slot): attachments to be excluded from matching. """ exclude = [slot.attachment for slot in self._attachment_slots] - slot.match(exclude) + slot.match_and_set(exclude) self._attachment_slots.append(slot) def has_multiple_studies( From db9ea29183dce1029fc29f5519c5d00b0d0de569 Mon Sep 17 00:00:00 2001 From: Edo Storm Date: Wed, 13 Nov 2024 15:53:51 +0100 Subject: [PATCH 17/22] feat: has_adults() for Study --- studies/models.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/studies/models.py b/studies/models.py index 91866a50..70932a9b 100644 --- a/studies/models.py +++ b/studies/models.py @@ -400,6 +400,10 @@ def last_session(self): def has_children(self): """Returns whether the Study contains non-adult AgeGroups""" return self.age_groups.filter(is_adult=False).exists() + + def has_adults(self): + """Returns whether the Study contains adult AgeGroups""" + return self.age_groups.filter(is_adult=True).exists() def has_participants_below_age(self, age): """Returns whether the Study contains AgeGroups with ages below the specified age""" From 4028328d858fcbbb48170b475358eea1678a1e84 Mon Sep 17 00:00:00 2001 From: Edo Storm Date: Wed, 13 Nov 2024 15:54:12 +0100 Subject: [PATCH 18/22] feat: base ConsentForm on whether Study.has_adults() --- proposals/utils/checkers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/utils/checkers.py b/proposals/utils/checkers.py index d7a7a761..fa5fc9b7 100644 --- a/proposals/utils/checkers.py +++ b/proposals/utils/checkers.py @@ -559,7 +559,7 @@ def check( self.stepper.add_slot(slot) #if there is no children, make the normal consentform required - else: + if self.study.has_adults(): self.stepper.add_slot( AttachmentSlot( self.study, From cbb0059e6fa5b66f307b5410fcab31a946fa7efb Mon Sep 17 00:00:00 2001 From: Edo Storm Date: Wed, 13 Nov 2024 15:56:33 +0100 Subject: [PATCH 19/22] style: black betty --- attachments/utils.py | 3 +-- proposals/utils/checkers.py | 4 ++-- studies/models.py | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/attachments/utils.py b/attachments/utils.py index 1c3b0c21..036fb9af 100644 --- a/attachments/utils.py +++ b/attachments/utils.py @@ -54,7 +54,7 @@ def match(self, exclude=[]): if instance not in exclude: return instance return False - + def match_and_set(self, exclude): """ Uses self.match() to find a matching attachment. If it finds one, it @@ -65,7 +65,6 @@ def match_and_set(self, exclude): self.attachment = matched_attachment self.kind = get_kind_from_str(matched_attachment.kind) - @property def classes(self): if self.required: diff --git a/proposals/utils/checkers.py b/proposals/utils/checkers.py index fa5fc9b7..8a15abcd 100644 --- a/proposals/utils/checkers.py +++ b/proposals/utils/checkers.py @@ -557,8 +557,8 @@ def check( if fulfilled_children_slot and slot is not fulfilled_children_slot: slot.force_desiredness = desiredness.OPTIONAL self.stepper.add_slot(slot) - - #if there is no children, make the normal consentform required + + # if there is no children, make the normal consentform required if self.study.has_adults(): self.stepper.add_slot( AttachmentSlot( diff --git a/studies/models.py b/studies/models.py index 70932a9b..7232d9e2 100644 --- a/studies/models.py +++ b/studies/models.py @@ -400,7 +400,7 @@ def last_session(self): def has_children(self): """Returns whether the Study contains non-adult AgeGroups""" return self.age_groups.filter(is_adult=False).exists() - + def has_adults(self): """Returns whether the Study contains adult AgeGroups""" return self.age_groups.filter(is_adult=True).exists() From 231434926d36de69932284287f945f0bbf5930de Mon Sep 17 00:00:00 2001 From: Michael Villeneuve Date: Thu, 14 Nov 2024 17:12:01 +0100 Subject: [PATCH 20/22] fix: Give match_and_set() a return value --- attachments/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/attachments/utils.py b/attachments/utils.py index 036fb9af..8efcd1f7 100644 --- a/attachments/utils.py +++ b/attachments/utils.py @@ -64,6 +64,8 @@ def match_and_set(self, exclude): if matched_attachment: self.attachment = matched_attachment self.kind = get_kind_from_str(matched_attachment.kind) + return self.attachment + return False @property def classes(self): From 2d1e3fc30306efae53118a53e4b629915bda73ea Mon Sep 17 00:00:00 2001 From: Michael Villeneuve Date: Thu, 14 Nov 2024 17:12:14 +0100 Subject: [PATCH 21/22] fix: potential TypeError: addition of list and set --- attachments/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attachments/utils.py b/attachments/utils.py index 8efcd1f7..db583e7e 100644 --- a/attachments/utils.py +++ b/attachments/utils.py @@ -197,7 +197,7 @@ def merge_groups(slots): # If we have fewer than two members, we just append # the members. Addition allows for the empty list edge # case to work. - out += item.members + out += list(item.members) continue out.append(item) return out From 159699c4bec13025a776d326d86d0214aff0fd1b Mon Sep 17 00:00:00 2001 From: Michael Villeneuve Date: Wed, 20 Nov 2024 17:25:18 +0100 Subject: [PATCH 22/22] merge: merge translations and do a style pass --- locale/en/LC_MESSAGES/django.po | 573 +++++++++++------- .../templates/proposals/attachments.html | 7 +- 2 files changed, 348 insertions(+), 232 deletions(-) diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po index b63070b3..1e89e842 100644 --- a/locale/en/LC_MESSAGES/django.po +++ b/locale/en/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-11-07 10:32+0100\n" +"POT-Creation-Date: 2024-11-20 17:15+0100\n" "PO-Revision-Date: 2024-04-03 12:32+0200\n" "Last-Translator: Anna Asbury \n" "Language-Team: \n" @@ -17,11 +17,11 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.4.1\n" -#: attachments/kinds.py:30 +#: attachments/kinds.py:31 msgid "Informatiebrief anoniem onderzoek" -msgstr "Information letter anonymous research" +msgstr "Information about the researcher" -#: attachments/kinds.py:32 +#: attachments/kinds.py:33 msgid "" "Je verzamelt en verwerkt de gegevens van je deelnemers anoniem. Je moet je " "deelnemers dan wél informeren op ethische gronden (zodat ze kunnen beslissen " @@ -29,133 +29,108 @@ msgid "" "op anonieme gegevens, hoef je geen informatie te verstrekken over de " "verwerking van persoonsgegevens." msgstr "" -"You collect and process your participants' data anonymously. You do have " -"to inform your participants on ethical grounds (so they can decide if they " -"want to participate voluntarily), but because the GDPR does not apply to " -"anonymous data, you do not have to provide information about the processing " -"of personal data." +"You have indicated that you will collect data anonymously. Because the GDPR does not regulate the collection of anonymous data, you do not need to inform or ask for consent relating to personal data. You will however still need to inform your participants on ethical grounds, so that they can make a well-informed choice on whether to participate. " -#: attachments/kinds.py:46 +#: attachments/kinds.py:47 msgid "Informatiebrief algemeen belang" -msgstr "Information letter public interest" +msgstr "Information letter for research based on public interest" -#: attachments/kinds.py:48 +#: attachments/kinds.py:49 msgid "" "Je kiest ervoor om de verwerking van persoonsgegevens te baseren op het " "algemeen belang. In beginsel is dit de standaardwerkwijze. \n" "Let op! Voor bepaalde aspecten van je onderzoek kan het desondanks nodig " "zijn om toestemming te vragen." msgstr "" -"You choose to process personal data on the legal basis public interest. " -"In principle, this is the standard operating procedure. \n" -"Please note! Certain aspects of your research may nevertheless require you " -"to obtain consent. Whether this is the case is indicated in the information letter below." +"You have indicated to legally base your processing of personal data on the public interest. This is the recommended way to conduct research. Though you should be careful, for certain aspects of your research it may still be necessary to collect consent." -#: attachments/kinds.py:60 +#: attachments/kinds.py:61 msgid "Informatiebrief toestemming" -msgstr "Information letter consent" +msgstr "Information letter for consent-based research" -#: attachments/kinds.py:62 +#: attachments/kinds.py:63 msgid "" "Er zijn redenen om de verwerking van persoonsgegevens te baseren op " "toestemming van de deelnemers. Bijvoorbeeld als er gevoelige data wordt " "verzameld of er met minderjarigen wordt gewerkt." -msgstr "There are reasons to base the processing of personal data on " -"participant consent. Such reasons could be if you are processing sensitive " -"data, or are working with minors." +msgstr "" -#: attachments/kinds.py:84 +#: attachments/kinds.py:86 msgid "Toestemmingsverklaring" -msgstr "Declaration of consent" +msgstr "Consent form" -#: attachments/kinds.py:86 +#: attachments/kinds.py:88 msgid "" "Je baseert de verwerking van persoonsgegevens binnen je onderzoek op de " "wettelijke grondslag toestemming. De deelnemers zijn volwassenen (16 jaar en " "ouder)." msgstr "" -"You base the processing of personal data within your research on the legal " -"basis consent. Participants are adults (16 years and older)." -#: attachments/kinds.py:95 +#: attachments/kinds.py:98 msgid "Toestemmingsverklaring algemeen belang bijzondere persoonsgegevens" -msgstr "Declaration of consent public interest special categories of data" +msgstr "Declaration of consent for public interest with special personal details" -#: attachments/kinds.py:97 +#: attachments/kinds.py:100 msgid "" "Je baseert de verwerking van persoonsgegevens binnen je onderzoek weliswaar " "op de wettelijke grondslag algemeen belang, maar je verzamelt zgn. " "bijzondere persoonsgegevens externe link en daarvoor heb je toestemming " "nodig." msgstr "" -"Although you base the processing of personal data within your research on " -"the legal basis public interest, you collect so-called special categories " -"of personal data external link and for that you need consent." -#: attachments/kinds.py:108 +#: attachments/kinds.py:111 msgid "Toestemmingsverklaring kinderen tot 16 jaar, ouders of voogden aanwezig" -msgstr "Declaration of consent children up to the age of 16, parents or caregivers present" +msgstr "" -#: attachments/kinds.py:110 +#: attachments/kinds.py:113 msgid "" "Je baseert de verwerking van persoonsgegevens binnen je onderzoek op de " "wettelijke grondslag toestemming. De deelnemers zijn kinderen jonger dan 16 " "jaar en minimaal één van de ouders of voogden is bij het onderzoek aanwezig." msgstr "" -"You base the processing of personal data within your research on the legal " -"basis consent. Your participants are children under the age of 16 and at " -"least one of the parents or guardians is present during the research." -#: attachments/kinds.py:121 +#: attachments/kinds.py:124 msgid "Toestemmingsverklaring kinderen tot 16 jaar, ouders of voogden afwezig" -msgstr "Declaration of consent children up to the age of 16, no parents or caregivers present" - +msgstr "" -#: attachments/kinds.py:123 +#: attachments/kinds.py:126 msgid "" "Je baseert de verwerking van persoonsgegevens binnen je onderzoek op de " "wettelijke grondslag toestemming. De deelnemers zijn kinderen jonger dan 16 " "jaar en er zijn geen ouders of voodgen aanwezig." msgstr "" -"You base the processing of personal data within your research on the legal " -"basis consent. Your participants are children under the age of 16 and no " -"parents or guardians are present during the research." -#: attachments/kinds.py:138 +#: attachments/kinds.py:142 msgid "Akkoordverklaring beeld- en geluidsopnames algemeen belang" -msgstr "Agreement video- or audiorecordings public interest" +msgstr "" -#: attachments/kinds.py:140 +#: attachments/kinds.py:144 msgid "" "Je baseert de verwerking van persoonsgegevens weliswaar op de wettelijke " "grondslag algemeen belang, maar je maakt beeld- en/of geluidsopnames en daar " "moeten je deelnemers op ethische gronden mee instemmen. Ook voor het verdere " "gebruik van die opnames kun je de afspraken schriftelijk vastleggen." msgstr "" -"Although you base the processing of personal data on the legal basis " -"public interest, you make video and/or audio recordings and for that you " -"need consent. For the further use of those recordings, you can also put agreements in writing." -#: attachments/kinds.py:152 +#: attachments/kinds.py:156 msgid "Script voor mondelinge toestemming opnames" -msgstr "Script for verbal consent recordings" +msgstr "" -#: attachments/kinds.py:154 +#: attachments/kinds.py:158 msgid "" "Je interviewt deelnemers en je maakt daarvan beeld- en/of geluidsopnames. De " "toestemming daarvoor, en de eventuele toestemming en afspraken met " "betrekking tot andere aspecten van de verwerking van persoonsgegevens, leg " "je vast in een aparte opname." msgstr "" -"You interview participants and make video and/or audio recordings of them. " -"You record consent for this, and any consent and agreements regarding other " -"aspects of the processing of personal data, in a separate recording." -#: attachments/kinds.py:169 +#: attachments/kinds.py:174 +#, fuzzy +#| msgid "Informatiebrief directeur/departementshoofd" msgid "Informatiebrief gatekeeper/schoolleiding" -msgstr "Information letter gatekeeper/schoolmanagement" +msgstr "Information letter school director/head of the department" -#: attachments/kinds.py:171 +#: attachments/kinds.py:176 msgid "" "Je wilt onderzoek gaan doen binnen een bepaalde instelling (bijv. een " "school) en je verzoekt de leiding van die instelling om medewerking. Voor " @@ -163,92 +138,131 @@ msgid "" "de hoogte zijn van de opzet van je onderzoek en van allerlei praktische " "aspecten." msgstr "" -"You want to conduct research within a particular institution (e.g., a school) " -"and you request the cooperation of the management of that institution. " -"To make an informed choice, the management of that institution must be aware " -"of the design of your research and a variety of practical aspects. " -#: attachments/kinds.py:183 +#: attachments/kinds.py:188 msgid "Akkoordverklaring gatekeeper/schoolleiding" -msgstr "Declaration of cooperation gatekeeper/schoolmanagement" +msgstr "" -#: attachments/kinds.py:185 +#: attachments/kinds.py:190 msgid "" "Je wilt onderzoek gaan doen binnen een bepaalde instelling (bijv. een " "school) en je verzoekt de leiding van die instelling om medewerking. De " "schoolleiding moet, na goed geïnformeerd te zijntoestemming geven voor het " "onderzoek." msgstr "" -"You want to conduct research within a particular institution (e.g., a school) " -"and you request the cooperation of the management of that institution. " -"The school management must, after having been properly informed, give consent" -"to the students' participation in the research." -#: attachments/kinds.py:200 +#: attachments/kinds.py:206 #: proposals/templates/proposals/proposal_data_management.html:17 #: proposals/utils/pdf_diff_logic.py:980 -#: reviews/templatetags/documents_list.py:224 +#: reviews/templatetags/documents_list.py:223 msgid "Data Management Plan" msgstr "Data Management Plan" -#: attachments/kinds.py:201 +#: attachments/kinds.py:207 msgid "Omschrijving DMP" -msgstr "description DMP" +msgstr "" -#: attachments/kinds.py:210 -msgid "Overige bestanden" -msgstr "Other attachments" +#: attachments/kinds.py:217 attachments/models.py:41 +#: proposals/views/attachment_views.py:55 +#, fuzzy +#| msgid "Overige bestanden" +msgid "Overig bestand" +msgstr "Other files" -#: attachments/kinds.py:211 +#: attachments/kinds.py:218 msgid "Voor alle overige soorten bestanden" -msgstr "For all other attachments" +msgstr "For miscellaneous files" -#: attachments/models.py:22 +#: attachments/models.py:23 +#: reviews/templates/reviews/review_attachments.html:77 msgid "Bestand" msgstr "File" -#: attachments/models.py:23 +#: attachments/models.py:24 msgid "Selecteer hier het bestand om toe te voegen." -msgstr "Select a file to upload." +msgstr "Choose your file to upload" -#: attachments/models.py:40 -msgid "Gelieve selecteren" -msgstr "Please select" +#: attachments/models.py:42 +#, fuzzy +#| msgid "bestand" +msgid "Type bestand" +msgstr "file" -#: attachments/models.py:46 +#: attachments/models.py:48 msgid "Geef je bestand een omschrijvende naam, het liefst maar enkele woorden." -msgstr "Give your file a descriptive name, preferably a short one." +msgstr "Use a few words to briefly describe your document" -#: attachments/models.py:53 +#: attachments/models.py:55 msgid "" "Geef hier optioneel je motivatie om dit bestand toe te voegen en waar je het " "voor gaat gebruiken tijdens je onderzoek. Eventuele opmerkingen voor de FETC " "kun je hier ook kwijt." msgstr "" -"Optionally, provide your motivation for uploading this file and what you " -"will be using it for. Other remarks for the FETC can also be provided here." +"Optionally motivate the inclusion of this document in your proposal, for " +"example by describing how it will be used in your study. Other remarks or " +"clarifications for the FETC-H can also be left here." + +#: attachments/templates/attachments/attachment_model.html:6 +msgid "FETC-bestandsnaam" +msgstr "FETC filename" + +#: attachments/templates/attachments/attachments_list.html:8 +#: proposals/templates/proposals/attachments.html:11 +#: proposals/utils/checkers.py:992 proposals/utils/stepper.py:260 +msgid "Documenten" +msgstr "Documents" + +#: attachments/templates/attachments/attachments_list.html:10 +msgid "Bekijk uitgebreid" +msgstr "View all" -#: attachments/templates/attachments/slot.html:16 +#: attachments/templates/attachments/attachments_list.html:28 +#: main/templatetags/compare_tags.py:63 +#: proposals/templates/proposals/vue_templates/proposal_list.html:51 +#: reviews/templates/reviews/review_attachments.html:69 +#: reviews/templates/reviews/review_detail_sidebar.html:30 +#: reviews/templates/reviews/simple_compare_link.html:7 +#: reviews/templates/reviews/vue_templates/decision_list.html:53 +#: reviews/templates/reviews/vue_templates/review_list.html:54 +msgid "Toon verschillen" +msgstr "Show differences" + +#: attachments/templates/attachments/attachments_list.html:33 +msgid "Nieuw bestand" +msgstr "New document" + +#: attachments/templates/attachments/optionality_group.html:5 +#, python-format +msgid "Een van deze %(count)s documenten is voldoende" +msgstr "" + +#: attachments/templates/attachments/slot.html:12 +#, fuzzy +#| msgid "Nieuwe sessie tevoegen" +msgid "Nog toe te voegen" +msgstr "Add new session" + +#: attachments/templates/attachments/slot.html:18 msgid "Wijzig" msgstr "Edit" -#: attachments/templates/attachments/slot.html:18 +#: attachments/templates/attachments/slot.html:20 msgid "Voeg toe" -msgstr "Upload" +msgstr "Add" -#: attachments/utils.py:11 +#: attachments/utils.py:12 msgid "Verplicht" msgstr "Required" -#: attachments/utils.py:12 +#: attachments/utils.py:13 msgid "Aangeraden" msgstr "Recommended" -#: attachments/utils.py:13 +#: attachments/utils.py:14 msgid "Optioneel" msgstr "Optional" -#: attachments/utils.py:14 +#: attachments/utils.py:15 msgid "Extra" msgstr "Extra" @@ -416,7 +430,7 @@ msgstr "Intervention saved" #: main/forms/conditional_form.py:12 main/forms/conditional_form.py:21 #: main/forms/conditional_form.py:32 main/forms/conditional_form.py:43 #: main/forms/conditional_form.py:59 main/forms/mixins.py:84 -#: proposals/forms.py:738 proposals/forms.py:824 proposals/forms.py:845 +#: proposals/forms.py:738 proposals/forms.py:824 proposals/forms.py:827 #: studies/forms.py:176 studies/forms.py:222 msgid "Dit veld is verplicht." msgstr "This field is required." @@ -619,6 +633,11 @@ msgstr "cdh.core.uu" msgid "Log in" msgstr "Log in" +#: main/templates/base/fetc_form_base.html:19 +#: reviews/templates/reviews/review_attachments.html:104 +msgid "Terug naar beoordeling" +msgstr "Back to review" + #: main/templates/base/form_buttons.html:7 msgid "<< Opslaan en vorige stap" msgstr "<< Save and go back to previous step" @@ -847,7 +866,7 @@ msgid "Nieuw amendement starten" msgstr "Create new amendment" #: main/templates/main/index.html:90 proposals/menus.py:112 -#: proposals/views/proposal_views.py:189 +#: proposals/views/proposal_views.py:190 msgid "Archief" msgstr "Archive" @@ -1036,15 +1055,6 @@ msgstr "Username" msgid "Wachtwoord" msgstr "Password" -#: main/templatetags/compare_tags.py:63 -#: proposals/templates/proposals/vue_templates/proposal_list.html:51 -#: reviews/templates/reviews/review_detail_sidebar.html:30 -#: reviews/templates/reviews/simple_compare_link.html:7 -#: reviews/templates/reviews/vue_templates/decision_list.html:53 -#: reviews/templates/reviews/vue_templates/review_list.html:54 -msgid "Toon verschillen" -msgstr "Show differences" - #: main/templatetags/fetc_filters.py:88 msgid "Onbekend aantal" msgstr "Unknown number of" @@ -1380,7 +1390,7 @@ msgid "" msgstr "This field shows only approved applications in which you are involved." #: proposals/forms.py:568 proposals/forms.py:722 proposals/forms.py:754 -#: proposals/forms.py:931 +#: proposals/forms.py:913 msgid "Dit veld is verplicht om verder te gaan." msgstr "This field is required to continue." @@ -1450,15 +1460,7 @@ msgstr "" msgid "Nieuwe beoogde startdatum" msgstr "New intended start date" -#: proposals/forms.py:833 -msgid "Toestemmingsverklaring voor traject {} nog niet toegevoegd." -msgstr "Declaration of consent for trajectory {} not yet added." - -#: proposals/forms.py:840 -msgid "Informatiebrief voor traject {} nog niet toegevoegd." -msgstr "Information letter for trajectory {} not yet added." - -#: proposals/forms.py:854 +#: proposals/forms.py:836 msgid "" "De embargo-periode kan maximaal 2 jaar zijn. Kies een datum binnen 2 jaar " "van vandaag." @@ -1466,7 +1468,7 @@ msgstr "" "The embargo-period can last a maximum of 2 years. Pick a date within 2 years " "from today." -#: proposals/forms.py:940 +#: proposals/forms.py:922 msgid "Vul in in welke talen de formulieren worden vertaald." msgstr "Please fill in the languages" @@ -1506,23 +1508,23 @@ msgstr "New application" msgid "Al mijn aanvragen" msgstr "All my applications" -#: proposals/menus.py:58 proposals/views/proposal_views.py:102 +#: proposals/menus.py:58 proposals/views/proposal_views.py:103 msgid "Mijn conceptaanvragen" msgstr "My draft applications" -#: proposals/menus.py:62 proposals/views/proposal_views.py:161 +#: proposals/menus.py:62 proposals/views/proposal_views.py:162 msgid "Mijn oefenaanvragen" msgstr "My practice applications" -#: proposals/menus.py:66 proposals/views/proposal_views.py:116 +#: proposals/menus.py:66 proposals/views/proposal_views.py:117 msgid "Mijn ingediende aanvragen" msgstr "My submitted applications" -#: proposals/menus.py:70 proposals/views/proposal_views.py:130 +#: proposals/menus.py:70 proposals/views/proposal_views.py:131 msgid "Mijn afgehandelde aanvragen" msgstr "My processed applications" -#: proposals/menus.py:74 proposals/views/proposal_views.py:144 +#: proposals/menus.py:74 proposals/views/proposal_views.py:145 msgid "Mijn aanvragen als eindverantwoordelijke" msgstr "My supervised applications" @@ -1812,7 +1814,7 @@ msgstr "" "proposals." #: proposals/models.py:462 proposals/utils/pdf_diff_logic.py:1005 -#: reviews/models.py:163 +#: reviews/models.py:172 msgid "Ruimte voor eventuele opmerkingen" msgstr "Space for possible comments" @@ -2055,51 +2057,52 @@ msgstr "WMO {title}, status {status}" #: proposals/templates/proposals/attach_form.html:7 msgid "Voeg een bestand toe" -msgstr "Upload a file" +msgstr "Add a file" #: proposals/templates/proposals/attach_form.html:11 msgid "Maak of wijzig een bestand" -msgstr "Create of edit a file" +msgstr "Add or edit a file" #: proposals/templates/proposals/attach_form.html:14 msgid "Je voegt een bestand toe aan het volgende:" -msgstr "You are adding an attachment to the following:" +msgstr "You are attaching a document to the following:" #: proposals/templates/proposals/attach_form.html:18 msgid "Je bewerkt het volgende bestand:" -msgstr "You are editing the following attachment:" +msgstr "You are editing the following file:" #: proposals/templates/proposals/attach_form.html:22 msgid "Dit bestand is gekoppeld aan het volgende:" msgstr "This file is attached to the following:" #: proposals/templates/proposals/attach_form.html:29 +#, python-format msgid "Traject %(order)s: %(name)s van" -msgstr "Trajectory %(order)s (%(name)s)" +msgstr "Trajectory %(order)s (%(name)s) of" #: proposals/templates/proposals/attach_form.html:33 msgid "de aanvraag" msgstr "the application" -#: proposals/templates/proposals/attach_form.html:36 +#: proposals/templates/proposals/attach_form.html:37 #, python-format msgid "" "Je gaat hier een %(name)s aan toevoegen. Wil je een ander soort bestand " "toevoegen? Ga dan terug naar de vorige pagina." msgstr "" -"You are about to add a %(name)s. If you are looking to upload a different " -"type of attachment, please return to the previous page." +"You will be attaching a %(name)s. If you wish to attach a different kind of " +"document, please return to the previous page" -#: proposals/templates/proposals/attach_form.html:47 +#: proposals/templates/proposals/attach_form.html:49 #: proposals/templates/proposals/detach_form.html:29 msgid "<< Ga terug" msgstr "<< Go back" -#: proposals/templates/proposals/attach_form.html:52 +#: proposals/templates/proposals/attach_form.html:54 msgid "Bestand verwijderen" msgstr "Delete file" -#: proposals/templates/proposals/attach_form.html:58 +#: proposals/templates/proposals/attach_form.html:60 msgid "Opslaan" msgstr "Save" @@ -2110,27 +2113,29 @@ msgstr "Save" msgid "Informatie over betrokken onderzoekers" msgstr "Information about other researchers" -#: proposals/templates/proposals/attachments.html:11 -#: proposals/utils/checkers.py:1039 proposals/utils/stepper.py:226 -#: reviews/templates/reviews/review_detail_sidebar.html:124 -msgid "Documenten" -msgstr "Documents" - -#: proposals/templates/proposals/attachments.html:12 +#: proposals/templates/proposals/attachments.html:15 msgid "Algemeen" msgstr "General" -#: proposals/templates/proposals/attachments.html:19 +#: proposals/templates/proposals/attachments.html:25 +#: proposals/templates/proposals/attachments.html:44 +msgid "Toevoegen" +msgstr "" + +#: proposals/templates/proposals/attachments.html:32 #: proposals/utils/pdf_diff_logic.py:319 proposals/utils/pdf_diff_logic.py:346 #: proposals/utils/pdf_diff_logic.py:355 proposals/utils/pdf_diff_logic.py:379 msgid "Traject " msgstr "Trajectory " +#: proposals/templates/proposals/compare_attachments.html:8 +#: proposals/templates/proposals/compare_attachments.html:50 #: proposals/templates/proposals/compare_documents.html:8 #: proposals/templates/proposals/compare_documents.html:50 msgid "Vergelijk documenten" msgstr "Compare documents" +#: proposals/templates/proposals/compare_attachments.html:52 #: proposals/templates/proposals/compare_documents.html:52 msgid "" "Hier kan je twee versies van een document vergelijken. Standaard geeft hij " @@ -2141,6 +2146,7 @@ msgstr "" "with a split view where removed text is marked in red and added text " "is marked in green." +#: proposals/templates/proposals/compare_attachments.html:60 #: proposals/templates/proposals/compare_documents.html:60 msgid "" "Je kan ook de bestanden gecombineerd bekijken, met dezelfde markeringen. " @@ -2149,26 +2155,32 @@ msgstr "" "Documents can also be compared with a combined view, with markings. To do " "so, click 'View combined'." +#: proposals/templates/proposals/compare_attachments.html:67 #: proposals/templates/proposals/compare_documents.html:67 msgid "Je vergelijkt" -msgstr "Comparing:" +msgstr "Comparing" +#: proposals/templates/proposals/compare_attachments.html:72 #: proposals/templates/proposals/compare_documents.html:72 msgid "Bekijk apart" msgstr "View separately" +#: proposals/templates/proposals/compare_attachments.html:73 #: proposals/templates/proposals/compare_documents.html:73 msgid "Bekijk gecombineerd" msgstr "View combined" +#: proposals/templates/proposals/compare_attachments.html:77 #: proposals/templates/proposals/compare_documents.html:77 msgid "Er zijn geen wijzigingen gevonden in dit document!" msgstr "No changes were found in this document!" +#: proposals/templates/proposals/compare_attachments.html:82 #: proposals/templates/proposals/compare_documents.html:82 msgid "Oud" msgstr "Old" +#: proposals/templates/proposals/compare_attachments.html:89 #: proposals/templates/proposals/compare_documents.html:88 msgid "Nieuw" msgstr "New" @@ -2180,7 +2192,7 @@ msgstr "Delete a file" #: proposals/templates/proposals/detach_form.html:13 msgid "Je verwijdert het volgende bestand:" -msgstr "You are deleting the following file:" +msgstr "You are deleting the following document:" #: proposals/templates/proposals/detach_form.html:19 msgid "" @@ -2189,9 +2201,10 @@ msgid "" "de geschiedenis van het document bewaard, en dat vergemakkelijkt het " "beoordeelproces aanzienlijk." msgstr "" -"If you would like to upload a new version of this file, do not delete it, but" -"return to the previous page and edit it. This ensures the document's history" -"will persist and significantly eases the review process." +"Do not delete this file if you merely want to attach a newer version of it. " +"If that is the case, please return to the previous page to select and save " +"the new version there. This allows us to track the history of documents " +"which greatly facilitates the review process." #: proposals/templates/proposals/detach_form.html:34 #: proposals/templates/proposals/proposal_confirm_delete.html:22 @@ -2372,7 +2385,7 @@ msgid "Kopiëren" msgstr "Copy" #: proposals/templates/proposals/proposal_data_management.html:7 -#: proposals/utils/proposal_utils.py:136 proposals/utils/stepper.py:227 +#: proposals/utils/proposal_utils.py:136 proposals/utils/stepper.py:261 msgid "Datamanagement" msgstr "Data management" @@ -2699,6 +2712,7 @@ msgid "Indiener" msgstr "Applicant" #: proposals/templates/proposals/proposal_pdf.html:113 +#: reviews/templates/reviews/review_attachments.html:53 msgid "Naam" msgstr "Name" @@ -2784,6 +2798,7 @@ msgstr "" #: proposals/templates/proposals/study_start.html:67 #: proposals/utils/pdf_diff_logic.py:326 #: reviews/templates/reviews/committee_members_workload.html:23 +#: reviews/templates/reviews/review_attachments.html:42 msgid "Traject" msgstr "Trajectory" @@ -3387,8 +3402,8 @@ msgid "" msgstr "" "Ethical assessment by a Medical Ethical Testing Committee (METC) required?" -#: proposals/utils/checkers.py:66 proposals/utils/stepper.py:223 -#: proposals/utils/stepper.py:232 proposals/utils/stepper.py:237 +#: proposals/utils/checkers.py:66 proposals/utils/stepper.py:257 +#: proposals/utils/stepper.py:266 proposals/utils/stepper.py:271 msgid "Basisgegevens" msgstr "Basic details" @@ -3417,7 +3432,7 @@ msgid "WMO applicatie" msgstr "WMO application" #: proposals/utils/checkers.py:321 proposals/utils/proposal_utils.py:116 -#: proposals/utils/stepper.py:225 +#: proposals/utils/stepper.py:259 msgid "Trajecten" msgstr "Trajectories" @@ -3429,46 +3444,46 @@ msgstr "Conclusion trajectory" msgid "Trajecten afronding" msgstr "Conclusion trajectories" -#: proposals/utils/checkers.py:612 studies/utils.py:67 +#: proposals/utils/checkers.py:613 studies/utils.py:67 msgid "Deelnemers" msgstr "Participants" -#: proposals/utils/checkers.py:649 +#: proposals/utils/checkers.py:650 #: studies/templates/studies/study_personal_data.html:7 #: studies/templates/studies/study_personal_data.html:22 msgid "Persoonlijke gegevens" msgstr "Personal data" -#: proposals/utils/checkers.py:683 +#: proposals/utils/checkers.py:684 msgid "Ontwerp" msgstr "Design" -#: proposals/utils/checkers.py:714 +#: proposals/utils/checkers.py:715 msgid "Traject overzicht" msgstr "Trajectory overview" -#: proposals/utils/checkers.py:749 +#: proposals/utils/checkers.py:750 msgid "Interventie" msgstr "Intervention" -#: proposals/utils/checkers.py:807 +#: proposals/utils/checkers.py:808 msgid "Observatie" msgstr "Observation" -#: proposals/utils/checkers.py:865 +#: proposals/utils/checkers.py:866 msgid "Sessies" msgstr "Sessions" -#: proposals/utils/checkers.py:1051 +#: proposals/utils/checkers.py:1069 msgid "Vertalingen" msgstr "Translations" -#: proposals/utils/checkers.py:1074 +#: proposals/utils/checkers.py:1092 msgid "Data management" msgstr "Data management" -#: proposals/utils/checkers.py:1100 proposals/utils/stepper.py:228 -#: proposals/utils/stepper.py:233 proposals/utils/stepper.py:239 +#: proposals/utils/checkers.py:1118 proposals/utils/stepper.py:262 +#: proposals/utils/stepper.py:267 proposals/utils/stepper.py:273 msgid "Indienen" msgstr "Submit" @@ -3571,7 +3586,7 @@ msgstr "FEtC-H: A revised application uses lab facilities" msgid "FETC-GW: nieuwe aanvraag gebruikt labfaciliteiten" msgstr "FEtC-H: New application uses lab facilities" -#: proposals/utils/stepper.py:224 proposals/utils/stepper.py:238 +#: proposals/utils/stepper.py:258 proposals/utils/stepper.py:272 msgid "WMO" msgstr "WMO" @@ -3587,40 +3602,44 @@ msgstr "Session {}, task {}" msgid "Sessie {} overzicht" msgstr "Session {} overview" -#: proposals/views/proposal_views.py:67 +#: proposals/views/attachment_views.py:323 +msgid "Geen bestanden gevonden" +msgstr "No documents found" + +#: proposals/views/proposal_views.py:68 msgid "Publiek archief" msgstr "Public archive" -#: proposals/views/proposal_views.py:68 +#: proposals/views/proposal_views.py:69 msgid "Dit overzicht toont alle goedgekeurde aanvragen." msgstr "This overview shows all approved applications." -#: proposals/views/proposal_views.py:87 +#: proposals/views/proposal_views.py:88 msgid "Mijn aanvraag" msgstr "My application" -#: proposals/views/proposal_views.py:88 +#: proposals/views/proposal_views.py:89 msgid "Dit overzicht toont al je aanvragen." msgstr "This overview shows all your applications." -#: proposals/views/proposal_views.py:103 +#: proposals/views/proposal_views.py:104 msgid "Dit overzicht toont al je nog niet ingediende aanvragen." msgstr "This overview shows all the applications you have not yet submitted." -#: proposals/views/proposal_views.py:117 +#: proposals/views/proposal_views.py:118 msgid "Dit overzicht toont al je ingediende aanvragen." msgstr "This overview shows all the applications you have submitted." -#: proposals/views/proposal_views.py:131 +#: proposals/views/proposal_views.py:132 msgid "Dit overzicht toont al je beoordeelde aanvragen." msgstr "This overview shows all your applications that have been assessed." -#: proposals/views/proposal_views.py:146 +#: proposals/views/proposal_views.py:147 msgid "" "Dit overzicht toont alle aanvragen waarvan je eindverantwoordelijke bent." msgstr "This overview shows all your supervised applications." -#: proposals/views/proposal_views.py:163 +#: proposals/views/proposal_views.py:164 msgid "" "Dit overzicht toont alle oefenaanvragen waar je als student, onderzoeker of " "eindverantwoordelijke bij betrokken bent." @@ -3628,20 +3647,20 @@ msgstr "" "This overview shows all practice applications in which you are involved as a " "student, researcher or accountable researcher." -#: proposals/views/proposal_views.py:243 +#: proposals/views/proposal_views.py:244 #, python-format msgid "Aanvraag %(title)s aangemaakt" msgstr "Application %(title)s created" -#: proposals/views/proposal_views.py:301 +#: proposals/views/proposal_views.py:302 msgid "Aanvraag verwijderd" msgstr "Application deleted" -#: proposals/views/proposal_views.py:586 +#: proposals/views/proposal_views.py:669 msgid "Wijzigingen opgeslagen" msgstr "Changes saved" -#: proposals/views/proposal_views.py:689 +#: proposals/views/proposal_views.py:772 msgid "Aanvraag gekopieerd" msgstr "Application copied" @@ -3702,11 +3721,11 @@ msgstr "long route (4-weeks)" msgid "Direct terug naar aanvrager (Nog niet in behandeling)" msgstr "Return directly to applicant (not yet under review)" -#: reviews/forms.py:41 reviews/menus.py:67 reviews/mixins.py:174 +#: reviews/forms.py:41 reviews/menus.py:67 reviews/mixins.py:192 msgid "Algemene Kamer" msgstr "General Chamber" -#: reviews/forms.py:42 reviews/menus.py:77 reviews/mixins.py:177 +#: reviews/forms.py:42 reviews/menus.py:77 reviews/mixins.py:195 msgid "Linguïstiek Kamer" msgstr "Linguistics Chamber" @@ -3734,7 +3753,7 @@ msgstr "Start date period:" msgid "Eind datum periode:" msgstr "End date period:" -#: reviews/menus.py:19 reviews/views.py:73 +#: reviews/menus.py:19 reviews/views.py:76 msgid "Mijn openstaande besluiten" msgstr "My pending decisions" @@ -3750,19 +3769,19 @@ msgstr "All pending decisions committee members" msgid "Alle openstaande besluiten eindverantwoordelijken" msgstr "All pending decisions supervisors" -#: reviews/menus.py:37 reviews/views.py:235 +#: reviews/menus.py:37 reviews/views.py:238 msgid "Nog af te handelen aanvragen" msgstr "Applications waiting for conclusion" -#: reviews/menus.py:42 reviews/views.py:247 +#: reviews/menus.py:42 reviews/views.py:250 msgid "Aanvragen in revisie" msgstr "Applications in revision" -#: reviews/menus.py:47 reviews/views.py:259 +#: reviews/menus.py:47 reviews/views.py:262 msgid "Alle lopende aanvragen" msgstr "All running applications" -#: reviews/menus.py:52 reviews/views.py:285 +#: reviews/menus.py:52 reviews/views.py:288 msgid "Alle ingezonden aanvragen" msgstr "All submitted applications" @@ -3822,7 +3841,7 @@ msgstr "Post hoc negative advice by FETC-H" msgid "Niet verder in behandeling genomen" msgstr "Not to be assessed further" -#: reviews/models.py:32 reviews/models.py:158 +#: reviews/models.py:32 reviews/models.py:167 #: reviews/templates/reviews/review_table.html:9 msgid "Beslissing" msgstr "Decision" @@ -3839,15 +3858,15 @@ msgstr "short (2-week) route" msgid "nog geen route" msgstr "no route assigned" -#: reviews/models.py:153 +#: reviews/models.py:162 msgid "goedgekeurd" msgstr "endorsed" -#: reviews/models.py:154 +#: reviews/models.py:163 msgid "niet goedgekeurd" msgstr "not endorsed" -#: reviews/models.py:155 +#: reviews/models.py:164 msgid "revisie noodzakelijk" msgstr "revision necessary" @@ -4093,13 +4112,15 @@ msgstr "" msgid "Beslissing opslaan" msgstr "Save decision" -#: reviews/templates/reviews/documents_list.html:26 -#: reviews/templates/reviews/documents_list.html:28 +#: reviews/templates/reviews/documents_list.html:30 +#: reviews/templates/reviews/documents_list.html:32 msgid "Data Management Plan wijzigen" msgstr "Edit Data Management Plan" -#: reviews/templates/reviews/documents_list.html:33 -#: reviews/templates/reviews/documents_list.html:35 +#: reviews/templates/reviews/documents_list.html:37 +#: reviews/templates/reviews/documents_list.html:39 +#: reviews/templates/reviews/review_attachments.html:29 +#: reviews/templates/reviews/review_attachments.html:31 msgid "Documenten wijzigen" msgstr "Edit documents" @@ -4124,6 +4145,64 @@ msgstr "" msgid "Bevestigen" msgstr "Confirm" +#: reviews/templates/reviews/review_attachments.html:15 +msgid "Aangeleverde documenten" +msgstr "Attached documents" + +#: reviews/templates/reviews/review_attachments.html:17 +msgid "" +"Hieronder vind je de meegezonden documenten bij deze aanvraag. Deze zijn " +"gesorteerd per object waar ze aan gekoppeld zijn. Dat kan een traject zijn " +"of de aanvraag in het algemeen." +msgstr "" +"Below you will find all documents attached to this review. These are listed " +"per object that they are added to, either a trajectory or the proposal as a " +"whole." + +#: reviews/templates/reviews/review_attachments.html:22 +msgid "" +"Je kunt documenten downloaden met zowel de originele als de genormaliseerde " +"bestandsnaam. Documenten die revisies zijn van vorige versies van hetzelfde " +"bestand kunnen vergeleken worden." +msgstr "" +"You can download the attachments with either the original or the generated " +"filename. Documents that are revised versions of previously attached " +"documents can be compared." + +#: reviews/templates/reviews/review_attachments.html:36 +msgid "Aanvraag in het geheel" +msgstr "Application in general" + +#: reviews/templates/reviews/review_attachments.html:39 +msgid "Het hoofdtraject" +msgstr "The main trajectory" + +#: reviews/templates/reviews/review_attachments.html:57 +msgid "Aanlevering" +msgstr "Provided as" + +#: reviews/templates/reviews/review_attachments.html:61 +#: reviews/templates/reviews/review_attachments.html:63 +msgid "Nieuw bij deze aanvraag" +msgstr "New with this review" + +#: reviews/templates/reviews/review_attachments.html:66 +msgid "Gereviseerd bestand" +msgstr "Revised file" + +#: reviews/templates/reviews/review_attachments.html:72 +msgid "Onveranderd" +msgstr "Unchanged file" + +#: reviews/templates/reviews/review_attachments.html:81 +#: reviews/templates/reviews/review_table.html:11 +msgid "Commentaar" +msgstr "Comments" + +#: reviews/templates/reviews/review_attachments.html:86 +msgid "Geen commentaar aangeleverd." +msgstr "Not provided." + #: reviews/templates/reviews/review_close_form.html:7 #: reviews/templates/reviews/review_close_form.html:27 #: reviews/templates/reviews/review_close_form.html:43 @@ -4246,6 +4325,10 @@ msgstr "" msgid "Er zijn de volgende opmerkingen bijgevoegd:
" msgstr "The following comments have been provided:
" +#: reviews/templates/reviews/review_detail_sidebar.html:130 +msgid "Documenten (oude systeem)" +msgstr "Documents (legacy)" + #: reviews/templates/reviews/review_discontinue_form.html:7 msgid "Beoordeling beëindigen" msgstr "Terminate review" @@ -4292,6 +4375,7 @@ msgstr "" "submitter." #: reviews/templates/reviews/review_discontinue_form.html:57 +#: reviews/utils/attachment_utils.py:131 msgid "Aanvraag" msgstr "Application" @@ -4304,10 +4388,6 @@ msgstr "%(title)s by %(author)s" msgid "Genomen op" msgstr "Decision made on" -#: reviews/templates/reviews/review_table.html:11 -msgid "Commentaar" -msgstr "Comments" - #: reviews/templates/reviews/review_table.html:18 msgid "open" msgstr "open" @@ -4342,50 +4422,58 @@ msgstr "Trajectory {}: {}" msgid "Extra documenten {}" msgstr "Extra documents {}" -#: reviews/templatetags/documents_list.py:196 +#: reviews/templatetags/documents_list.py:195 msgid "Aanmelding" msgstr "Application" -#: reviews/templatetags/documents_list.py:198 +#: reviews/templatetags/documents_list.py:197 +#: reviews/utils/attachment_utils.py:134 msgid "Aanvraag in PDF-vorm" msgstr "Application in PDF format" -#: reviews/templatetags/documents_list.py:210 +#: reviews/templatetags/documents_list.py:209 +#: reviews/utils/attachment_utils.py:139 msgid "Eerdere goedkeuring" msgstr "Prior approval" -#: reviews/templatetags/documents_list.py:217 +#: reviews/templatetags/documents_list.py:216 +#: reviews/utils/attachment_utils.py:145 msgid "Aanvraag bij voortoetsing" msgstr "Application for preliminary assessment" -#: reviews/templatetags/documents_list.py:240 +#: reviews/templatetags/documents_list.py:239 +#: reviews/utils/attachment_utils.py:155 msgid "Beslissing METC" msgstr "Decision by METC" -#: reviews/templatetags/documents_list.py:262 +#: reviews/templatetags/documents_list.py:272 msgid "Informed consent" msgstr "Informed consent" -#: reviews/templatetags/documents_list.py:263 +#: reviews/templatetags/documents_list.py:273 msgid "Informatiebrief" msgstr "Information letter" -#: reviews/templatetags/documents_list.py:265 +#: reviews/templatetags/documents_list.py:275 msgid "Consent declaratie directeur/departementshoofd" msgstr "Declaration of consent school director/head of the department" -#: reviews/templatetags/documents_list.py:270 +#: reviews/templatetags/documents_list.py:280 msgid "Informatiebrief directeur/departementshoofd" msgstr "Information letter school director/head of the department" -#: reviews/templatetags/documents_list.py:274 +#: reviews/templatetags/documents_list.py:284 msgid "Informatiebrief ouders" msgstr "Information letter for the parents" -#: reviews/templatetags/documents_list.py:282 +#: reviews/templatetags/documents_list.py:292 msgid "Toestemmingsdocument observatie" msgstr "Consent document for observation" +#: reviews/utils/attachment_utils.py:109 studies/utils.py:96 +msgid "Traject {}" +msgstr "Trajectory {}" + #: reviews/utils/review_actions.py:118 msgid "Pas jouw beslissing en/of commentaar aan" msgstr "Edit your feedback on this proposal" @@ -4561,19 +4649,19 @@ msgstr "" "The application contains psychophysiological measurements on children under " "{} year(s) old." -#: reviews/views.py:63 +#: reviews/views.py:66 msgid "Mijn besluiten" msgstr "My results" -#: reviews/views.py:85 +#: reviews/views.py:88 msgid "Openstaande besluiten commissieleden" msgstr "Pending decisions committee members" -#: reviews/views.py:208 +#: reviews/views.py:211 msgid "Openstaande besluiten eindverantwoordelijken" msgstr "Pending decisions supervisors" -#: reviews/views.py:594 +#: reviews/views.py:610 msgid "" "Deze aanvraag is al beoordeeld, dus je kan je beoordeling niet meer " "toevoegen/aanpassen" @@ -4919,16 +5007,16 @@ msgstr "" "em> minimal? I.e. is the chance of and/or magnitude of potential damage to " "participants clearly above that of the \"background risk\"?" -#: studies/models.py:472 +#: studies/models.py:477 #, python-format msgid "Study details for proposal %s" msgstr "Study details for proposal %s" -#: studies/models.py:477 +#: studies/models.py:482 msgid "Maak je gebruik van passieve informed consent?" msgstr "Will you use passive informed consent?" -#: studies/models.py:480 +#: studies/models.py:485 msgid "" "Wanneer je kinderen via een instelling (dus ook school) werft en je de " "ouders niet laat ondertekenen, maar in plaats daarvan de leiding van die " @@ -4944,7 +5032,7 @@ msgstr "" "a>." # studies/models.py:229 -#: studies/models.py:493 +#: studies/models.py:498 msgid "" "Licht je antwoord toe. Wij willen je wijzen op het reglement, sectie 3.1 'd' " "en 'e'. Passive consent is slechts in enkele gevallen toegestaan en draagt " @@ -4954,16 +5042,16 @@ msgstr "" "'d' and 'e'. Passive consent is allowed under certain situations but is not " "preferred by the committee." -#: studies/models.py:510 +#: studies/models.py:515 msgid "Upload hier de toestemmingsverklaring (in .pdf of .doc(x)-formaat)" msgstr "" "Please upload the declaration of consent here (in .pdf or .doc(x)-format)" -#: studies/models.py:518 +#: studies/models.py:523 msgid "Upload hier de informatiebrief (in .pdf of .doc(x)-formaat)" msgstr "Please upload the information letter here (in .pdf or .doc(x)-format)" -#: studies/models.py:527 +#: studies/models.py:532 msgid "" "Upload hier de toestemmingsverklaring voor de leiding of het management van " "de instelling (in .pdf of .doc(x)-format)" @@ -4971,7 +5059,7 @@ msgstr "" "Please upload the declaration of consent for the management of the school or " "institution (in .pdf or .doc(x)-format)" -#: studies/models.py:532 +#: studies/models.py:537 msgid "" "Upload indien mogelijk een ondertekende versie van het document. Upload als " "deze nog niet bestaat een blanco versie, en stuur de ondertekende versie " @@ -4982,7 +5070,7 @@ msgstr "" "and follow up by sending a signed copy to the secretary of the FEtC-H once " "available." -#: studies/models.py:540 +#: studies/models.py:545 msgid "" "Upload hier de informatiebrief voor de leiding of het management van de " "instelling (in .pdf of .doc(x)-formaat)" @@ -4990,7 +5078,7 @@ msgstr "" "Please upload the the information letter for the management of the school or " "institution (in .pdf or .doc(x)-format)" -#: studies/models.py:550 +#: studies/models.py:555 msgid "" "Upload hier de informatiebrief voor de ouders of verzorgers (in .pdf of ." "doc(x)-formaat)" @@ -5230,10 +5318,6 @@ msgstr "Type(s) of research" msgid "Overzicht" msgstr "Overview" -#: studies/utils.py:96 -msgid "Traject {}" -msgstr "Trajectory {}" - #: studies/views/study_views.py:41 msgid "Studie opgeslagen" msgstr "Application saved" @@ -5634,3 +5718,36 @@ msgstr "Task edited" #: tasks/views/task_views.py:81 msgid "Taak verwijderd" msgstr "Task deleted" + +#~ msgid "Gelieve selecteren" +#~ msgstr "Please select" + +#~ msgid "Verouderde documenten" +#~ msgstr "Legacy documents" + +#~ msgid "" +#~ "De portal heeft recent het systeem voor het toevoegen van documenten " +#~ "vernieuwd. Door de omvang van de veranderingen is het foutgevoelig om de " +#~ "documenten uit het oude systeem automatisch te importeren. Daarom " +#~ "verzoeken we je om eerder toegevoegde documenten vanuit het oude systeem " +#~ "zelf op de goede plek te zetten. Alle oude documenten bij deze aanvraag " +#~ "zijn hieronder weergegeven." +#~ msgstr "" +#~ "Recently the document and attachments system has been thoroughly revised. " +#~ "Because of the extent of the changes, automatically importing documents " +#~ "from the old system is somewhat error-prone. Therefore we ask that you " +#~ "manually reinsert your documents from the old system. Documents that were " +#~ "previously attached in the old system are displayed below." + +#~ msgid "" +#~ "Het opnieuw toevoegen van deze documenten hoeft maar één keer, en is " +#~ "alleen nodig voor aanvragen die lopen tijdens deze overgangsperiode." +#~ msgstr "" +#~ "You will only have to reattach these documents once, and only for " +#~ "applications that were running during the update." + +#~ msgid "Toestemmingsverklaring voor traject {} nog niet toegevoegd." +#~ msgstr "Declaration of consent for trajectory {} not yet added." + +#~ msgid "Informatiebrief voor traject {} nog niet toegevoegd." +#~ msgstr "Information letter for trajectory {} not yet added." diff --git a/proposals/templates/proposals/attachments.html b/proposals/templates/proposals/attachments.html index 3cba765b..9453f966 100644 --- a/proposals/templates/proposals/attachments.html +++ b/proposals/templates/proposals/attachments.html @@ -48,8 +48,7 @@
Voeg optioneel bestand
{% endfor %} {% endblock %} + {% block form-buttons %} - {% if not secretary_return_link %} - {{ block.super }} - {% endif %} - {% endblock %} + {% if not secretary_return_link %}{{ block.super }}{% endif %} +{% endblock %}