diff --git a/packages/client/src/forms/handlebarHelpers.ts b/packages/client/src/forms/handlebarHelpers.ts new file mode 100644 index 00000000000..fbe2f5286d8 --- /dev/null +++ b/packages/client/src/forms/handlebarHelpers.ts @@ -0,0 +1,30 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * OpenCRVS is also distributed under the terms of the Civil Registration + * & Healthcare Disclaimer located at http://opencrvs.org/license. + * + * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. + */ + +import { referenceApi } from '@client/utils/referenceApi' +import * as Handlebars from 'handlebars' + +export let handlebarHelpers: Record + +export async function initHandlebarHelpers() { + handlebarHelpers = await referenceApi.importHandlebarHelpers() +} + +export function registerHandlebarHelpers() { + if (handlebarHelpers) { + for (const funcName of Object.keys(handlebarHelpers)) { + const func = handlebarHelpers[funcName] + if (typeof func === 'function') { + Handlebars.registerHelper(funcName, func) + } + } + } +} diff --git a/packages/client/src/offline/actions.ts b/packages/client/src/offline/actions.ts index 821f018ba02..73a25e1b6f9 100644 --- a/packages/client/src/offline/actions.ts +++ b/packages/client/src/offline/actions.ts @@ -24,7 +24,8 @@ import { IApplicationConfigAnonymous, LoadFormsResponse, LoadValidatorsResponse, - LoadConditionalsResponse + LoadConditionalsResponse, + LoadHandlebarHelpersResponse } from '@client/utils/referenceApi' import { System } from '@client/utils/gateway' import { UserDetails } from '@client/utils/userUtils' @@ -324,6 +325,16 @@ export const validatorsFailed = (error: Error) => ({ payload: error }) +export const handlebarsLoaded = (payload: LoadHandlebarHelpersResponse) => ({ + type: 'OFFLINE/HANDLEBARS_LOADED' as const, + payload: payload +}) + +export const handlebarsFailed = (error: Error) => ({ + type: 'OFFLINE/HANDLEBARS_FAILED' as const, + payload: error +}) + export const conditionalsLoaded = (payload: LoadConditionalsResponse) => ({ type: 'OFFLINE/CONDITIONALS_LOADED' as const, payload: payload @@ -367,3 +378,5 @@ export type Action = | ReturnType | ReturnType | ReturnType + | ReturnType + | ReturnType diff --git a/packages/client/src/offline/reducer.ts b/packages/client/src/offline/reducer.ts index aca26ff9288..f1f532f7c01 100644 --- a/packages/client/src/offline/reducer.ts +++ b/packages/client/src/offline/reducer.ts @@ -46,6 +46,7 @@ import { Action as NotificationAction, configurationErrorNotification } from '@client/notification/actions' +import { initHandlebarHelpers } from '@client/forms/handlebarHelpers' export const OFFLINE_LOCATIONS_KEY = 'locations' export const OFFLINE_FACILITIES_KEY = 'facilities' @@ -236,6 +237,11 @@ const VALIDATORS_CMD = Cmd.run(() => initValidators(), { failActionCreator: actions.validatorsFailed }) +const HANDLEBARS_CMD = Cmd.run(() => initHandlebarHelpers(), { + successActionCreator: actions.handlebarsLoaded, + failActionCreator: actions.handlebarsFailed +}) + const RETRY_TIMEOUT = 5000 function delay(cmd: RunCmd, time: number) { @@ -252,6 +258,7 @@ function getDataLoadingCommands() { CONFIG_CMD, CONDITIONALS_CMD, VALIDATORS_CMD, + HANDLEBARS_CMD, FORMS_CMD, CONTENT_CMD ]) diff --git a/packages/client/src/setupTests.ts b/packages/client/src/setupTests.ts index 6721cad969d..7dd999b23e8 100644 --- a/packages/client/src/setupTests.ts +++ b/packages/client/src/setupTests.ts @@ -111,6 +111,17 @@ vi.mock('@client/forms/validators', async () => { } }) +vi.mock('@client/forms/handlebarHelpers', async () => { + const actual = (await vi.importActual( + '@client/forms/handlebarHelpers' + )) as any + return { + ...actual, + handlebarHelpers: {}, + initHandlebarHelpers: () => Promise.resolve() + } +}) + /* * Initialize mocks */ @@ -181,7 +192,8 @@ vi.doMock( loadConfigAnonymousUser: () => Promise.resolve(mockConfigResponse), loadForms: () => Promise.resolve(mockOfflineData.forms.forms), importConditionals: () => Promise.resolve({}), - importValidators: () => Promise.resolve({}) + importValidators: () => Promise.resolve({}), + importHandlebarHelpers: () => Promise.resolve({}) } }) ) diff --git a/packages/client/src/utils/referenceApi.ts b/packages/client/src/utils/referenceApi.ts index 765d582ab39..dd0340589c5 100644 --- a/packages/client/src/utils/referenceApi.ts +++ b/packages/client/src/utils/referenceApi.ts @@ -203,6 +203,19 @@ export async function importConditionals(): Promise { return conditionals } +export type LoadHandlebarHelpersResponse = Record< + string, + Handlebars.HelperDelegate +> +async function importHandlebarHelpers(): Promise { + // https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations + const handlebars = await import( + /* @vite-ignore */ `${window.config.COUNTRY_CONFIG_URL}/handlebars.js` + ) + + return handlebars +} + async function loadContent(): Promise { const url = `${window.config.COUNTRY_CONFIG_URL}/content/client` @@ -345,5 +358,6 @@ export const referenceApi = { loadForms, importValidators, importConditionals, + importHandlebarHelpers, loadConfigAnonymousUser } diff --git a/packages/client/src/views/PrintCertificate/PDFUtils.ts b/packages/client/src/views/PrintCertificate/PDFUtils.ts index 2394ec2fb18..052a4f0b29e 100644 --- a/packages/client/src/views/PrintCertificate/PDFUtils.ts +++ b/packages/client/src/views/PrintCertificate/PDFUtils.ts @@ -31,6 +31,7 @@ import { fetchImageAsBase64 } from '@client/utils/imageUtils' import { getOfflineData } from '@client/offline/selectors' import isValid from 'date-fns/isValid' import format from 'date-fns/format' +import { registerHandlebarHelpers } from '@client/forms/handlebarHelpers' type TemplateDataType = string | MessageDescriptor | Array function isMessageDescriptor( @@ -97,6 +98,7 @@ export function executeHandlebarsTemplate( }, cache ) + registerHandlebarHelpers() Handlebars.registerHelper( 'intl',