diff --git a/catalog/src/main/assets/component_modal.json b/catalog/src/main/assets/component_modal.json index 99c24c2623..54b8dc9222 100644 --- a/catalog/src/main/assets/component_modal.json +++ b/catalog/src/main/assets/component_modal.json @@ -2,6 +2,24 @@ "resourceType": "Questionnaire", "item": [ { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl", + "valueCodeableConcept": { + "coding": [ + { + "system": "http://hl7.org/fhir/questionnaire-item-control", + "code": "check-box", + "display": "Check Box" + } + ], + "text": "Check box" + } + }, + { + "url": "https://github.com/google/android-fhir/StructureDefinition/dialog" + } + ], "linkId": "1.1", "type": "choice", "repeats": true, @@ -44,48 +62,6 @@ "code": "diarrhoea", "display": "Diarrhoea" } - }, - { - "valueCoding": { - "code": "fever", - "display": "Fever" - } - }, - { - "valueCoding": { - "code": "injury", - "display": "Injury" - } - }, - { - "valueCoding": { - "code": "jaundice", - "display": "Jaundice" - } - }, - { - "valueCoding": { - "code": "mental-health", - "display": "Mental health" - } - }, - { - "valueCoding": { - "code": "nausea", - "display": "Nausea" - } - }, - { - "valueCoding": { - "code": "pain", - "display": "Pain" - } - }, - { - "valueCoding": { - "code": "bleeding", - "display": "Bleeding" - } } ] } diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireEditAdapter.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireEditAdapter.kt index 2b2ea328cf..90f43a53c6 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireEditAdapter.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireEditAdapter.kt @@ -25,6 +25,7 @@ import androidx.recyclerview.widget.RecyclerView import com.google.android.fhir.datacapture.contrib.views.PhoneNumberViewHolderFactory import com.google.android.fhir.datacapture.extensions.inflate import com.google.android.fhir.datacapture.extensions.itemControl +import com.google.android.fhir.datacapture.extensions.shouldUseDialog import com.google.android.fhir.datacapture.views.NavigationViewHolder import com.google.android.fhir.datacapture.views.QuestionnaireViewItem import com.google.android.fhir.datacapture.views.factories.AttachmentViewHolderFactory @@ -241,8 +242,11 @@ internal class QuestionnaireEditAdapter( ): QuestionnaireViewHolderType { val questionnaireItem = questionnaireViewItem.questionnaireItem - // Use the view type that the client wants if they specified an itemControl - return questionnaireItem.itemControl?.viewHolderType + // Use the view type that the client wants if they specified an itemControl or dialog extension + return when { + questionnaireItem.shouldUseDialog -> QuestionnaireViewHolderType.DIALOG_SELECT + else -> questionnaireItem.itemControl?.viewHolderType + } // Otherwise, choose a sensible UI element automatically ?: run { val numOptions = questionnaireViewItem.enabledAnswerOptions.size diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/extensions/MoreQuestionnaireItemComponents.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/extensions/MoreQuestionnaireItemComponents.kt index 0acd26c93f..a29e0151e8 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/extensions/MoreQuestionnaireItemComponents.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/extensions/MoreQuestionnaireItemComponents.kt @@ -61,6 +61,9 @@ internal const val EXTENSION_ITEM_CONTROL_URL_ANDROID_FHIR = internal const val EXTENSION_ITEM_CONTROL_SYSTEM_ANDROID_FHIR = "https://github.com/google/android-fhir/questionnaire-item-control" +internal const val EXTENSION_DIALOG_URL_ANDROID_FHIR = + "https://github.com/google/android-fhir/StructureDefinition/dialog" + internal enum class StyleUrl(val url: String) { BASE("https://github.com/google/android-fhir/tree/master/datacapture/android-style"), PREFIX_TEXT_VIEW("prefix_text_view"), @@ -237,6 +240,15 @@ val QuestionnaireItemComponent.itemControlCode: String? val QuestionnaireItemComponent.itemControl: ItemControlTypes? get() = ItemControlTypes.values().firstOrNull { it.extensionCode == itemControlCode } +private val QuestionnaireItemComponent.hasDialogExtension: Boolean + get() = this.extension.any { it.url == EXTENSION_DIALOG_URL_ANDROID_FHIR } + +val QuestionnaireItemComponent.shouldUseDialog: Boolean + get() = + this.hasDialogExtension && + (this.itemControl?.viewHolderType == QuestionnaireViewHolderType.CHECK_BOX_GROUP || + this.itemControl?.viewHolderType == QuestionnaireViewHolderType.RADIO_GROUP) + /** * The desired orientation for the list of choices. * diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireEditAdapterTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireEditAdapterTest.kt index 6dd1a3e33d..7f90968396 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireEditAdapterTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireEditAdapterTest.kt @@ -19,6 +19,7 @@ package com.google.android.fhir.datacapture import android.os.Build import android.widget.FrameLayout import androidx.test.core.app.ApplicationProvider +import com.google.android.fhir.datacapture.extensions.EXTENSION_DIALOG_URL_ANDROID_FHIR import com.google.android.fhir.datacapture.extensions.EXTENSION_ITEM_CONTROL_SYSTEM import com.google.android.fhir.datacapture.extensions.EXTENSION_ITEM_CONTROL_SYSTEM_ANDROID_FHIR import com.google.android.fhir.datacapture.extensions.EXTENSION_ITEM_CONTROL_URL @@ -496,6 +497,82 @@ class QuestionnaireEditAdapterTest { .isEqualTo(QuestionnaireViewHolderType.DROP_DOWN.value) } + @Test + fun `getItemViewType() with radio button and dialog extension should return dialog select view holder type`() { + val questionnaireEditAdapter = QuestionnaireEditAdapter() + val questionnaireItem = + Questionnaire.QuestionnaireItemComponent().setType(Questionnaire.QuestionnaireItemType.CHOICE) + questionnaireItem.apply { + addExtension( + Extension() + .setUrl(EXTENSION_ITEM_CONTROL_URL) + .setValue( + CodeableConcept() + .addCoding( + Coding() + .setCode(ItemControlTypes.RADIO_BUTTON.extensionCode) + .setDisplay("Radio Button") + .setSystem(EXTENSION_ITEM_CONTROL_SYSTEM), + ), + ), + ) + addExtension(Extension().setUrl(EXTENSION_DIALOG_URL_ANDROID_FHIR)) + } + questionnaireEditAdapter.submitList( + listOf( + QuestionnaireAdapterItem.Question( + QuestionnaireViewItem( + questionnaireItem, + QuestionnaireResponse.QuestionnaireResponseItemComponent(), + validationResult = NotValidated, + answersChangedCallback = { _, _, _, _ -> }, + ), + ), + ), + ) + + assertThat(questionnaireEditAdapter.getItemViewType(0)) + .isEqualTo(QuestionnaireViewHolderType.DIALOG_SELECT.value) + } + + @Test + fun `getItemViewType() with check box and dialog extension should return dialog select view holder type`() { + val questionnaireEditAdapter = QuestionnaireEditAdapter() + val questionnaireItem = + Questionnaire.QuestionnaireItemComponent().setType(Questionnaire.QuestionnaireItemType.CHOICE) + questionnaireItem.apply { + addExtension( + Extension() + .setUrl(EXTENSION_ITEM_CONTROL_URL) + .setValue( + CodeableConcept() + .addCoding( + Coding() + .setCode(ItemControlTypes.CHECK_BOX.extensionCode) + .setDisplay("Check Box") + .setSystem(EXTENSION_ITEM_CONTROL_SYSTEM), + ), + ), + ) + addExtension(Extension().setUrl(EXTENSION_DIALOG_URL_ANDROID_FHIR)) + } + questionnaireEditAdapter.submitList( + listOf( + QuestionnaireAdapterItem.Question( + QuestionnaireViewItem( + questionnaireItem, + QuestionnaireResponse.QuestionnaireResponseItemComponent(), + validationResult = NotValidated, + answersChangedCallback = { _, _, _, _ -> }, + ), + ), + ), + ) + + assertThat(questionnaireEditAdapter.getItemViewType(0)) + .isEqualTo(QuestionnaireViewHolderType.DIALOG_SELECT.value) + } + // TODO: test errors thrown for unsupported types @Test diff --git a/docs/use/extensions.md b/docs/use/extensions.md index 2d9e200de1..77f89e0937 100644 --- a/docs/use/extensions.md +++ b/docs/use/extensions.md @@ -2,4 +2,6 @@ This page lists [FHIR Extensions](http://hl7.org/fhir/extensibility.html) defined by the Android FHIR SDK. -* UUID +* Dialog extension (https://github.com/google/android-fhir/StructureDefinition/dialog) + + This extension can only be used if the questionnaire item type is `choice` and has an item-control of type `check-box` or `radio-button`.