diff --git a/buildSrc/src/main/kotlin/Releases.kt b/buildSrc/src/main/kotlin/Releases.kt index 38cb8d700c..e53da77fd7 100644 --- a/buildSrc/src/main/kotlin/Releases.kt +++ b/buildSrc/src/main/kotlin/Releases.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2023-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -54,7 +54,7 @@ object Releases { object DataCapture : LibraryArtifact { override val artifactId = "data-capture" - override val version = "1.0.0" + override val version = "1.1.0" override val name = "Android FHIR Structured Data Capture Library" } diff --git a/datacapture/sampledata/layout_paginated.json b/datacapture/sampledata/layout_paginated.json new file mode 100644 index 0000000000..cf27bca894 --- /dev/null +++ b/datacapture/sampledata/layout_paginated.json @@ -0,0 +1,60 @@ +{ + "resourceType": "Questionnaire", + "item": [ + { + "linkId": "1", + "type": "group", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl", + "valueCodeableConcept": { + "coding": [ + { + "system": "http://hl7.org/fhir/questionnaire-item-control", + "code": "page", + "display": "Page" + } + ], + "text": "Page" + } + } + ], + "item": [ + { + "linkId": "1.1", + "type": "display", + "text": "Personal information", + "prefix": "1." + } + ] + }, + { + "linkId": "2", + "type": "group", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl", + "valueCodeableConcept": { + "coding": [ + { + "system": "http://hl7.org/fhir/questionnaire-item-control", + "code": "page", + "display": "Page" + } + ], + "text": "Page" + } + } + ], + "item": [ + { + "linkId": "2.1", + "type": "date", + "text": "Date of birth", + "prefix": "2.", + "required": true + } + ] + } + ] +} diff --git a/datacapture/src/androidTest/java/com/google/android/fhir/datacapture/test/QuestionnaireUiEspressoTest.kt b/datacapture/src/androidTest/java/com/google/android/fhir/datacapture/test/QuestionnaireUiEspressoTest.kt index 96b75cba10..e5ee755f80 100644 --- a/datacapture/src/androidTest/java/com/google/android/fhir/datacapture/test/QuestionnaireUiEspressoTest.kt +++ b/datacapture/src/androidTest/java/com/google/android/fhir/datacapture/test/QuestionnaireUiEspressoTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2023-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -105,6 +105,30 @@ class QuestionnaireUiEspressoTest { ) } + @Test + fun shouldHideNextButtonIfDisabled() { + buildFragmentFromQuestionnaire("/layout_paginated.json", true) + + clickOnText("Next") + + onView(withId(R.id.pagination_next_button)) + .check( + ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.GONE)), + ) + } + + @Test + fun shouldDisplayNextButtonIfEnabled() { + buildFragmentFromQuestionnaire("/layout_paginated.json", true) + + onView(withId(R.id.pagination_next_button)) + .check( + ViewAssertions.matches( + ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE), + ), + ) + } + @Test fun integerTextEdit_inputOutOfRange_shouldShowError() { buildFragmentFromQuestionnaire("/text_questionnaire_integer.json") @@ -503,6 +527,7 @@ class QuestionnaireUiEspressoTest { val questionnaireFragment = QuestionnaireFragment.builder() .setQuestionnaire(questionnaireJsonString) + .setShowCancelButton(true) .showReviewPageBeforeSubmit(isReviewMode) .build() activityScenarioRule.scenario.onActivity { activity -> diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireFragment.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireFragment.kt index 70cc0b86b8..83841800c7 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireFragment.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireFragment.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2023-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -190,10 +190,10 @@ class QuestionnaireFragment : Fragment() { reviewModeEditButton.visibility = View.GONE if (displayMode.pagination.isPaginated) { - paginationPreviousButton.visibility = View.VISIBLE - paginationPreviousButton.isEnabled = displayMode.pagination.hasPreviousPage - paginationNextButton.visibility = View.VISIBLE - paginationNextButton.isEnabled = displayMode.pagination.hasNextPage + paginationPreviousButton.visibility = + if (displayMode.pagination.hasPreviousPage) View.VISIBLE else View.GONE + paginationNextButton.visibility = + if (displayMode.pagination.hasNextPage) View.VISIBLE else View.GONE } else { paginationPreviousButton.visibility = View.GONE paginationNextButton.visibility = View.GONE diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/EditTextDecimalViewHolderFactory.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/EditTextDecimalViewHolderFactory.kt index 31a5058c53..a4fb8d2443 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/EditTextDecimalViewHolderFactory.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/EditTextDecimalViewHolderFactory.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022-2023 Google LLC + * Copyright 2022-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,16 +47,17 @@ internal object EditTextDecimalViewHolderFactory : ) { val questionnaireItemViewItemDecimalAnswer = questionnaireViewItem.answers.singleOrNull()?.valueDecimalType?.value?.toString() - val draftAnswer = questionnaireViewItem.draftAnswer?.toString() - val decimalStringToDisplay = questionnaireItemViewItemDecimalAnswer ?: draftAnswer - - if ( - decimalStringToDisplay?.toDoubleOrNull() != + if (questionnaireItemViewItemDecimalAnswer.isNullOrEmpty() && draftAnswer.isNullOrEmpty()) { + textInputEditText.setText("") + } else if ( + questionnaireItemViewItemDecimalAnswer?.toDoubleOrNull() != textInputEditText.text.toString().toDoubleOrNull() ) { - textInputEditText.setText(decimalStringToDisplay) + textInputEditText.setText(questionnaireItemViewItemDecimalAnswer) + } else if (draftAnswer != null && draftAnswer != textInputEditText.text.toString()) { + textInputEditText.setText(draftAnswer) } // Update error message if draft answer present if (draftAnswer != null) { diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/EditTextIntegerViewHolderFactory.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/EditTextIntegerViewHolderFactory.kt index bb87204486..b9da83ca2b 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/EditTextIntegerViewHolderFactory.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/EditTextIntegerViewHolderFactory.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022-2023 Google LLC + * Copyright 2022-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -64,14 +64,16 @@ internal object EditTextIntegerViewHolderFactory : questionnaireViewItem.answers.singleOrNull()?.valueIntegerType?.value?.toString() val draftAnswer = questionnaireViewItem.draftAnswer?.toString() - val text = answer ?: draftAnswer - // Update the text on the UI only if the value of the saved answer or draft answer // is different from what the user is typing. We compare the two fields as integers to // avoid shifting focus if the text values are different, but their integer representation // is the same (e.g. "001" compared to "1") - if ((text?.toIntOrNull() != textInputEditText.text.toString().toIntOrNull())) { - textInputEditText.setText(text) + if (answer.isNullOrEmpty() && draftAnswer.isNullOrEmpty()) { + textInputEditText.setText("") + } else if (answer?.toIntOrNull() != textInputEditText.text.toString().toIntOrNull()) { + textInputEditText.setText(answer) + } else if (draftAnswer != null && draftAnswer != textInputEditText.text.toString()) { + textInputEditText.setText(draftAnswer) } // Update error message if draft answer present diff --git a/datacapture/src/main/res/values/styles.xml b/datacapture/src/main/res/values/styles.xml index 4fe62672e7..750f97cd7a 100644 --- a/datacapture/src/main/res/values/styles.xml +++ b/datacapture/src/main/res/values/styles.xml @@ -400,7 +400,7 @@