Skip to content

Commit

Permalink
Merge pull request #918 from aehrc/main
Browse files Browse the repository at this point in the history
Merging main into acdc-pilot
  • Loading branch information
fongsean authored Jul 12, 2024
2 parents d033b0a + 1e82e51 commit 00581f4
Show file tree
Hide file tree
Showing 24 changed files with 742 additions and 176 deletions.
31 changes: 31 additions & 0 deletions .github/workflows/build_test_lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,34 @@ jobs:

- name: Check formatting
run: npm run check-formatting

deploy-storybook:
name: Deploy Storybook to S3
runs-on: ubuntu-latest
permissions:
contents: read
pages: write
id-token: write
steps:
- uses: actions/checkout@v4

- name: Use Node.js 18.x
uses: actions/setup-node@v4
with:
node-version: 18
cache: npm

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::209248795938:role/SmartFormsReactAppDeployment
aws-region: ap-southeast-2

- name: Install dependencies
run: npm ci

- name: Build application
run: npm run build-storybook -w packages/smart-forms-renderer

- name: Upload static Storybook site to S3
run: aws s3 sync packages/smart-forms-renderer/storybook-static s3://smart-forms-storybook/storybook
8 changes: 5 additions & 3 deletions .github/workflows/deploy_app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ on:
push:
branches: ['main']

permissions:
contents: read
pages: write
id-token: write

jobs:
build:
name: Deploy Smart Forms app to S3
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4

Expand Down
29 changes: 1 addition & 28 deletions .github/workflows/deploy_docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,31 +34,4 @@ jobs:
run: npm run build -w documentation

- name: Upload static Docusaurus site to S3
run: aws s3 sync documentation/build s3://smart-forms-docs/docs

deploy-storybook:
name: Deploy Storybook to S3
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Use Node.js 18.x
uses: actions/setup-node@v4
with:
node-version: 18
cache: npm

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::209248795938:role/SmartFormsReactAppDeployment
aws-region: ap-southeast-2

- name: Install dependencies
run: npm ci

- name: Build application
run: npm run build-storybook -w packages/smart-forms-renderer

- name: Upload static Storybook site to S3
run: aws s3 sync packages/smart-forms-renderer/storybook-static s3://smart-forms-storybook/storybook
run: aws s3 sync documentation/build s3://smart-forms-docs/docs --cache-control no-cache
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Powered by SMART on FHIR and Structured Data Capture, Smart Forms allow you to e
<h4><a href="https://smartforms.csiro.au">Show me the app ➡️</a></h4>

<h4><a href="https://smartforms.csiro.au/docs">Check out the documentation 📚</a></h4>
Update 11/07/2024: The documentation link isn't working. It is currently being fixed.

