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/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/dialog"
FikriMilano marked this conversation as resolved.
Show resolved Hide resolved

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,84 @@ class QuestionnaireEditAdapterTest {
.isEqualTo(QuestionnaireViewHolderType.DROP_DOWN.value)
}

@Suppress("ktlint:standard:max-line-length")
FikriMilano marked this conversation as resolved.
Show resolved Hide resolved
@Test
fun getItemViewType_choiceItemType_itemControlExtensionWithRadioButton_andDialogExtension_shouldReturnDialogSelectViewHolderType() {
FikriMilano marked this conversation as resolved.
Show resolved Hide resolved
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)
}

@Suppress("ktlint:standard:max-line-length")
@Test
fun getItemViewType_choiceItemType_itemControlExtensionWithCheckBox_andDialogExtension_shouldReturnDialogSelectViewHolderType() {
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
Loading