From 502016f620074c5297ca87554e2c56d3307a76f7 Mon Sep 17 00:00:00 2001
From: delphvr <delphine.vanrossum@student.uclouvain.be>
Date: Tue, 11 Mar 2025 12:19:41 +0100
Subject: [PATCH 1/3] study data divided in 4 fields

---
 backend/app/models/studies.py                 |  5 +-
 backend/app/schemas/studies.py                | 10 ++-
 frontend/src/lang/en.json                     | 11 ++-
 frontend/src/lang/fr.json                     | 10 ++-
 .../lib/components/studies/StudyForm.svelte   | 48 +++++++++--
 frontend/src/lib/types/study.ts               | 85 +++++++++++++++----
 6 files changed, 137 insertions(+), 32 deletions(-)

diff --git a/backend/app/models/studies.py b/backend/app/models/studies.py
index fd0db73b..4882e143 100644
--- a/backend/app/models/studies.py
+++ b/backend/app/models/studies.py
@@ -21,7 +21,10 @@ class Study(Base):
     consent_participation = Column(String)
     consent_privacy = Column(String)
     consent_rights = Column(String)
-    consent_study_data = Column(String)
+    study_data_organisation = Column(String)
+    study_data_address = Column(String)
+    study_data_contact = Column(String)
+    study_data_email = Column(String)
 
     users = relationship("User", secondary="study_users")
     tests = relationship("Test", secondary="study_tests")
diff --git a/backend/app/schemas/studies.py b/backend/app/schemas/studies.py
index 5f22ab24..6dbeac99 100644
--- a/backend/app/schemas/studies.py
+++ b/backend/app/schemas/studies.py
@@ -13,7 +13,10 @@ class StudyCreate(BaseModel):
     consent_participation: str
     consent_privacy: str
     consent_rights: str
-    consent_study_data: str
+    study_data_organisation: str
+    study_data_address: str
+    study_data_contact: str
+    study_data_email: str
 
     user_ids: list[int] = []
     test_ids: list[int] = []
@@ -29,7 +32,10 @@ class Study(BaseModel):
     consent_participation: str
     consent_privacy: str
     consent_rights: str
-    consent_study_data: str
+    study_data_organisation: str
+    study_data_address: str
+    study_data_contact: str
+    study_data_email: str
 
     users: list[User] = []
     tests: list[Test] = []
diff --git a/frontend/src/lang/en.json b/frontend/src/lang/en.json
index 8fa7b314..7c0efdc7 100644
--- a/frontend/src/lang/en.json
+++ b/frontend/src/lang/en.json
@@ -145,7 +145,10 @@
 			"programed": "Scheduled",
 			"status": "Status",
 			"topics": "Topics",
-			"toggle": "Participants"
+			"toggle": "Participants",
+			"title": "Study Title",
+			"OrganisationUni": "Organization/University",
+			"Address": "Address"
 		}
 	},
 	"button": {
@@ -430,5 +433,11 @@
 			"tutor": "Tutor",
 			"tutors": "Tutor(s)"
 		}
+	},
+	"studies": {
+		"studyDescription": "Research Project (title and/or funding of the project this study is part of)",
+		"addressD": "Place Cardinal Mercier 14, 1348 Louvain-la-Neuve",
+		"contact": "Contact Person/Principal Investigator",
+		"email": "Email of PI/Contact Person"
 	}
 }
diff --git a/frontend/src/lang/fr.json b/frontend/src/lang/fr.json
index 21fa5fef..4b2ad4ce 100644
--- a/frontend/src/lang/fr.json
+++ b/frontend/src/lang/fr.json
@@ -378,6 +378,10 @@
 		"consentPrivacy": "Les données collectées (par exemple, les transcriptions des conversations, les résultats de tests, les mesures de frappe, les informations sur les participants comme l'age ou le genre) seront traitées de manière confidentielle et anonyme. Elles seront conservées après leur anonymisation intégrale et ne pourront être utilisées qu'à des fins scientifiques ou pédagogiques. Elles pourront éventuellement être partagées avec d'autres chercheurs ou enseignants, mais toujours dans ce cadre strictement de recherche ou d'enseignement.",
 		"consentRights": "Votre participation à cette étude est volontaire. Vous pouvez à tout moment décider de ne plus participer à l'étude sans avoir à vous justifier. Vous pouvez également demander à ce que vos données soient supprimées à tout moment. Si vous avez des questions ou des préoccupations concernant cette étude, vous pouvez contacter le responsable de l'étude.",
 		"consentStudyData": "Informations sur l'étude.",