---
Smart Forms is a Typescript-based [React](https://reactjs.org/) forms web application currently ongoing development by [CSIRO's Australian e-Health Research Centre](https://aehrc.csiro.au/) as part of the Primary Care Data Quality project funded by the Australian Government Department of Health.
Expand Down
19 changes: 13 additions & 6 deletions deployment/cloudfront/SmartFormsRedirectToCorrectRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,21 +82,28 @@ function handler(event) {
}


// Handle Docz routes
if (uri.includes('/docz')) {
// Reroute to smartforms.csiro.au/docz/index.html
if (uri === '/docz/') {
// Handle Docs routes
if (uri.includes('/docs')) {
// Reroute to smartforms.csiro.au/docs/index.html
if (uri === '/docs/') {
request.uri += 'index.html';
return request;
}

if (uri === '/docz') {
if (uri === '/docs') {
request.uri = '/redirect.html';
return request;
}

if (!uri.includes('.')) {
request.uri += '/index.html';
// For https://smartforms.csiro.au/docs/sdc/population/ cases
if (uri.endsWith('/')) {
request.uri += 'index.html';
}
// For https://smartforms.csiro.au/docs/sdc/population cases
else {
request.uri += '/index.html';
}
return request;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,12 @@ export class EhrProxyAppStack extends cdk.Stack {
listener.addAction('EhrProxyExtractAction', {
action: ListenerAction.forward([extractTargetGroup]),
priority: 1,
conditions: [ListenerCondition.pathPatterns(['/fhir/QuestionnaireResponse/$extract'])]
conditions: [
ListenerCondition.pathPatterns([
'/fhir/QuestionnaireResponse/$extract',
'/fhir/StructureMap/$convert'
])
]
});

// Create a target for the transform service
Expand Down
1 change: 1 addition & 0 deletions documentation/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ This documentation is intended to provide a guide on how to use Smart Forms. It
- [Components](/docs/components): A showcase of supported Questionnaire form components.
- [SDC](/docs/sdc): A section around the conformance and usage of functionalities defined in the SDC specification.
- [Developer Usage](/docs/dev): A guide on how to use the form renderer in your own application.
- [FHIR Operations](/docs/operations): A guide on using the $populate, $assemble and $extract operations.

### Referenced FHIR Specifications

Expand Down
33 changes: 33 additions & 0 deletions documentation/docs/operations/assemble.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
sidebar_position: 3
---

# $assemble

## Useful links

**Deployed service: https://smartforms.csiro.au/api/fhir/Questionnaire/$assemble**

FHIR Operation definition: http://hl7.org/fhir/uv/sdc/OperationDefinition/Questionnaire-assemble

Github: https://github.com/aehrc/smart-forms/tree/main/services/assemble-express

Dockerhub: https://hub.docker.com/r/aehrc/smart-forms-assemble

## Usage

A Questionnaire resource can be assembled using a **POST** request to a URL such as:

```http request
https://smartforms.csiro.au/api/fhir/Questionnaire/$assemble (type-level)
```

#### Parameters

| Name | Cardinality | Type | Documentation |
| ------------- | ----------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| questionnaire | 1..1 | Questionnaire | The [Modular Questionnaire](https://hl7.org/fhir/uv/sdc/StructureDefinition-sdc-questionnaire-modular.html) to assemble the content of. |

#### Try it out

[<img src="https://run.pstmn.io/button.svg" alt="Run In Postman"/>](https://elements.getpostman.com/redirect?entityId=22885901-2af2cfbb-3a0a-49c6-8404-105ef0751415&entityType=collection)
196 changes: 196 additions & 0 deletions documentation/docs/operations/extract.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
---
sidebar_position: 4
---

# StructureMap $extract

This $extract **proof-of-concept** reference implementation is an abstraction on top of an existing StructureMap $transform operation.
We leveraged Brian Postlethwaite's [.NET FHIR Mapping Language engine](https://github.com/brianpos/fhir-net-mappinglanguage/tree/main/demo-map-server) to expose a StructureMap $transform operation on https://proxy.smartforms.io/fhir/StructureMap/$transform.

:::note

This reference implementation is a proof-of-concept. It is highly likely that the underlying implementation will change in the future.

:::

## Useful links

#### Services links

Deployed service: https://proxy.smartforms.io/fhir/QuestionnaireResponse/$extract

Underlying $transform service: https://proxy.smartforms.io/fhir/StructureMap/$transform

FHIR Mapping Language to StructureMap $convert service: https://proxy.smartforms.io/fhir/StructureMap/$convert

#### Specification links

FHIR $extract operation definition: http://hl7.org/fhir/uv/sdc/OperationDefinition/QuestionnaireResponse-extract

FHIR $transform operation definition: https://hl7.org/fhir/r4/structuremap-operation-transform.html

FHIR Mapping Language $convert workflow: https://confluence.hl7.org/pages/viewpage.action?pageId=76158820#UsingtheFHIRMappingLanguage-WebServices

FHIR StructureMap-based extraction: https://hl7.org/fhir/uv/sdc/extraction.html#structuremap-based-extraction

#### Source code links

Github: https://github.com/aehrc/smart-forms/tree/main/services/extract-express

Dockerhub: https://hub.docker.com/r/aehrc/smart-forms-extract

## Usage

Resource(s) can be extracted from a QuestionnaireResponse using a **POST** request to a URL such as:

```http request
https://proxy.smartforms.io/fhir/QuestionnaireResponse/$extract (type-level)
```

#### Parameters

| Name | Cardinality | Type | Documentation |
| ---------------------- | ----------- | -------- | ------------------------------------------------------------------------------------------------------- |
| questionnaire-response | 1..1 | Resource | The QuestionnaireResponse to extract data from. Used when the operation is invoked at the 'type' level. |

#### Try it out

[<img src="https://run.pstmn.io/button.svg" alt="Run In Postman"/>](https://elements.getpostman.com/redirect?entityId=22885901-2af2cfbb-3a0a-49c6-8404-105ef0751415&entityType=collection)

## How it works

The $extract operation is an abstraction on top of an existing StructureMap $transform operation.

#### The underlying $transform

A [$transform](https://hl7.org/fhir/r4/structuremap-operation-transform.html) operation requires two input parameters:

1. `source` - Contains the structure map defining the mapping rules
2. `content` - Contains the data to be transformed (in terms of SDC, this is the QuestionnaireResponse)

The output of $transform is the transformed data, a FHIR resource.

Taking this logic, we can use a StructureMap `$transform` operation to perform the extraction of resources from a QuestionnaireResponse. Let's say we want to extract a bundle containing an Observation resource from a QuestionnaireResponse.
We need a StructureMap that maps the data from the QuestionnaireResponse to the Observation resource. Normally we would write this mapping in [FHIR Mapping Language](https://www.hl7.org/fhir/mapping-language.html) and convert it to a StructureMap.

For more information on using the FHIR Mapping Language, refer to https://confluence.hl7.org/display/FHIR/Using+the+FHIR+Mapping+Language. Brian has a really awesome tool that can help you write and test your mappings at https://fhirpath-lab.com/FhirMapper2.

Once we have both the `source` StructureMap and the `content` QuestionnaireResponse, our $transform request body should look roughly like this:

```json
{
"resourceType": "Parameters",
"parameter": [
{
"name": "source",
"resource": //<insert StructureMap here> -
}
},
{
"name": "content",
"resource": //<insert QuestionnaireResponse here> - a filled QR from
}
]
}
```

Relevant resources:

`source`- https://smartforms.csiro.au/api/fhir/StructureMap/extract-bmi

`content`- http://smartforms.csiro.au/fhir/Questionnaire/CalculatedExpressionBMICalculatorPrepop

[//]: # 'turn it into a microservice'

Running the $transform operation will return the transformed data, which in this case is a Bundle resource containing the Observation resource:

```json
{
"resourceType": "Bundle",
"id": "<uuid>",
"type": "transaction",
"entry": [
{
"request": {
"method": "POST",
"url": "Observation"
},
"resource": {
"resourceType": "Observation",
"status": "final",
"code": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": "60621009",
"display": "Body mass index"
}
]
},
"subject": {
"reference": "Patient/pat-sf"
},
"valueQuantity": {
"value": 29.55,
"unit": "kg/m2",
"system": "http://unitsofmeasure.org",
"code": "kg/m2"
}
}
}
]
}
```

#### The $extract operation

Using the logic above, we can abstract the $transform operation into a $extract operation. The $extract operation requires only one input parameter (or you can just provide the QuestionnaireResponse in the request body):

`questionnaire-response` - Contains the QuestionnaireResponse to extract data from

The provided QuestionnaireResponse should fulfill two criteria:

1. It needs to contain a canonical reference in its `questionnaire` property.

```json
{
...
"questionnaire": "https://smartforms.csiro.au/docs/sdc/population/calculated-expression-1|0.1.0",
...
}
```

2. The referenced Questionnaire should have a [questionnaire-targetStructureMap](http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-targetStructureMap) extension. This extension needs to contain a canonical reference to a StructureMap that maps the data from the QuestionnaireResponse to the desired resource(s).

```json
{
...
"extension": [
{
"url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-targetStructureMap",
"valueCanonical": "https://smartforms.csiro.au/docs/StructureMap/extract-bmi"
}
],
...
}
```

The $extract POC implementation defines a definitional repository to resolve Questionnaires and StructureMaps - https://smartforms.csiro.au/api/fhir. See https://hub.docker.com/r/aehrc/smart-forms-extract for more information.

The $extract operation will resolve the referenced Questionnaire + StructureMap, and set the StructureMap as the `source` in the $transform operation. The `content` will be the provided QuestionnaireResponse.

The underlying $transform operation will be executed, and the transformed data will be returned as the output of the $extract operation.

## The $convert operation

Brian's [.NET FHIR Mapping Language engine](https://github.com/brianpos/fhir-net-mappinglanguage/tree/main/demo-map-server) has a handy debug mode that can be activated by adding `debug=true` to the $transform query parameters.
The debug payload contains useful details such as warnings/errors, trace output, the converted StructureMap, and the output resource.

Conveniently, it also accepts both a FHIR Mapping Language map and a StructureMap resource as the `source` input.
This means we can use it as a $convert operation to convert a FHIR Mapping Language map to a StructureMap resource.

```
https://proxy.smartforms.io/fhir/StructureMap/$convert
```

It expects the request headers for the `Content-Type` to be `text/plain`. The request body should contain the FHIR Mapping Language map, and the response will contain the converted StructureMap resource.
Loading

0 comments on commit 00581f4

Please sign in to comment.