Skip to content

Commit ed8a65b

Browse files
authored
Merge pull request #11 from redlink-gmbh/umm/MORE-Platform#252-extend-studymanager-frontend-with-observation-groups
Umm/MORE-Platform#252 extend studymanager frontend with observation groups
2 parents c5208b9 + 98bffae commit ed8a65b

18 files changed

Lines changed: 947 additions & 118 deletions

openapi/StudyManagerAPI.yaml

Lines changed: 173 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
openapi: 3.0.2
1+
openapi: 3.0.3
22
info:
33
version: 1.0.0
44
title: StudyManager API
@@ -350,6 +350,10 @@ paths:
350350
in: query
351351
schema:
352352
$ref: '#/components/schemas/Id'
353+
- name: observationGroup
354+
in: query
355+
schema:
356+
$ref: '#/components/schemas/Id'
353357
- name: referenceDate
354358
in: query
355359
description: reference date used to calculate relative schedules
@@ -476,6 +480,110 @@ paths:
476480
'404':
477481
description: Not found
478482

483+
/studies/{studyId}/observationGroups:
484+
post:
485+
tags:
486+
- observationGroups
487+
operationId: createObservationGroup
488+
description: Create a new observation group for a study
489+
parameters:
490+
- $ref: '#/components/parameters/StudyId'
491+
requestBody:
492+
required: true
493+
content:
494+
application/json:
495+
schema:
496+
$ref: '#/components/schemas/ObservationGroup'
497+
responses:
498+
'201':
499+
description: Observation group successfully created
500+
content:
501+
application/json:
502+
schema:
503+
$ref: '#/components/schemas/ObservationGroup'
504+
'400':
505+
description: Observation group creation failed because of a bad request
506+
'500':
507+
description: Error while creating the observation group
508+
get:
509+
tags:
510+
- observationGroups
511+
description: List all observation groups for a study
512+
operationId: listObservationGroups
513+
parameters:
514+
- $ref: '#/components/parameters/StudyId'
515+
responses:
516+
'200':
517+
description: Successfully listed all observation groups
518+
content:
519+
application/json:
520+
schema:
521+
type: array
522+
items:
523+
$ref: '#/components/schemas/ObservationGroup'
524+
'404':
525+
description: No study for the parsed studyId found
526+
527+
/studies/{studyId}/observationGroups/{observationGroupId}:
528+
get:
529+
tags:
530+
- observationGroups
531+
description: Get observation group information
532+
operationId: getObservationGroup
533+
parameters:
534+
- $ref: '#/components/parameters/StudyId'
535+
- $ref: '#/components/parameters/ObservationGroupId'
536+
responses:
537+
'200':
538+
description: Successfully returned observation group information
539+
content:
540+
application/json:
541+
schema:
542+
$ref: '#/components/schemas/ObservationGroup'
543+
'404':
544+
description: Not found
545+
put:
546+
tags:
547+
- observationGroups
548+
description: Update a observation group
549+
operationId: updateObservationGroup
550+
parameters:
551+
- $ref: '#/components/parameters/StudyId'
552+
- $ref: '#/components/parameters/ObservationGroupId'
553+
requestBody:
554+
content:
555+
application/json:
556+
schema:
557+
$ref: '#/components/schemas/ObservationGroup'
558+
responses:
559+
'200':
560+
description: Successfully updated observation group
561+
content:
562+
application/json:
563+
schema:
564+
$ref: '#/components/schemas/ObservationGroup'
565+
'400':
566+
description: Could not update study group because of a bad request
567+
'404':
568+
description: Not found
569+
'500':
570+
description: Error while updating the observation group
571+
delete:
572+
tags:
573+
- observationGroups
574+
description: Delete a observation group
575+
operationId: deleteObservationGroup
576+
parameters:
577+
- $ref: '#/components/parameters/StudyId'
578+
- $ref: '#/components/parameters/ObservationGroupId'
579+
responses:
580+
'200':
581+
description: Observation group deleted
582+
'404':
583+
description: Not found
584+
'500':
585+
description: Error while deleting the observation group
586+
479587
/studies/{studyId}/participants:
480588
post:
481589
tags:
@@ -1657,6 +1765,36 @@ components:
16571765
type: string
16581766
format: date-time
16591767
readOnly: true
1768+
ObservationGroup:
1769+
type: object
1770+
properties:
1771+
studyId:
1772+
$ref: '#/components/schemas/StudyId'
1773+
observationGroupId:
1774+
$ref: '#/components/schemas/Id'
1775+
title:
1776+
type: string
1777+
purpose:
1778+
type: string
1779+
numberOfParticipants:
1780+
type: integer
1781+
readOnly: true
1782+
numberOfObservations:
1783+
type: integer
1784+
readOnly: true
1785+
numberOfInterventions:
1786+
type: integer
1787+
readOnly: true
1788+
created:
1789+
type: string
1790+
format: date-time
1791+
readOnly: true
1792+
modified:
1793+
type: string
1794+
format: date-time
1795+
readOnly: true
1796+
required:
1797+
- title
16601798
StudyDuration:
16611799
type: object
16621800
properties:
@@ -1701,6 +1839,12 @@ components:
17011839
type: string
17021840
format: date-time
17031841
readOnly: true
1842+
observationGroupIds:
1843+
type: array
1844+
description: The set of observation group Ids the participant is part of
1845+
items:
1846+
$ref: '#/components/schemas/IdReference'
1847+
uniqueItems: true
17041848
created:
17051849
type: string
17061850
format: date-time
@@ -1746,11 +1890,6 @@ components:
17461890
- $ref: './RelativeEvent.yaml/#/components/schemas/RelativeEvent'
17471891
discriminator:
17481892
propertyName: type
1749-
# mapping:
1750-
# event:
1751-
# $ref: './Event.yaml/#/components/schemas/Event'
1752-
# relativeEvent:
1753-
# $ref: './RelativeEvent.yaml/#/components/schemas/RelativeEvent'
17541893
created:
17551894
type: string
17561895
format: date-time
@@ -1764,6 +1903,12 @@ components:
17641903
noSchedule:
17651904
type: boolean
17661905
default: false
1906+
observationGroupIds:
1907+
type: array
1908+
description: The set of observation group Ids the observation is part of
1909+
items:
1910+
$ref: '#/components/schemas/IdReference'
1911+
uniqueItems: true
17671912

