From 798670a825469adfb9bf31e2e53afc8ec3f75a38 Mon Sep 17 00:00:00 2001 From: Martin Ndegwa Date: Fri, 19 Apr 2024 19:00:27 +0300 Subject: [PATCH 1/7] Add List Entry to Transform Services - StructureMap extraction --- .../fhircore/engine/util/helper/TransformSupportServices.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/android/engine/src/main/java/org/smartregister/fhircore/engine/util/helper/TransformSupportServices.kt b/android/engine/src/main/java/org/smartregister/fhircore/engine/util/helper/TransformSupportServices.kt index 40f7a9d566..2fed60e047 100644 --- a/android/engine/src/main/java/org/smartregister/fhircore/engine/util/helper/TransformSupportServices.kt +++ b/android/engine/src/main/java/org/smartregister/fhircore/engine/util/helper/TransformSupportServices.kt @@ -28,6 +28,7 @@ import org.hl7.fhir.r4.model.Encounter import org.hl7.fhir.r4.model.EpisodeOfCare import org.hl7.fhir.r4.model.Group import org.hl7.fhir.r4.model.Immunization +import org.hl7.fhir.r4.model.ListResource import org.hl7.fhir.r4.model.Location import org.hl7.fhir.r4.model.Observation import org.hl7.fhir.r4.model.Patient @@ -81,6 +82,7 @@ class TransformSupportServices @Inject constructor(val simpleWorkerContext: Simp "Task_Restriction" -> Task.TaskRestrictionComponent() "AdverseEvent_SuspectEntity" -> AdverseEvent.AdverseEventSuspectEntityComponent() "Location_Position" -> Location.LocationPositionComponent() + "List_Entry" -> ListResource.ListEntryComponent() else -> ResourceFactory.createResourceOrType(name) } } From bcd251deba88144dc19e718c0751b63121bb302b Mon Sep 17 00:00:00 2001 From: Martin Ndegwa Date: Fri, 19 Apr 2024 19:01:03 +0300 Subject: [PATCH 2/7] Migrate Engine, SDC and Knowledger artifacts --- android/gradle/libs.versions.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index 069f9896c6..f8470638dd 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -16,14 +16,14 @@ android-x-test= "1.5.2" core-testing = "2.2.0" coverallsGradlePlugin = "2.12.0" cqfFhirCr = "3.0.0-PRE9" -data-capture = "1.1.0-preview7-SNAPSHOT" +data-capture = "1.1.0-preview8-SNAPSHOT" datastore = "1.0.0" desugar-jdk-libs = "2.0.4" dokkaBase = "1.8.20" easy-rules-jexl = "4.1.0" espresso-core = "3.5.1" fhir-common-utils = "1.0.0-SNAPSHOT" -fhir-engine = "1.0.0-preview5-SNAPSHOT" +fhir-engine = "1.0.0-preview6-SNAPSHOT" foundation = "1.6.3" fragment-ktx = "1.6.2" glide = "4.16.0" @@ -37,7 +37,7 @@ jsonPath = "2.8.0" junit = "1.1.5" junit-jupiter = "5.9.1" junit-ktx = "1.1.5" -knowledge = "0.1.0-alpha03-preview3.1-SNAPSHOT" +knowledge = "0.1.0-alpha03-preview4-SNAPSHOT" kotlin = "1.9.22" kotlinx-coroutines = "1.7.3" kotlinx-serialization-json = "1.6.0" From 9fe0d24ee7cb16ec9902a08f58d1cc8059ce8de9 Mon Sep 17 00:00:00 2001 From: Brandy Date: Mon, 22 Apr 2024 03:22:51 +0300 Subject: [PATCH 3/7] Test variable evaluation via cqf expressions (#3200) * set up the file * adds the intro part * adds how to work with today function * adds how to add dob as lower bound of date picker * concludes * update cqf expression documentation * revert location change * cleanup --------- Co-authored-by: ageryck Co-authored-by: pld --- .../config-types/forms/_category_.yml | 1 + .../{ => forms}/questionnaire.mdx | 2 +- .../config-types/forms/validation.mdx | 102 +++ .../how-register-and-profile-works.mdx | 698 ------------------ .../configuring/config-types/register.mdx | 4 +- 5 files changed, 106 insertions(+), 701 deletions(-) create mode 100644 docs/engineering/android-app/configuring/config-types/forms/_category_.yml rename docs/engineering/android-app/configuring/config-types/{ => forms}/questionnaire.mdx (99%) create mode 100644 docs/engineering/android-app/configuring/config-types/forms/validation.mdx delete mode 100644 docs/engineering/android-app/configuring/config-types/how-register-and-profile-works.mdx diff --git a/docs/engineering/android-app/configuring/config-types/forms/_category_.yml b/docs/engineering/android-app/configuring/config-types/forms/_category_.yml new file mode 100644 index 0000000000..46e1f0d937 --- /dev/null +++ b/docs/engineering/android-app/configuring/config-types/forms/_category_.yml @@ -0,0 +1 @@ +label: Forms diff --git a/docs/engineering/android-app/configuring/config-types/questionnaire.mdx b/docs/engineering/android-app/configuring/config-types/forms/questionnaire.mdx similarity index 99% rename from docs/engineering/android-app/configuring/config-types/questionnaire.mdx rename to docs/engineering/android-app/configuring/config-types/forms/questionnaire.mdx index 8330d2e38f..d7ae684242 100644 --- a/docs/engineering/android-app/configuring/config-types/questionnaire.mdx +++ b/docs/engineering/android-app/configuring/config-types/forms/questionnaire.mdx @@ -1,5 +1,5 @@ --- -title: Questionnaires and forms +title: Questionnaires --- # Questionnaire configuration diff --git a/docs/engineering/android-app/configuring/config-types/forms/validation.mdx b/docs/engineering/android-app/configuring/config-types/forms/validation.mdx new file mode 100644 index 0000000000..8fd27704d1 --- /dev/null +++ b/docs/engineering/android-app/configuring/config-types/forms/validation.mdx @@ -0,0 +1,102 @@ +# Validation + +There are many ways to validate Questionnaire components and widgets, e.g. `date-picker`, `numeric field` among others. + +## Validation of Questionnaire's Date picker + +Date picker is a widget that supports date selection, you can specify the minimum and maximum ranges for selectable dates. +The `minDate` must be before the `maxDate`. + +### Working with the `today()` function + +The `valueString` allows you to format the date. + +`_valueDate` indicates that you are working with dates when using [`cqf calculated values`](https://hl7.org/fhir/extensions/StructureDefinition-cqf-calculatedValue.html), which are expressions that determine a calculated value. + +`valueExpression` allows you to specify the `language` used, usually`fhirpath`, and `expression` is the formula to be evaluated. + +The below example shows how you can set today as the minimum value of a date picker: + +```json + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/entryFormat", + "valueString": "d/M/y" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/minValue", + "_valueDate": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/cqf-calculatedValue", + "valueExpression": { + "language": "text/fhirpath", + "expression": "today()" + } + } + ] + } + } + ], +``` + +### Loading a date in the date picker range + +In this example we will show how to load a patients birth date as the minimum value of a date picker. + +First you must use the [standard launch context](http://hl7.org/fhir/uv/sdc/STU3/CodeSystem-launchContext.html) for the Questionnaire. Then use `code` to define what resource to fetch the date from. + +```json + "extension": [ + { + "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-targetStructureMap", + "valueCanonical": "https://fhir.demo.smartregister.org/fhir/StructureMap/a-given-id" + }, + { + "extension": [ + { + "url": "name", + "valueCoding": { + "system": "http://hl7.org/fhir/uv/sdc/CodeSystem/launchContext", + "code": "patient", + "display": "Patient" + } + }, + { + "url": "type", + "valueCode": "Patient" + } + ], + "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-launchContext" + } + ], +``` + +On the date picker reference the Patient's date of birth as the minimum date by using the code specified in the Questionnaire launchContext at targetStructureMap level. We can access the date of birth as shown below: + +```json + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/entryFormat", + "valueString": "d/M/y" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/minValue", + "_valueDate": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/cqf-calculatedValue", + "valueExpression": { + "language": "text/fhirpath", + "expression": "patient.birthDate" + } + } + ] + } + } + ], +``` + + Some other examples are: + - To set the minimum value ninety days ago use the valueExpression `today() - 90 days` + - To set the maximum value five days in the future use `today() + 5 days` diff --git a/docs/engineering/android-app/configuring/config-types/how-register-and-profile-works.mdx b/docs/engineering/android-app/configuring/config-types/how-register-and-profile-works.mdx deleted file mode 100644 index 87571acdc1..0000000000 --- a/docs/engineering/android-app/configuring/config-types/how-register-and-profile-works.mdx +++ /dev/null @@ -1,698 +0,0 @@ -# How register and profile works together with widgets. - -## Register - -Register is a list used to show user configured fhirResource. - -By Clicking a single register item you are directed to profile this means every register have a corresponding profile. - -To learn more about registers visit this page [registers](https://docs.opensrp.io/engineering/android-app/configuring/config-types/register) - -Below is a .json config that shows how register is used. - -```json - -{ - "appId": "app", - "configType": "register", - "id": "householdRegister", - "pageSize": 20, - "fhirResource": { - "baseResource": { - "resource": "Group", - "dataQueries": [ - { - "paramName": "type", - "filterCriteria": [ - { - "dataType": "CODE", - "value": { - "system": "http://hl7.org/fhir/group-type", - "code": "person" - } - } - ] - }, - { - "paramName": "code", - "filterCriteria": [ - { - "dataType": "CODE", - "value": { - "system": "https://www.snomed.org", - "code": "code_number" - } - } - ] - } - ], - "sortConfigs": [ - { - "paramName": "_lastUpdated", - "dataType": "DATE", - "order": "DESCENDING" - } - ] - }, - "relatedResources": [ - { - "resource": "Patient", - "isRevInclude": false, - "searchParameter": "member", - "relatedResources": [ - { - "resource": "Condition", - "searchParameter": "subject" - }, - { - "resource": "CarePlan", - "searchParameter": "subject" - }, - { - "id": "overdueTasks", - "resource": "Task", - "searchParameter": "subject", - "resultAsCount": true, - "dataQueries": [ - { - "paramName": "status", - "filterCriteria": [ - { - "dataType": "CODE", - "value": { - "system": "http://hl7.org/fhir/task-status", - "code": "failed" - } - } - ] - } - ] - }, - { - "id": "dueTasks", - "resource": "Task", - "searchParameter": "subject", - "resultAsCount": true, - "dataQueries": [ - { - "paramName": "status", - "filterCriteria": [ - { - "dataType": "CODE", - "value": { - "system": "http://hl7.org/fhir/task-status", - "code": "ready" - } - } - ] - } - ] - } - ] - } - ] - }, - "activeResourceFilters": [ - { - "resourceType": "Group", - "active": "true" - }, - { - "resourceType": "Patient", - "active": "true" - } - ], - "searchBar": { - "visible": true, - "display": "{{ search.name.or.id }}", - "computedRules": [ - "familyName", - "familyId" - ] - }, - "registerCard": { - "rules": [ - { - "name": "familyLogicalId", - "condition": "true", - "actions": [ - "data.put('familyLogicalId', fhirPath.extractValue(Group, 'Group.id'))" - ] - }, - { - "name": "familyName", - "condition": "true", - "actions": [ - "data.put('familyName', fhirPath.extractValue(Group, 'Group.name'))" - ] - }, - { - "name": "familyId", - "condition": "true", - "actions": [ - "data.put('familyId', fhirPath.extractValue(Group, 'Group.identifier[0].value'))" - ] - }, - { - "name": "familyVillage", - "condition": "true", - "actions": [ - "data.put('familyVillage', fhirPath.extractValue(Group, 'Group.characteristic[0].code.text'))" - ] - }, - { - "name": "dueTaskCount", - "condition": "true", - "actions": [ - "data.put('dueTaskCount', service.computeTotalCount(dueTasks))" - ] - }, - { - "name": "overDueTaskCount", - "condition": "true", - "actions": [ - "data.put('overDueTaskCount', service.computeTotalCount(overdueTasks))" - ] - }, - { - "name": "totalTaskCount", - "condition": "true", - "priority": 2, - "actions": [ - "var sum = data.get('dueTaskCount') + data.get('overDueTaskCount'); data.put('totalTaskCount', sum == 0 ? '' : sum)" - ] - }, - { - "name": "serviceStatus", - "condition": "true", - "priority": 2, - "actions": [ - "data.put('serviceStatus', data.get('dueTaskCount') > 0 ? 'DUE' : data.get('overDueTaskCount') > 0 ? 'OVERDUE' : 'UPCOMING' )" - ] - }, - { - "name": "serviceMemberIcons", - "condition": "true", - "actions": [ - "data.put('serviceMemberIcons', StringUtils:join([service.mapResourcesToLabeledCSV(Patient, \"Patient.active and (Patient.birthDate >= today() - 5 'years')\", 'CHILD'), service.mapResourcesToLabeledCSV(Condition, \"Condition.code.text = 'Pregnant'\", 'PREGNANT_WOMAN')], ','))" - ] - } - ], - "views": [ - { - "viewType": "COLUMN", - "children": [ - { - "viewType": "SERVICE_CARD", - "details": [ - { - "viewType": "COMPOUND_TEXT", - "primaryText": "@{familyName} Family", - "primaryTextColor": "#000000" - }, - { - "viewType": "COMPOUND_TEXT", - "primaryText": "@{familyVillage} - HH No: @{familyId}", - "fontSize": 14.0, - "primaryTextColor": "#000000" - } - ], - "showVerticalDivider": true, - "serviceMemberIcons": "@{serviceMemberIcons}", - "serviceButton": { - "visible": true, - "text": "@{totalTaskCount}", - "status": "@{serviceStatus}", - "fontSize": 14.0, - "buttonType": "BIG", - "actions": [ - { - "trigger": "ON_CLICK", - "workflow": "LAUNCH_PROFILE", - "id": "householdProfile", - "params": [ - { - "paramType": "PARAMDATA", - "key": "familyLogicalId", - "value": "@{familyLogicalId}" - } - ] - } - ] - }, - "actions": [ - { - "trigger": "ON_CLICK", - "workflow": "LAUNCH_PROFILE", - "id": "householdProfile", - "params": [ - { - "paramType": "PARAMDATA", - "key": "familyLogicalId", - "value": "@{familyLogicalId}" - } - ] - } - ] - } - ] - } - ] - }, - "noResults": { - "title": "No households added", - "message": "Sorry, you haven't added any households to your register", - "actionButton": { - "id": "noResultsButton", - "visible": true, - "display": "Add household", - "actions": [ - { - "trigger": "ON_CLICK", - "workflow": "LAUNCH_QUESTIONNAIRE", - "id": "householdRegister", - "questionnaire": { - "id": "questionnaire_id", - "title": "Add household", - "saveButtonText": "Add Household", - "setPractitionerDetails": true, - "setOrganizationDetails": true - } - } - ] - } - } -} -``` -The json above shows how you can create a register that is coupled with views dataQueries and rules. - -`fhirResource` this specifies the config rules the execute rules of data to be shown on the user interface. - -`baseResource` is the parent resource which is been focused on. `relatedResources` are said to be resources which are part of baseResource. - -`dataQueries` contains the `CQL` statement written in the database. - -`sortConfigs` applies sorting of the data from the database. - -`rules` extracts the data to be rendered on the UI. It comprises of the `name` , `condition` and `action` the action part of the rule is the `fhirPathExpression` that is used to extract data from json. - -`searchBar` is used to show the search field on the ui it also specifies what need to be searched on the search field. - -`view` this specifies the widgets used to display data on the user interface. - -`noResults` this is used to specify what need to be show on the user interface when the extracted data is not obtained, it also have the action part that give you ability to add an action you would need to perform when no data is displayed. - - - - - -## Profiles - -In Fhircore profile are of two types we have `Household profile` and `default profile`. - -Household profile is used to show how households are displayed in the UI while default profile is used to show information about a single user. - -To learn more about profiles feel free to visit this page [profiles](https://docs.opensrp.io/engineering/android-app/configuring/config-types/profile) - -Below is a json configs that shows how rules data queries,views are embedded in the house hold profile. - -```json -{ - "appId": "appId", - "configType": "profile", - "id": "householdProfile", - "fhirResource": { - "baseResource": { - "resource": "Group", - "dataQueries": [ - { - "paramName": "type", - "filterCriteria": [ - { - "dataType": "CODING", - "value": { - "system": "http://hl7.org/fhir/group-type", - "code": "person" - } - } - ] - }, - { - "paramName": "code", - "filterCriteria": [ - { - "dataType": "CODEABLECONCEPT", - "value": { - "system": "https://www.snomed.org", - "code": "35359004" - } - } - ] - } - ] - }, - "relatedResources": [ - { - "resource": "Patient", - "isRevInclude": false, - "searchParameter": "member", - "relatedResources": [ - { - "resource": "Condition", - "searchParameter": "subject" - }, - { - "resource": "CarePlan", - "searchParameter": "subject" - }, - ], - "sortConfigs": [ - { - "paramName": "_lastUpdated", - "dataType": "DATE", - "order": "DESCENDING" - } - ] - }, - ] - }, - "fabActions": [ - { - "id": "ActionButton", - "visible": true, - "display": "{{ add.member }}", - "menuIconConfig": { - "type": "local", - "reference": "ic_add" - }, - "actions": [ - { - "trigger": "ON_CLICK", - "workflow": "LAUNCH_QUESTIONNAIRE", - "questionnaire": { - "id": "questionnaire_id", - "title": "Add household member", - "saveButtonText": "Add Member", - "resourceType": "Patient", - "groupResource": { - "groupIdentifier": "@{familyLogicalId}", - "memberResourceType": "Patient" - }, - "snackBarMessage": { - "message": "Household member has been added", - "actionLabel": "", - "duration": "Short" - } - }, - } - ] - } - ], - "rules": [ - { - "name": "familyName", - "condition": "true", - "actions": [ - "data.put('familyName', fhirPath.extractValue(Group, 'Group.name'))" - ] - }, - ], - "topAppBar": { - "title": { - "viewType": "COMPOUND_TEXT", - "primaryText": "@{familyName} Family", - "primaryTextColor": "#FFFFFF", - "fontSize": 20.0, - "maxLines": 1, - "primaryTextFontWeight": "BOLD" - }, - "content": [ - { - "viewType": "COMPOUND_TEXT", - "primaryText": "@{familyName} Family", - "primaryTextColor": "#FFFFFF", - "fontSize": 16.0, - "maxLines": 1, - "primaryTextFontWeight": "BOLD" - }, - { - "viewType": "COLUMN", - "backgroundColor": "primaryColor", - "children": [ - { - "viewType": "COMPOUND_TEXT", - "primaryText": "@{familyVillage} - HH No: @{familyId}", - "primaryTextColor": "#FFFFFF", - "colorOpacity": 0.76, - "fontSize": 16.0 - } - ] - } - ] - }, - "views": [ - { - "viewType": "CARD", - "header": { - "viewType": "COMPOUND_TEXT", - "primaryText": "HOUSEHOLD MEMBERS", - "primaryTextColor": "#6F7274", - "fontSize": 18.0, - "padding": 16 - }, - "contentPadding": 0, - "content": [ - { - "viewType": "LIST", - "padding": 16, - "resources": [ - { - "id": "householdPatients", - "resourceType": "Patient", - "relatedResources": [ - { - "resourceType": "CarePlan", - "fhirPathExpression": "CarePlan.subject.reference" - }, - { - "resourceType": "Condition", - "fhirPathExpression": "Condition.subject.reference" - }, - ] - } - ], - "registerCard": { - "rules": [ - { - "name": "patientFirstName", - "condition": "true", - "actions": [ - "data.put('patientFirstName', fhirPath.extractValue(Patient, \"Patient.name[0].select(given[0])\"))" - ] - }, - { - "name": "patientMiddleName", - "condition": "true", - "actions": [ - "data.put('patientMiddleName', fhirPath.extractValue(Patient, \"Patient.name[0].select(text)\"))" - ] - }, - { - "name": "patientLastName", - "condition": "true", - "actions": [ - "data.put('patientLastName', fhirPath.extractValue(Patient, \"Patient.name[0].select(family)\"))" - ] - }, - { - "name": "patientAge", - "condition": "true", - "actions": [ - "data.put('patientAge', service.extractAge(Patient))" - ] - }, - { - "name": "patientActive", - "condition": "true", - "actions": [ - "data.put('patientActive', fhirPath.extractValue(Patient, 'Patient.active'))" - ] - }, - ], - "views": [ - { - "viewType": "SERVICE_CARD", - "details": [ - { - "viewType": "COMPOUND_TEXT", - "primaryText": "@{patientName}", - "primaryTextColor": "@{patientTextColor}" - }, - { - "viewType": "COMPOUND_TEXT", - "primaryText": "@{statuses}", - "primaryTextColor": "#939596" - } - ], - "serviceMemberIcons": "@{serviceMemberIcons}", - "serviceButton": { - "visible": "@{showMemberTasks}", - "text": "@{taskDescription}", - "status": "@{serviceStatus}", - "enabled": "@{patientActive}", - "actions": [ - { - "trigger": "ON_CLICK", - "workflow": "LAUNCH_QUESTIONNAIRE", - "questionnaire": { - "id": "@{taskQuestionnaireId}", - "title": "@{taskDescription}", - "saveButtonText": "Save", - "taskId": "@{taskId}", - "resourceIdentifier": "@{taskFor}" - } - } - ] - }, - "actions": [ - { - "trigger": "ON_CLICK", - "workflow": "LAUNCH_PROFILE", - "id": "defaultProfile", - "params": [ - { - "paramType": "UPDATE_DATE_ON_EDIT", - "key": "familyLogicalId", - "value": "@{familyLogicalId}" - }, - { - "paramType": "PARAMDATA", - "key": "isFamilyHeadExists", - "value": "@{isFamilyHeadExists}" - } - ] - } - ] - } - ] - } - } - ] - } - ], - "overFlowMenuItems": [ - { - "title": "Family details", - "titleColor": "#000000", - "visible": "true", - "actions": [ - { - "trigger": "ON_CLICK", - "workflow": "LAUNCH_QUESTIONNAIRE", - "questionnaire": { - "id": "questionnaire_id", - "title": "{{add.family}}", - "saveButtonText": "Update household details", - "setPractitionerDetails": true, - "setOrganizationDetails": true, - "type": "EDIT", - "resourceIdentifier": "@{familyLogicalId}", - "resourceType": "Group", - "params": [ - { - "key": "familyLogicalId", - "value": "@{familyLogicalId}", - "paramType": "UPDATE_DATE_ON_EDIT" - } - ], - "snackBarMessage": { - "message": "Household details have been updated", - "actionLabel": "", - "duration": "Short" - } - } - } - ] - }, - { - "title": "Change family head", - "titleColor": "#000000", - "visible": "true", - "actions": [ - { - "trigger": "ON_CLICK", - "workflow": "CHANGE_MANAGING_ENTITY", - "managingEntity": { - - } - } - ] - }, - { - "title": "View past encounters", - "titleColor": "@{patientTextColor}", - "visible": "true", - "enabled": "true", - "actions": [ - { - "trigger": "ON_CLICK", - "workflow": "LAUNCH_PROFILE", - "id": "householdpastencountersProfile" - } - ] - }, - { - "title": "Remove family", - "titleColor": "#FF0000", - "visible": "true", - "showSeparator": "true", - "actions": [ - { - "trigger": "ON_CLICK", - "workflow": "LAUNCH_QUESTIONNAIRE", - "params": [ - { - "key": "familyId", - "value": "@{familyLogicalId}", - "paramType": "UPDATE_DATE_ON_EDIT" - }, - { - "key": "familyName", - "value": "@{familyName}" - } - ], - "onSubmitActions": [ - { - "trigger": "ON_QUESTIONNAIRE_SUBMISSION", - "workflow": "LAUNCH_REGISTER", - "id": "householdRegister", - "display": "All Households", - "popNavigationBackStack": true - } - ] - } - ] - } - ] -} -``` - -To Create a full functional household profile config the json above gives a vivid description of how to go about it from the app Id to connecting your views that you would need to be show on your application UI. - -The config start by declaring a application id and the config type that is under use. - -It then defined the fhirResource that would be used `baseResource` is the parent resource under consideration while `relatedResources` are the resources reference from baseResource. relatedResources can be nested that it a relatedResources can be within a relatedResources. - -`dataQueries` contains the `CQL` statement written in the database. - -`sortConfigs` applies sorting of the data from the database. - -`fabActions` this config shows how you can display a floating action button and all the operations it is associated with. That is it's event and state. - -`rules` extracts the data to be rendered on the UI. It comprises of the `name` , `condition` and `action` the action part of the rule is the `fhirPathExpression` that is used to extract data from json. - -`topAppBar` is a configuration for the application to app topAppBar it has a title part which is a `compound text` widget and content part which also take other form of widgets. - -`view` this displays the data on the UI. each view has its property. From the example above a `card` widget has a `list` widget and a service card widget. - - diff --git a/docs/engineering/android-app/configuring/config-types/register.mdx b/docs/engineering/android-app/configuring/config-types/register.mdx index 74d9046385..d15d22fdd3 100644 --- a/docs/engineering/android-app/configuring/config-types/register.mdx +++ b/docs/engineering/android-app/configuring/config-types/register.mdx @@ -1,10 +1,10 @@ --- -title: Registers and lists +title: Registers --- # Register configuration -Registers are the entry point to FHIRCore application. Typically this is a list used to displayed the configured [FHIR resources](https://www.hl7.org/FHIR/resourcelist.html). Clicking on a register item directs the user to the configured profile. +Registers are the entry point to OpenSRP applications. Typically this is a list used to displayed the configured [FHIR resources](https://www.hl7.org/FHIR/resourcelist.html). Clicking on a register item directs the user to the configured profile. :::info For every register in the application there should at least be one profile configuration. Similar registers can re-use the same profile configuration. From 50f41de2719a100f0dce844b9a8835807308a336 Mon Sep 17 00:00:00 2001 From: Martin Ndegwa Date: Mon, 22 Apr 2024 14:36:05 +0300 Subject: [PATCH 4/7] =?UTF-8?q?Fix=20Build=20=F0=9F=92=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fhircore/engine/FhirExtractionTest.kt | 11 +---------- .../smartregister/fhircore/quest/integration/Faker.kt | 6 ++++++ .../quest/ui/questionnaire/QuestionnaireViewModel.kt | 1 - 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/android/engine/src/test/java/org/smartregister/fhircore/engine/FhirExtractionTest.kt b/android/engine/src/test/java/org/smartregister/fhircore/engine/FhirExtractionTest.kt index 7e3bb13f6a..1de24932db 100644 --- a/android/engine/src/test/java/org/smartregister/fhircore/engine/FhirExtractionTest.kt +++ b/android/engine/src/test/java/org/smartregister/fhircore/engine/FhirExtractionTest.kt @@ -16,13 +16,8 @@ package org.smartregister.fhircore.engine -import android.content.Context -import androidx.test.core.app.ApplicationProvider import androidx.work.WorkManager import androidx.work.WorkRequest -import ca.uhn.fhir.context.FhirContext -import ca.uhn.fhir.context.FhirVersionEnum -import ca.uhn.fhir.parser.IParser import com.google.android.fhir.FhirEngine import com.google.android.fhir.datacapture.mapping.ResourceMapper import com.google.android.fhir.datacapture.mapping.StructureMapExtractionContext @@ -70,12 +65,10 @@ import org.smartregister.fhircore.engine.util.helper.TransformSupportServices class FhirExtractionTest : RobolectricTest() { @get:Rule(order = 0) val hiltRule = HiltAndroidRule(this) val fhirEngine: FhirEngine = mockk() - val context = ApplicationProvider.getApplicationContext() @Inject lateinit var transformSupportServices: TransformSupportServices - lateinit var structureMapUtilities: StructureMapUtilities + private lateinit var structureMapUtilities: StructureMapUtilities private val defaultRepository: DefaultRepository = mockk() - private val iParser: IParser = FhirContext.forCached(FhirVersionEnum.R4).newJsonParser() @Before fun setup() { @@ -100,7 +93,6 @@ class FhirExtractionTest : RobolectricTest() { questionnaireResponse = questionnaireResponse, structureMapExtractionContext = StructureMapExtractionContext( - context = context, structureMapProvider = { _, _ -> resources.structureMap }, transformSupportServices = transformSupportServices, ), @@ -190,7 +182,6 @@ class FhirExtractionTest : RobolectricTest() { questionnaireResponse = questionnaireResponse, structureMapExtractionContext = StructureMapExtractionContext( - context = context, structureMapProvider = { _, _ -> resources.structureMap }, transformSupportServices = transformSupportServices, ), diff --git a/android/quest/src/androidTest/java/org/smartregister/fhircore/quest/integration/Faker.kt b/android/quest/src/androidTest/java/org/smartregister/fhircore/quest/integration/Faker.kt index b1d7363122..e052c0efcf 100644 --- a/android/quest/src/androidTest/java/org/smartregister/fhircore/quest/integration/Faker.kt +++ b/android/quest/src/androidTest/java/org/smartregister/fhircore/quest/integration/Faker.kt @@ -85,6 +85,12 @@ object Faker { override suspend fun purge(type: ResourceType, id: String, forcePurge: Boolean) {} + override suspend fun purge( + type: ResourceType, + ids: Set, + forcePurge: Boolean, + ) {} + override suspend fun search(search: Search): List> = emptyList() diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireViewModel.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireViewModel.kt index 22ea7e0bfd..259091ffc6 100644 --- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireViewModel.kt +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireViewModel.kt @@ -553,7 +553,6 @@ constructor( questionnaireResponse = questionnaireResponse, structureMapExtractionContext = StructureMapExtractionContext( - context = context, transformSupportServices = transformSupportServices, structureMapProvider = { structureMapUrl: String?, _: IWorkerContext -> structureMapUrl?.substringAfterLast("/")?.let { From 429cc5c8e462533014514f5622d6bb29cb4595b4 Mon Sep 17 00:00:00 2001 From: Martin Ndegwa Date: Tue, 23 Apr 2024 10:27:16 +0300 Subject: [PATCH 5/7] =?UTF-8?q?Fix=20CI=20build=20=F0=9F=92=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/smartregister/fhircore/quest/RegisterContentTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/android/quest/src/test/java/org/smartregister/fhircore/quest/RegisterContentTest.kt b/android/quest/src/test/java/org/smartregister/fhircore/quest/RegisterContentTest.kt index 4ba0c9411c..0952998024 100644 --- a/android/quest/src/test/java/org/smartregister/fhircore/quest/RegisterContentTest.kt +++ b/android/quest/src/test/java/org/smartregister/fhircore/quest/RegisterContentTest.kt @@ -55,7 +55,6 @@ class RegisterContentTest : RobolectricTest() { sourceGroup: String, ): StructureMapExtractionContext { return StructureMapExtractionContext( - context = context, transformSupportServices = transformSupportServices, structureMapProvider = { _: String, _: IWorkerContext -> StructureMapUtilities(worker, transformSupportServices) From ba2bb390050fde53e11175c3da29df09c4f1df83 Mon Sep 17 00:00:00 2001 From: Martin Ndegwa Date: Tue, 23 Apr 2024 11:27:22 +0300 Subject: [PATCH 6/7] Upgrade FHIR SDK Engine library --- android/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index f8470638dd..b54256ddaf 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -23,7 +23,7 @@ dokkaBase = "1.8.20" easy-rules-jexl = "4.1.0" espresso-core = "3.5.1" fhir-common-utils = "1.0.0-SNAPSHOT" -fhir-engine = "1.0.0-preview6-SNAPSHOT" +fhir-engine = "1.0.0-preview7-SNAPSHOT" foundation = "1.6.3" fragment-ktx = "1.6.2" glide = "4.16.0" From fcf9495c1be3e7377c6fb1c5ec1700dcf5ca4159 Mon Sep 17 00:00:00 2001 From: Martin Ndegwa Date: Tue, 23 Apr 2024 14:59:32 +0300 Subject: [PATCH 7/7] Bump up FHIR Engine Artifact --- android/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index b54256ddaf..e4c504441f 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -23,7 +23,7 @@ dokkaBase = "1.8.20" easy-rules-jexl = "4.1.0" espresso-core = "3.5.1" fhir-common-utils = "1.0.0-SNAPSHOT" -fhir-engine = "1.0.0-preview7-SNAPSHOT" +fhir-engine = "1.0.0-preview7.1-SNAPSHOT" foundation = "1.6.3" fragment-ktx = "1.6.2" glide = "4.16.0"