Skip to content

Commit

Permalink
Merge branch 'master' into sp/cancel-job
Browse files Browse the repository at this point in the history
  • Loading branch information
santosh-pingle authored Nov 22, 2024
2 parents 502215a + 507e89c commit 7c4dd0d
Show file tree
Hide file tree
Showing 57 changed files with 1,910 additions and 56 deletions.
2 changes: 0 additions & 2 deletions buildSrc/src/main/kotlin/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ object Dependencies {
const val mockWebServer = "com.squareup.okhttp3:mockwebserver:${Versions.http}"

const val jsonToolsPatch = "com.github.java-json-tools:json-patch:${Versions.jsonToolsPatch}"
const val material = "com.google.android.material:material:${Versions.material}"
const val sqlcipher = "net.zetetic:android-database-sqlcipher:${Versions.sqlcipher}"
const val timber = "com.jakewharton.timber:timber:${Versions.timber}"
const val woodstox = "com.fasterxml.woodstox:woodstox-core:${Versions.woodstox}"
Expand Down Expand Up @@ -143,7 +142,6 @@ object Dependencies {

const val jsonToolsPatch = "1.13"
const val jsonAssert = "1.5.1"
const val material = "1.9.0"
const val retrofit = "2.9.0"
const val gsonConverter = "2.1.0"
const val sqlcipher = "4.5.4"
Expand Down
6 changes: 6 additions & 0 deletions buildSrc/src/main/kotlin/Releases.kt
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ object Releases {
const val versionCode = 1
const val versionName = "1.0"
}

object WorkflowDemo {
const val applicationId = "com.google.android.fhir.workflow.demo"
const val versionCode = 1
const val versionName = "1.0"
}
}

fun Project.publishArtifact(artifact: LibraryArtifact) {
Expand Down
2 changes: 1 addition & 1 deletion catalog/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ dependencies {

coreLibraryDesugaring(Dependencies.desugarJdkLibs)

implementation(Dependencies.material)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.core)
implementation(libs.androidx.fragment)
implementation(libs.androidx.navigation.fragment)
implementation(libs.androidx.navigation.ui)
implementation(libs.kotlin.stdlib)
implementation(libs.material)

implementation(project(path = ":datacapture"))
implementation(project(path = ":engine"))
Expand Down
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
2 changes: 1 addition & 1 deletion contrib/barcode/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ dependencies {
implementation(Dependencies.Mlkit.barcodeScanning)
implementation(Dependencies.Mlkit.objectDetection)
implementation(Dependencies.Mlkit.objectDetectionCustom)
implementation(Dependencies.material)
implementation(Dependencies.timber)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.core)
implementation(libs.androidx.fragment)
implementation(libs.material)

testImplementation(Dependencies.mockitoInline)
testImplementation(Dependencies.mockitoKotlin)
Expand Down
2 changes: 1 addition & 1 deletion contrib/locationwidget/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ dependencies {

implementation(project(":datacapture"))
implementation(Dependencies.playServicesLocation)
implementation(Dependencies.material)
implementation(Dependencies.timber)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.core)
implementation(libs.androidx.fragment)
implementation(libs.kotlinx.coroutines.playservices)
implementation(libs.material)

coreLibraryDesugaring(Dependencies.desugarJdkLibs)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import androidx.core.view.isVisible
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.google.common.truth.Truth.assertThat
import org.hl7.fhir.r4.model.Questionnaire
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
Expand Down Expand Up @@ -55,4 +56,30 @@ class LocationGpsCoordinateViewHolderFactoryInstrumentedTest {
)
.isEqualTo(InputType.TYPE_NULL)
}

@Test
fun matcherShouldReturnTrueForOriginalGpsCoordinateUrl() {
val questionnaireItem = Questionnaire.QuestionnaireItemComponent()
questionnaireItem.addExtension(
LocationGpsCoordinateViewHolderFactory.PRIMARY_GPS_COORDINATE_EXTENSION_URL,
null,
)
assertThat(LocationGpsCoordinateViewHolderFactory.matcher(questionnaireItem)).isTrue()
}

@Test
fun matcherShouldReturnTrueForOldGpsCoordinateUrl() {
val questionnaireItem = Questionnaire.QuestionnaireItemComponent()
questionnaireItem.addExtension(
LocationGpsCoordinateViewHolderFactory.GPS_COORDINATE_EXTENSION_URL,
null,
)
assertThat(LocationGpsCoordinateViewHolderFactory.matcher(questionnaireItem)).isTrue()
}

@Test
fun matcherShouldReturnFalseForNoGpsCoordinateUrl() {
val questionnaireItem = Questionnaire.QuestionnaireItemComponent()
assertThat(LocationGpsCoordinateViewHolderFactory.matcher(questionnaireItem)).isFalse()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,11 @@ object LocationGpsCoordinateViewHolderFactory :
header.context.tryUnwrapContext()?.apply {
val gpsCoordinateExtensionValue =
questionnaireViewItem.questionnaireItem
.getExtensionByUrl(GPS_COORDINATE_EXTENSION_URL)
.value as StringType
.getExtensionByUrl(PRIMARY_GPS_COORDINATE_EXTENSION_URL)
?.value as? StringType
?: questionnaireViewItem.questionnaireItem
.getExtensionByUrl(GPS_COORDINATE_EXTENSION_URL)
.value as StringType
when (gpsCoordinateExtensionValue.valueAsString) {
GPS_COORDINATE_EXTENSION_VALUE_LATITUDE -> {
supportFragmentManager.setFragmentResultListener(
Expand Down Expand Up @@ -148,9 +151,12 @@ object LocationGpsCoordinateViewHolderFactory :
}

fun matcher(questionnaireItem: Questionnaire.QuestionnaireItemComponent): Boolean {
return questionnaireItem.hasExtension(GPS_COORDINATE_EXTENSION_URL)
return questionnaireItem.hasExtension(PRIMARY_GPS_COORDINATE_EXTENSION_URL) ||
questionnaireItem.hasExtension(GPS_COORDINATE_EXTENSION_URL)
}

const val PRIMARY_GPS_COORDINATE_EXTENSION_URL =
"https://github.com/google/android-fhir/StructureDefinition/gps-coordinate"
const val GPS_COORDINATE_EXTENSION_URL = "gps-coordinate"
const val GPS_COORDINATE_EXTENSION_VALUE_LATITUDE = "latitude"
const val GPS_COORDINATE_EXTENSION_VALUE_LONGITUDE = "longitude"
Expand Down
2 changes: 1 addition & 1 deletion datacapture/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ dependencies {
exclude(module = "commons-logging")
exclude(module = "httpclient")
}
implementation(Dependencies.material)
implementation(Dependencies.timber)
implementation(libs.android.fhir.common)
implementation(libs.androidx.appcompat)
Expand All @@ -101,6 +100,7 @@ dependencies {
implementation(libs.glide)
implementation(libs.kotlin.stdlib)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.material)

testImplementation(Dependencies.mockitoInline)
testImplementation(Dependencies.mockitoKotlin)
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
2 changes: 1 addition & 1 deletion demo/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ dependencies {

coreLibraryDesugaring(Dependencies.desugarJdkLibs)

implementation(Dependencies.material)
implementation(Dependencies.timber)
implementation(libs.androidx.activity)
implementation(libs.androidx.appcompat)
Expand All @@ -60,6 +59,7 @@ dependencies {
implementation(libs.kotlin.stdlib)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.material)
implementation(project(":datacapture")) {
exclude(group = "com.google.android.fhir", module = "engine")
}
Expand Down
8 changes: 7 additions & 1 deletion docs/use/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,10 @@

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`.

* GPS Coordinate URL extension (https://github.com/google/android-fhir/StructureDefinition/gps-coordinate)

This URL extension can only be used if the questionnaire item type is `decimal` and has a valueString `latitude` or `longitude` .
Loading

0 comments on commit 7c4dd0d

Please sign in to comment.