Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into update-reference-…
Browse files Browse the repository at this point in the history
…indexes
  • Loading branch information
LZRS committed Nov 28, 2024
2 parents 5842e96 + 205bfda commit 61d617d
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.google.android.fhir.datacapture.extensions
import android.content.Context
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.method.LinkMovementMethod
import android.view.View.GONE
import android.view.View.VISIBLE
import android.widget.Button
Expand Down Expand Up @@ -82,7 +83,10 @@ fun initHelpViews(
}
}
}
helpTextView.updateTextAndVisibility(questionnaireItem.localizedHelpSpanned)
helpTextView.apply {
updateTextAndVisibility(questionnaireItem.localizedHelpSpanned)
movementMethod = LinkMovementMethod.getInstance()
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.google.android.fhir.datacapture.views

import android.content.Context
import android.text.method.LinkMovementMethod
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.LinearLayout
Expand Down Expand Up @@ -55,11 +56,17 @@ class GroupHeaderView(context: Context, attrs: AttributeSet?) : LinearLayout(con
helpCardStateChangedCallback = questionnaireViewItem.helpCardStateChangedCallback,
)
prefix.updateTextAndVisibility(questionnaireViewItem.questionnaireItem.localizedPrefixSpanned)
// CQF expression takes precedence over static question text
question.updateTextAndVisibility(questionnaireViewItem.questionText)
hint.updateTextAndVisibility(
questionnaireViewItem.enabledDisplayItems.getLocalizedInstructionsSpanned(),
)
question.apply {
// CQF expression takes precedence over static question text
updateTextAndVisibility(questionnaireViewItem.questionText)
movementMethod = LinkMovementMethod.getInstance()
}
hint.apply {
updateTextAndVisibility(
questionnaireViewItem.enabledDisplayItems.getLocalizedInstructionsSpanned(),
)
movementMethod = LinkMovementMethod.getInstance()
}
visibility = getHeaderViewVisibility(prefix, question, hint)
applyCustomOrDefaultStyle(
questionnaireViewItem.questionnaireItem,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.google.android.fhir.datacapture.views

import android.content.Context
import android.text.method.LinkMovementMethod
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.LinearLayout
Expand Down Expand Up @@ -55,13 +56,17 @@ class HeaderView(context: Context, attrs: AttributeSet?) : LinearLayout(context,
helpCardStateChangedCallback = questionnaireViewItem.helpCardStateChangedCallback,
)
prefix.updateTextAndVisibility(questionnaireViewItem.questionnaireItem.localizedPrefixSpanned)
// CQF expression takes precedence over static question text
question.updateTextAndVisibility(
appendAsteriskToQuestionText(question.context, questionnaireViewItem),
)
hint.updateTextAndVisibility(
questionnaireViewItem.enabledDisplayItems.getLocalizedInstructionsSpanned(),
)
question.apply {
// CQF expression takes precedence over static question text
updateTextAndVisibility(appendAsteriskToQuestionText(question.context, questionnaireViewItem))
movementMethod = LinkMovementMethod.getInstance()
}
hint.apply {
updateTextAndVisibility(
questionnaireViewItem.enabledDisplayItems.getLocalizedInstructionsSpanned(),
)
movementMethod = LinkMovementMethod.getInstance()
}
// Make the entire view GONE if there is nothing to show. This is to avoid an empty row in the
// questionnaire.
visibility = getHeaderViewVisibility(prefix, question, hint)
Expand Down
20 changes: 20 additions & 0 deletions docs/use/WFL/Demo-app.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Demo App

The *Workflow Demo* app demonstrates the capabilities of CarePlan Generation API and the Activity Flow API. The app has a Patient card in the top showing the details and a carousel in the bottom with each card representing a particular phase of the activity flow.

To run this app in Android Studio, [create a run/debug configuration](https://developer.android.com/studio/run/rundebugconfig) for the `workflow_demo` module using the [Android App](https://developer.android.com/studio/run/rundebugconfig#android-application) template and run the app using the configuration.

Alternatively, run the following command to build and install the debug APK on your device/emulator:

```shell
./gradlew :workflow_demo:installDebug
```

## Instructions
1. Click on the **Initialize** button to install the required dependencies for an activity flow. The dependencies are already bundled in the assets folder of the workflow demo app. After the dependencies are successfully installed, **Start** Button becomes enabled in the _Proposal_ card.
2. Now, click on the **Start** to generate a CarePlan which intern has a _Proposal_ Resource. This resource is then used by the app to create a new Activity Flow and the _Proposal_ card now shows the details of the resource with the **Start** button disabled now. The carousel auto moves to the next Phase Card i.e. _Plan_.
3. Repeat step 2 to move forward through the phases.
4. To restart the Activity click **Restart** Flow that removes all the resources related to the flow and moves the app back to step 2.
5. The overflow menu on the action bar may be used to switch between various Activities supported in the demo app.

![Workflow Demo](workflow_demo_app.gif)
128 changes: 128 additions & 0 deletions docs/use/WFL/Run-an-Activity-Flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# ActivityFlow

![Activity Flow](activity_flow.svg)

The `ActivityFlow` class manages the workflow of clinical recommendations according to the [FHIR Clinical Practice Guidelines (CPG) specification](https://build.fhir.org/ig/HL7/cqf-recommendations/activityflow.html#activity-lifecycle---request-phases-proposal-plan-order). It implements an activity flow as defined in the FHIR CPG IG, allowing you to guide clinical recommendations through various phases (proposal, plan, order, perform).

You can start new workflows with an appropriate request resource from the generated [CarePlan](Generate-A-Care-Plan.md) or resume existing ones from any phase.

**Important Considerations:**

* **Thread Safety:** The `ActivityFlow` is not thread-safe. Concurrent changes from multiple threads may lead to unexpected behavior.
* **Blocking Operations:** Some methods of `ActivityFlow` and its associated `Phase` interface may block the caller thread. Ensure these are called from a worker thread to avoid UI freezes.

## Creating an ActivityFlow

Use the appropriate `ActivityFlow.of()` factory function to create an instance. You can start anew flow with a `CPGRequestResource` or resume an existing flow from a `CPGRequestResource` or `CPGEventResource` based on the current state.

**Example:**
```kotlin
val repository = FhirEngineRepository(FhirContext.forR4Cached(), fhirEngine)
val request = CPGMedicationRequest( medicationRequestGeneratedByCarePlan)
val flow = ActivityFlow.of(repository, request)
```

## Navigating phases

An `ActivityFlow` progresses through a series of phases, represented by the `Phase` class. Access the current phase using `getCurrentPhase()`.

**Example:**
```kotlin
when (val phase = flow.getCurrentPhase( )) {
is Phase.ProposalPhase -> { /* Handle proposal phase */ }
is Phase.PlanPhase -> { /* Handle plan phase */ }
// ... other phases
}
```

## Transitioning between the phases

`ActivityFlow` provides functions to prepare and initiate the next phase:

* **`prepare...()`:** Creates a new request or event for the next phase without persisting changes.
* **`initiate...()`:** Creates a new phase based on the provided request/event and persists changes to the repository.

**Example:**
```kotlin
val preparedPlan = flow.preparePlan().getOrThrow( )
// ... modify preparedPlan
val planPhase = flow.initiatePlan(preparedPlan).getOrThrow( )
```

## Transitioning to Perform Phase

The `preparePerform()` function requires the event type as a parameter since the perform phase can create different event resources.

**Example:**
```kotlin
val preparedPerformEvent = flow.preparePerform( CPGMedicationDispenseEvent::class.java).getOrThrow()
// ... update preparedPerformEvent
val performPhase = flow.initiatePerform( preparedPerformEvent). getOrThrow( )
```

## Updating states in a phase

* **`RequestPhase`:** (`ProposalPhase`, `PlanPhase`, `OrderPhase`) allows updating the request state using `update()`.
```kotlin
proposalPhase.update(
proposalPhase.getRequestResource().apply { setStatus(Status.ACTIVE) }
)
```
* **`EventPhase`:** (`PerformPhase`) allows updating the event state using `update()` and completing the phase using `complete()`.
```kotlin
performPhase.update(
performPhase.getEventResource().apply { setStatus(EventStatus.COMPLETED) }
)
```
## API List
### Factory functions

* `ActivityFlow.of(...)`: Various overloads for creating `ActivityFlow` instances with different resource types. Refer to the code for specific usage.

### Phase transition API

* `preparePlan()`: Prepares a plan resource.
* `initiatePlan(...)`: Initiates the plan phase.
* `prepareOrder()`: Prepares an order resource.
* `initiateOrder(...)`: Initiates the order phase.
* `preparePerform(...)`: Prepares an event resource for the perform phase.
* `initiatePerform(...)`: Initiates the perform phase.

### Other API
* `getCurrentPhase()`: Returns the current `Phase` of the workflow.

### Request phase API

* `getRequestResource()`: Returns a copy of resource.
* `update(..)`: Updates the resource.
* `suspend(..)`: Suspends the phase.
* `resume(..)`: Resumes the phase.
* `enteredInError(..)`: Marks the request entered-in-error.
* `reject(..)`: Rejects the phase.

### Event phase API

* `getEventResource()`: Returns a copy of resource.
* `update(..)`: Updates the resource.
* `suspend(..)`: Suspends the phase.
* `resume(..)`: Resumes the phase.
* `enteredInError(..)`: Marks the event entered-in-error.
* `start(..)`: Starts the event.
* `notDone(..)`: Marks the event not-done.
* `stop(..)`: Stop the event.
* `complete(..)`: Marks the event as complete.


## Supported activities
The library currently doesn't implement all of the activities outlined in the [activity profiles](https://build.fhir.org/ig/HL7/cqf-recommendations/profiles.html#activity-profiles). New activities may be added as per the requirement from the application developers.

| Activity | Request | Event |
|--------------------|-------------------------|-----------------------|
| Send a message | CPGCommunicationRequest | CPGCommunication |
| Order a medication | CPGMedicationRequest | CPGMedicationDispense |

## Additional resources

* [FHIR Clinical Practice Guidelines IG](https://build.fhir.org/ig/HL7/cqf-recommendations/)
* [Activity Flow](https://build.fhir.org/ig/HL7/cqf-recommendations/activityflow.html#activity-flow)
* [Activity Profiles](https://build.fhir.org/ig/HL7/cqf-recommendations/profiles.html#activity-profiles)
1 change: 1 addition & 0 deletions docs/use/WFL/activity_flow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 7 additions & 2 deletions docs/use/WFL/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ The [Workflow](https://build.fhir.org/workflow.html) Library provides decision s

1. The [PlanDefinition](https://build.fhir.org/plandefinition.html) resource describes a plan or protocol for the care of a given patient. This could include a treatment plan for a specific condition, a discharge plan for a hospitalized patient, or a care plan for managing chronic illness. The output of this operation will be a CarePlan resource, which represents the plan that has been tailored and applied to the specific patient or group of patients. The CarePlan resource will include details about the actions that are part of the plan, the timing and frequency of those actions, and any relevant supporting information. It may also include references to other resources that are relevant to the plan, such as observations or procedures that are part of the plan. The Apply operator can be used to determine the specific actions or interventions that should be taken as part of a care plan, based on the patient's current status and other relevant factors. For example, it could be used to determine which medications a patient should be prescribed or to identify any necessary referrals to other healthcare providers.

1. The [Activity Flow](https://build.fhir.org/ig/HL7/cqf-recommendations/activityflow.html#activity-flow) is based on the workflow module in FHIR. It is used to create activities for the request resources generated in a CarePlan and take them through the various phases(proposal, plan, order, and perform) of the activity lifecycle.

1. The [Library](https://build.fhir.org/library.html) resource describes a container for clinical knowledge assets. One of these assets is a shareable library of clinical logic, written in Clinical Quality Language (CQL). Users of the Workflow library can call an evaluation operator directly from the Library resource and run individual expressions at will. The output will be Parameters resource with the results of each expression evaluated. This operator should be used when the use case does not fit into a PlanDefinition or a Measure Evaluate.

It's recommended that these 3 types of resources are authored within the scope of a [FHIR IG](https://www.hl7.org/fhir/implementationguide.html). The IG can then be published online and imported by the Android SDK. To import an IG, Android SDK users must simply copy the required files from the IG package into the `assets` folder and parse those files using the regular FHIR Parser.
Expand All @@ -14,14 +16,17 @@ The workflow library is dependent on the [Engine library](../FEL/index.md). Oper

Future features of the library will provide support for Tasking and other Workflow related requirements

## Next Steps
## Next steps

* [Getting Started](Getting-Started.md)
* Guides
* Workflow Guides
* [Generate a Care Plan](Generate-A-Care-Plan.md)
* [Run an Activity Flow](Run-an-Activity-Flow.md)
* [Evaluate a Measure](Evaluate-a-Measure.md)
* Other Operations
* [Evaluate a Library](Evaluate-a-Library.md)
* [Compile CQL](Compile-and-Execute-CQL.md)


## Data safety

Expand Down
Binary file added docs/use/WFL/workflow_demo_app.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions mkdocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ nav:
- use/WFL/Evaluate-a-Measure.md
- use/WFL/Evaluate-a-Library.md
- use/WFL/Compile-and-Execute-CQL.md
- use/WFL/Run-an-Activity-Flow.md
- Demo App: use/WFL/Demo-app.md
- use/extensions.md
- API Doc: use/api.md
- Use Snapshots: use/snapshots.md
Expand Down

0 comments on commit 61d617d

Please sign in to comment.