17681913
OccurredObservation:
17691914
type: object
@@ -1990,6 +2135,12 @@ components:
19902135
type: array
19912136
items:
19922137
$ref: '#/components/schemas/Action'
2138+
observationGroupIds:
2139+
type: array
2140+
description: The set of observation group Ids the intervention is part of
2141+
items:
2142+
$ref: '#/components/schemas/IdReference'
2143+
uniqueItems: true
19932144
created:
19942145
type: string
19952146
format: date-time
@@ -2059,6 +2210,10 @@ components:
20592210
type: array
20602211
items:
20612212
$ref: '#/components/schemas/StudyGroup'
2213+
observationGroups:
2214+
type: array
2215+
items:
2216+
$ref: '#/components/schemas/ObservationGroup'
20622217
observations:
20632218
type: array
20642219
items:
@@ -2081,6 +2236,11 @@ components:
20812236
properties:
20822237
studyGroup:
20832238
type: integer
2239+
observationGroups:
2240+
type: array
2241+
items:
2242+
type: integer
2243+
uniqueItems: true
20842244

20852245
IntegrationInfo:
20862246
type: object
@@ -2441,6 +2601,13 @@ components:
24412601
type: integer
24422602
format: int32
24432603
required: true
2604+
ObservationGroupId:
2605+
name: observationGroupId
2606+
in: path
2607+
schema:
2608+
type: integer
2609+
format: int32
2610+
required: true
24442611
ParticipantId:
24452612
name: participantId
24462613
in: path

