diff --git a/package.json b/package.json index 755e4c3..e1d3138 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,8 @@ "react-router-dom": "^4.3.1", "reactjs-popup": "^1.5.0", "redux": "^4.0.5", - "whatwg-fetch": "^1.0.0" + "whatwg-fetch": "^1.0.0", + "html-entities": "^2.6.0" }, "resolutions": { "**/**/lodash": "^4.17.12", diff --git a/src/common/utils/encodingUtils.js b/src/common/utils/encodingUtils.js index 396b958..8746e59 100644 --- a/src/common/utils/encodingUtils.js +++ b/src/common/utils/encodingUtils.js @@ -1,3 +1,5 @@ +import { decode } from 'html-entities'; + /* * 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 @@ -18,6 +20,39 @@ export function utf8ToBase64(str) { return btoa(binaryString); } +export function unescapeHtml(str) { + if (typeof str !== 'string') return str; + return decode(str); +} + +export function deepUnescapeStrings(obj) { + if (typeof obj === 'string') { + return unescapeHtml(obj); + } + if (Array.isArray(obj)) { + return obj.map(deepUnescapeStrings); + } + if (typeof obj === 'object' && obj !== null) { + const result = {}; + for (const key of Object.keys(obj)) { + result[key] = deepUnescapeStrings(obj[key]); + } + return result; + } + return obj; +} + +export function unescapeFormResourceValue(valueString) { + if (!valueString) return valueString; + try { + const parsed = JSON.parse(valueString); + const unescaped = deepUnescapeStrings(parsed); + return JSON.stringify(unescaped); + } catch (e) { + return valueString; + } +} + export function base64ToUtf8(b64) { if (b64 === undefined || b64 === null || b64 === '') { return ''; diff --git a/src/form-builder/components/FormDetailContainer.jsx b/src/form-builder/components/FormDetailContainer.jsx index ba155f2..3fb6baf 100644 --- a/src/form-builder/components/FormDetailContainer.jsx +++ b/src/form-builder/components/FormDetailContainer.jsx @@ -38,6 +38,7 @@ import isEqual from 'lodash/isEqual'; import { clearTranslations } from '../actions/control'; import { formEventUpdate, saveEventUpdate } from '../actions/control'; import { Exception } from 'form-builder/helpers/Exception'; +import { unescapeFormResourceValue } from 'common/utils/encodingUtils'; import { saveFormNameTranslations, saveTranslations, @@ -97,6 +98,9 @@ export class FormDetailContainer extends Component { `${formBuilderConstants.formUrl}/${this.props.match.params.formUuid}?${params}` ) .then((data) => { + if (data.resources.length > 0 && data.resources[0].value) { + data.resources[0].value = unescapeFormResourceValue(data.resources[0].value); + } const parsedFormValue = data.resources.length > 0 ? JSON.parse(data.resources[0].value) : {}; const formDefVersion = parsedFormValue.formDefVersion || 1.0; @@ -611,7 +615,7 @@ export class FormDetailContainer extends Component { name: form.name, id: responseObject.form.id, dataType: responseObject.dataType, - value: responseObject.value, + value: unescapeFormResourceValue(responseObject.value), uuid: responseObject.uuid, }; form.resources = [formResource]; diff --git a/src/form-builder/components/FormPreviewModal.jsx b/src/form-builder/components/FormPreviewModal.jsx index 8cc9ea7..33677c0 100644 --- a/src/form-builder/components/FormPreviewModal.jsx +++ b/src/form-builder/components/FormPreviewModal.jsx @@ -10,7 +10,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import PropTypes from 'prop-types'; -import 'bahmni-form-controls/dist/helpers.js'; +import 'bahmni-form-controls/helpers.js'; import { Exception } from 'form-builder/helpers/Exception'; import { Container } from 'bahmni-form-controls';