Skip to content

Commit

Permalink
Merge pull request #852 from aehrc/main
Browse files Browse the repository at this point in the history
Merging main to acdc-pilot
  • Loading branch information
fongsean authored Jun 12, 2024
2 parents ba47cb3 + 180a482 commit 0db633d
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 11 deletions.
2 changes: 1 addition & 1 deletion apps/smart-forms-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"dependencies": {
"@aehrc/sdc-assemble": "^1.2.0",
"@aehrc/sdc-populate": "^2.2.1",
"@aehrc/smart-forms-renderer": "^0.35.4",
"@aehrc/smart-forms-renderer": "^0.35.5",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@fontsource/material-icons": "^5.0.16",
Expand Down
2 changes: 1 addition & 1 deletion documentation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"typecheck": "tsc"
},
"dependencies": {
"@aehrc/smart-forms-renderer": "^0.35.4",
"@aehrc/smart-forms-renderer": "^0.35.5",
"@docusaurus/core": "^3.4.0",
"@docusaurus/preset-classic": "^3.4.0",
"@docusaurus/theme-live-codeblock": "^3.4.0",
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/smart-forms-renderer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@aehrc/smart-forms-renderer",
"version": "0.35.4",
"version": "0.35.5",
"description": "FHIR Structured Data Captured (SDC) rendering engine for Smart Forms",
"main": "lib/index.js",
"scripts": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import type { LaunchContext } from './populate.interface';
import type { EnableWhenExpressions, EnableWhenItems } from './enableWhen.interface';
import type { CalculatedExpression } from './calculatedExpression.interface';
import type { AnswerExpression } from './answerExpression.interface';
import type { Coding } from 'fhir/r4';
import type { Coding, QuestionnaireItemAnswerOption } from 'fhir/r4';

export interface QuestionnaireModel {
itemTypes: Record<string, string>;
Expand All @@ -32,6 +32,7 @@ export interface QuestionnaireModel {
enableWhenExpressions: EnableWhenExpressions;
calculatedExpressions: Record<string, CalculatedExpression[]>;
answerExpressions: Record<string, AnswerExpression>;
answerOptions: Record<string, QuestionnaireItemAnswerOption[]>;
processedValueSetCodings: Record<string, Coding[]>;
processedValueSetUrls: Record<string, string>;
fhirPathContext: Record<string, any>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import { createSelectors } from './selector';
import { mutateRepeatEnableWhenExpressionInstances } from '../utils/enableWhenExpression';
import { questionnaireResponseStore } from './questionnaireResponseStore';
import { createQuestionnaireResponseItemMap } from '../utils/questionnaireResponseStoreUtils/updatableResponseItems';
import { insertCompleteAnswerOptionsIntoQuestionnaire } from '../utils/questionnaireStoreUtils/insertAnswerOptions';

/**
* QuestionnaireStore properties and methods
Expand Down Expand Up @@ -180,6 +181,13 @@ export const questionnaireStore = createStore<QuestionnaireStoreType>()((set, ge
terminologyServerUrl
);

// Insert answerOptions with displays into questionnaire
questionnaire = insertCompleteAnswerOptionsIntoQuestionnaire(
questionnaire,
questionnaireModel.answerOptions
);

// Initialise form with questionnaire response and properties in questionnaire model
const {
initialEnableWhenItems,
initialEnableWhenLinkedQuestions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* limitations under the License.
*/

import type { Coding } from 'fhir/r4';
import type { Coding, QuestionnaireItemAnswerOption } from 'fhir/r4';
import type { CodeSystemLookupPromise } from '../../interfaces/lookup.interface';
import * as FHIR from 'fhirclient';

Expand Down Expand Up @@ -56,6 +56,45 @@ export async function addDisplayToProcessedCodings(
return processedCodings;
}

// Use this for a Record<linkId, answerOption[]>
export async function addDisplayToAnswerOptions(
answerOptions: Record<string, QuestionnaireItemAnswerOption[]>,
terminologyServerUrl: string
): Promise<Record<string, QuestionnaireItemAnswerOption[]>> {
// Store code system lookup promises for codings without displays
const codeSystemLookupPromises: Record<string, CodeSystemLookupPromise> = {};
for (const key in answerOptions) {
const options = answerOptions[key];
for (const option of options) {
if (option.valueCoding && !option.valueCoding.display) {
const query = `system=${option.valueCoding.system}&code=${option.valueCoding.code}`;
codeSystemLookupPromises[query] = {
promise: getCodeSystemLookupPromise(query, terminologyServerUrl),
oldCoding: option.valueCoding
};
}
}
}

// Resolves lookup promises in one go and assign newCodings to processedCodings
const resolvedCodeSystemLookupPromises = await resolveLookupPromises(codeSystemLookupPromises);
for (const key in answerOptions) {
const options = answerOptions[key];

for (const option of options) {
if (option.valueCoding) {
const lookUpKey = `system=${option.valueCoding.system}&code=${option.valueCoding.code}`;
const resolvedLookup = resolvedCodeSystemLookupPromises[lookUpKey];
if (resolvedLookup?.newCoding?.display) {
option.valueCoding.display = resolvedLookup.newCoding.display;
}
}
}
}

return answerOptions;
}

// Use this for an array of codings
export async function addDisplayToCodingArray(
codings: Coding[],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import type { Variables } from '../../interfaces/variables.interface';
import { resolveValueSets } from './resolveValueSets';
import { addAdditionalVariables } from './addAdditionalVariables';
import { getLinkIdTypeTuples } from '../qItem';
import { addDisplayToProcessedCodings } from './addDisplayToCodings';
import { addDisplayToAnswerOptions, addDisplayToProcessedCodings } from './addDisplayToCodings';

export async function createQuestionnaireModel(
questionnaire: Questionnaire,
Expand Down Expand Up @@ -62,8 +62,13 @@ export async function createQuestionnaireModel(
terminologyServerUrl
);

const { enableWhenItems, enableWhenExpressions, calculatedExpressions, answerExpressions } =
extractOtherExtensionsResult;
const {
enableWhenItems,
enableWhenExpressions,
calculatedExpressions,
answerExpressions,
answerOptions
} = extractOtherExtensionsResult;
variables = extractOtherExtensionsResult.variables;
valueSetPromises = extractOtherExtensionsResult.valueSetPromises;

Expand All @@ -83,6 +88,12 @@ export async function createQuestionnaireModel(
terminologyServerUrl
);

// In answerOptions, add display values to codings lacking them
const completeAnswerOptions = await addDisplayToAnswerOptions(
answerOptions,
terminologyServerUrl
);

return {
itemTypes,
tabs,
Expand All @@ -92,6 +103,7 @@ export async function createQuestionnaireModel(
enableWhenExpressions,
calculatedExpressions,
answerExpressions,
answerOptions: completeAnswerOptions,
processedValueSetCodings,
processedValueSetUrls,
fhirPathContext: {}
Expand All @@ -107,6 +119,7 @@ function createEmptyModel(): QuestionnaireModel {
calculatedExpressions: {},
enableWhenExpressions: { singleExpressions: {}, repeatExpressions: {} },
answerExpressions: {},
answerOptions: {},
enableWhenItems: { singleItems: {}, repeatItems: {} },
processedValueSetCodings: {},
processedValueSetUrls: {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type {
Expression,
Questionnaire,
QuestionnaireItem,
QuestionnaireItemAnswerOption,
QuestionnaireItemEnableWhen
} from 'fhir/r4';
import type { CalculatedExpression } from '../../interfaces/calculatedExpression.interface';
Expand Down Expand Up @@ -55,6 +56,7 @@ interface ReturnParamsRecursive {
calculatedExpressions: Record<string, CalculatedExpression[]>;
answerExpressions: Record<string, AnswerExpression>;
valueSetPromises: Record<string, ValueSetPromise>;
answerOptions: Record<string, QuestionnaireItemAnswerOption[]>;
}

export function extractOtherExtensions(
Expand All @@ -70,6 +72,7 @@ export function extractOtherExtensions(
};
const calculatedExpressions: Record<string, CalculatedExpression[]> = {};
const answerExpressions: Record<string, AnswerExpression> = {};
const answerOptions: Record<string, QuestionnaireItemAnswerOption[]> = {};

if (!questionnaire.item || questionnaire.item.length === 0) {
return {
Expand All @@ -81,6 +84,7 @@ export function extractOtherExtensions(
},
calculatedExpressions: {},
answerExpressions: {},
answerOptions: {},
valueSetPromises: valueSetPromises
};
}
Expand All @@ -95,6 +99,7 @@ export function extractOtherExtensions(
enableWhenExpressions,
calculatedExpressions,
answerExpressions,
answerOptions,
valueSetPromises,
defaultTerminologyServerUrl: terminologyServerUrl,
parentRepeatGroupLinkId: isRepeatGroup ? topLevelItem.linkId : undefined
Expand All @@ -107,6 +112,7 @@ export function extractOtherExtensions(
enableWhenExpressions,
calculatedExpressions,
answerExpressions,
answerOptions,
valueSetPromises
};
}
Expand All @@ -119,6 +125,7 @@ interface extractExtensionsFromItemRecursiveParams {
enableWhenExpressions: EnableWhenExpressions;
calculatedExpressions: Record<string, CalculatedExpression[]>;
answerExpressions: Record<string, AnswerExpression>;
answerOptions: Record<string, QuestionnaireItemAnswerOption[]>;
valueSetPromises: Record<string, ValueSetPromise>;
defaultTerminologyServerUrl: string;
parentRepeatGroupLinkId?: string;
Expand All @@ -135,6 +142,7 @@ function extractExtensionsFromItemRecursive(
enableWhenExpressions,
calculatedExpressions,
answerExpressions,
answerOptions,
valueSetPromises,
defaultTerminologyServerUrl,
parentRepeatGroupLinkId
Expand Down Expand Up @@ -201,6 +209,12 @@ function extractExtensionsFromItemRecursive(
};
}

// Get answerOptions
const options = item.answerOption ?? null;
if (options) {
answerOptions[item.linkId] = options;
}

const valueSetUrl = item.answerValueSet;
if (valueSetUrl) {
if (!valueSetPromises[valueSetUrl] && !valueSetUrl.startsWith('#')) {
Expand Down Expand Up @@ -229,6 +243,7 @@ function extractExtensionsFromItemRecursive(
enableWhenExpressions,
calculatedExpressions,
answerExpressions,
answerOptions,
valueSetPromises
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2024 Commonwealth Scientific and Industrial Research
* Organisation (CSIRO) ABN 41 687 119 230.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import type { Questionnaire, QuestionnaireItem, QuestionnaireItemAnswerOption } from 'fhir/r4';

/**
* Filter x-fhir-query variables from questionnaire's extensions needed for population
*
* @author Sean Fong
*/
export function insertCompleteAnswerOptionsIntoQuestionnaire(
questionnaire: Questionnaire,
completeAnswerOptions: Record<string, QuestionnaireItemAnswerOption[]>
): Questionnaire {
if (questionnaire.item && questionnaire.item.length > 0) {
for (const qItem of questionnaire.item) {
insertCompleteAnswerOptionsRecursive(qItem, completeAnswerOptions);
}
}

return questionnaire;
}

function insertCompleteAnswerOptionsRecursive(
qItem: QuestionnaireItem,
completeAnswerOptions: Record<string, QuestionnaireItemAnswerOption[]>
) {
if (qItem.item) {
for (const childItem of qItem.item) {
insertCompleteAnswerOptionsRecursive(childItem, completeAnswerOptions);
}
}

if (qItem.answerOption) {
const options = completeAnswerOptions[qItem.linkId];
if (options) {
qItem.answerOption = options;
}
}

return;
}

0 comments on commit 0db633d

Please sign in to comment.