Untitled
unknown
plain_text
3 years ago
39 kB
6
Indexable
/* eslint-disable no-undef */ import { Formio } from 'formiojs'; // import DCEye from '../../../Assets/icons/DCEye' // import DCFillEye from '../../../Assets/icons/DCFillEye' const FieldComponent = Formio.Components.components.field; export const editForm = Formio.Components.components.nested.editForm; /** * Here we will derive from the base component which all Form.io form components derive from. * * @param component * @param options * @param data * @constructor */ const PasswordShow = class extends FieldComponent { constructor(component, options, data) { super(component, options, data); this.show = false; this.val = ''; } static schema() { return FieldComponent.schema({ type: 'passwordshow', key: 'passwordshow', tableView: true, show: false, val: '', }); } static builderInfo() { return { title: 'Password Show', group: 'basic', icon: 'fa fa-asterisk', weight: 70, documentation: 'http://help.form.io/userguide/#table', schema: PasswordShow.schema(), }; } showHide() { this.show = !this.show; } render() { // eslint-disable-next-line react/react-in-jsx-scope let table = `<div ref="element" style="display:flex;align-items:center;border:1px solid #ced4da"><input style="border:none"class="form-control passwordtext" ref="input" value="" type=${ this.show ? 'text' : 'password' }> ${ this.show ? '<span ref="btnref" class="InputRef"><img src="https://img.icons8.com/material-outlined/24/000000/visible--v2.png"/></span>' : '<span ref="btnref" class="InputRef"><img src="https://img.icons8.com/material/24/000000/visible--v1.png"/></span>' } </div>`; return super.render(table); } /** * After the html string has been mounted into the dom, the dom element is returned here. Use refs to find specific * elements to attach functionality to. * * @param element * @returns {Promise} */ attach(element) { const refs = {}; this.show = false; this.loadRefs(element, refs); let el = document.querySelector('.InputRef'); let els = document.querySelector('.passwordtext'); els?.addEventListener('change', event => { this.val = event.target.value; this.updateValue(); }); el?.addEventListener('click', () => { this.show = !this.show; this.val = els.value; if (this.show) { el.innerHTML = '<img src="https://img.icons8.com/material-outlined/24/000000/visible--v2.png"/>'; els.type = 'text'; } else { el.innerHTML = '<img src="https://img.icons8.com/material/24/000000/visible--v1.png"/>'; els.type = 'password'; } this.updateValue(); }); // Allow basic component functionality to attach like field logic and tooltips. return super.attach(element); } /** * Get the value of the component from the dom elements. * * @returns {Array} */ getValue() { return this.val; } /** * Set the value of the component into the dom elements. * * @param value * @returns {boolean} */ setValue(value) { if (!value) { return; } this.val = value; } }; Formio.registerComponent('passwordshow', PasswordShow); // Components.addComponent('passwordshow', PasswordShow); export default PasswordShow; ========================================================== import { submitFormAPI, updateSubmission } from 'apis/Forms/index.api'; import React, { useEffect, Fragment, useCallback, useState } from 'react'; import { Div } from 'UIKit/index'; import './Assets/bootstrap.min.scss'; import './Assets/formio.full.min.scss'; import './style.scss'; import ReactPixel from 'react-facebook-pixel'; import useToast from 'Modules/Toasts'; import DCForm from 'Assets/icons/DCForm'; import { publicFileUpload } from '../PublicFileUpload'; import mime from 'mime-types'; import { Formio } from 'formiojs'; import PasswordShow from './passwordShow'; const FormView = ({ formData, formInfo, readOnly, submissionData, inUserForm }) => { const [onSubmitMessage, setSubmitMessage] = useState(false); const { showToast } = useToast(); function loadScript(scriptURL) { const script = document.createElement('script'); script.src = scriptURL; script.async = true; document.body.appendChild(script); return new Promise((resolve, reject) => { script.onload = () => { document.body.removeChild(script); resolve(); }; script.onerror = () => { document.body.removeChild(script); reject(); }; }); } const pageRedirect = useCallback(url => { window.location.href = `http://${url}`; }, []); const handlePixelId = useCallback((pixel_id, data, event) => { const options = { autoConfig: true, debug: false, }; ReactPixel.init(pixel_id, null, options); ReactPixel.trackSingle(pixel_id, event, data); }, []); function dataURLtoFile(dataurl, filename) { var arr = dataurl?.split(','), _mime = arr[0]?.match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new File([u8arr], filename, { type: _mime }); } const handleFiles = useCallback( async submission => { for (const item in submission?.data) { if ( (item.includes('file') || item.includes('image') || item.includes('signature')) && submission.data[item].length ) { let file = ''; if (item.match(/^signature.*$/)) { file = dataURLtoFile(submission.data[item], `${item}.jpg`); } else { file = dataURLtoFile( submission.data[item][0]?.url, submission.data[item][0]?.originalName, ); } let realType = file.type; if (file.name.split('.').pop() === 'csv') { realType = mime.lookup('csv'); } const response = await publicFileUpload( file, { type: realType, name: file.name, size: file.size, }, formInfo?.id, ); if (response.status === 'Success') { submission.data[item] = [{ key: response.key, size: file.size }]; } else { return { response: 'failed' }; } } } return { response: 'success', data: submission }; }, [formInfo?.id], ); const handleFormSubmit = useCallback( async submission => { const modifiedData = await handleFiles(submission); if (modifiedData.response === 'success') { let data = { data: modifiedData.data, rid: formInfo?.rId, rqid: formInfo?.rqId, }; if (submissionData) { updateSubmission( { updateData: submission.data }, formInfo?.id, submissionData.id, ) .then(() => { showToast({ type: 'success', message: 'Submission updated successfully', }); }) .catch(() => { showToast({ type: 'error', message: 'Failed to update submission', }); }); } else { submitFormAPI(data, formInfo?.formId) .then(() => { setSubmitMessage(true); if (formInfo.redirect) { setSubmitMessage(false); pageRedirect(formInfo.redirect); } if (formInfo.onSubmitOption) { handlePixelId(formInfo.pixelId, data, formInfo.onSubmitOption); } }) .catch(err => { showToast({ type: 'error', message: 'Failed to submit form', }); console.error(err); }); } } else { showToast({ type: 'error', message: 'Failed to upload Files', }); } }, [formInfo, handleFiles, handlePixelId, pageRedirect, showToast, submissionData], ); const handleSubmitDisable = useCallback(() => { let labelForSubmit = formData.components.find(item => item.key === 'submit'); let filteredComponets = formData.components.filter(el => el.type !== 'button'); let data = [ ...filteredComponets, { type: 'button', label: labelForSubmit.label, key: 'submit', disableOnInvalid: true, disabled: true, input: true, }, ]; return data; }, [formData?.components]); useEffect(() => { (async () => { // eslint-disable-next-line no-undef Formio.registerComponent('passwordshow', PasswordShow); // eslint-disable-next-line no-undef Formio.use({ components: { passwordshow: PasswordShow, }, }); loadScript(`${process.env.REACT_APP_ASSETS_BASE_URL}/formio.full.min.js`) .then(() => { if (readOnly) { let subDataValue; if (submissionData.hasOwnProperty('data')) { subDataValue = submissionData[Object.keys(submissionData.data)[0]]; } else { subDataValue = submissionData?.firstName; } if (formData.display === 'form') { if (submissionData && (subDataValue || subDataValue === '')) { const filteredComponets = formData.components.filter( el => el.type !== 'button', ); filteredComponets.forEach(el => { if (['date', 'datetime'].includes(el.type)) { el.type = 'textfield'; } }); // eslint-disable-next-line no-undef Formio.createForm( document.getElementById('dcFormBuilderView'), { components: filteredComponets, display: 'form' }, { readOnly: true, renderMode: 'html', }, ).then(instance => { // eslint-disable-next-line no-undef instance.submission = { data: submissionData }; if (submissionData?.passwordshow) { document.querySelector('.passwordtext').value = submissionData?.passwordshow; document.querySelector('.passwordtext').readOnly = true; } }); } } else { if (submissionData && (subDataValue || subDataValue === '')) { const filteredComponets = formData.components.filter( el => el.type !== 'button', ); filteredComponets.forEach(el => { if (['date', 'datetime'].includes(el.type)) el.type = 'textfield'; }); // eslint-disable-next-line no-undef Formio.createForm( document.getElementById('dcFormBuilderView'), { components: filteredComponets, display: 'wizard' }, { readOnly: true, renderMode: 'html', }, ).then(instance => { // eslint-disable-next-line no-undef instance.submission = { data: submissionData }; }); } } } else { let submitDisableData = formData.components; // Not wanted to comment the fucntion, so used 0. this is for disabling submit button in classic-form if (0) { submitDisableData = handleSubmitDisable(); } // eslint-disable-next-line no-undef Formio.createForm( document.getElementById('dcFormBuilderView'), { ...formData, components: !inUserForm ? submitDisableData : formData.components, }, { buttonSettings: { showCancel: false, showPrevious: true, showNext: true, showSubmit: true, }, }, ).then(form => { if (submissionData) form.submission = { data: submissionData }; // Register for the submit event to get the completed submission. form.on('submit', submission => { if (!inUserForm) form.resetValue(); else handleFormSubmit(submission); }); }); } }) .catch(() => {}); })(); }, [ formData, handleFiles, handleFormSubmit, handleSubmitDisable, inUserForm, readOnly, submissionData, ]); return ( <Fragment> <Div className="DCFormBuilder"> {onSubmitMessage ? ( <Div className="FPDThanks"> <Div className="FPDTInner"> <Div className="FPDTIcon"> <DCForm /> </Div> <Div className="FPDTTitle"> <center>{formInfo.message}</center> </Div> </Div> </Div> ) : ( <Div className="DCFBInner"> <div id="dcFormBuilderView" className="DCFBVew" /> </Div> )} </Div> </Fragment> ); }; export default FormView; ===================================================== /* eslint-disable no-undef */ import React, { useEffect, Fragment, useState, useCallback, useContext, useRef } from 'react'; import { Button, Div, H1, IconButton, PageContainer, PageView, ToolTip, Dialog, TopBar, // CircularLoader, Skeleton, } from 'UIKit/index'; import DCCrossClose from 'Assets/icons/DCCrossClose'; // import DCUndo from 'Assets/icons/DCUndo'; // import DCRedo from 'Assets/icons/DCRedo'; import DCEye from 'Assets/icons/DCEye'; import BuilderStyle from './builderStyle'; import BuilderOption from './builderOption'; import FormView from './formView'; import './Assets/bootstrap.min.scss'; import './Assets/formio.full.min.scss'; import './style.scss'; import FormsContext from '../FormsContext/Context/Context'; import useErrorDialog from 'Hooks/ErrorDialog/useErrorDialog'; import sideBarConfig from './Assets/sideBarConfig'; import editFormConfig from './Assets/editFormConfig'; import { useLocation } from 'react-router-dom'; import { getForm } from 'apis/Forms/index.api'; import useToast from 'Modules/Toasts'; import { useHistory } from 'react-router-dom/cjs/react-router-dom.min'; import useMediaQuery from 'UIKit/useMediaQuery'; import DCFillPencil from 'Assets/icons/DCFillPencil'; import PasswordShow from './passwordShow'; // import { Formio } from 'formiojs'; function useQuery() { return new URLSearchParams(useLocation().search); } const FormBuilder = ({ formType, sideBarResponsiveView, setSideBarResponsiveView, fromBuilder, }) => { const matches450 = useMediaQuery('(max-width: 450px)'); const matches576 = useMediaQuery('(max-width: 576px)'); const { autoSave, id, updateStyle, addId, updateOptions, addFormComponents, formComponents, options, style, } = useContext(FormsContext); const [formData, setFormData] = useState(formComponents || { components: [] }); const [loading, setLoading] = useState(false); let location = useLocation(); const search = location.search; const idInURL = new URLSearchParams(search).get('id'); const firstRun = useRef(true); const showErrorDialog = useErrorDialog(); const { showToast } = useToast(); function loadScript(scriptURL) { const script = document.createElement('script'); script.src = scriptURL; script.async = true; document.body.appendChild(script); return new Promise((resolve, reject) => { script.onload = () => { document.body.removeChild(script); resolve(); }; script.onerror = () => { document.body.removeChild(script); reject(); }; }); } useEffect(() => { if (id === '' && firstRun.current && !fromBuilder.length) { firstRun.current = false; setLoading(true); const resp = getForm(idInURL, localStorage.getItem('createTemplate')); resp.then(response => { const template = localStorage.getItem('createTemplate') === 'true'; const info = template ? response.data : response.data[0]; addId(template ? info.id : info.form_secret_id); addFormComponents(info.forms); setFormData(info.forms); updateOptions({ formName: info.form_name, category: info.category_id, tag: info.tags_id, message: info.thank_you_message, redirect: info.redirectUrl, fbPixelId: info.fbPixelId, fbPixelEvents: { pageView: { label: info.page_view_option }, onSubmit: { label: info.on_submit_option }, }, categories: [], tags: [], }); info.style && updateStyle(info.style); setLoading(false); }).catch(err => { showToast({ type: 'error', message: err.message || 'Failed to load form', }); showErrorDialog(); setLoading(false); }); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const [builderLoading, setBuilderLoading] = useState(true); let queryParams = useQuery(); const action = queryParams.get('action'); const history = useHistory(); useEffect(() => { if (id !== '' && !loading) { setBuilderLoading(true); loadScript(`${process.env.REACT_APP_ASSETS_BASE_URL}/formio.full.min.js`) .then(() => { setBuilderLoading(false); Formio.registerComponent('passwordshow', PasswordShow); // eslint-disable-next-line no-undef Formio.use({ components: { passwordshow: PasswordShow, }, }); // Formio.Components.addComponent('passwordshow',PasswordShow) }) .then(() => { // eslint-disable-next-line no-undef Formio.builder( document.getElementById('dcFormBuilder'), { display: formType === 'classic-form' ? 'form' : 'wizard', components: formComponents?.components, }, { noNewEdit: true, builder: sideBarConfig, editForm: editFormConfig, status: (action === 'edit-classic-form' || action === 'edit-group-form' || action === 'edit-card-form') && history.location.state?.responseCount ? 'Edit' : 'New', }, ).then(form => { form.on('change', () => { // eslint-disable-next-line no-undef // Formio.Components.addComponent('passwordshow',PasswordShow) addFormComponents(form.schema); setFormData(form.schema); setSideBarResponsiveView(false); }); }); }) .catch(() => {}); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [id, loading]); useEffect(() => { let formdata = { forms: formData, }; autoSave(formdata, id); // eslint-disable-next-line react-hooks/exhaustive-deps }, [formData]); const [tabMenuView, setTabMenuView] = useState('fields'); const handleDCTabMenu = useCallback(tab => { setTabMenuView(tab); }, []); // Builder Style const firstSave = useRef(true); const [labelShow, setLabelShow] = useState(true); const handleLabelShowToggle = useCallback(() => { setLabelShow(prev => !prev); }, []); const [backgroundColor, setBackgroundColor] = useState(style?.backgroundColor || '#ffffff'); const handleBackgroundColor = useCallback(color => { setBackgroundColor(color); document.documentElement.style.setProperty('--form-background', color); }, []); const [fontColor, setFontColor] = useState(style?.fontColor || '#000'); const handleFontColor = useCallback(color => { setFontColor(color); document.documentElement.style.setProperty('--form-label-font-color', color); }, []); const [borderColor, setBorderColor] = useState(style?.borderColor || '#000'); const handleBorderColor = useCallback(color => { setBorderColor(color); document.documentElement.style.setProperty('--form-border-color', color); }, []); const [btnBackgroundColor, setBtnBackgroundColor] = useState(style?.btnBackgroundColor); const handleBtnBackgroundColor = useCallback(color => { setBtnBackgroundColor(color); document.documentElement.style.setProperty('--form-button-background-color', color); }, []); const [btnFontColor, setBtnFontColor] = useState(style?.btnFontColor || '#ffffff'); const handleBtnFontColor = useCallback(color => { setBtnFontColor(color); document.documentElement.style.setProperty('--form-button-font-color', color); }, []); const [borderWidth, setBorderWidth] = useState(style?.borderWidth || 0); const handleBorderWidth = useCallback(e => { setBorderWidth(e.target.value); document.documentElement.style.setProperty('--form-border-width', `${e.target.value}px`); }, []); const [borderRadius, setBorderRadius] = useState(style?.borderRadius || 0); const handleBorderRadius = useCallback(e => { setBorderRadius(e.target.value); document.documentElement.style.setProperty('--form-border-radius', `${e.target.value}px`); }, []); const [width, setWidth] = useState(style?.width || 100); const handleWidth = useCallback(e => { setWidth(e.target.value); document.documentElement.style.setProperty('--form-width', `${e.target.value}%`); }, []); const [pageBackground, setPageBackground] = useState(style?.pageBackground || '#ffffff'); const handlePageBackground = useCallback(color => { setPageBackground(color); document.documentElement.style.setProperty('--form-page-background', color); }, []); const [formPreview, setFormPreview] = useState(false); const handleFormPreviewOpen = useCallback(() => { setFormPreview(true); }, []); const handleFormPreviewClose = useCallback(() => { setFormPreview(false); }, []); const callAutoSave = useCallback( data => { let formdata = { style: data, }; autoSave(formdata, id); }, [autoSave, id], ); useEffect(() => { setBtnFontColor(style?.btnFontColor); setBackgroundColor(style?.backgroundColor); setFontColor(style?.fontColor); setBorderColor(style?.borderColor); setBorderWidth(style?.borderWidth); setBorderRadius(style?.borderRadius); setWidth(style?.width); setPageBackground(style?.pageBackground); setBtnBackgroundColor(style?.btnBackgroundColor); document.documentElement.style.setProperty( '--form-border-width', `${style?.borderWidth}px`, ); document.documentElement.style.setProperty('--form-width', `${style?.width}%`); document.documentElement.style.setProperty('--form-page-background', style?.pageBackground); document.documentElement.style.setProperty( '--form-border-radius', `${style?.borderRadius}px`, ); document.documentElement.style.setProperty('--form-button-font-color', style?.btnFontColor); document.documentElement.style.setProperty('--form-background', style?.backgroundColor); document.documentElement.style.setProperty('--form-label-font-color', style?.fontColor); document.documentElement.style.setProperty('--form-border-color', style?.borderColor); document.documentElement.style.setProperty( '--form-button-background-color', style?.btnBackgroundColor, ); return () => { document.documentElement.style.setProperty('--form-border-width', `0px`); document.documentElement.style.setProperty('--form-width', `100%`); document.documentElement.style.setProperty('--form-page-background', '#ffffff'); document.documentElement.style.setProperty('--form-border-radius', `0px`); document.documentElement.style.setProperty('--form-button-font-color', '#ffffff'); document.documentElement.style.setProperty('--form-background', '#ffffff'); document.documentElement.style.setProperty('--form-label-font-color', '#000'); document.documentElement.style.setProperty('--form-border-color', '#000'); document.documentElement.style.setProperty('--form-button-background-color', '#4A90E2'); }; }, [style]); useEffect(() => { if (!firstSave.current && id !== '') callAutoSave({ label: labelShow, pageBackground: pageBackground, backgroundColor: backgroundColor, fontColor: fontColor, borderColor: borderColor, borderWidth: borderWidth, borderRadius: borderRadius, width: width, btnBackgroundColor: btnBackgroundColor, btnFontColor: btnFontColor, }); else document.documentElement.style.setProperty('--form-border-color', '#000000'); firstSave.current = false; }, [ autoSave, backgroundColor, borderColor, borderRadius, id, borderWidth, btnBackgroundColor, btnFontColor, callAutoSave, fontColor, labelShow, pageBackground, width, ]); return ( <Fragment> {formPreview ? ( <Dialog classes={{ row: 'FormPreviewDialogRow' }} dialogType={'fullWidth'} open={formPreview} onClose={handleFormPreviewClose} > <Div className={'FormPreviewDialog'}> <TopBar> <Div className={'HeaderBar'}> <H1 className={'HeaderBarTitle'}>Form Preview</H1> <Div className={'HeaderBarClose'}> <IconButton onClick={handleFormPreviewClose}> <DCCrossClose /> </IconButton> </Div> </Div> </TopBar> <FormView formData={formData} /> </Div> </Dialog> ) : null} <PageContainer> <PageView noSidebar classes={{ container: 'DCFBContainer ' + (sideBarResponsiveView ? 'DCFBCSBRV' : ''), }} > <Div className="DCFBBar"> <Div className="DCFBBTabs"> <Button buttonType={tabMenuView === 'fields' ? 'BlueFillBtn' : ''} onClick={() => { handleDCTabMenu('fields'); }} > Fields </Button> <Button buttonType={tabMenuView === 'styles' ? 'BlueFillBtn' : ''} onClick={() => { handleDCTabMenu('styles'); }} > Styles </Button> <Button buttonType={tabMenuView === 'options' ? 'BlueFillBtn' : ''} onClick={() => { handleDCTabMenu('options'); }} > Options </Button> </Div> <Div className="DCFBBURTP"> {/* <Div className={'DCFBBURTPUR'}> <ToolTip content={'Undo'}> <IconButton buttonType={'headerIconBtn'} onClick={handleUndo} > <DCUndo /> </IconButton> </ToolTip> <ToolTip content={'Redo'}> <IconButton buttonType={'headerIconBtn'} onClick={handleRedo} > <DCRedo /> </IconButton> </ToolTip> </Div> */} <Div className="DCFBBURTPTitle"> {options.formName}{' '} <IconButton buttonType={'circleBtn'} onClick={() => handleDCTabMenu('options')} > <ToolTip content={'Edit Form Name'}> <DCFillPencil onClick={() => handleDCTabMenu('options')} /> </ToolTip> </IconButton> </Div> <Div className="DCFBBURTPTView"> <ToolTip content={'Form Preview'} placement={'left-center'}> <IconButton buttonType={' headerIconBtn'} onClick={handleFormPreviewOpen} > <DCEye /> </IconButton> </ToolTip> </Div> </Div> </Div> {loading || builderLoading ? ( <Div className="DCFSkeleton"> <Div className="DCFSSide"> {Array.from(Array(15).keys()).map(item => ( <Skeleton height={40} key={item} /> ))} </Div> <Div className="DCFSRight"> {Array.from(Array(7).keys()).map(item => ( <Skeleton height={100} key={item} /> ))} </Div> </Div> ) : ( <Div className="DCFormBuilder"> {tabMenuView !== 'fields' ? ( <Div className="DCFBSidebar"> {tabMenuView === 'styles' ? ( <BuilderStyle labelShow={labelShow} handleLabelShowToggle={handleLabelShowToggle} backgroundColor={backgroundColor} handleBackgroundColor={handleBackgroundColor} fontColor={fontColor} handleFontColor={handleFontColor} borderColor={borderColor} handleBorderColor={handleBorderColor} btnBackgroundColor={btnBackgroundColor} handleBtnBackgroundColor={handleBtnBackgroundColor} btnFontColor={btnFontColor} handleBtnFontColor={handleBtnFontColor} borderWidth={borderWidth} handleBorderWidth={handleBorderWidth} borderRadius={borderRadius} handleBorderRadius={handleBorderRadius} width={width} handleWidth={handleWidth} pageBackground={pageBackground} handlePageBackground={handlePageBackground} customPlacement={matches450 ? 'bottom-center' : ''} /> ) : null} {tabMenuView === 'options' ? ( <BuilderOption customPlacement={matches576 ? 'bottom-center' : ''} /> ) : null} </Div> ) : null} <div id="dcFormBuilder" className={ (tabMenuView !== 'fields' ? 'DCFBSRemove' : '') + (!labelShow ? ' DCFBSHideLabel' : '') } /> </Div> )} </PageView> </PageContainer> </Fragment> ); }; export default FormBuilder;
Editor is loading...