Skip to content

Commit

Permalink
Add dialog extension (google#2663)
Browse files Browse the repository at this point in the history
* Add lookup item control type

* Use dialog extension instead of dialog item-control

* Update comment

* spotless

* Revert lookup item control

* Address review

* Add dialog extension to the docs

* Update extensions.md
  • Loading branch information
FikriMilano authored Nov 14, 2024
1 parent 11ed6f0 commit b59acf2
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 45 deletions.
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
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`.

0 comments on commit b59acf2

Please sign in to comment.