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

Implement the entryMode extension #1301

Merged

Conversation

aurangzaibumer
Copy link
Collaborator

@aurangzaibumer aurangzaibumer commented Apr 18, 2022

IMPORTANT: All PRs must be linked to an issue (except for extremely trivial and straightforward changes).

Issue# 1272

Description
Clear and concise code change description.

Alternative(s) considered
Have you considered any alternatives? And if so, why have you chosen the approach in this PR?

Type
Choose one: Feature

Screenshots/Video

issue_1272.mp4

Checklist

  • I have read and acknowledged the Code of conduct.
  • I have read the Contributing page.
  • I have signed the Google Individual CLA, or I am covered by my company's Corporate CLA.
  • I have discussed my proposed solution with code owners in the linked issue(s) and we have agreed upon the general approach.
  • I have run ./gradlew spotlessApply and ./gradlew spotlessCheck to check my code follows the style guide of this project.
  • I have run ./gradlew check and ./gradlew connectedCheck to test my changes locally.
  • I have built and run the demo app(s) to verify my change fixes the issue and/or does not break the demo app(s).

@joiskash
Copy link
Collaborator

Oh there is some weird bug that shows overlapped questions 0:44. Is there any reproducibility ? We will have to create an issue regarding this. But otherwise, looks great!

cc: @jingtang10

@aurangzaibumer
Copy link
Collaborator Author

@dubdabasoduba as per discussion on standup, there is a PR for submit button #1215 this needs to be merged first in order to work on the submit button so probably we can create a separate ticket for submit button implementation so this can be merged if reviewed.

Copy link
Collaborator

@joiskash joiskash left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this a little more, I figured that this more than just validation.. This is triggering some logic on page change events within the QuestionnaireFragment. So we could refactor as such. This will allow more complex use cases such as :

  1. Not allowing to switch page until a minimum amount of time has passed
  2. Not allowing page change if the answers are exactly the same as the previous questionnaire answered . (this can happen in cases were there is a monetary incentive to complete forms)

Validation of all the items on the page can be the default implementation provided by the library. Developers can choose to add this in their Strategies too.

By having a context, the main point is that the strategy can be changed during run time. So a developer can do something like

dataConfig.questionnairePageEventContext.setStrategy(newStrategy)

at any point in the code during run time.

Create a context class that will be stored in the DataCapture Config

class QuestionnairePageChangeEventContext{
  private var pageChangeStrategy : PageChangeStrategy = DefaultStrategy()

  fun setStrategy(pageChangeStrategy : PageChangeStrategy ){
      this.pageChangeStrategy = pageChangeStrategy
  }
  
  //This function will be called in the QuestionnaireViewModel goToNextPage and if returns true  then pageFlow.value will be changed.

  fun triggerPageNextEvent( list: List<QuestionnaireItemViewItem> ):Boolean{
  return pageChangeStrategy.shouldGoToNextPage(list)
  }

  //This function will be called in the QuestionnaireViewModel goToPreviousPage and if returns true  then pageFlow.value will be changed.

  fun triggerPreviousEvent( list: List<QuestionnaireItemViewItem> ):Boolean{
  return pageChangeStrategy.shouldGoToPreviousPage(list)
  }
}

The strategy interface will be like this.

interface PageChangeStrategy {

  fun shouldGoToPreviousPage(list: List<QuestionnaireItemViewItem>): Boolean

  fun shouldGoToNextPage(list: List<QuestionnaireItemViewItem>): Boolean

}

The default implementation can be like :

class DefaultPageChangeStrategy: PageChangeStrategy{

  override fun shouldGoToPreviousPage(list: List<QuestionnaireItemViewItem>): Boolean{
    return list.any { it.isErrorTriggered }
  }

  override fun shouldGoToNextPage(list: List<QuestionnaireItemViewItem>): Boolean
    return list.any { it.isErrorTriggered }
  }

and finally the change in the viewmodel can be as such:

internal class QuestionnaireViewModel(application: Application, state: SavedStateHandle) :{
  private val questionnairePageEventContext by lazy {
    DataCapture.getConfiguration(getApplication()).questionnairePageEventContext // declare and initialize this in the DataConfig. It should never be null
  }
.
.
.
  internal fun goToPreviousPage() {
    if (questionnairePageEventContext.triggerPagePreviousEvent()){
              pageFlow.value = pageFlow.value!!.previousPage()
     }
  }
  
  internal fun goToNextPage() {
    if (questionnairePageEventContext.triggerPageNextEvent()){
              pageFlow.value = pageFlow.value!!.nextPage()
     }
  }
}

Some one from google can comment on this, @jingtang @kevinmost

@codecov
Copy link

codecov bot commented Apr 19, 2022

Codecov Report

Merging #1301 (3e70103) into master (61c383e) will not change coverage.
The diff coverage is n/a.

❗ Current head 3e70103 differs from pull request most recent head 35b7774. Consider uploading reports for the commit 35b7774 to get more accurate results

@@      Coverage Diff       @@
##   master   #1301   +/-   ##
==============================
==============================

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@aurangzaibumer
Copy link
Collaborator Author

