diff --git a/src/common/apis/formTranslationApi.js b/src/common/apis/formTranslationApi.js index eca3aafc..4d758583 100644 --- a/src/common/apis/formTranslationApi.js +++ b/src/common/apis/formTranslationApi.js @@ -11,3 +11,14 @@ export function translationsFor(formName, formVersion, locale, formUuid) { export function saveTranslations(translations) { return httpInterceptor.post(formBuilderConstants.saveTranslationsUrl, translations); } + +export function saveFormNameTranslations(nameTranslations, referenceUuid) { + return httpInterceptor.post(new UrlHelper() + .bahmniSaveFormNameTranslateUrl(referenceUuid), nameTranslations); +} + + +export function getFormNameTranslations(formName, formUuid) { + return httpInterceptor.get(new UrlHelper() + .bahmniFormNameTranslateUrl(formName, formUuid), 'text'); +} diff --git a/src/form-builder/actions/control.js b/src/form-builder/actions/control.js index 5858710e..403cef25 100644 --- a/src/form-builder/actions/control.js +++ b/src/form-builder/actions/control.js @@ -11,7 +11,7 @@ export const addSourceMap = (sourceMap) => ({ type: 'ADD_SOURCE_MAP', sourceMap export const setChangedProperty = (property, id) => ({ type: 'SET_CHANGED_PROPERTY', property, id }); -export const sourceChangedProperty = (source) => ({ type: 'SOURCE_CHANGED', source }); +export const sourceChangedProperty = (source, id) => ({ type: 'SOURCE_CHANGED', source, id }); export const dragSourceUpdate = (cell) => ({ type: 'DRAG_SOURCE_CHANGED', cell }); @@ -35,3 +35,9 @@ export const removeLocaleTranslation = (locale) => ({ type: 'REMOVE_LOCALE_TRANSLATIONS', locale }); export const clearTranslations = () => ({ type: 'CLEAR_TRANSLATIONS' }); + +export const formConditionsEventUpdate = (events) => ({ type: 'FORM_CONDITIONS_CHANGED', events }); + +export const formLoad = (controls) => ({ type: 'FORM_LOAD', controls }); + +export const deleteControl = (id) => ({ type: 'DELETE_CONTROL', id }); diff --git a/src/form-builder/components/ControlReduxWrapper.jsx b/src/form-builder/components/ControlReduxWrapper.jsx index ef6c8a39..5b8efc3c 100644 --- a/src/form-builder/components/ControlReduxWrapper.jsx +++ b/src/form-builder/components/ControlReduxWrapper.jsx @@ -152,6 +152,7 @@ export class ControlWrapper extends Draggable { controlId={this.props.metadata.id} controlName={this.props.metadata.name} deleteControl={this.props.deleteControl} + dispatch={this.props.dispatch} /> ); } diff --git a/src/form-builder/components/DeleteControlModal.jsx b/src/form-builder/components/DeleteControlModal.jsx index c2e3097a..f36fa381 100644 --- a/src/form-builder/components/DeleteControlModal.jsx +++ b/src/form-builder/components/DeleteControlModal.jsx @@ -1,5 +1,6 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; +import { deleteControl } from 'form-builder/actions/control'; export default class DeleteControlModal extends Component { @@ -7,6 +8,7 @@ export default class DeleteControlModal extends Component { e.preventDefault(); this.props.deleteControl(this.props.controlId); this.props.closeModal(); + this.props.dispatch(deleteControl(this.props.controlId)); } handleEsc(e) { @@ -45,4 +47,5 @@ DeleteControlModal.propTypes = { controlId: PropTypes.string, controlName: PropTypes.string, deleteControl: PropTypes.func.isRequired, + dispatch: PropTypes.func.isRequired, }; diff --git a/src/form-builder/components/FormBuilder.jsx b/src/form-builder/components/FormBuilder.jsx index 208de9bf..55889116 100644 --- a/src/form-builder/components/FormBuilder.jsx +++ b/src/form-builder/components/FormBuilder.jsx @@ -15,12 +15,12 @@ import { saveAs } from 'file-saver'; import NotificationContainer from 'common/Notification'; import { remove } from 'lodash'; import Spinner from 'common/Spinner'; - +import { formEventUpdate, saveEventUpdate } from 'form-builder/actions/control'; export default class FormBuilder extends Component { - constructor() { - super(); + constructor(props) { + super(props); this.state = { showModal: false, selectedForms: [], notification: {}, loading: false }; this.setState = this.setState.bind(this); @@ -32,6 +32,7 @@ export default class FormBuilder extends Component { this.formConceptValidationResults = {}; this.handleSelectedForm = this.handleSelectedForm.bind(this); this.parseErrorMessage = 'Parse Error While Importing.. Please import a valid form'; + this.clearEventEditors(); } getFormVersion(formName) { @@ -88,6 +89,11 @@ export default class FormBuilder extends Component { return validJsonFiles; } + clearEventEditors() { + this.props.dispatch(saveEventUpdate('')); + this.props.dispatch(formEventUpdate('')); + } + validateAndLoadZipFile(jsonZip) { const self = this; const maxAllowedSize = 5 * 1024 * 1024; @@ -221,6 +227,7 @@ export default class FormBuilder extends Component { const { formJson, translations } = formData; const formName = formJson.name; const value = JSON.parse(formJson.resources[0].value); + const nameTranslations = formJson.resources[1] && formJson.resources[1].value; const form = { name: formName, version: '1', @@ -239,7 +246,7 @@ export default class FormBuilder extends Component { }); self.updateImportErrors(fileName, message); } else { - self.formJSONs.push({ form, value, formName, translations }); + self.formJSONs.push({ form, value, formName, translations, nameTranslations }); } }); } @@ -271,15 +278,16 @@ export default class FormBuilder extends Component { const self = this; const importFormJsonPromises = []; formJsons.forEach(formJson => { - const { form, value, formName, translations } = formJson; - importFormJsonPromises.push(self.saveFormJson(form, value, formName, translations)); + const { form, value, formName, translations, nameTranslations } = formJson; + importFormJsonPromises.push(self.saveFormJson(form, value, formName, translations, + nameTranslations)); }); Promise.all(importFormJsonPromises) .then(() => self.hideLoader()) .catch(() => self.hideLoader()); } - saveFormJson(form, value, formName, translations) { + saveFormJson(form, value, formName, translations, nameTranslations) { const self = this; const val = value; return httpInterceptor.post(formBuilderConstants.formUrl, form).then((response) => { @@ -292,9 +300,18 @@ export default class FormBuilder extends Component { value: JSON.stringify(value), uuid: '', }; - const translationsWithFormUuid = translations.map((eachTranslation) => Object.assign({}, - eachTranslation, { formUuid: response.uuid })); - self.props.saveFormResource(formResource, translationsWithFormUuid); + const formNameTranslationsResource = !!nameTranslations && { + form: { + name: formName, + uuid: response.uuid, + }, + value: nameTranslations, + uuid: '', + }; + const translationsWithFormUuid = translations.map((eachTranslation) => + Object.assign({}, eachTranslation, { formUuid: response.uuid })); + self.props.saveFormResource(formResource, translationsWithFormUuid, + formNameTranslationsResource); }) .catch(() => { const formUuid = self.getFormUuid(formName); @@ -312,7 +329,15 @@ export default class FormBuilder extends Component { value: JSON.stringify(value), uuid: data.resources[0].uuid, }; - self.props.saveFormResource(formResource, translations); + const formNameTranslationsResource = !!nameTranslations && { + form: { + name: formName, + uuid: formUuid, + }, + value: nameTranslations, + uuid: '', + }; + self.props.saveFormResource(formResource, translations, formNameTranslationsResource); }); }); } @@ -479,6 +504,7 @@ export default class FormBuilder extends Component { FormBuilder.propTypes = { data: PropTypes.array.isRequired, + dispatch: PropTypes.func.isRequired, match: PropTypes.shape({ path: PropTypes.string.isRequired, url: PropTypes.string.isRequired, diff --git a/src/form-builder/components/FormBuilderContainer.jsx b/src/form-builder/components/FormBuilderContainer.jsx index 05e0e4c1..ad5e68d4 100644 --- a/src/form-builder/components/FormBuilderContainer.jsx +++ b/src/form-builder/components/FormBuilderContainer.jsx @@ -12,7 +12,7 @@ import sortBy from 'lodash/sortBy'; import formHelper from '../helpers/formHelper'; import { connect } from 'react-redux'; import { setDefaultLocale } from '../actions/control'; -import { saveTranslations } from 'common/apis/formTranslationApi'; +import { saveFormNameTranslations, saveTranslations } from 'common/apis/formTranslationApi'; export class FormBuilderContainer extends Component { @@ -103,21 +103,23 @@ export class FormBuilderContainer extends Component { } } - saveTranslations(translations) { + saveTranslations(translations, formNameTranslations) { const self = this; self.setMessage('Importing Translations...', commonConstants.responseType.success); - saveTranslations(translations || []) - .then(() => { - self.getFormData(); - self.setMessage('Imported Successfully', - commonConstants.responseType.success); - }) - .catch(() => { - this.setMessage('Error Importing Translations', commonConstants.responseType.error); - }); + const translationsPromises = [saveTranslations(translations || [])]; + if (formNameTranslations) { + translationsPromises.push(saveFormNameTranslations(formNameTranslations, null)); + } + + Promise.all(translationsPromises).then(() => { + self.getFormData(); + self.setMessage('Imported Successfully', commonConstants.responseType.success); + }).catch(() => { + this.setMessage('Error Importing Translations', commonConstants.responseType.error); + }); } - saveFormResource(formJson, formTranslations) { + saveFormResource(formJson, formTranslations, formNameTranslationsResource) { const self = this; self.setMessage('Importing Form...', commonConstants.responseType.success); httpInterceptor.post(formBuilderConstants.bahmniFormResourceUrl, formJson) @@ -127,7 +129,7 @@ export class FormBuilderContainer extends Component { formTranslation.version = form.form.version || translation.version; return formTranslation; }); - self.saveTranslations(updatedTranslations); + self.saveTranslations(updatedTranslations, formNameTranslationsResource); }) .catch(() => { this.setMessage('Error Importing Form', commonConstants.responseType.error); @@ -143,12 +145,13 @@ export class FormBuilderContainer extends Component { /> this.onValidationError(messages)} routes={this.props.routes} saveForm={(formName) => this.saveForm(formName)} - saveFormResource={(formJson, translations) => - this.saveFormResource(formJson, translations)} + saveFormResource={(formJson, translations, nameTranslations) => + this.saveFormResource(formJson, translations, nameTranslations)} /> ); diff --git a/src/form-builder/components/FormConditionsModal.js b/src/form-builder/components/FormConditionsModal.js new file mode 100644 index 00000000..b9687d94 --- /dev/null +++ b/src/form-builder/components/FormConditionsModal.js @@ -0,0 +1,118 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import ObsControlScriptEditorModal from 'form-builder/components/ObsControlScriptEditorModal'; + +export default class FormConditionsModal extends Component { + constructor(props) { + super(props); + this.state = { selectedControlEventTitleId: undefined, + selectedControlEventTitleName: undefined, selectedControlScript: undefined }; + this.selectedControlOption = undefined; + this.selectedControlTitleId = undefined; + this.selectedControlTitleName = undefined; + this.selectedControlScript = undefined; + this.updateSelectedOption = this.updateSelectedOption.bind(this); + } + + updateSelectedOption(element) { + this.selectedControlOption = element.target.value; + const selectedControlEventObj = this.props.controlEvents.find(control => + control.id === this.selectedControlOption); + const selectedControlScriptObj = selectedControlEventObj ? + selectedControlEventObj.events : undefined; + this.selectedControlTitleId = selectedControlEventObj ? selectedControlEventObj.id : undefined; + this.selectedControlTitleName = selectedControlEventObj ? selectedControlEventObj.name : + undefined; + this.selectedControlScript = selectedControlScriptObj ? + selectedControlScriptObj.onValueChange : undefined; + this.setState({ selectedControlEventTitleId: this.selectedControlTitleId }); + this.setState({ selectedControlEventTitleName: this.selectedControlTitleName }); + this.setState({ selectedControlScript: this.selectedControlScript }); + } + + showObsControlScriptEditorModal(controlScript, controlEventTitleId, controlEventTitleName) { + if (controlEventTitleId !== undefined) { + return ( + ); + } + return null; + } + render() { + const obs = this.props.controlEvents !== undefined ? this.props.controlEvents : []; + const ObsWithControlEvents = obs.filter(o => o.events !== undefined); + const obsWithoutControlEvents = obs.filter(o => o.events === undefined); + const formDetailEvents = this.props.formDetails.events ? this.props.formDetails.events + : { onFormInit: undefined, onFormSave: undefined }; + return ( +
+

{this.props.formTitle} - Form Conditions

+ +
+
+ { this.showObsControlScriptEditorModal(formDetailEvents.onFormInit, null, + 'Form Event')} +
+ { this.showObsControlScriptEditorModal(formDetailEvents.onFormSave, null, + 'Save Event')} +
+
+
+
+
+ + +
+ +
+ { + ObsWithControlEvents.map((e) => + this.showObsControlScriptEditorModal(e.events.onValueChange, e.id, e.name) + ) + } +
+ { +
{this.showObsControlScriptEditorModal(this.state.selectedControlScript, + this.state.selectedControlEventTitleId, this.state.selectedControlEventTitleName)} + +
+ } +
+ +
+ +
+ +
+ ); + } +} + +FormConditionsModal.propTypes = { + close: PropTypes.func.isRequired, + controlEvents: PropTypes.array, + formDetails: PropTypes.shape({ + events: PropTypes.object, + }), + formTitle: PropTypes.string, + selectedControlEventTitleId: PropTypes.string, + selectedControlEventTitleName: PropTypes.string, + selectedControlScript: PropTypes.string, + updateScript: PropTypes.func.isRequired, +}; + +FormConditionsModal.defaultProps = { + formDetails: { events: {} }, +}; + diff --git a/src/form-builder/components/FormDetail.jsx b/src/form-builder/components/FormDetail.jsx index e2ef44bc..b99d1396 100644 --- a/src/form-builder/components/FormDetail.jsx +++ b/src/form-builder/components/FormDetail.jsx @@ -10,6 +10,8 @@ import FormHelper from 'form-builder/helpers/formHelper'; import FormEventEditor from 'form-builder/components/FormEventEditor.jsx'; import ScriptEditorModal from 'form-builder/components/ScriptEditorModal'; import Popup from 'reactjs-popup'; +import FormConditionsModal from 'form-builder/components/FormConditionsModal'; + export default class FormDetail extends Component { constructor() { @@ -17,15 +19,15 @@ export default class FormDetail extends Component { this.canvasRef = this.canvasRef.bind(this); this.canvas = undefined; window.onscroll = () => { - if (document.getElementsByClassName('column-side').length === 1) { - if (window.scrollY <= 62) { - const element = document.getElementsByClassName('column-side'); - element[0].className = 'column-side'; - } - if (window.scrollY >= 63 && window.scrollY <= 500) { - const element = document.getElementsByClassName('column-side'); - element[0].className = 'column-side scrolled'; - } + const getByClass = (elementClassName) => document.getElementsByClassName(elementClassName); + const isViewMode = getByClass('info-view-mode-wrap').length === 1; + const heightCheck = isViewMode ? 120 : 66; + const element = getByClass('column-side'); + const isPresent = element.length === 1; + if (isPresent && window.scrollY > heightCheck) { + element[0].className = 'column-side scrolled'; + } else { + element[0].className = 'column-side'; } }; } @@ -68,7 +70,27 @@ export default class FormDetail extends Component { const FormEventEditorContent = (props) => { const script = props.property ? getScript(props.property, props.formDetails) : ''; const showEditor = props.property && (props.property.formInitEvent - || props.property.formSaveEvent); + || props.property.formSaveEvent || props.property.formConditionsEvent); + if (!showEditor) { + return (
); + } + if (props.property.formConditionsEvent) { + return (
+ {showEditor && + + + + } +
); + } return (
{showEditor && +
@@ -139,6 +167,7 @@ export default class FormDetail extends Component { FormDetail.propTypes = { defaultLocale: PropTypes.string, + formControlEvents: PropTypes.Array, formData: PropTypes.shape({ id: PropTypes.number, name: PropTypes.string.isRequired, @@ -148,6 +177,9 @@ FormDetail.propTypes = { version: PropTypes.string.isRequired, editable: PropTypes.bool, }), + formDetails: PropTypes.shape({ + events: PropTypes.object, + }), setError: PropTypes.func.isRequired, updateFormEvents: PropTypes.func, updateFormName: PropTypes.func, diff --git a/src/form-builder/components/FormDetailContainer.jsx b/src/form-builder/components/FormDetailContainer.jsx index 0f3857f2..bb810278 100644 --- a/src/form-builder/components/FormDetailContainer.jsx +++ b/src/form-builder/components/FormDetailContainer.jsx @@ -7,7 +7,7 @@ import FormDetail from 'form-builder/components/FormDetail.jsx'; import FormBuilderHeader from 'form-builder/components/FormBuilderHeader.jsx'; import FormBuilderBreadcrumbs from 'form-builder/components/FormBuilderBreadcrumbs.jsx'; import { connect } from 'react-redux'; -import { blurControl, deselectControl, removeControlProperties, removeSourceMap } +import { blurControl, deselectControl, removeControlProperties, removeSourceMap, formLoad } from 'form-builder/actions/control'; import NotificationContainer from 'common/Notification'; import Spinner from 'common/Spinner'; @@ -18,22 +18,23 @@ import FormHelper from 'form-builder/helpers/formHelper'; import formHelper from '../helpers/formHelper'; import get from 'lodash/get'; import isEqual from 'lodash/isEqual'; -import { clearTranslations, formEventUpdate, saveEventUpdate } from '../actions/control'; +import { clearTranslations } from '../actions/control'; +import { formEventUpdate, saveEventUpdate } from '../actions/control'; import { Exception } from 'form-builder/helpers/Exception'; -import { saveTranslations } from 'common/apis/formTranslationApi'; +import { saveFormNameTranslations, saveTranslations } from 'common/apis/formTranslationApi'; import FormPreviewModal from 'form-builder/components/FormPreviewModal.jsx'; import Popup from 'reactjs-popup'; export class FormDetailContainer extends Component { - constructor(props) { super(props); this.timeoutId = undefined; + this.formJson = undefined; this.state = { formData: undefined, showModal: false, showPreview: false, notification: {}, - httpReceived: false, loading: true, formList: [], + httpReceived: false, loading: true, formList: [], formControls: [], originalFormName: undefined, formEvents: {}, referenceVersion: undefined, - formPreviewJson: undefined }; + referenceFormUuid: undefined, formPreviewJson: undefined }; this.setState = this.setState.bind(this); this.setErrorMessage = this.setErrorMessage.bind(this); this.onSave = this.onSave.bind(this); @@ -43,6 +44,7 @@ export class FormDetailContainer extends Component { this.cloneFormResource = this.cloneFormResource.bind(this); this.onPreview = this.onPreview.bind(this); this.generateFormPreviewJson = this.generateFormPreviewJson.bind(this); + props.dispatch(deselectControl()); props.dispatch(removeSourceMap()); props.dispatch(removeControlProperties()); @@ -57,9 +59,15 @@ export class FormDetailContainer extends Component { httpInterceptor .get(`${formBuilderConstants.formUrl}/${this.props.match.params.formUuid}?${params}`) .then((data) => { + const parsedFormValue = data.resources.length > 0 ? + JSON.parse(data.resources[0].value) : {}; this.setState({ formData: data, httpReceived: true, - loading: false, originalFormName: data.name, referenceVersion: data.version }); - this.getFormJson(); + loading: false, originalFormName: data.name, + referenceVersion: parsedFormValue.referenceVersion, + referenceFormUuid: parsedFormValue.referenceFormUuid }); + this.formJson = this.getFormJson(); + const formControlsArray = this.getObsControlEvents(this.formJson); + this.props.dispatch(formLoad(formControlsArray)); }) .catch((error) => { this.setErrorMessage(error); @@ -70,6 +78,7 @@ export class FormDetailContainer extends Component { this.getFormList(); } + componentWillUpdate(nextProps, nextState) { if (!isEqual(nextProps, this.props) || !isEqual(nextState, this.state)) { this.props.dispatch(deselectControl()); @@ -107,6 +116,8 @@ export class FormDetailContainer extends Component { const formResourceUuid = this.state.formData && this.state.formData.resources.length > 0 ? this.state.formData.resources[0].uuid : ''; formJson.translationsUrl = formBuilderConstants.translationsUrl; + formJson.referenceVersion = this.state.referenceVersion; + formJson.referenceFormUuid = this.state.referenceFormUuid; const formResource = { form: { name: formName, @@ -143,6 +154,28 @@ export class FormDetailContainer extends Component { this.generateFormPreviewJson(); } + + getObsControlEvents(control) { + let obsControlEvents = []; + if (control && control !== undefined && control.controls !== undefined) { + const childControls = control.controls; + const obsControls = childControls.filter(ctrl => ctrl.type === 'obsControl'); + const nonObscontrols = childControls.filter(ctrl => ctrl.type !== 'obsControl'); + + nonObscontrols.forEach(ctrl => { + if (ctrl.controls !== undefined) { + const childObsControlEvents = this.getObsControlEvents(ctrl); + if (childObsControlEvents && childObsControlEvents !== undefined) { + obsControlEvents = obsControlEvents.concat(childObsControlEvents); + } + } + }); + obsControlEvents = obsControlEvents.concat(obsControls.map(ctrl => + ({ id: ctrl.id, name: ctrl.concept.name, events: ctrl.events }))); + } + return obsControlEvents; + } + getFormJson() { if (this.formDetail) { return this.formDetail.getFormJson(); @@ -194,8 +227,9 @@ export class FormDetailContainer extends Component { _createTranslationReqObject(container, locale) { const { version, name, uuid } = this.state.formData; const referenceVersion = this.state.referenceVersion; + const referenceFormUuid = this.state.referenceFormUuid; const translations = Object.assign({}, container, { formUuid: uuid, - formName: name, version, locale, referenceVersion }); + formName: name, version, locale, referenceVersion, referenceFormUuid }); return [translations]; } @@ -285,7 +319,9 @@ export class FormDetailContainer extends Component { { editable: true } ); this.props.dispatch(clearTranslations()); - this.setState({ formData: editableFormData }); + this.setState({ formData: editableFormData, + referenceVersion: this.state.formData.version, + referenceFormUuid: this.state.formData.uuid }); } generateFormPreviewJson() { @@ -310,7 +346,7 @@ export class FormDetailContainer extends Component { position="top center" > this.closePreview()} - formJson={this.state.formPreviewJson} + formJson={this.state.formPreviewJson} setErrorMessage={this.setErrorMessage} /> ); } @@ -341,7 +377,18 @@ export class FormDetailContainer extends Component { _saveTranslationsAndPublishForm(formUuid, translations) { this.setState({ loading: true }); - saveTranslations(translations).then(() => { + const formNameTranslations = { + form: { + name: this.state.originalFormName, + uuid: this.props.match.params.formUuid, + }, value: '', + }; + const translationsPromises = [saveTranslations(translations)]; + if (this.state.referenceFormUuid && this.state.formData.version !== '1') { + translationsPromises.push(saveFormNameTranslations(formNameTranslations, + this.state.referenceFormUuid)); + } + Promise.all(translationsPromises).then(() => { httpInterceptor.post(new UrlHelper().bahmniFormPublishUrl(formUuid)) .then((response) => { const successNotification = { @@ -465,7 +512,9 @@ export class FormDetailContainer extends Component { {this.showPreviewModal()} { this.formDetail = r; }} setError={this.setErrorMessage} updateFormEvents={(events) => this.updateFormEvents(events)} @@ -482,6 +531,10 @@ export class FormDetailContainer extends Component { FormDetailContainer.propTypes = { defaultLocale: PropTypes.string, dispatch: PropTypes.func, + formControlEvents: PropTypes.array, + formDetails: PropTypes.shape({ + events: PropTypes.object, + }), match: PropTypes.shape({ path: PropTypes.string.isRequired, url: PropTypes.string.isRequired, @@ -500,6 +553,8 @@ function mapStateToProps(state) { return { defaultLocale: state.formDetails && state.formDetails.defaultLocale, translations: state.translations, + formDetails: state.formDetails, + formControlEvents: state.controlDetails.allObsControlEvents, }; } diff --git a/src/form-builder/components/FormEventEditor.jsx b/src/form-builder/components/FormEventEditor.jsx index 70bc3521..1ac16ceb 100644 --- a/src/form-builder/components/FormEventEditor.jsx +++ b/src/form-builder/components/FormEventEditor.jsx @@ -1,10 +1,10 @@ import React from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; -import { formEventUpdate, saveEventUpdate, setChangedProperty } from 'form-builder/actions/control'; - +import { formEventUpdate, saveEventUpdate } from 'form-builder/actions/control'; +import { setChangedProperty, formConditionsEventUpdate } from 'form-builder/actions/control'; export const FormEventEditor = (props) => { - const { property, formDetails, closeEventEditor } = props; + const { property, formDetails, closeEventEditor, formControlEvents } = props; const updateScript = (script) => { props.updateScript(script, property); }; @@ -12,7 +12,7 @@ export const FormEventEditor = (props) => { return (
{React.cloneElement(props.children, { property, formDetails, closeEventEditor, - updateScript })} + formControlEvents, updateScript })}
); }; @@ -20,15 +20,18 @@ export const FormEventEditor = (props) => { FormEventEditor.propTypes = { children: PropTypes.element.isRequired, closeEventEditor: PropTypes.func.isRequired, + formControlEvents: PropTypes.Array, formDetails: PropTypes.shape({ events: PropTypes.shape({ onFormInit: PropTypes.string, onFormSave: PropTypes.string, + onFormConditionsUpdate: PropTypes.string, }), }), property: PropTypes.shape({ formInitEvent: PropTypes.bool, formSaveEvent: PropTypes.bool, + formConditionsEvent: PropTypes.bool, }), updateScript: PropTypes.func.isRequired, @@ -36,20 +39,22 @@ FormEventEditor.propTypes = { const mapStateToProps = (state) => ({ property: state.controlProperty ? state.controlProperty.property : undefined, - formDetails: state.formDetails, + formDetails: state.formDetails, formControlEvents: state.controlDetails.allObsControlEvents, }); const mapDispatchToProps = (dispatch) => ({ closeEventEditor: () => { dispatch(setChangedProperty({ formInitEvent: false })); dispatch(setChangedProperty({ formSaveEvent: false })); + dispatch(setChangedProperty({ formConditionsEvent: false })); }, updateScript: (script, property) => { - const isSaveEvent = property.formSaveEvent; - if (isSaveEvent) { + if (property.formSaveEvent) { dispatch(saveEventUpdate(script)); - } else { + } else if (property.formInitEvent) { dispatch(formEventUpdate(script)); + } else if (property.formConditionsEvent) { + dispatch(formConditionsEventUpdate(script)); } }, }); diff --git a/src/form-builder/components/FormPreviewModal.jsx b/src/form-builder/components/FormPreviewModal.jsx index 8bbcfaf5..8a0fd140 100644 --- a/src/form-builder/components/FormPreviewModal.jsx +++ b/src/form-builder/components/FormPreviewModal.jsx @@ -1,38 +1,58 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { Container as Container } from 'bahmni-form-controls'; import 'bahmni-form-controls/dist/helpers.js'; +import { Exception } from 'form-builder/helpers/Exception'; export default class FormPreviewModal extends React.Component { + static formatErrors(error) { + if (Array.isArray(error)) { + return error.map(e => e.message || '[ERROR]').join(' | '); + } + return error.message || '[ERROR]'; + } + constructor(props) { super(props); this.state = { formData: {}, - observations: [], + container: {}, + defaultLocale: localStorage.getItem('openmrsDefaultLocale'), }; - this.getContainer = this.getContainer.bind(this); + this.onSave = this.onSave.bind(this); + this.setContainer = this.setContainer.bind(this); } - getContainer(metadata) { + componentDidMount() { + this.setContainer([]); + } + + onSave() { + const formJson = this.props.formJson; + if (this.state.container.state && formJson.events.onFormSave) { + /* eslint-disable no-undef */ + try { + const records = runEventScript(this.state.container.state.data, formJson.events.onFormSave); + unMountForm(document.getElementById('form-container')); + this.setContainer(getObservations(records)); + } catch (e) { + this.props.setErrorMessage(new Exception(FormPreviewModal.formatErrors(e)).getException()); + } + } + } + + setContainer(observations) { + const metadata = this.props.formJson; if (metadata) { - return (); + const container = renderWithControls(metadata, observations, 'form-container', false, null, + false, this.state.defaultLocale, ''); + this.setState({ container }); } - return null; } render() { if (this.props.formJson) { - const metadata = this.props.formJson; return (
@@ -40,9 +60,14 @@ export default class FormPreviewModal extends React.Component {
- {this.getContainer(metadata)} +
+