Skip to content

Commit

Permalink
refactors and clean ups
Browse files Browse the repository at this point in the history
  • Loading branch information
pirupius committed Oct 18, 2023
1 parent cdafd1b commit b75ed87
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 114 deletions.
13 changes: 8 additions & 5 deletions src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ export interface OHRIFormSection {
questions: Array<OHRIFormField>;
inlineRendering?: 'single-line' | 'multiline' | 'automatic';
readonly?: string | boolean;
reference?: FormReference;
}

export interface OHRIFormQuestionOptions {
Expand Down Expand Up @@ -271,12 +272,14 @@ export interface DataSourceParameters {
config?: Record<string, any>;
}

export interface ReferencedForm {
formName: string;
alias: string;
export interface FormReference {
form: string;
page: string;
section: string;
excludeQuestions?: Array<string>;
}

export interface FormComponent {
export interface ReferencedForm {
formName: string;
alias: string;
component: OHRIFormSchema;
}
11 changes: 5 additions & 6 deletions src/hooks/useFormJson.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import formComponent from '../../__mocks__/forms/omrs-forms/form-component.json'
import artComponent from '../../__mocks__/forms/omrs-forms/component_art.json';
import hospitalizationComponent from '../../__mocks__/forms/omrs-forms/component_hospitalization.json';
import preclinicReviewComponent from '../../__mocks__/forms/omrs-forms/component_preclinic-review.json';
import { delay } from 'rxjs/operators';

const MINI_FORM_NAME = 'Mini Form';
const MINI_FORM_UUID = '112d73b4-79e5-4be8-b9ae-d0840f00d4cf';
Expand Down Expand Up @@ -137,11 +138,13 @@ describe('useFormJson', () => {
await act(async () => {
hook = renderHook(() => useFormJson(null, formComponent, null, null));
});
delay(5000);

expect(hook.result.current.isLoading).toBe(false);
expect(hook.result.current.error).toBe(undefined);
expect(hook.result.current.formJson.name).toBe(COMPONENT_FORM_NAME);


// verify subforms
verifyFormComponents(hook.result.current.formJson);
});
Expand All @@ -161,10 +164,6 @@ function verifyEmbeddedForms(formJson) {
}

function verifyFormComponents(formJson) {
// assert that the nestedForm2's (level one subform) pages have been aligned with the parent because they share the same encounterType
expect(formJson.pages.length).toBe(3);
// the mini form (it's not flattened into the parent form because it has a different encounterType)
const nestedSubform = formJson.pages[2].subform.form;
expect(nestedSubform.name).toBe(MINI_FORM_NAME);
expect(nestedSubform.pages.length).toBe(1);
// assert that alias has been replaced with the actual component
expect(formJson.pages.length).toBe(1);
}
139 changes: 36 additions & 103 deletions src/hooks/useFormJson.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect, useState } from 'react';
import { FormComponent, OHRIFormSchema, ReferencedForm } from '../api/types';
import { OHRIFormSchema, OHRIFormSection, ReferencedForm } from '../api/types';
import { isTrue } from '../utils/boolean-utils';
import { applyFormIntent } from '../utils/forms-loader';
import { fetchOpenMRSForm, fetchClobData } from '../api/api';
Expand Down Expand Up @@ -53,8 +53,7 @@ export async function loadFormJson(
// Form components
const formComponentsRefs = getReferencedForms(formJson);
const resolvedFormComponents = await loadFormComponents(formComponentsRefs);
const formComponents = mapFormComponents(formComponentsRefs, resolvedFormComponents);

const formComponents = mapFormComponents(resolvedFormComponents);
updateFormJsonWithComponents(formJson, formComponents);

return refineFormJson(formJson, formSessionIntent);
Expand Down Expand Up @@ -154,7 +153,7 @@ async function loadFormComponents(formComponentRefs: Array<ReferencedForm>): Pro
return Promise.all(formComponentRefs.map((formComponent) => loadFormJson(formComponent.formName, null, null)));
}

function mapFormComponents(formComponentRefs: Array<ReferencedForm>, formComponents: Array<OHRIFormSchema>) {
function mapFormComponents(formComponents: Array<OHRIFormSchema>): Map<string, OHRIFormSchema> {
const formComponentsMap: Map<string, OHRIFormSchema> = new Map();

formComponents.forEach((formComponent) => {
Expand All @@ -165,115 +164,49 @@ function mapFormComponents(formComponentRefs: Array<ReferencedForm>, formCompone
}

function updateFormJsonWithComponents(formJson: OHRIFormSchema, formComponents: Map<string, OHRIFormSchema>): void {
// form components
formComponents.forEach((subform) => {
const matchingPage = formJson.pages.find((page) => page.subform?.name === subform.name);
if (matchingPage) {
matchingPage.subform.form = subform;
}
});
}

function loadFormComponents2(schema: Object): Array<any> {
const referencedObjects: Array<any> = [];
this.extractPlaceholderObjects(schema, referencedObjects);
return referencedObjects;
}

function extractPlaceholderObjects(subSchema: any, objectsArray: Array<Object>): void {
if (!subSchema) {
return;
}
if (Array.isArray(subSchema)) {
for (let i = 0; i < subSchema.length; i++) {
if (subSchema[i]) {
this.extractPlaceholderObjects(subSchema[i], objectsArray);
formComponents.forEach((component, alias) => {
//loop through pages and search sections for reference key
formJson.pages.forEach((page) => {
if (page.sections) {
page.sections.forEach((section) => {
if (section.reference && section.reference.form === alias) {
// resolve referenced component section
let resolvedFormSection = getReferencedFormSection(section, component);
// add resulting referenced component section to section
Object.assign(section, resolvedFormSection);
}
});
}
}
} else if (typeof subSchema === 'object') {
if (subSchema.reference) {
objectsArray.push(subSchema);
} else if (this.isSchemaSubObjectExpandable(subSchema)) {
const toExpand = subSchema.pages || subSchema.sections || subSchema.questions;
this.extractPlaceholderObjects(toExpand, objectsArray);
}
}
}

function fillPlaceholderObject(placeHolderObject: Object, referenceObject: Object): Object {
for (const member in referenceObject) {
if (!placeHolderObject[member]) {
placeHolderObject[member] = referenceObject[member];
}
}
return placeHolderObject;
});
});
}

function replaceAllPlaceholdersWithActualObjects(
keyValReferencedForms: Object,
placeHoldersArray: Array<any>,
): Array<any> {
placeHoldersArray.forEach((placeHolder) => {
const referencedObject: Object = this.getReferencedObject(placeHolder.reference, keyValReferencedForms);
function getReferencedFormSection(formSection: OHRIFormSection, formComponent: OHRIFormSchema): OHRIFormSection {
let referencedFormSection: OHRIFormSection;

if (referencedObject) {
console.error('Form compile: Error finding referenced object', placeHolder.reference);
} else {
placeHolder = this.fillPlaceholderObject(placeHolder, referencedObject);
placeHolder = this.removeExcludedQuestionsFromPlaceholder(placeHolder);
delete placeHolder['reference'];
// search for component page and section reference from component
let matchingComponentPage = formComponent.pages.filter((page) => page.label === formSection.reference.page);
if (matchingComponentPage.length > 0) {
let matchingComponentSection = matchingComponentPage[0].sections.filter(
(componentSection) => componentSection.label === formSection.reference.section,
);
if (matchingComponentSection.length > 0) {
referencedFormSection = matchingComponentSection[0];
}
});
return placeHoldersArray;
}

function removeObjectFromArray(array: Array<any>, object: Object): void {
const indexOfObject = array.indexOf(object);
if (indexOfObject === -1) {
return;
}

array.splice(indexOfObject, 1);
return filterExcludedQuestions(referencedFormSection);
}

function removeExcludedQuestionsFromPlaceholder(placeHolder: any): Object {
if (Array.isArray(placeHolder.reference.excludeQuestions)) {
placeHolder.reference.excludeQuestions.forEach((excludedQuestionId) => {
const questionsArray: Array<any> = this.getQuestionsArrayByQuestionIdInSchema(placeHolder, excludedQuestionId);

if (!Array.isArray(questionsArray)) {
return;
}
const question = this.getQuestionByIdInSchema(questionsArray, excludedQuestionId);

this.removeObjectFromArray(questionsArray, question);
function filterExcludedQuestions(formSection: OHRIFormSection): OHRIFormSection {
if (formSection.reference.excludeQuestions) {
const excludeQuestions = formSection.reference.excludeQuestions;
formSection.questions = formSection.questions.filter((question) => {
return !excludeQuestions.includes(question.id);
});
}
return placeHolder;
}

function getReferencedObject(referenceData: any, keyValReferencedForms: Object): Object {
if (referenceData.form) {
console.error('Form compile: reference missing form attribute', referenceData);
return;
}
if (keyValReferencedForms[referenceData.form]) {
console.error('Form compile: referenced form alias not found', referenceData);
return;
}
if (!referenceData.questionId) {
return this.getQuestionByIdInSchema(keyValReferencedForms[referenceData.form], referenceData.questionId);
}
// delete reference from section
delete formSection.reference;

if (!referenceData.page && !referenceData.section) {
return this.getSectionInSchemaByPageLabelBySectionLabel(
keyValReferencedForms[referenceData.form],
referenceData.page,
referenceData.section,
);
}
if (!referenceData.page) {
return this.getPageInSchemaByLabel(keyValReferencedForms[referenceData.form], referenceData.page);
}
console.error('Form compile: Unsupported reference type', referenceData.reference);
return formSection;
}

0 comments on commit b75ed87

Please sign in to comment.