Thinking about this a little more, I figured that this more than just validation.. This is triggering some logic on page change events within the QuestionnaireFragment. So we could refactor as such. This will allow more complex use cases such as :

  1. Not allowing to switch page until a minimum amount of time has passed
  2. Not allowing page change if the answers are exactly the same as the previous questionnaire answered . (this can happen in cases were there is a monetary incentive to complete forms)

Validation of all the items on the page can be the default implementation provided by the library. Developers can choose to add this in their Strategies too.

By having a context, the main point is that the strategy can be changed during run time. So a developer can do something like

dataConfig.questionnairePageEventContext.setStrategy(newStrategy)

at any point in the code during run time.

Create a context class that will be stored in the DataCapture Config

class QuestionnairePageChangeEventContext{
  private var pageChangeStrategy : PageChangeStrategy 

  fun setStrategy(pageChangeStrategy : PageChangeStrategy ){
      this.pageChangeStrategy = pageChangeStrategy
  }
  
  //This function will be called in the QuestionnaireViewModel goToNextPage and if returns true  then pageFlow.value will be changed.

  fun pageNextEvent( list: List<QuestionnaireItemViewItem> ):Boolean{
  return pageChangeStrategy.shouldGoToNextPage(list)
  }

  //This function will be called in the QuestionnaireViewModel goToPreviousPage and if returns true  then pageFlow.value will be changed.

  fun pagePreviousEvent( list: List<QuestionnaireItemViewItem> ):Boolean{
  return pageChangeStrategy.shouldGoToPreviousPage(list)
  }
}

The strategy interface will be like this.

interface PageChangeStrategy {

  fun shouldGoToPreviousPage(list: List<QuestionnaireItemViewItem>): Boolean

  fun shouldGoToNextPage(list: List<QuestionnaireItemViewItem>): Boolean

}

The default implementation can be like :

class DefaultPageChangeStrategy: PageChangeStrategy{

  override fun shouldGoToPreviousPage(list: List<QuestionnaireItemViewItem>): Boolean{
    return list.any { it.isErrorTriggered }
  }

  override fun shouldGoToNextPage(list: List<QuestionnaireItemViewItem>): Boolean
    return list.any { it.isErrorTriggered }
  }

and finally the change in the viewmodel can be as such:

internal class QuestionnaireViewModel(application: Application, state: SavedStateHandle) :{
  private val questionnairePageEventContext by lazy {
    DataCapture.getConfiguration(getApplication()).questionnairePageEventContext // declare and initialize this in the DataConfig. It should never be null
  }
.
.
.
  internal fun goToPreviousPage() {
    if (questionnairePageEventContext.pagePreviousEvent()){
              pageFlow.value = pageFlow.value!!.previousPage()
     }
  }
  
  internal fun goToNextPage() {
    if (questionnairePageEventContext.pageNextEvent()){
              pageFlow.value = pageFlow.value!!.nextPage()
     }
  }
}

Some one from google can comment on this, @jingtang @kevinmost

feedback implemented, please review @joiskash . Thanks

Copy link
Collaborator

@joiskash joiskash left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, left a few comments. I request someone from google and Ona to review this before you write the UTs. @jingtang10 @f-odhiambo

@jingtang10
Copy link
Collaborator

@santosh-pingle can you leave some comments please

@aurangzaibumer
Copy link
Collaborator Author

aurangzaibumer commented Apr 21, 2022

Great work, left a few comments. I request someone from google and Ona to review this before you write the UTs. @jingtang10 @f-odhiambo

cc @dubdabasoduba

@santosh-pingle
Copy link
Collaborator

@santosh-pingle can you leave some comments please

sure.

@aurangzaibumer aurangzaibumer marked this pull request as ready for review April 22, 2022 06:41
@aurangzaibumer
Copy link
Collaborator Author

@jingtang10 can you please review on your availability. thanks

@jingtang10 jingtang10 enabled auto-merge (squash) August 16, 2022 10:06
auto-merge was automatically disabled August 16, 2022 13:07

Head branch was pushed to by a user without write access

aurangzaibumer and others added 3 commits August 16, 2022 18:10
…QuestionnaireViewModel.kt


checked a case with this changes

User opened the questionnaire and taps on the next button without touching any items
isPaginated is FALSE, it will trigger the validation for the current page items
now errors are shown the required fields, now user tried to tap again on the next button
since isPaginated is already TRUE, this will save the additional validation in this case.
You are right @jingtang10 . This makes sense to me.

Co-authored-by: Jing Tang <[email protected]>
@jingtang10 jingtang10 changed the title 1272 Allow/disallow pagination based on validation result (e.g. can't go to next page with validation error) Implement the entryMode extension Aug 21, 2022
@jingtang10 jingtang10 enabled auto-merge (squash) August 21, 2022 09:19
@jingtang10 jingtang10 merged commit 765a785 into google:master Aug 21, 2022
@santosh-pingle
Copy link
Collaborator

@aurangzaibumer can you please add some questionnaire examples?

@aurangzaibumer
Copy link
Collaborator Author

@aurangzaibumer can you please add some questionnaire examples?

"extension": [ 
    {
      "url" : "http:https://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-entryMode",
      "valueCode" : "prior-edit"
    } 
 ]

for more entry-mode codes : http:https://build.fhir.org/ig/HL7/sdc/ValueSet-entryMode.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P1 High priority issue type:enhancement New feature or request
Projects
Archived in project
6 participants