Skip to content

Commit

Permalink
Add custom populatedContext property to in app population
Browse files Browse the repository at this point in the history
  • Loading branch information
fongsean committed Jul 22, 2024
1 parent ba9fbbb commit 13212d5
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ function PlaygroundRenderer(props: PlaygroundRendererProps) {

const sourceQuestionnaire = useQuestionnaireStore.use.sourceQuestionnaire();
const targetStructureMap = useExtractOperationStore.use.targetStructureMap();
const setPopulatedContext = useQuestionnaireStore.use.setPopulatedContext();

const [isPopulating, setIsPopulating] = useState(false);

Expand Down Expand Up @@ -70,10 +71,13 @@ function PlaygroundRenderer(props: PlaygroundRendererProps) {
return;
}

const { populatedResponse } = populateResult;
const { populatedResponse, populatedContext } = populateResult;

// Call to buildForm to pre-populate the QR which repaints the entire BaseRenderer view
await buildForm(sourceQuestionnaire, populatedResponse, undefined, TERMINOLOGY_SERVER_URL);
if (populatedContext) {
setPopulatedContext(populatedContext);
}

setIsPopulating(false);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ import type {

export function createPopulateInputParameters(
questionnaire: Questionnaire,
patient: Patient,
user: Practitioner | null,
encounter: Encounter | null,
launchContexts: LaunchContext[],
sourceQueries: SourceQuery[],
questionnaireLevelVariables: QuestionnaireLevelXFhirQueryVariable[],
context: Record<string, any>,
patient: Patient,
user?: Practitioner,
encounter?: Encounter
context: Record<string, any>
): Parameters | null {
const patientSubject = createPatientSubject(questionnaire, patient);
if (!patientSubject) {
Expand Down Expand Up @@ -73,10 +73,10 @@ export function createPopulateInputParameters(
for (const launchContext of launchContexts) {
const launchContextParam = createLaunchContextParam(
launchContext,
context,
patient,
user,
encounter
encounter,
context
);
if (launchContextParam) {
contexts.push(launchContextParam);
Expand Down Expand Up @@ -147,10 +147,10 @@ function createLocalParam(): ParametersParameter {

function createLaunchContextParam(
launchContext: LaunchContext,
context: Record<string, any>,
patient: Patient,
user?: Practitioner,
encounter?: Encounter
user: Practitioner | null,
encounter: Encounter | null,
fhirPathContext: Record<string, any>
): ParametersParameter | null {
const name = launchContext.extension[0].valueId ?? launchContext.extension[0].valueCoding?.code;
if (!name) {
Expand All @@ -174,7 +174,7 @@ function createLaunchContextParam(
}

// Update context with launchContext resources
context[name] = resource;
fhirPathContext[name] = resource;

return {
name: 'context',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ import type {
Patient,
Practitioner,
Questionnaire,
QuestionnaireItem,
QuestionnaireResponse
} from 'fhir/r4';
import type {
CustomContextResultParameter,
FetchResourceCallback,
InputParameters,
IssuesParameter,
Expand All @@ -42,10 +44,13 @@ import type {
QuestionnaireLevelXFhirQueryVariable,
SourceQuery
} from '../interfaces/inAppPopulation.interface';
import { Base64 } from 'js-base64';
import { isRecord } from '@aehrc/smart-forms-app/src/features/prepopulate/typePredicates/isRecord';

export interface PopulateResult {
populatedResponse: QuestionnaireResponse;
issues?: OperationOutcome;
populatedContext?: Record<string, any>;
}

/**
Expand Down Expand Up @@ -103,7 +108,7 @@ export async function populateQuestionnaire(params: PopulateQuestionnaireParams)
// Get launch contexts, source queries and questionnaire-level variables
const launchContexts = getLaunchContexts(questionnaire);
const sourceQueries = getSourceQueries(questionnaire);
const questionnaireLevelVariables = getQuestionnaireLevelXFhirQueryVariables(questionnaire);
const questionnaireLevelVariables = getXFhirQueryVariables(questionnaire);

if (
launchContexts.length === 0 &&
Expand All @@ -119,13 +124,13 @@ export async function populateQuestionnaire(params: PopulateQuestionnaireParams)
// Define population input parameters from launch contexts, source queries and questionnaire-level variables
const inputParameters = createPopulateInputParameters(
questionnaire,
patient,
user ?? null,
encounter ?? null,
launchContexts,
sourceQueries,
questionnaireLevelVariables,
context,
patient,
user,
encounter
context
);

if (!inputParameters) {
Expand Down Expand Up @@ -164,22 +169,30 @@ export async function populateQuestionnaire(params: PopulateQuestionnaireParams)
const issuesParameter = outputParameters.parameter.find((param) => param.name === 'issues') as
| IssuesParameter
| undefined;
const contextResultParameter = outputParameters.parameter.find(
(param) => param.name === 'contextResult-custom'
) as CustomContextResultParameter | undefined;

const populateResult: PopulateResult = {
populatedResponse: responseParameter.resource
};

// Add populated context to populateResult if it exists
if (contextResultParameter?.valueAttachment.data) {
const contextResult = JSON.parse(Base64.decode(contextResultParameter.valueAttachment.data));

if (isRecord(contextResult)) {
populateResult.populatedContext = contextResult;
}
}

if (issuesParameter) {
return {
populateSuccess: true,
populateResult: {
populatedResponse: responseParameter.resource,
issues: issuesParameter.resource
}
};
populateResult.issues = issuesParameter.resource;
}

return {
populateSuccess: true,
populateResult: {
populatedResponse: responseParameter.resource
}
populateResult: populateResult
};
}

Expand Down Expand Up @@ -327,14 +340,43 @@ function isXFhirQueryVariable(
);
}

function getQuestionnaireLevelXFhirQueryVariables(
function getXFhirQueryVariables(
questionnaire: Questionnaire
): QuestionnaireLevelXFhirQueryVariable[] {
const xFhirQueryVariables: QuestionnaireLevelXFhirQueryVariable[] = [];
if (questionnaire.extension && questionnaire.extension.length > 0) {
return questionnaire.extension.filter((extension) =>
isXFhirQueryVariable(extension)
) as QuestionnaireLevelXFhirQueryVariable[];
xFhirQueryVariables.push(
...(questionnaire.extension.filter((extension) =>
isXFhirQueryVariable(extension)
) as QuestionnaireLevelXFhirQueryVariable[])
);
}

return [];
if (questionnaire.item && questionnaire.item.length > 0) {
for (const qItem of questionnaire.item) {
xFhirQueryVariables.push(
...(getXFhirQueryVariablesRecursive(qItem) as QuestionnaireLevelXFhirQueryVariable[])
);
}
}

return xFhirQueryVariables;
}

function getXFhirQueryVariablesRecursive(qItem: QuestionnaireItem) {
let xFhirQueryVariables: Extension[] = [];

if (qItem.item) {
for (const childItem of qItem.item) {
xFhirQueryVariables = xFhirQueryVariables.concat(getXFhirQueryVariablesRecursive(childItem));
}
}

if (qItem.extension) {
xFhirQueryVariables.push(
...qItem.extension.filter((extension) => isXFhirQueryVariable(extension))
);
}

return xFhirQueryVariables;
}

0 comments on commit 13212d5

Please sign in to comment.