src/components/InterventionsList.vue

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Licensed under the Elastic License 2.0. */
1515
ComponentFactory,
1616
StudyRole,
1717
StudyStatus,
18-
ListComponentsComponentTypeEnum, Observation
18+
ListComponentsComponentTypeEnum, Observation, ObservationGroup
1919
} from '@gs';
2020
import {
2121
MoreTableAction,
@@ -24,7 +24,7 @@ Licensed under the Elastic License 2.0. */
2424
MoreTableRowActionResult,
2525
MoreTableChoice,
2626
MoreTableSortOptions,
27-
RowSelectionMode,
27+
RowSelectionMode, MoreInterventionListTableRow
2828
} from '../models/MoreTableModel';
2929
import ConfirmDialog from 'primevue/confirmdialog';
3030
import DynamicDialog from 'primevue/dynamicdialog';
@@ -45,12 +45,13 @@ Licensed under the Elastic License 2.0. */
4545
const { t } = useI18n();
4646
const { handleIndividualError } = useErrorHandling();
4747
48-
const interventionList: Ref<Intervention[]> = ref([]);
48+
const interventionList: Ref<MoreInterventionListTableRow[]> = ref([]);
4949
const dialog = useDialog();
5050
5151
const props = defineProps({
5252
studyId: { type: Number, required: true },
5353
studyGroups: { type: Array as PropType<Array<StudyGroup>>, required: true },
54+
observationGroups: { type: Array as PropType<Array<ObservationGroup>>, required: true},
5455
studyStatus: { type: String as PropType<StudyStatus>, required: true },
5556
});
5657
@@ -76,6 +77,18 @@ Licensed under the Elastic License 2.0. */
7677
value: null,
7778
} as MoreTableChoice);
7879
80+
const observationGroupStatuses: MoreTableChoice[] = props.observationGroups.map(
81+
(observationGroup) =>
82+
({
83+
label: observationGroup.title,
84+
value: observationGroup.observationGroupId?.toString(),
85+
}) as MoreTableChoice,
86+
);
87+
88+
function getObservationGroupItem(id: number): MoreTableChoice | undefined {
89+
return observationGroupStatuses?.find((groupStatus) => groupStatus.value === id.toString())
90+
}
91+
7992
async function getActionFactories(): Promise<ComponentFactory[]> {
8093
return componentsApi
8194
.listComponents(ListComponentsComponentTypeEnum.Action)
@@ -114,6 +127,19 @@ Licensed under the Elastic License 2.0. */
114127
placeholder: t('global.placeholder.entireStudy'),
115128
columnWidth: '10vw',
116129
},
130+
{
131+
field: 'observationGroupValues',
132+
header: t('observationGroup.plural'),
133+
type: MoreTableFieldType.multiselect,
134+
arrayLabels: observationGroupStatuses,
135+
editable: {
136+
enabled: actionsVisible,
137+
values: observationGroupStatuses
138+
},
139+
sortable: true,
140+
placeholder: t('global.placeholder.noGroup'),
141+
columnWidth: '10vw'
142+
},
117143
];
118144
119145
const rowActions: MoreTableAction[] = [
@@ -206,6 +232,10 @@ Licensed under the Elastic License 2.0. */
206232
studyId: intervention.studyId,
207233
interventionId: intervention.interventionId,
208234
studyGroupId: intervention.studyGroupId,
235+
observationGroupIds: intervention.observationGroupIds,
236+
observationGroupValues: intervention.observationGroupIds?.length
237+
? intervention.observationGroupIds?.map((id) => getObservationGroupItem(id))
238+
: [],
209239
title: intervention.title,
210240
purpose: intervention.purpose,
211241
schedule: intervention.schedule,
@@ -285,12 +315,16 @@ Licensed under the Elastic License 2.0. */
285315
}
286316
}
287317
288-
async function changeValue(intervention: Intervention): Promise<void> {
318+
async function changeValue(intervention: MoreInterventionListTableRow): Promise<void> {
319+
const {observationGroupValues, ...newIntervention} = intervention
289320
await interventionsApi
290321
.updateIntervention(
291322
props.studyId,
292-
intervention.interventionId as number,
293-
intervention,
323+
newIntervention.interventionId as number,
324+
{
325+
...newIntervention,
326+
observationGroupIds: observationGroupValues?.map((choice: MoreTableChoice) => parseInt(choice.value as string)) ?? []
327+
},
294328
)
295329
.then(listInterventions)
296330
.catch((e: AxiosError) =>

0 commit comments

Comments
 (0)