{"version":3,"file":"form-fns.js","mappings":"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","sources":["webpack://empori-base/./src/backoffice/util.ts","webpack://empori-base/./src/controls/Forms/handleCaptcha.ts","webpack://empori-base/./src/controls/Forms/handleFileChanges.ts","webpack://empori-base/./src/controls/Forms/FormSelectorFns.ts"],"sourcesContent":["// eslint-disable-next-line max-len\r\nexport const emailRegex = /^(([^<>()[\\]\\.,;:\\s@\\\"]+(\\.[^<>()[\\]\\.,;:\\s@\\\"]+)*)|(\\\".+\\\"))@(([^<>()[\\]\\.,;:\\s@\\\"]+\\.)+[^<>()[\\]\\.,;:\\s@\\\"]{2,})$/i;\r\n\r\nexport const isDev = process.env.NODE_ENV !== 'production';\r\n\r\nexport type MappedArrayObject = {\r\n [key: string]: T;\r\n};\r\n\r\nexport type GroupedArrayObject = {\r\n [key: string]: T[];\r\n};\r\n\r\nexport function arrayToObject(array: T[], key: (item: T) => string): MappedArrayObject {\r\n const obj: MappedArrayObject = {};\r\n\r\n for (let item of array) {\r\n obj[key(item)] = item;\r\n }\r\n\r\n return obj;\r\n}\r\n\r\nexport function groupArray(array: T[], key: (item: T) => string): GroupedArrayObject {\r\n const obj: GroupedArrayObject = {};\r\n\r\n for (let item of array) {\r\n const itemKey = key(item);\r\n (obj[itemKey] || (obj[itemKey] = [])).push(item);\r\n }\r\n\r\n return obj;\r\n}\r\n\r\nexport function camelCase(value?: string) {\r\n if (!value || value.length <= 1) {\r\n return value ?? '';\r\n }\r\n\r\n return value.charAt(0).toLocaleLowerCase() + value.substring(1);\r\n}\r\n\r\nconst formatMustasch = /{([^{}]*)}/g;\r\n\r\n/**\r\n * Format a string template in a provided mustasch format using an object as a lookup source.\r\n *\r\n * @example\r\n * formatObject('test {key1} format', { key1: 'string' }) // \"test string format\"\r\n *\r\n * @param format Format string template.\r\n * @param object Object to use as lookup.\r\n * @param replacementFunc Optional callback function for each parsed tag.\r\n * Returned `string` will be used instead of given mapped item.\r\n * @returns Formatted string template.\r\n */\r\nexport function formatObject(format: string, object?: any, replacementFunc?: (key: string, item: any) => string) {\r\n if (object == null) {\r\n return '';\r\n }\r\n\r\n return format.replace(formatMustasch, (a: string, b: string) => {\r\n let val = object[b] ?? object[camelCase(b)];\r\n let formatVal = replacementFunc?.(b, val);\r\n return formatVal ?? val;\r\n });\r\n}\r\n\r\nconst byte = 1024;\r\nexport const FileSizeUnits = {\r\n KiB: byte,\r\n MiB: byte * byte,\r\n GiB: byte * byte * byte,\r\n TiB: byte * byte * byte * byte,\r\n PiB: byte * byte * byte * byte * byte,\r\n EiB: byte * byte * byte * byte * byte * byte\r\n};\r\n\r\n/**\r\n * Returns a new array with one item replaced at given index.\r\n * Does not mutate the original array.\r\n * @param items The original array\r\n * @param index What item to replace\r\n * @param newItem The new replacementitem\r\n */\r\nexport function replaceItem(items: T[], index: number, newItem: T) {\r\n return items.map((item, idx) => idx === index ? newItem : item);\r\n}\r\n\r\nexport const FileExtensions = {\r\n PDF: '.pdf',\r\n MP4: '.mp4',\r\n OGG: '.ogg',\r\n SVG: '.svg'\r\n};","import { FormDetails } from '../../empracoTypes';\r\nlet captchaTimer: NodeJS.Timeout;\r\n\r\nfunction loadNewCaptcha(formDetails: FormDetails) {\r\n const captchaImage = document.getElementById(formDetails.spamProtectionDetails.captchaImgId) as HTMLImageElement;\r\n captchaImage.src = formDetails.spamProtectionDetails.fetchUrlEmporiCaptcha + '?' + new Date().getTime();\r\n\r\n}\r\n\r\nexport function refreshCaptcha(formDetails: FormDetails) {\r\n if (captchaTimer) {\r\n loadNewCaptcha(formDetails);\r\n clearInterval(captchaTimer);\r\n captchaTimer = setInterval(() => {\r\n loadNewCaptcha(formDetails);\r\n }, 300000);// 5min.\r\n }\r\n}\r\n\r\nexport function handleCaptcha(formDetails: FormDetails) {\r\n\r\n loadNewCaptcha(formDetails);\r\n captchaTimer = setInterval(() => {\r\n loadNewCaptcha(formDetails);\r\n }, 300000);\r\n\r\n const captchaImage = document.getElementById(formDetails.spamProtectionDetails.captchaImgId) as HTMLImageElement;\r\n const refreshBtn = captchaImage.nextElementSibling;\r\n\r\n // get refresh button\r\n refreshBtn?.addEventListener('click', () => {\r\n refreshCaptcha(formDetails);\r\n });\r\n}\r\n\r\n","import { FileSizeUnits } from '../../backoffice/util';\r\nimport { FormDetails } from '../../empracoTypes';\r\nimport { formTexts } from './FormSelectorFns';\r\n\r\nfunction ClearFiles(element: HTMLDivElement, input: HTMLInputElement, text: Element) {\r\n element.innerHTML = '';\r\n element.title = formTexts.clearTitle;\r\n element.onclick = () => {\r\n input.value = '';\r\n element.innerHTML = '';\r\n text.innerHTML = formTexts.noFiles;\r\n };\r\n}\r\n\r\nfunction showFileErrorMessage(showError: boolean, target: HTMLInputElement, message: string | null) {\r\n const inputDesc = target.closest('div.node-file')?.querySelector('p.input-desc');\r\n if (inputDesc != null) {\r\n inputDesc.hidden = showError;\r\n }\r\n\r\n const errorDesc = target.closest('div.node-file')?.querySelector('p.error-desc');\r\n if (errorDesc != null) {\r\n if (message != null) {\r\n errorDesc.innerHTML = message;\r\n }\r\n errorDesc.hidden = !showError;\r\n }\r\n\r\n if (showError) {\r\n target.closest('div.file-input-container')?.classList.add('error-file');\r\n } else {\r\n target.closest('div.file-input-container')?.classList.remove('error-file');\r\n }\r\n};\r\n\r\nexport function handleFileChanges(formDetails: FormDetails, formEl: HTMLFormElement) {\r\n const fileInputs = formEl.querySelectorAll('input[type=file]');\r\n const formLimit = formDetails.form.settings.maxUploadFileSize;\r\n const globalLimit = formDetails.globalMaxUploadFileSize;\r\n\r\n // Calculates in megabytes\r\n const getFileSizeLimit = () => {\r\n\r\n if (formLimit && formLimit > 0) {\r\n return formLimit * FileSizeUnits.MiB;\r\n }\r\n\r\n if (globalLimit && globalLimit > 0) {\r\n return globalLimit * FileSizeUnits.MiB;\r\n }\r\n\r\n return 0;\r\n };\r\n\r\n const fileSizeLimit = getFileSizeLimit();\r\n\r\n\r\n const addLoadingSpinner = (elm?: Element | null) => {\r\n\r\n if (!elm) {\r\n return () => {\r\n // DO NOTHING\r\n };\r\n }\r\n setTimeout(() => {\r\n elm.innerHTML = '';\r\n });\r\n return () => {\r\n elm.innerHTML = '';\r\n };\r\n };\r\n\r\n if (fileInputs && fileInputs.length > 0) {\r\n fileInputs.forEach(input => {\r\n input.addEventListener('change', event => {\r\n\r\n const target = event.currentTarget as HTMLInputElement;\r\n if (target == null || target.value == null || target.value === '') {\r\n return;\r\n }\r\n\r\n const files = target.files;\r\n if (!files) {\r\n return;\r\n }\r\n const clearEl = input.parentElement?.nextElementSibling as HTMLDivElement;\r\n const removeLoadingSpinner = addLoadingSpinner(clearEl);\r\n const textEl = target.nextElementSibling?.querySelector('.upload-status');\r\n const fileExtensionArr = files![0].name.split('.');\r\n const fileExtension = '.' + fileExtensionArr[fileExtensionArr.length - 1];\r\n const fileSize = files\r\n ? Array.from(files).reduce((prev, num) => { return prev + num.size; }, 0)\r\n : 0;\r\n\r\n const getFileTypes = () => {\r\n return formDetails.form.inputs.find(inp => inp.uniqueName === input.id)?.allowedFiles ?? [];\r\n };\r\n const fileTypes = getFileTypes();\r\n\r\n const verifyFileType = () => {\r\n if (fileTypes && !fileTypes.length) {\r\n return true; // Allow all types\r\n }\r\n\r\n const type = files[0].type;\r\n return fileTypes.filter(s => s && s.type === type || s.type === fileExtension).length > 0;\r\n };\r\n\r\n const reset = () => {\r\n target.files = null;\r\n target.value = '';\r\n setTimeout(() => { clearEl.innerHTML = ''; });\r\n if (textEl) {\r\n textEl.innerHTML = formTexts.noFiles;\r\n }\r\n };\r\n\r\n const fileSizeAllowed = fileSizeLimit === 0 || fileSize <= fileSizeLimit;\r\n const fileTypesAllowed = verifyFileType();\r\n\r\n // File size validation error.\r\n if (textEl && files && !fileSizeAllowed) {\r\n reset();\r\n\r\n const mbValue = formLimit && formLimit > 0\r\n ? formLimit\r\n : globalLimit && globalLimit > 0\r\n ? globalLimit : 0;\r\n\r\n // eslint-disable-next-line max-len\r\n const errorMessage = `File size exceeded maximum allowed upload file size of ${mbValue} MB. Please upload less or smaller files.`;\r\n showFileErrorMessage(true, target, errorMessage);\r\n return;\r\n }\r\n\r\n // File type validation error.\r\n if (textEl && files && !fileTypesAllowed) {\r\n reset();\r\n const allowedTypes = fileTypes.map(m => m.type).join(', ');\r\n const errorMessage = `Only supports ${allowedTypes} file ${fileTypes.length > 1 ? 'formats' : 'format'}.`;\r\n showFileErrorMessage(true, target, errorMessage);\r\n }\r\n\r\n // File upload succeeded.\r\n if (textEl && clearEl && fileTypesAllowed && fileSizeAllowed) {\r\n setTimeout(() => {\r\n showFileErrorMessage(false, target, null);\r\n let filesText = files.length > 1 ? `${files.length} files` : files[0].name;\r\n textEl.innerHTML = filesText;\r\n ClearFiles(clearEl, target, textEl);\r\n removeLoadingSpinner();\r\n return;\r\n }, 400);\r\n }\r\n });\r\n });\r\n };\r\n}","import { FormDetails } from '../../empracoTypes';\r\nimport { handleCaptcha, refreshCaptcha } from './handleCaptcha';\r\nimport { handleFileChanges } from './handleFileChanges';\r\n\r\nexport const formTexts = {\r\n noFiles: 'No files',\r\n clearTitle: 'Clear the files in this input',\r\n fileRequiredError: 'Please select a file as it is required',\r\n validationError: 'Could not send form. Check validation errors!'\r\n};\r\n\r\nexport interface ValidationProps {\r\n formDetails: FormDetails;\r\n form: HTMLFormElement;\r\n}\r\n\r\nexport default async function FormSelectorFns(formDetails: FormDetails) {\r\n\r\n const form = document.getElementById(formDetails.formId) as HTMLFormElement;\r\n if (!form) {\r\n return;\r\n }\r\n // Handle empori captcha\r\n if (formDetails.spamProtectionDetails.isEmporiCaptchaEnabled) { handleCaptcha(formDetails); }\r\n\r\n // Sets event listeners to file input changes in the current form.\r\n handleFileChanges(formDetails, form);\r\n\r\n // Validate the form and use event.preventDefault() to stop the form from submitting.\r\n form.addEventListener('submit', async (event) => {\r\n event.preventDefault();\r\n\r\n const submitter = event.submitter;\r\n if (!submitter || submitter && submitter.nodeName !== 'INPUT') {\r\n return;\r\n }\r\n\r\n const statusEl = document.getElementById(formDetails.statusKey);\r\n\r\n if (statusEl) {\r\n statusEl.style.display = 'block';\r\n statusEl.innerHTML = 'Skickar formulärsdata...';\r\n }\r\n\r\n const messageEl = document.getElementById(formDetails.messageKey);\r\n\r\n try {\r\n await fetch(formDetails.fetchUrl, {\r\n method: 'POST',\r\n body: new FormData(form),\r\n redirect: 'follow'\r\n }).then(res => {\r\n if (res.redirected) {\r\n window.location.href = res.url;\r\n } else if (res.ok) {\r\n form.style.display = 'none';\r\n if (messageEl) {\r\n messageEl.style.display = 'block';\r\n }\r\n if (statusEl) {\r\n statusEl.style.display = 'none';\r\n }\r\n } else {\r\n if (statusEl) {\r\n res.text().then(errorMsg => {\r\n statusEl.innerHTML = `${errorMsg}`;\r\n statusEl.classList.add('not-autorized');\r\n refreshCaptcha(formDetails);\r\n });\r\n }\r\n }\r\n }).catch(err => {\r\n if (statusEl) {\r\n statusEl.innerHTML = `
${err}
`;\r\n }\r\n });\r\n } catch (error) {\r\n if (statusEl) {\r\n statusEl.innerHTML = `
${error}
`;\r\n }\r\n }\r\n });\r\n}\r\n\r\n"],"names":["FileSizeUnits","KiB","MiB","byte","GiB","TiB","PiB","EiB","FileExtensions","PDF","MP4","OGG","SVG","captchaTimer","loadNewCaptcha","formDetails","document","getElementById","spamProtectionDetails","captchaImgId","src","fetchUrlEmporiCaptcha","Date","getTime","refreshCaptcha","clearInterval","setInterval","showFileErrorMessage","showError","target","message","inputDesc","closest","querySelector","hidden","errorDesc","innerHTML","classList","add","remove","formTexts","noFiles","clearTitle","fileRequiredError","validationError","FormSelectorFns","form","formId","isEmporiCaptchaEnabled","refreshBtn","nextElementSibling","addEventListener","handleCaptcha","formEl","fileInputs","querySelectorAll","formLimit","settings","maxUploadFileSize","globalLimit","globalMaxUploadFileSize","fileSizeLimit","length","forEach","input","event","currentTarget","value","files","clearEl","parentElement","removeLoadingSpinner","elm","setTimeout","textEl","fileExtensionArr","name","split","fileExtension","fileSize","Array","from","reduce","prev","num","size","fileTypes","inputs","find","inp","uniqueName","id","allowedFiles","getFileTypes","reset","fileSizeAllowed","fileTypesAllowed","type","filter","s","verifyFileType","errorMessage","map","m","join","filesText","element","text","title","onclick","ClearFiles","handleFileChanges","preventDefault","submitter","nodeName","statusEl","statusKey","style","display","messageEl","messageKey","fetch","fetchUrl","method","body","FormData","redirect","then","res","redirected","window","location","href","url","ok","errorMsg","catch","err","error"],"sourceRoot":""}