From ba656fe21e859c2690560f690911c24612f46c0e Mon Sep 17 00:00:00 2001 From: Madhuram Jajoo Date: Fri, 3 Mar 2023 23:47:40 +0530 Subject: [PATCH 1/5] ac --- .../datacapture/QuestionnaireViewModel.kt | 8 +- .../enablement/EnablementEvaluator.kt | 14 +- .../MoreQuestionnaireItemComponents.kt | 18 +- .../fhir/datacapture/views/GroupHeaderView.kt | 13 +- .../fhir/datacapture/views/HeaderView.kt | 22 +- .../views/QuestionnaireViewItem.kt | 3 +- .../factories/AttachmentViewHolderFactory.kt | 2 +- .../AutoCompleteViewHolderFactory.kt | 2 +- .../BooleanChoiceViewHolderFactory.kt | 6 +- .../CheckBoxGroupViewHolderFactory.kt | 7 +- .../factories/DatePickerViewHolderFactory.kt | 2 +- .../DateTimePickerViewHolderFactory.kt | 2 +- .../DialogSelectViewHolderFactory.kt | 18 +- .../factories/DisplayViewHolderFactory.kt | 2 +- .../factories/DropDownViewHolderFactory.kt | 4 +- .../factories/EditTextViewHolderFactory.kt | 4 +- .../views/factories/GroupViewHolderFactory.kt | 2 +- .../factories/RadioGroupViewHolderFactory.kt | 6 +- .../factories/ReviewViewHolderFactory.kt | 4 +- .../factories/SliderViewHolderFactory.kt | 2 +- .../datacapture/views/GroupHeaderViewTest.kt | 240 +++++++++------- .../fhir/datacapture/views/HeaderViewTest.kt | 256 +++++++++++------- .../factories/ReviewViewHolderFactoryTest.kt | 34 +-- 23 files changed, 399 insertions(+), 272 deletions(-) diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireViewModel.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireViewModel.kt index 613c094e4a..a7989bcfb3 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireViewModel.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireViewModel.kt @@ -627,7 +627,13 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat answersChangedCallback = answersChangedCallback, resolveAnswerValueSet = { resolveAnswerValueSet(it) }, resolveAnswerExpression = { resolveAnswerExpression(it) }, - draftAnswer = draftAnswerMap[questionnaireResponseItem] + draftAnswer = draftAnswerMap[questionnaireResponseItem], + enabledDisplayItems = + questionnaireItem.item.filter { + it.type == Questionnaire.QuestionnaireItemType.DISPLAY && + (it.isInstructionsCode || it.isFlyoverCode || it.isHelpCode) && + EnablementEvaluator(questionnaireResponse).evaluate(it, questionnaireResponseItem) + } ) ) ) diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt index 9c647fc0ff..674b7c2239 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt @@ -114,6 +114,7 @@ internal class EnablementEvaluator(val questionnaireResponse: QuestionnaireRespo if (enableWhenList.size == 1) { return evaluateEnableWhen( enableWhenList.single(), + questionnaireItem, questionnaireResponseItem, ) } @@ -124,9 +125,9 @@ internal class EnablementEvaluator(val questionnaireResponse: QuestionnaireRespo // enabled if ANY `enableWhen` constraint is satisfied. return when (val value = questionnaireItem.enableBehavior) { Questionnaire.EnableWhenBehavior.ALL -> - enableWhenList.all { evaluateEnableWhen(it, questionnaireResponseItem) } + enableWhenList.all { evaluateEnableWhen(it, questionnaireItem, questionnaireResponseItem) } Questionnaire.EnableWhenBehavior.ANY -> - enableWhenList.any { evaluateEnableWhen(it, questionnaireResponseItem) } + enableWhenList.any { evaluateEnableWhen(it, questionnaireItem, questionnaireResponseItem) } else -> throw IllegalStateException("Unrecognized enable when behavior $value") } } @@ -136,10 +137,15 @@ internal class EnablementEvaluator(val questionnaireResponse: QuestionnaireRespo */ private fun evaluateEnableWhen( enableWhen: Questionnaire.QuestionnaireItemEnableWhenComponent, + questionnaireItem: Questionnaire.QuestionnaireItemComponent, questionnaireResponseItem: QuestionnaireResponse.QuestionnaireResponseItemComponent, ): Boolean { - val targetQuestionnaireResponseItem = - findEnableWhenQuestionnaireResponseItem(questionnaireResponseItem, enableWhen.question) + val targetQuestionnaireResponseItem: QuestionnaireResponse.QuestionnaireResponseItemComponent? = + if (questionnaireItem.type == Questionnaire.QuestionnaireItemType.DISPLAY && + questionnaireResponseItem.linkId == enableWhen.question + ) + questionnaireResponseItem + else findEnableWhenQuestionnaireResponseItem(questionnaireResponseItem, enableWhen.question) return if (Questionnaire.QuestionnaireItemOperator.EXISTS == enableWhen.operator) { // True iff the answer value of the enable when is equal to whether an answer exists in the // target questionnaire response item diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/extensions/MoreQuestionnaireItemComponents.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/extensions/MoreQuestionnaireItemComponents.kt index fec18af260..3c185d79b1 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/extensions/MoreQuestionnaireItemComponents.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/extensions/MoreQuestionnaireItemComponents.kt @@ -308,9 +308,11 @@ val Questionnaire.QuestionnaireItemComponent.localizedPrefixSpanned: Spanned? * code is used as the instructions of the parent question. */ internal val Questionnaire.QuestionnaireItemComponent.localizedInstructionsSpanned: Spanned? + get() = item.localizedInstructionsSpanned + +internal val List.localizedInstructionsSpanned: Spanned? get() { - return item - .firstOrNull { questionnaireItem -> + return this.firstOrNull { questionnaireItem -> questionnaireItem.type == Questionnaire.QuestionnaireItemType.DISPLAY && questionnaireItem.isInstructionsCode } @@ -322,9 +324,11 @@ internal val Questionnaire.QuestionnaireItemComponent.localizedInstructionsSpann * present) is used as the fly-over text of the parent question. */ internal val Questionnaire.QuestionnaireItemComponent.localizedFlyoverSpanned: Spanned? + get() = item.localizedFlyoverSpanned + +internal val List.localizedFlyoverSpanned: Spanned? get() = - item - .firstOrNull { questionnaireItem -> + this.firstOrNull { questionnaireItem -> questionnaireItem.type == Questionnaire.QuestionnaireItemType.DISPLAY && questionnaireItem.displayItemControl == DisplayItemControlType.FLYOVER } @@ -335,9 +339,11 @@ internal val Questionnaire.QuestionnaireItemComponent.localizedFlyoverSpanned: S * code is used as the instructions of the parent question. */ internal val Questionnaire.QuestionnaireItemComponent.localizedHelpSpanned: Spanned? + get() = item.localizedHelpSpanned + +internal val List.localizedHelpSpanned: Spanned? get() { - return item - .firstOrNull { questionnaireItem -> questionnaireItem.isHelpCode } + return this.firstOrNull { questionnaireItem -> questionnaireItem.isHelpCode } ?.localizedTextSpanned } diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/GroupHeaderView.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/GroupHeaderView.kt index f507c0340a..4093a5ab32 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/GroupHeaderView.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/GroupHeaderView.kt @@ -25,7 +25,6 @@ import com.google.android.fhir.datacapture.R import com.google.android.fhir.datacapture.localizedInstructionsSpanned import com.google.android.fhir.datacapture.localizedPrefixSpanned import com.google.android.fhir.datacapture.localizedTextSpanned -import org.hl7.fhir.r4.model.Questionnaire internal class GroupHeaderView(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) { @@ -34,14 +33,16 @@ internal class GroupHeaderView(context: Context, attrs: AttributeSet?) : LayoutInflater.from(context).inflate(R.layout.group_type_header_view, this, true) } - fun bind(questionnaireItem: Questionnaire.QuestionnaireItemComponent) { + fun bind(questionnaireViewItem: QuestionnaireViewItem) { val prefix = findViewById(R.id.prefix) val question = findViewById(R.id.question) val hint = findViewById(R.id.hint) - initHelpButton(this, questionnaireItem) - prefix.updateTextAndVisibility(questionnaireItem.localizedPrefixSpanned) - question.updateTextAndVisibility(questionnaireItem.localizedTextSpanned) - hint.updateTextAndVisibility(questionnaireItem.localizedInstructionsSpanned) + initHelpButton(this, questionnaireViewItem) + prefix.updateTextAndVisibility(questionnaireViewItem.questionnaireItem.localizedPrefixSpanned) + question.updateTextAndVisibility(questionnaireViewItem.questionnaireItem.localizedTextSpanned) + hint.updateTextAndVisibility( + questionnaireViewItem.enabledDisplayItems?.localizedInstructionsSpanned + ) visibility = getViewGroupVisibility(prefix, question, hint) } } diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/HeaderView.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/HeaderView.kt index bc7cc984d2..9688bce185 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/HeaderView.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/HeaderView.kt @@ -33,7 +33,6 @@ import com.google.android.fhir.datacapture.localizedInstructionsSpanned import com.google.android.fhir.datacapture.localizedPrefixSpanned import com.google.android.fhir.datacapture.localizedTextSpanned import com.google.android.material.card.MaterialCardView -import org.hl7.fhir.r4.model.Questionnaire /** View for the prefix, question, and hint of a questionnaire item. */ internal class HeaderView(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) { @@ -47,11 +46,13 @@ internal class HeaderView(context: Context, attrs: AttributeSet?) : LinearLayout private var hint: TextView = findViewById(R.id.hint) private var errorTextView: TextView = findViewById(R.id.error_text_at_header) - fun bind(questionnaireItem: Questionnaire.QuestionnaireItemComponent) { - prefix.updateTextAndVisibility(questionnaireItem.localizedPrefixSpanned) - question.updateTextAndVisibility(questionnaireItem.localizedTextSpanned) - hint.updateTextAndVisibility(questionnaireItem.localizedInstructionsSpanned) - initHelpButton(this, questionnaireItem) + fun bind(questionnaireViewItem: QuestionnaireViewItem) { + prefix.updateTextAndVisibility(questionnaireViewItem.questionnaireItem.localizedPrefixSpanned) + question.updateTextAndVisibility(questionnaireViewItem.questionnaireItem.localizedTextSpanned) + hint.updateTextAndVisibility( + questionnaireViewItem.enabledDisplayItems?.localizedInstructionsSpanned + ) + initHelpButton(this, questionnaireViewItem) // Make the entire view GONE if there is nothing to show. This is to avoid an empty row in the // questionnaire. visibility = getViewGroupVisibility(prefix, question, hint) @@ -93,13 +94,10 @@ internal fun getViewGroupVisibility(vararg view: TextView): Int { return GONE } -internal fun initHelpButton( - view: View, - questionnaireItem: Questionnaire.QuestionnaireItemComponent -) { +internal fun initHelpButton(view: View, questionnaireViewItem: QuestionnaireViewItem) { val helpButton = view.findViewById