+		"studyDescription": "Projet de recherche (titre et/ou financement du projet dans lequel s'inscrit cette étude)",
+		"addressD": "Place Cardinal Mercier 14, 1348 Louvain-la-Neuve",
+		"contact": "Personne de contact/chercheur principal",
+		"email": "Email du PI/de la personne de contact",
 		"tab": {
 			"study": "Étude",
 			"code": "Code",
@@ -487,14 +491,16 @@
 			"inProgress": "En cours",
 			"finished": "Terminée",
 			"topics": "Topics",
-			"title": "Titre",
+			"title": "Titre de l'étude",
 			"users": "Utilisateurs",
 			"description": "Description",
 			"email": "E-mail",
 			"toggle": "Participants",
 			"groups": "groupes",
 			"questions": "questions",
-			"tests": "tests"
+			"tests": "tests",
+			"OrganisationUni": "Organisation/Université",
+			"Address": "Adresse"
 		}
 	},
 	"inputs": {
diff --git a/frontend/src/lib/components/studies/StudyForm.svelte b/frontend/src/lib/components/studies/StudyForm.svelte
index 316dc64f..9cd142be 100644
--- a/frontend/src/lib/components/studies/StudyForm.svelte
+++ b/frontend/src/lib/components/studies/StudyForm.svelte
@@ -40,8 +40,10 @@
 		form?.consentPrivacy ?? (study ? study.consentPrivacy : $t('studies.consentPrivacy'));
 	let consentRights =
 		form?.consentRights ?? (study ? study.consentRights : $t('studies.consentRights'));
-	let consentStudyData =
-		form?.consentStudyData ?? (study ? study.consentStudyData : $t('studies.consentStudyData'));
+	let studyOrganisation = study ? study.studyOrganisation : '';
+	let studyAddress = form?.studyAddress ?? (study ? study.studyAddress : $t('studies.addressD'));
+	let studyContact = study ? study.studyContact : '';
+	let studyPIemail = study ? study.studyPIemail : '';
 
 	let newUsername: string = $state('');
 	let newUserModal = $state(false);
@@ -128,7 +130,7 @@
 		<!-- Title & description -->
 		<label class="label" for="title">{$t('utils.words.title')} *</label>
 		<input class="input w-full" type="text" id="title" name="title" required bind:value={title} />
-		<label class="label" for="description">{$t('utils.words.description')}</label>
+		<label class="label" for="description">{$t('studies.studyDescription')}</label>
 		<textarea
 			use:autosize
 			class="input w-full max-h-52"
@@ -268,17 +270,47 @@
 			value={consentRights}
 			required
 		></textarea>
-		<label class="label text-sm" for="consentStudyData"
-			>{$t('register.consent.studyData.title')} *</label
+		<h3 class="py-2 px-1">{$t('register.consent.studyData.title')}</h3>
+		<label class="label text-sm" for="StudyOrganisation"
+			>{$t('utils.words.OrganisationUni')} *</label
 		>
 		<textarea
 			use:autosize
 			class="input w-full max-h-52"
-			id="consentStudyData"
-			name="consentStudyData"
-			value={consentStudyData}
+			id="StudyOrganisation"
+			name="StudyOrganisation"
+			value={studyOrganisation}
 			required
 		></textarea>
+		<label class="label text-sm" for="StudyAddress">{$t('utils.words.Address')} *</label>
+		<textarea
+			use:autosize
+			class="input w-full max-h-52"
+			id="StudyAddress"
+			name="StudyAddress"
+			value={studyAddress}
+			required
+		></textarea>
+		<label class="label text-sm" for="StudyContact">{$t('studies.contact')} *</label>
+		<textarea
+			use:autosize
+			class="input w-full max-h-52"
+			id="StudyContact"
+			name="StudyContact"
+			value={studyContact}
+			required
+		></textarea>
+		<label class="label text-sm" for="StudyPIemail">
+			{$t('studies.email')} *
+		</label>
+		<input
+			class="input w-full"
+			id="StudyPIemail"
+			name="StudyPIemail"
+			type="email"
+			bind:value={studyPIemail}
+			required
+		/>
 
 		<!-- submit, cancel and delete buttons -->
 		<div class="mt-4 mb-6">
diff --git a/frontend/src/lib/types/study.ts b/frontend/src/lib/types/study.ts
index 16f235ef..060231d3 100644
--- a/frontend/src/lib/types/study.ts
+++ b/frontend/src/lib/types/study.ts
@@ -22,8 +22,11 @@ export default class Study {
 	private _consentParticipation: string;
 	private _consentPrivacy: string;
 	private _consentRights: string;
-	private _consentStudyData: string;
 	private _tests: Test[];
+	private _studyOrganisation: string;
+	private _studyAddress: string;
+	private _studyContact: string;
+	private _studyPIemail: string;
 
 	private constructor(
 		id: number,
@@ -36,8 +39,11 @@ export default class Study {
 		consentParticipation: string,
 		consentPrivacy: string,
 		consentRights: string,
-		consentStudyData: string,
-		tests: Test[]
+		tests: Test[],
+		studyOrganisation: string,
+		studyAddress: string,
+		studyContact: string,
+		studyPIemail: string
 	) {
 		this._id = id;
 		this._title = title;
@@ -49,8 +55,11 @@ export default class Study {
 		this._consentParticipation = consentParticipation;
 		this._consentPrivacy = consentPrivacy;
 		this._consentRights = consentRights;
-		this._consentStudyData = consentStudyData;
 		this._tests = tests;
+		this._studyOrganisation = studyOrganisation;
+		this._studyAddress = studyAddress;
+		this._studyContact = studyContact;
+		this._studyPIemail = studyPIemail;
 	}
 
 	get id(): number {
@@ -133,14 +142,6 @@ export default class Study {
 		this._consentRights = value;
 	}
 
-	get consentStudyData(): string {
-		return this._consentStudyData;
-	}
-
-	set consentStudyData(value: string) {
-		this._consentStudyData = value;
-	}
-
 	get tests(): Test[] {
 		return this._tests;
 	}
@@ -149,6 +150,38 @@ export default class Study {
 		this._tests = value;
 	}
 
+	get studyOrganisation(): string {
+		return this._studyOrganisation;
+	}
+
+	set studyOrganisation(value: string) {
+		this._studyOrganisation = value;
+	}
+
+	get studyAddress(): string {
+		return this._studyAddress;
+	}
+
+	set studyAddress(value: string) {
+		this._studyAddress = value;
+	}
+
+	get studyContact(): string {
+		return this._studyContact;
+	}
+
+	set studyContact(value: string) {
+		this._studyContact = value;
+	}
+
+	get studyPIemail(): string {
+		return this._studyPIemail;
+	}
+
+	set studyPIemail(value: string) {
+		this._studyPIemail = value;
+	}
+
 	/**
 	 * Creates a new Study and saves it in the database.
 	 * @async
@@ -165,6 +198,10 @@ export default class Study {
 		consentRights: string,
 		consentStudyData: string,
 		tests: Test[],
+		studyOrganisation: string,
+		studyAddress: string,
+		studyContact: string,
+		studyPIemail: string,
 		users: User[],
 		f: fetchType = fetch
 	): Promise<Study | null> {
@@ -179,7 +216,10 @@ export default class Study {
 			consentParticipation,
 			consentPrivacy,
 			consentRights,
-			consentStudyData,
+			studyOrganisation,
+			studyAddress,
+			studyContact,
+			studyPIemail,
 			users.map((u) => u.id)
 		);
 
@@ -195,8 +235,11 @@ export default class Study {
 				consentParticipation,
 				consentPrivacy,
 				consentRights,
-				consentStudyData,
-				tests
+				tests,
+				studyOrganisation,
+				studyAddress,
+				studyContact,
+				studyPIemail
 			);
 		}
 		return null;
@@ -228,7 +271,10 @@ export default class Study {
 			if (data.consent_participation) this._consentParticipation = data.consent_participation;
 			if (data.consent_privacy) this._consentPrivacy = data.consent_privacy;
 			if (data.consent_rights) this._consentRights = data.consent_rights;
-			if (data.consent_study_data) this._consentStudyData = data.consent_study_data;
+			if (data.study_organisation) this._studyOrganisation = data.study_organisation;
+			if (data.study_address) this._studyAddress = data.study_address;
+			if (data.study_contact) this._studyContact = data.study_contact;
+			if (data.study_pi_email) this._studyPIemail = data.study_pi_email;
 			if (data.tests) this._tests = data.tests;
 			return true;
 		}
@@ -292,8 +338,11 @@ export default class Study {
 			json.consent_participation,
 			json.consent_privacy,
 			json.consent_rights,
-			json.consent_study_data,
-			[]
+			[],
+			json.study_data_organisation,
+			json.study_data_address,
+			json.study_data_contact,
+			json.study_data_email
 		);
 
 		study._users = User.parseAll(json.users);
-- 
GitLab


From a2bcc5c2f57dea5aeda71a77f71d97d5cab409ad Mon Sep 17 00:00:00 2001
From: delphvr <delphine.vanrossum@student.uclouvain.be>
Date: Tue, 11 Mar 2025 12:19:53 +0100
Subject: [PATCH 2/3] study data divided in 4 fields

---
 frontend/src/lib/api/studies.ts               | 10 ++++++--
 .../routes/admin/studies/new/+page.server.ts  | 24 +++++++++++++------
 2 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/frontend/src/lib/api/studies.ts b/frontend/src/lib/api/studies.ts
index c4fa2439..8d116735 100644
--- a/frontend/src/lib/api/studies.ts
+++ b/frontend/src/lib/api/studies.ts
@@ -31,7 +31,10 @@ export async function createStudyAPI(
 	consentParticipation: string,
 	consentPrivacy: string,
 	consentRights: string,
-	consentStudyData: string,
+	studyOrganisation: string,
+	studyAddress: string,
+	studyContact: string,
+	studyPIemail: string,
 	user_ids: number[]
 ): Promise<number | null> {
 	const response = await fetch('/api/studies', {
@@ -47,7 +50,10 @@ export async function createStudyAPI(
 			consent_participation: consentParticipation,
 			consent_privacy: consentPrivacy,
 			consent_rights: consentRights,
-			consent_study_data: consentStudyData,
+			study_data_organisation: studyOrganisation,
+			study_data_address: studyAddress,
+			study_data_contact: studyContact,
+			study_data_email: studyPIemail,
 			user_ids
 		})
 	});
diff --git a/frontend/src/routes/admin/studies/new/+page.server.ts b/frontend/src/routes/admin/studies/new/+page.server.ts
index be9f5194..09b23ed3 100644
--- a/frontend/src/routes/admin/studies/new/+page.server.ts
+++ b/frontend/src/routes/admin/studies/new/+page.server.ts
@@ -14,7 +14,10 @@ export const actions: Actions = {
 		const consentParticipation = formData.get('consentParticipation')?.toString();
 		const consentPrivacy = formData.get('consentPrivacy')?.toString();
 		const consentRights = formData.get('consentRights')?.toString();
-		const consentStudyData = formData.get('consentStudyData')?.toString();
+		const studyOrganisation = formData.get('StudyOrganisation')?.toString();
+		const studyAddress = formData.get('StudyAddress')?.toString();
+		const studyContact = formData.get('StudyContact')?.toString();
+		const studyPIemail = formData.get('StudyPIemail')?.toString();
 
 		if (
 			!title ||
@@ -24,10 +27,13 @@ export const actions: Actions = {
 			!consentParticipation ||
 			!consentPrivacy ||
 			!consentRights ||
-			!consentStudyData
+			!studyOrganisation ||
+			!studyAddress ||
+			!studyContact ||
+			!studyPIemail
 		) {
 			return {
-				message: 'Invalid request 1'
+				message: 'Invalid request: Missing required fields'
 			};
 		}
 
@@ -40,20 +46,20 @@ export const actions: Actions = {
 
 		if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
 			return {
-				message: 'Invalid request 2'
+				message: 'Invalid request: Invalid dates'
 			};
 		}
 
 		const nbSession = parseInt(nbSessionStr, 10);
 		if (isNaN(nbSession)) {
 			return {
-				message: 'Invalid request 3'
+				message: 'Invalid request: Invalid number of sessions'
 			};
 		}
 
 		if (startDate.getTime() > endDate.getTime()) {
 			return {
-				message: 'End time cannot be before start time'
+				message: 'End date cannot be before start date'
 			};
 		}
 
@@ -81,7 +87,10 @@ export const actions: Actions = {
 			consentParticipation,
 			consentPrivacy,
 			consentRights,
-			consentStudyData,
+			studyOrganisation,
+			studyAddress,
+			studyContact,
+			studyPIemail,
 			user_ids
 		);
 
@@ -94,3 +103,4 @@ export const actions: Actions = {
 		return redirect(303, '/admin/studies');
 	}
 };
+null as any as Actions;
-- 
GitLab


From bdf5b897b7c1d7e2daecd26fa183461bdc17b919 Mon Sep 17 00:00:00 2001
From: delphvr <delphine.vanrossum@student.uclouvain.be>
Date: Tue, 11 Mar 2025 15:49:56 +0100
Subject: [PATCH 3/3] alembic update script

---
 ...fa66b7_study_data_divided_in_more_field.py | 37 +++++++++++++++++++
 1 file changed, 37 insertions(+)
 create mode 100644 backend/alembic/versions/c4ff1cfa66b7_study_data_divided_in_more_field.py

diff --git a/backend/alembic/versions/c4ff1cfa66b7_study_data_divided_in_more_field.py b/backend/alembic/versions/c4ff1cfa66b7_study_data_divided_in_more_field.py
new file mode 100644
index 00000000..b00a4956
--- /dev/null
+++ b/backend/alembic/versions/c4ff1cfa66b7_study_data_divided_in_more_field.py
@@ -0,0 +1,37 @@
+"""study_data_divided_in_more_field
+
+Revision ID: c4ff1cfa66b7
+Revises: 344d94d32fa1
+Create Date: 2025-03-11 15:37:02.225207
+
+"""
+
+from typing import Sequence, Union
+
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision: str = "c4ff1cfa66b7"
+down_revision: Union[str, None] = "344d94d32fa1"
+branch_labels: Union[str, Sequence[str], None] = None
+depends_on: Union[str, Sequence[str], None] = None
+
+
+def upgrade() -> None:
+    op.drop_column("studies", "consent_study_data")
+    op.add_column(
+        "studies", sa.Column("study_data_organisation", sa.String, nullable=False)
+    )
+    op.add_column("studies", sa.Column("study_data_address", sa.String, nullable=False))
+    op.add_column("studies", sa.Column("study_data_contact", sa.String, nullable=False))
+    op.add_column("studies", sa.Column("study_data_email", sa.String, nullable=False))
+
+
+def downgrade() -> None:
+    op.add_column("studies", sa.Column("consent_study_data", sa.String, nullable=False))
+    op.drop_column("studies", "study_data_organisation")
+    op.drop_column("studies", "study_data_address")
+    op.drop_column("studies", "study_data_contact")
+    op.drop_column("studies", "study_data_email")
-- 
GitLab