From 9d6898feaed9eefe94ffbad62daa89ec964c12e4 Mon Sep 17 00:00:00 2001 From: iaigner Date: Fri, 10 Nov 2023 09:06:08 +0100 Subject: [PATCH 001/182] MORE2-9: Relative Scheduler Dialog + small adaptations --- openapi/Event.yaml | 3 + openapi/RelativeEvent.yaml | 62 +++ openapi/StudyManagerAPI.yaml | 17 +- src/components/ObservationList.vue | 4 +- src/components/dialog/ObservationDialog.vue | 22 +- src/components/shared/RelativeScheduler.vue | 493 ++++++++++++++++++ src/components/shared/Scheduler.vue | 1 + .../subComponents/SchedulerInfoBlock.vue | 38 +- src/i18n/de.json | 53 +- src/i18n/en.json | 56 +- 10 files changed, 726 insertions(+), 23 deletions(-) create mode 100644 openapi/RelativeEvent.yaml create mode 100644 src/components/shared/RelativeScheduler.vue diff --git a/openapi/Event.yaml b/openapi/Event.yaml index 8f9ba706..33b0dc87 100644 --- a/openapi/Event.yaml +++ b/openapi/Event.yaml @@ -9,6 +9,9 @@ components: Event: type: object properties: + type: + type: string + default: Event dtstart: type: string format: date-time diff --git a/openapi/RelativeEvent.yaml b/openapi/RelativeEvent.yaml new file mode 100644 index 00000000..2e6833f1 --- /dev/null +++ b/openapi/RelativeEvent.yaml @@ -0,0 +1,62 @@ +openapi: "3.0.3" +info: + title: TimeRange Model for Relative Events + version: "1.0" + +components: + schemas: + Duration: + type: object + description: A duration of time + properties: + value: + type: integer + description: number of units + unit: + type: string + description: unit of time + enum: + - MINUTE + - HOUR + - DAY + RelativeDate: + type: object + description: A date relative to a specific base date (e.g study start) + properties: + offset: + $ref: '#/components/schemas/Duration' + time: + type: string + format: time + description: Follows ISO 8601 format for time + RelativeRecurrenceRule: + type: object + description: A recurrence rule relative to dtstart + properties: + frequency: + $ref: '#/components/schemas/Duration' + description: How often to repeat + endAfter: + $ref: '#/components/schemas/Duration' + description: How long to repeat + + RelativeEvent: + type: object + description: An event that occurs at a relative time + required: + - type + - dtstart + - dtend + properties: + type: + type: string + default: RelativeEvent + dtstart: + $ref: '#/components/schemas/RelativeDate' + description: When the event starts + dtend: + $ref: '#/components/schemas/RelativeDate' + description: When the event ends + rrrule: + $ref: '#/components/schemas/RelativeRecurrenceRule' + description: How to repeat the event diff --git a/openapi/StudyManagerAPI.yaml b/openapi/StudyManagerAPI.yaml index d36dbb8e..38fee259 100644 --- a/openapi/StudyManagerAPI.yaml +++ b/openapi/StudyManagerAPI.yaml @@ -1422,7 +1422,16 @@ components: type: object additionalProperties: true schedule: - $ref: './Event.yaml/#/components/schemas/Event' + oneOf: + - $ref: './Event.yaml/#/components/schemas/Event' + - $ref: './RelativeEvent.yaml/#/components/schemas/RelativeEvent' + discriminator: + propertyName: type + # mapping: + # event: + # $ref: './Event.yaml/#/components/schemas/Event' + # relativeEvent: + # $ref: './RelativeEvent.yaml/#/components/schemas/RelativeEvent' created: type: string format: date-time @@ -1514,7 +1523,11 @@ components: purpose: type: string schedule: - $ref: './Event.yaml/#/components/schemas/Event' + oneOf: + - $ref: './Event.yaml/#/components/schemas/Event' + - $ref: './RelativeEvent.yaml/#/components/schemas/RelativeEvent' + discriminator: + propertyName: type trigger: $ref: '#/components/schemas/Trigger' actions: diff --git a/src/components/ObservationList.vue b/src/components/ObservationList.vue index 9c2370cf..08a7a060 100644 --- a/src/components/ObservationList.vue +++ b/src/components/ObservationList.vue @@ -116,6 +116,7 @@ columnWidth: '3vw', editable: true, }, + /* { field: 'schedule.dtstart', header: t('global.labels.start'), @@ -129,7 +130,7 @@ type: MoreTableFieldType.nestedDatetime, columnWidth: '3vw', sortable: true, - }, + }, */ ]; const tableActions: MoreTableAction[] = [ @@ -367,7 +368,6 @@ openObservationDialog(dialogTitle, observation); } } - listObservations(); diff --git a/src/components/dialog/ObservationDialog.vue b/src/components/dialog/ObservationDialog.vue index 05d2e7fd..180681a6 100644 --- a/src/components/dialog/ObservationDialog.vue +++ b/src/components/dialog/ObservationDialog.vue @@ -6,12 +6,13 @@ import Dropdown from 'primevue/dropdown'; import { Observation, - Event, ValidationReport, StudyStatus, + ObservationSchedule, } from '../../generated-sources/openapi'; import { MoreTableChoice } from '../../models/MoreTableModel'; import Scheduler from '../shared/Scheduler.vue'; + import RelativeScheduler from '../shared/RelativeScheduler.vue'; import { useDialog } from 'primevue/usedialog'; import { useComponentsApi } from '../../composable/useApi'; import { useStudyStore } from '../../stores/studyStore'; @@ -52,9 +53,10 @@ : factory.visibility.hiddenByDefault ); - const scheduler: Ref = ref( + const scheduler: Ref = ref( observation.schedule ? observation.schedule : {} ); + const studyGroupId = ref(observation.studyGroupId); const jsonError = ref(); @@ -67,13 +69,17 @@ return undefined; } - function openScheduler() { - dialog.open(Scheduler, { + function openScheduler(schedulerType: string) { + dialog.open(schedulerType === 'relative' ? RelativeScheduler : Scheduler, { data: { scheduler: scheduler.value, + schedulerType: scheduler.value.type, }, props: { - header: t('scheduler.dialogTitle'), + header: + schedulerType === 'relative' + ? t('scheduler.relativeDialogTitle') + : t('scheduler.dialogTitle'), style: { width: '50vw', }, @@ -91,7 +97,6 @@ }, }); } - function validate() { let parsedProps: any; try { @@ -133,7 +138,6 @@ }; } } - console.log(scheduler.value); const returnObservation = { observationId: observation.observationId, @@ -241,7 +245,7 @@ diff --git a/src/components/shared/RelativeScheduler.vue b/src/components/shared/RelativeScheduler.vue new file mode 100644 index 00000000..ff020b66 --- /dev/null +++ b/src/components/shared/RelativeScheduler.vue @@ -0,0 +1,493 @@ + + + + + diff --git a/src/components/shared/Scheduler.vue b/src/components/shared/Scheduler.vue index 5dda6b03..a7c2aaef 100644 --- a/src/components/shared/Scheduler.vue +++ b/src/components/shared/Scheduler.vue @@ -458,6 +458,7 @@ if (!calendarInputErrors.value.start && !calendarInputErrors.value.end) { try { const returnEvent: Event = { + type: 'Event', dtstart: s.toISOString(), dtend: e.toISOString(), rrule: undefined, diff --git a/src/components/subComponents/SchedulerInfoBlock.vue b/src/components/subComponents/SchedulerInfoBlock.vue index 1ae180e5..601a60ee 100644 --- a/src/components/subComponents/SchedulerInfoBlock.vue +++ b/src/components/subComponents/SchedulerInfoBlock.vue @@ -1,14 +1,18 @@ @@ -98,4 +104,13 @@ opacity: 0; } } + + .cron-rel-warning { + border: 1px solid var(--surface-50); + border-radius: 6px; + background-color: var(--surface-50); + } + .warning-icon { + font-size: 30px; + } diff --git a/src/i18n/de.json b/src/i18n/de.json index f2c7491f..5380f59f 100644 --- a/src/i18n/de.json +++ b/src/i18n/de.json @@ -34,7 +34,8 @@ "to": "zu", "message": "Nachricht", "option": "Option", - "data": "Daten" + "data": "Daten", + "scheduleType": "Zeitplan-Typ" }, "placeholder": { "entireStudy": "Gesamte Studie", @@ -852,6 +853,8 @@ "timeOutsideStudyRange": "Bitte stellen Sie sicher, dass das Start- und Enddatum sich innerhalb der Studiendauer befindet." }, "dialog": { + "description": "Ein relativer Zeitplan wird durch die tatsächliche Anmeldezeit jedes Teilnehmers bestimmt. Sie können jederzeit zwischen dem Beginn und Ende der Studie starten, und die festgelegte Dauer umfasst ihren aktiven Beteiligungszeitraum.", + "noSetScheduleDesc": "Wenn kein Schedule gesetzt wird, wird die gesamte Studienzeit als Standard-Zeitraum als absoluter Zeitplan verwendet.", "repeatEvent": "Event wiederholen", "singleEventTitle": "Einzelnes Datenerhebungs-Event", "repeatEventTitle": "Datenerhebungs-Event wiederholen", @@ -860,14 +863,15 @@ "endAfter": "Ende nach", "relativeSchedule": { "dialogTitle":"Relativen Zeitplan verwalten", - "description": "Ein relativer Zeitplan wird durch die tatsächliche Anmeldezeit jedes Teilnehmers bestimmt. Sie können jederzeit zwischen dem Beginn und Ende der Studie starten, und die festgelegte Dauer umfasst ihren aktiven Beteiligungszeitraum.", - "noSetScheduleDesc": "Wenn kein Schedule gesetzt wird, wird die gesamte Studienzeit als Standard-Zeitraum als absoluter Zeitplan verwendet.", "startValue": "Startet am", "endValue": "Endet am", - "ends": "Endet", - "endsAfter": "Tage nach dem individuellen Studienstart.", - "repeated": "Wiederholung", - "times": "Mal", + "interventionWarning": "Beachten Sie, dass das Festlegen eines absoluten Datums (Einstellen von Tag oder Monat) über den Cron-Zeitplan möglicherweise nicht besonders effektiv ist, wenn Sie mit relativen Beobachtungsplänen arbeiten. Relative Beobachtungspläne werden auf Grundlage des individuellen Studienbeginns der Teilnehmer (Anmeldung) berechnet.", + "rrule": { + "ends": "Endet", + "endsAfter": "Tage nach dem individuellen Studienstart.", + "repeated": "Wiederholung", + "times": "Mal" + }, "placeholder": { "dtstartOffset": "Offset in Tage(n)", "dtstartTime": "Strat Zeit", diff --git a/src/i18n/en.json b/src/i18n/en.json index 7ed701e7..5e633dd7 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -34,7 +34,8 @@ "to": "to", "message": "Message", "option": "Option", - "data": "Data" + "data": "Data", + "scheduleType": "Schedule Type" }, "placeholder": { "entireStudy": "Entire study", @@ -905,6 +906,7 @@ "description": "A relative schedule is determined by each participant's actual log-in time. They can start anytime between the study's beginning and end, and the set duration covers their active participation period.", "startValue": "Starts on", "endValue": "Ends on", + "interventionWarning": "Note that setting an absolute date (setting day or month) via cron scheduler might not be that effective when working with relative observation schedules. Relative observation schedules will be calculated based on the individual study start of participants (log in).", "rrrule": { "ends": "Ends", "endsAfter": "days after individual study start.", From ce9efaa7e79af78456d3b58231b0b840b4f5f685 Mon Sep 17 00:00:00 2001 From: iaigner Date: Tue, 14 Nov 2023 10:34:30 +0100 Subject: [PATCH 009/182] MORE2-12: fix calculation, some small styling problems, etc. --- src/components/dialog/ObservationDialog.vue | 1 - src/components/shared/RelativeScheduler.vue | 36 +++++++++++-------- .../subComponents/SchedulerInfoBlock.vue | 33 ++++++++++++----- src/i18n/de.json | 26 ++++++++++++++ src/i18n/en.json | 4 ++- 5 files changed, 75 insertions(+), 25 deletions(-) diff --git a/src/components/dialog/ObservationDialog.vue b/src/components/dialog/ObservationDialog.vue index c8057cb9..74f0f866 100644 --- a/src/components/dialog/ObservationDialog.vue +++ b/src/components/dialog/ObservationDialog.vue @@ -239,7 +239,6 @@
- {{ $t('scheduler.dialog.relativeSchedule.startValue') }} + {{ $t('scheduler.preview.unit.date') }}
- {{ $t('scheduler.dialog.relativeSchedule.endValue') }} + {{ $t('scheduler.preview.unit.time') }}
@@ -404,7 +412,7 @@
- + {{ $t('scheduler.dialog.relativeSchedule.error.rrrule.notValid') }} @@ -468,7 +476,7 @@
-
+