Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dialog extension #2663

Merged
merged 10 commits into from
Nov 14, 2024
60 changes: 18 additions & 42 deletions catalog/src/main/assets/component_modal.json
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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"
}
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
FikriMilano marked this conversation as resolved.
Show resolved Hide resolved
else -> questionnaireItem.itemControl?.viewHolderType
}
// Otherwise, choose a sensible UI element automatically
?: run {
val numOptions = questionnaireViewItem.enabledAnswerOptions.size
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down Expand Up @@ -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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion docs/use/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Loading