@formio/js 5.0.0-dev.5745.3c80f7d → 5.0.0-dev.5748.cd8883d
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Changelog.md +1 -0
- package/dist/formio.form.js +3 -3
- package/dist/formio.form.min.js +1 -1
- package/dist/formio.full.js +3 -3
- package/dist/formio.full.min.js +1 -1
- package/lib/cjs/components/day/Day.d.ts +2 -2
- package/lib/cjs/components/day/Day.js +3 -3
- package/lib/cjs/components/file/File.d.ts +1 -1
- package/lib/cjs/components/file/File.js +10 -1
- package/lib/cjs/translations/en.d.ts +0 -1
- package/lib/cjs/translations/en.js +0 -1
- package/lib/mjs/components/day/Day.d.ts +2 -2
- package/lib/mjs/components/day/Day.js +3 -3
- package/lib/mjs/components/file/File.d.ts +1 -1
- package/lib/mjs/components/file/File.js +10 -1
- package/lib/mjs/translations/en.d.ts +0 -1
- package/lib/mjs/translations/en.js +0 -1
- package/package.json +1 -1
package/Changelog.md
CHANGED
|
@@ -45,6 +45,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|
|
45
45
|
- FIO-8809: fixed runtime error in setForm when passing string argument to Formio.builder
|
|
46
46
|
- FIO-8684: Fixes cannot attach more than one component to the PDF form
|
|
47
47
|
- FIO-8719: fixed validation for Data Grid component inside nested wizard
|
|
48
|
+
- FIO-8621: added error event on file upload
|
|
48
49
|
|
|
49
50
|
### New Features
|
|
50
51
|
|
package/dist/formio.form.js
CHANGED
|
@@ -5104,7 +5104,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5104
5104
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
5105
5105
|
|
|
5106
5106
|
"use strict";
|
|
5107
|
-
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst moment_1 = __importDefault(__webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\"));\nconst Field_1 = __importDefault(__webpack_require__(/*! ../_classes/field/Field */ \"./lib/cjs/components/_classes/field/Field.js\"));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nclass DayComponent extends Field_1.default {\n static schema(...extend) {\n return Field_1.default.schema({\n type: 'day',\n label: 'Day',\n key: 'day',\n fields: {\n day: {\n type: 'number',\n placeholder: '',\n required: false\n },\n month: {\n type: 'select',\n placeholder: '',\n required: false\n },\n year: {\n type: 'number',\n placeholder: '',\n required: false\n }\n },\n dayFirst: false\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Day',\n group: 'advanced',\n icon: 'calendar',\n documentation: '/userguide/form-building/advanced-components#day',\n weight: 50,\n schema: DayComponent.schema()\n };\n }\n static get conditionOperatorsSettings() {\n return Object.assign(Object.assign({}, super.conditionOperatorsSettings), { operators: ['isDateEqual', 'isNotDateEqual', 'isEmpty', 'isNotEmpty', 'dateLessThan', 'dateGreaterThan', 'dateLessThanOrEqual', 'dateGreaterThanOrEqual'] });\n }\n static savedValueTypes(schema) {\n schema = schema || {};\n return (0, utils_1.getComponentSavedTypes)(schema) || [utils_1.componentValueTypes.string];\n }\n constructor(component, options, data) {\n if (component.maxDate && component.maxDate.indexOf('moment(') === -1) {\n component.maxDate = (0, moment_1.default)(component.maxDate, 'YYYY-MM-DD').toISOString();\n }\n if (component.minDate && component.minDate.indexOf('moment(') === -1) {\n component.minDate = (0, moment_1.default)(component.minDate, 'YYYY-MM-DD').toISOString();\n }\n super(component, options, data);\n }\n static get serverConditionSettings() {\n return DayComponent.conditionOperatorsSettings;\n }\n /**\n * The empty value for day component.\n * @returns {''} - The empty value of the day component.\n */\n get emptyValue() {\n return '';\n }\n get valueMask() {\n return /^\\d{2}\\/\\d{2}\\/\\d{4}$/;\n }\n get dayRequired() {\n return this.showDay && lodash_1.default.get(this.component, 'fields.day.required', false);\n }\n get showDay() {\n return !lodash_1.default.get(this.component, 'fields.day.hide', false);\n }\n get monthRequired() {\n return this.showMonth && lodash_1.default.get(this.component, 'fields.month.required', false);\n }\n get showMonth() {\n return !lodash_1.default.get(this.component, 'fields.month.hide', false);\n }\n get yearRequired() {\n return this.showYear && lodash_1.default.get(this.component, 'fields.year.required', false);\n }\n get showYear() {\n return !lodash_1.default.get(this.component, 'fields.year.hide', false);\n }\n get defaultSchema() {\n return DayComponent.schema();\n }\n get shouldDisabled() {\n return super.shouldDisabled || this.parentDisabled;\n }\n get inputInfo() {\n const info = super.elementInfo();\n info.type = 'input';\n info.attr.type = 'hidden';\n info.changeEvent = 'input';\n return info;\n }\n inputDefinition(name) {\n let min, max;\n if (name === 'day') {\n min = 1;\n max = 31;\n }\n if (name === 'month') {\n min = 1;\n max = 12;\n }\n if (name === 'year') {\n min = lodash_1.default.get(this.component, 'fields.year.minYear', 1900) || 1900;\n max = lodash_1.default.get(this.component, 'fields.year.maxYear', 2030) || 1900;\n }\n return {\n type: 'input',\n ref: name,\n attr: {\n id: `${this.component.key}-${name}`,\n class: `form-control ${this.transform('class', `formio-day-component-${name}`)}`,\n type: this.component.fields[name].type === 'select' ? 'select' : 'number',\n placeholder: this.t(this.component.fields[name].placeholder),\n step: 1,\n min,\n max,\n }\n };\n }\n selectDefinition(name) {\n return {\n multiple: false,\n ref: name,\n widget: 'html5',\n attr: {\n id: `${this.component.key}-${name}`,\n class: 'form-control',\n name,\n lang: this.options.language\n }\n };\n }\n get days() {\n if (this._days) {\n return this._days;\n }\n this._days = [\n { value: '', label: lodash_1.default.get(this.component, 'fields.day.placeholder', '') }\n ];\n for (let x = 1; x <= 31; x++) {\n this._days.push({\n value: x,\n label: x.toString()\n });\n }\n return this._days;\n }\n get months() {\n if (this._months) {\n return this._months;\n }\n this._months = [\n {\n value: '',\n label: lodash_1.default.get(this.component, 'fields.month.placeholder') || (this.hideInputLabels ? this.t('Month') : '')\n },\n { value: 1, label: 'January' },\n { value: 2, label: 'February' },\n { value: 3, label: 'March' },\n { value: 4, label: 'April' },\n { value: 5, label: 'May' },\n { value: 6, label: 'June' },\n { value: 7, label: 'July' },\n { value: 8, label: 'August' },\n { value: 9, label: 'September' },\n { value: 10, label: 'October' },\n { value: 11, label: 'November' },\n { value: 12, label: 'December' }\n ];\n return this._months;\n }\n get years() {\n if (this._years) {\n return this._years;\n }\n this._years = [\n { value: '', label: lodash_1.default.get(this.component, 'fields.year.placeholder', '') }\n ];\n const minYears = lodash_1.default.get(this.component, 'fields.year.minYear', 1900) || 1900;\n const maxYears = lodash_1.default.get(this.component, 'fields.year.maxYear', 2030) || 2030;\n for (let x = minYears; x <= maxYears; x++) {\n this._years.push({\n value: x,\n label: x.toString()\n });\n }\n return this._years;\n }\n setErrorClasses(elements, dirty, hasError) {\n super.setErrorClasses(elements, dirty, hasError);\n super.setErrorClasses([this.refs.day, this.refs.month, this.refs.year], dirty, hasError);\n }\n removeInputError(elements) {\n super.removeInputError([this.refs.day, this.refs.month, this.refs.year]);\n super.removeInputError(elements);\n }\n init() {\n super.init();\n const minYear = this.component.fields.year.minYear;\n const maxYear = this.component.fields.year.maxYear;\n this.component.maxYear = maxYear;\n this.component.minYear = minYear;\n const dateFormatInfo = (0, utils_1.getLocaleDateFormatInfo)(this.options.language);\n this.dayFirst = this.component.useLocaleSettings\n ? dateFormatInfo.dayFirst\n : this.component.dayFirst;\n }\n render() {\n if (this.isHtmlRenderMode()) {\n return super.render(this.renderTemplate('input'));\n }\n return super.render(this.renderTemplate('day', {\n dayFirst: this.dayFirst,\n showDay: this.showDay,\n showMonth: this.showMonth,\n showYear: this.showYear,\n day: this.renderField('day'),\n month: this.renderField('month'),\n year: this.renderField('year'),\n }));\n }\n renderField(name) {\n if (this.component.fields[name].type === 'select') {\n return this.renderTemplate('select', {\n input: this.selectDefinition(name),\n selectOptions: this[`${name}s`].reduce((html, option) => html + this.renderTemplate('selectOption', {\n option,\n selected: false,\n attrs: {}\n }), ''),\n });\n }\n else {\n return this.renderTemplate('input', {\n prefix: this.prefix,\n suffix: this.suffix,\n input: this.inputDefinition(name)\n });\n }\n }\n attach(element) {\n this.loadRefs(element, { day: 'single', month: 'single', year: 'single', input: 'multiple' });\n const superAttach = super.attach(element);\n const updateValueAndSaveFocus = (element, name) => () => {\n try {\n this.saveCaretPosition(element, name);\n }\n catch (err) {\n console.warn('An error occurred while trying to save caret position', err);\n }\n this.updateValue(null, {\n modified: true,\n });\n };\n if (this.shouldDisabled) {\n this.setDisabled(this.refs.day, true);\n this.setDisabled(this.refs.month, true);\n this.setDisabled(this.refs.year, true);\n if (this.refs.input) {\n this.refs.input.forEach((input) => this.setDisabled(input, true));\n }\n }\n else {\n this.addEventListener(this.refs.day, 'input', updateValueAndSaveFocus(this.refs.day, 'day'));\n // TODO: Need to rework this to work with day select as well.\n // Change day max input when month changes.\n this.addEventListener(this.refs.month, 'input', () => {\n const maxDay = this.refs.year ? parseInt(new Date(this.refs.year.value, this.refs.month.value, 0).getDate(), 10)\n : '';\n const day = this.getFieldValue('day');\n if (!this.component.fields.day.hide && maxDay) {\n this.refs.day.max = maxDay;\n }\n if (maxDay && day > maxDay) {\n this.refs.day.value = this.refs.day.max;\n }\n updateValueAndSaveFocus(this.refs.month, 'month')();\n });\n this.addEventListener(this.refs.year, 'input', updateValueAndSaveFocus(this.refs.year, 'year'));\n this.addEventListener(this.refs.input, this.info.changeEvent, () => this.updateValue(null, {\n modified: true\n }));\n [this.refs.day, this.refs.month, this.refs.year].filter((element) => !!element).forEach((element) => {\n super.addFocusBlurEvents(element);\n });\n }\n this.setValue(this.dataValue);\n // Force the disabled state with getters and setters.\n this.disabled = this.shouldDisabled;\n return superAttach;\n }\n validateRequired(setting, value) {\n const { day, month, year } = this.parts;\n if (this.dayRequired && !day) {\n return false;\n }\n if (this.monthRequired && !month) {\n return false;\n }\n if (this.yearRequired && !year) {\n return false;\n }\n if (!(0, utils_1.boolValue)(setting)) {\n return true;\n }\n return !this.isEmpty(value);\n }\n set disabled(disabled) {\n super.disabled = disabled;\n if (!this.refs.year || !this.refs.month || !this.refs.day) {\n return;\n }\n if (disabled) {\n this.refs.year.setAttribute('disabled', 'disabled');\n this.refs.month.setAttribute('disabled', 'disabled');\n this.refs.day.setAttribute('disabled', 'disabled');\n }\n else {\n this.refs.year.removeAttribute('disabled');\n this.refs.month.removeAttribute('disabled');\n this.refs.day.removeAttribute('disabled');\n }\n }\n normalizeValue(value) {\n if (!value || this.valueMask.test(value)) {\n return value;\n }\n const dateParts = [];\n const valueParts = value.split('/');\n const [DAY, MONTH, YEAR] = this.component.dayFirst ? [0, 1, 2] : [1, 0, 2];\n const defaultValue = this.component.defaultValue ? this.component.defaultValue.split('/') : '';\n const getNextPart = (shouldTake, defaultValue) => dateParts.push(shouldTake ? valueParts.shift() : defaultValue);\n if (this.dayFirst) {\n getNextPart(this.showDay, defaultValue ? defaultValue[DAY] : '00');\n }\n getNextPart(this.showMonth, defaultValue ? defaultValue[MONTH] : '00');\n if (!this.dayFirst) {\n getNextPart(this.showDay, defaultValue ? defaultValue[DAY] : '00');\n }\n getNextPart(this.showYear, defaultValue ? defaultValue[YEAR] : '0000');\n return dateParts.join('/');\n }\n /**\n * Set the value at a specific index and updates the component's refs.\n * @param {number} index - The index to set.\n * @param {any} value - The value to set.\n * @returns {null|void} - Returns null if the value is invalid, otherwise void.\n */\n setValueAt(index, value) {\n // temporary solution to avoid input reset\n // on invalid date.\n if (value === 'Invalid date') {\n return null;\n }\n const parts = value.split('/');\n let day;\n if (this.component.dayFirst) {\n day = parts.shift();\n }\n const month = parts.shift();\n if (!this.component.dayFirst) {\n day = parts.shift();\n }\n const year = parts.shift();\n if (this.refs.day && this.showDay) {\n this.refs.day.value = day === '00' ? '' : parseInt(day, 10);\n }\n if (this.refs.month && this.showMonth) {\n this.refs.month.value = month === '00' ? '' : parseInt(month, 10);\n }\n if (this.refs.year && this.showYear) {\n this.refs.year.value = year === '0000' ? '' : parseInt(year, 10);\n }\n }\n getFieldValue(name) {\n const parts = this.dataValue ? this.dataValue.split('/') : [];\n let val = 0;\n switch (name) {\n case 'month':\n val = parts[this.dayFirst ? 1 : 0];\n break;\n case 'day':\n val = parts[this.dayFirst ? 0 : 1];\n break;\n case 'year':\n val = parts[2];\n break;\n }\n val = parseInt(val, 10);\n return (!lodash_1.default.isNaN(val) && lodash_1.default.isNumber(val)) ? val : 0;\n }\n get parts() {\n return {\n day: this.getFieldValue('day'),\n month: this.getFieldValue('month'),\n year: this.getFieldValue('year'),\n };\n }\n /**\n * Get the format for the value string.\n * @returns {string} - the format for the value string.\n */\n get format() {\n let format = '';\n if (this.component.dayFirst && this.showDay) {\n format += 'D/';\n }\n if (this.showMonth) {\n format += 'M/';\n }\n if (!this.component.dayFirst && this.showDay) {\n format += 'D/';\n }\n if (this.showYear) {\n format += 'YYYY';\n return format;\n }\n else {\n // Trim off the \"/\" from the end of the format string.\n return format.length ? format.substring(0, format.length - 1) : format;\n }\n }\n /**\n * Return the date for this component.\n * @param {any} value - The value to convert to a date.\n * @returns {null|string} - The date string.\n */\n getDate(value) {\n let defaults = [], day, month, year;\n // Map positions to identifiers to get default values for each part of day\n const [DAY, MONTH, YEAR] = this.component.dayFirst ? [0, 1, 2] : [1, 0, 2];\n const defaultValue = value || this.component.defaultValue;\n if (defaultValue) {\n defaults = defaultValue.split('/').map(x => parseInt(x, 10));\n }\n if (this.showDay && this.refs.day) {\n day = parseInt(this.refs.day.value, 10);\n }\n if (day === undefined || lodash_1.default.isNaN(day)) {\n day = defaults[DAY] && !lodash_1.default.isNaN(defaults[DAY]) ? defaults[DAY] : 0;\n }\n if (this.showMonth && this.refs.month) {\n // Months are 0 indexed.\n month = parseInt(this.refs.month.value, 10);\n }\n if (month === undefined || lodash_1.default.isNaN(month)) {\n month = defaults[MONTH] && !lodash_1.default.isNaN(defaults[MONTH]) ? defaults[MONTH] : 0;\n }\n if (this.showYear && this.refs.year) {\n year = parseInt(this.refs.year.value);\n }\n if (year === undefined || lodash_1.default.isNaN(year)) {\n year = defaults[YEAR] && !lodash_1.default.isNaN(defaults[YEAR]) ? defaults[YEAR] : 0;\n }\n let result;\n if (!day && !month && !year) {\n return null;\n }\n // add trailing zeros if the data is showed\n day = this.showDay ? day.toString().padStart(2, 0) : '';\n month = this.showMonth ? month.toString().padStart(2, 0) : '';\n year = this.showYear ? year.toString().padStart(4, 0) : '';\n if (this.component.dayFirst) {\n result = `${day}${this.showDay && this.showMonth || this.showDay && this.showYear ? '/' : ''}${month}${this.showMonth && this.showYear ? '/' : ''}${year}`;\n }\n else {\n result = `${month}${this.showDay && this.showMonth || this.showMonth && this.showYear ? '/' : ''}${day}${this.showDay && this.showYear ? '/' : ''}${year}`;\n }\n return result;\n }\n /**\n * Return the date string for this component.\n * @returns {string|null} - The date string for this component.\n */\n get date() {\n return this.getDate();\n }\n /**\n * Return the raw value.\n * @returns {string} - The raw value of the component.\n */\n get validationValue() {\n return this.dataValue;\n }\n getValue() {\n const result = super.getValue();\n return (!result) ? this.dataValue : result;\n }\n /**\n * Get the value at a specific index.\n * @param {number} index - The index to get the value from.\n * @returns {*} - The value at index.\n */\n getValueAt(index) {\n const date = this.date || this.emptyValue;\n if (date) {\n this.refs.input[index].value = date;\n return this.refs.input[index].value;\n }\n else {\n this.refs.input[index].value = '';\n return null;\n }\n }\n /**\n * Get the input value of the date.\n * @param {any} value - The value to convert to a string.\n * @returns {string|null} - The string value of the date.\n */\n getValueAsString(value) {\n return this.getDate(value) || '';\n }\n focus(field) {\n var _a, _b, _c;\n if (field && typeof field === 'string' && this.refs[field]) {\n this.refs[field].focus();\n }\n else if (this.dayFirst && this.showDay || !this.dayFirst && !this.showMonth && this.showDay) {\n (_a = this.refs.day) === null || _a === void 0 ? void 0 : _a.focus();\n }\n else if (this.dayFirst && !this.showDay && this.showMonth || !this.dayFirst && this.showMonth) {\n (_b = this.refs.month) === null || _b === void 0 ? void 0 : _b.focus();\n }\n else if (!this.showDay && !this.showDay && this.showYear) {\n (_c = this.refs.year) === null || _c === void 0 ? void 0 : _c.focus();\n }\n }\n restoreCaretPosition() {\n var _a;\n if ((_a = this.root) === null || _a === void 0 ? void 0 : _a.currentSelection) {\n const { selection, index } = this.root.currentSelection;\n if (this.refs[index]) {\n const input = this.refs[index];\n const isInputRangeSelectable = (i) => /text|search|password|tel|url/i.test((i === null || i === void 0 ? void 0 : i.type) || '');\n if (isInputRangeSelectable(input)) {\n input.setSelectionRange(...selection);\n }\n }\n }\n }\n isPartialDay(value) {\n if (!value) {\n return false;\n }\n const [DAY, MONTH, YEAR] = this.component.dayFirst ? [0, 1, 2] : [1, 0, 2];\n const values = value.split('/');\n return (values[DAY] === '00' || values[MONTH] === '00' || values[YEAR] === '0000');\n }\n getValidationFormat() {\n return this.dayFirst ? 'DD-MM-YYYY' : 'MM-DD-YYYY';\n }\n}\nexports[\"default\"] = DayComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/day/Day.js?");
|
|
5107
|
+
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst moment_1 = __importDefault(__webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\"));\nconst Field_1 = __importDefault(__webpack_require__(/*! ../_classes/field/Field */ \"./lib/cjs/components/_classes/field/Field.js\"));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nclass DayComponent extends Field_1.default {\n static schema(...extend) {\n return Field_1.default.schema({\n type: 'day',\n label: 'Day',\n key: 'day',\n fields: {\n day: {\n type: 'number',\n placeholder: '',\n required: false\n },\n month: {\n type: 'select',\n placeholder: '',\n required: false\n },\n year: {\n type: 'number',\n placeholder: '',\n required: false\n }\n },\n dayFirst: false\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Day',\n group: 'advanced',\n icon: 'calendar',\n documentation: '/userguide/form-building/advanced-components#day',\n weight: 50,\n schema: DayComponent.schema()\n };\n }\n static get conditionOperatorsSettings() {\n return Object.assign(Object.assign({}, super.conditionOperatorsSettings), { operators: ['isDateEqual', 'isNotDateEqual', 'isEmpty', 'isNotEmpty', 'dateLessThan', 'dateGreaterThan', 'dateLessThanOrEqual', 'dateGreaterThanOrEqual'] });\n }\n static savedValueTypes(schema) {\n schema = schema || {};\n return (0, utils_1.getComponentSavedTypes)(schema) || [utils_1.componentValueTypes.string];\n }\n constructor(component, options, data) {\n if (component.maxDate && component.maxDate.indexOf('moment(') === -1) {\n component.maxDate = (0, moment_1.default)(component.maxDate, 'YYYY-MM-DD').toISOString();\n }\n if (component.minDate && component.minDate.indexOf('moment(') === -1) {\n component.minDate = (0, moment_1.default)(component.minDate, 'YYYY-MM-DD').toISOString();\n }\n super(component, options, data);\n }\n static get serverConditionSettings() {\n return DayComponent.conditionOperatorsSettings;\n }\n /**\n * The empty value for day component.\n * @returns {'00/00/0000'} - The empty value of the day component.\n */\n get emptyValue() {\n return '00/00/0000';\n }\n get valueMask() {\n return /^\\d{2}\\/\\d{2}\\/\\d{4}$/;\n }\n get dayRequired() {\n return this.showDay && lodash_1.default.get(this.component, 'fields.day.required', false);\n }\n get showDay() {\n return !lodash_1.default.get(this.component, 'fields.day.hide', false);\n }\n get monthRequired() {\n return this.showMonth && lodash_1.default.get(this.component, 'fields.month.required', false);\n }\n get showMonth() {\n return !lodash_1.default.get(this.component, 'fields.month.hide', false);\n }\n get yearRequired() {\n return this.showYear && lodash_1.default.get(this.component, 'fields.year.required', false);\n }\n get showYear() {\n return !lodash_1.default.get(this.component, 'fields.year.hide', false);\n }\n get defaultSchema() {\n return DayComponent.schema();\n }\n get shouldDisabled() {\n return super.shouldDisabled || this.parentDisabled;\n }\n get inputInfo() {\n const info = super.elementInfo();\n info.type = 'input';\n info.attr.type = 'hidden';\n info.changeEvent = 'input';\n return info;\n }\n inputDefinition(name) {\n let min, max;\n if (name === 'day') {\n min = 1;\n max = 31;\n }\n if (name === 'month') {\n min = 1;\n max = 12;\n }\n if (name === 'year') {\n min = lodash_1.default.get(this.component, 'fields.year.minYear', 1900) || 1900;\n max = lodash_1.default.get(this.component, 'fields.year.maxYear', 2030) || 1900;\n }\n return {\n type: 'input',\n ref: name,\n attr: {\n id: `${this.component.key}-${name}`,\n class: `form-control ${this.transform('class', `formio-day-component-${name}`)}`,\n type: this.component.fields[name].type === 'select' ? 'select' : 'number',\n placeholder: this.t(this.component.fields[name].placeholder),\n step: 1,\n min,\n max,\n }\n };\n }\n selectDefinition(name) {\n return {\n multiple: false,\n ref: name,\n widget: 'html5',\n attr: {\n id: `${this.component.key}-${name}`,\n class: 'form-control',\n name,\n lang: this.options.language\n }\n };\n }\n get days() {\n if (this._days) {\n return this._days;\n }\n this._days = [\n { value: '', label: lodash_1.default.get(this.component, 'fields.day.placeholder', '') }\n ];\n for (let x = 1; x <= 31; x++) {\n this._days.push({\n value: x,\n label: x.toString()\n });\n }\n return this._days;\n }\n get months() {\n if (this._months) {\n return this._months;\n }\n this._months = [\n {\n value: '',\n label: lodash_1.default.get(this.component, 'fields.month.placeholder') || (this.hideInputLabels ? this.t('Month') : '')\n },\n { value: 1, label: 'January' },\n { value: 2, label: 'February' },\n { value: 3, label: 'March' },\n { value: 4, label: 'April' },\n { value: 5, label: 'May' },\n { value: 6, label: 'June' },\n { value: 7, label: 'July' },\n { value: 8, label: 'August' },\n { value: 9, label: 'September' },\n { value: 10, label: 'October' },\n { value: 11, label: 'November' },\n { value: 12, label: 'December' }\n ];\n return this._months;\n }\n get years() {\n if (this._years) {\n return this._years;\n }\n this._years = [\n { value: '', label: lodash_1.default.get(this.component, 'fields.year.placeholder', '') }\n ];\n const minYears = lodash_1.default.get(this.component, 'fields.year.minYear', 1900) || 1900;\n const maxYears = lodash_1.default.get(this.component, 'fields.year.maxYear', 2030) || 2030;\n for (let x = minYears; x <= maxYears; x++) {\n this._years.push({\n value: x,\n label: x.toString()\n });\n }\n return this._years;\n }\n setErrorClasses(elements, dirty, hasError) {\n super.setErrorClasses(elements, dirty, hasError);\n super.setErrorClasses([this.refs.day, this.refs.month, this.refs.year], dirty, hasError);\n }\n removeInputError(elements) {\n super.removeInputError([this.refs.day, this.refs.month, this.refs.year]);\n super.removeInputError(elements);\n }\n init() {\n super.init();\n const minYear = this.component.fields.year.minYear;\n const maxYear = this.component.fields.year.maxYear;\n this.component.maxYear = maxYear;\n this.component.minYear = minYear;\n const dateFormatInfo = (0, utils_1.getLocaleDateFormatInfo)(this.options.language);\n this.dayFirst = this.component.useLocaleSettings\n ? dateFormatInfo.dayFirst\n : this.component.dayFirst;\n }\n render() {\n if (this.isHtmlRenderMode()) {\n return super.render(this.renderTemplate('input'));\n }\n return super.render(this.renderTemplate('day', {\n dayFirst: this.dayFirst,\n showDay: this.showDay,\n showMonth: this.showMonth,\n showYear: this.showYear,\n day: this.renderField('day'),\n month: this.renderField('month'),\n year: this.renderField('year'),\n }));\n }\n renderField(name) {\n if (this.component.fields[name].type === 'select') {\n return this.renderTemplate('select', {\n input: this.selectDefinition(name),\n selectOptions: this[`${name}s`].reduce((html, option) => html + this.renderTemplate('selectOption', {\n option,\n selected: false,\n attrs: {}\n }), ''),\n });\n }\n else {\n return this.renderTemplate('input', {\n prefix: this.prefix,\n suffix: this.suffix,\n input: this.inputDefinition(name)\n });\n }\n }\n attach(element) {\n this.loadRefs(element, { day: 'single', month: 'single', year: 'single', input: 'multiple' });\n const superAttach = super.attach(element);\n const updateValueAndSaveFocus = (element, name) => () => {\n try {\n this.saveCaretPosition(element, name);\n }\n catch (err) {\n console.warn('An error occurred while trying to save caret position', err);\n }\n this.updateValue(null, {\n modified: true,\n });\n };\n if (this.shouldDisabled) {\n this.setDisabled(this.refs.day, true);\n this.setDisabled(this.refs.month, true);\n this.setDisabled(this.refs.year, true);\n if (this.refs.input) {\n this.refs.input.forEach((input) => this.setDisabled(input, true));\n }\n }\n else {\n this.addEventListener(this.refs.day, 'input', updateValueAndSaveFocus(this.refs.day, 'day'));\n // TODO: Need to rework this to work with day select as well.\n // Change day max input when month changes.\n this.addEventListener(this.refs.month, 'input', () => {\n const maxDay = this.refs.year ? parseInt(new Date(this.refs.year.value, this.refs.month.value, 0).getDate(), 10)\n : '';\n const day = this.getFieldValue('day');\n if (!this.component.fields.day.hide && maxDay) {\n this.refs.day.max = maxDay;\n }\n if (maxDay && day > maxDay) {\n this.refs.day.value = this.refs.day.max;\n }\n updateValueAndSaveFocus(this.refs.month, 'month')();\n });\n this.addEventListener(this.refs.year, 'input', updateValueAndSaveFocus(this.refs.year, 'year'));\n this.addEventListener(this.refs.input, this.info.changeEvent, () => this.updateValue(null, {\n modified: true\n }));\n [this.refs.day, this.refs.month, this.refs.year].filter((element) => !!element).forEach((element) => {\n super.addFocusBlurEvents(element);\n });\n }\n this.setValue(this.dataValue);\n // Force the disabled state with getters and setters.\n this.disabled = this.shouldDisabled;\n return superAttach;\n }\n validateRequired(setting, value) {\n const { day, month, year } = this.parts;\n if (this.dayRequired && !day) {\n return false;\n }\n if (this.monthRequired && !month) {\n return false;\n }\n if (this.yearRequired && !year) {\n return false;\n }\n if (!(0, utils_1.boolValue)(setting)) {\n return true;\n }\n return !this.isEmpty(value);\n }\n set disabled(disabled) {\n super.disabled = disabled;\n if (!this.refs.year || !this.refs.month || !this.refs.day) {\n return;\n }\n if (disabled) {\n this.refs.year.setAttribute('disabled', 'disabled');\n this.refs.month.setAttribute('disabled', 'disabled');\n this.refs.day.setAttribute('disabled', 'disabled');\n }\n else {\n this.refs.year.removeAttribute('disabled');\n this.refs.month.removeAttribute('disabled');\n this.refs.day.removeAttribute('disabled');\n }\n }\n normalizeValue(value) {\n if (!value || this.valueMask.test(value)) {\n return value;\n }\n const dateParts = [];\n const valueParts = value.split('/');\n const [DAY, MONTH, YEAR] = this.component.dayFirst ? [0, 1, 2] : [1, 0, 2];\n const defaultValue = this.component.defaultValue ? this.component.defaultValue.split('/') : '';\n const getNextPart = (shouldTake, defaultValue) => dateParts.push(shouldTake ? valueParts.shift() : defaultValue);\n if (this.dayFirst) {\n getNextPart(this.showDay, defaultValue ? defaultValue[DAY] : '00');\n }\n getNextPart(this.showMonth, defaultValue ? defaultValue[MONTH] : '00');\n if (!this.dayFirst) {\n getNextPart(this.showDay, defaultValue ? defaultValue[DAY] : '00');\n }\n getNextPart(this.showYear, defaultValue ? defaultValue[YEAR] : '0000');\n return dateParts.join('/');\n }\n /**\n * Set the value at a specific index and updates the component's refs.\n * @param {number} index - The index to set.\n * @param {any} value - The value to set.\n * @returns {null|void} - Returns null if the value is invalid, otherwise void.\n */\n setValueAt(index, value) {\n // temporary solution to avoid input reset\n // on invalid date.\n if (!value || value === 'Invalid date') {\n return null;\n }\n const parts = value.split('/');\n let day;\n if (this.component.dayFirst) {\n day = parts.shift();\n }\n const month = parts.shift();\n if (!this.component.dayFirst) {\n day = parts.shift();\n }\n const year = parts.shift();\n if (this.refs.day && this.showDay) {\n this.refs.day.value = day === '00' ? '' : parseInt(day, 10);\n }\n if (this.refs.month && this.showMonth) {\n this.refs.month.value = month === '00' ? '' : parseInt(month, 10);\n }\n if (this.refs.year && this.showYear) {\n this.refs.year.value = year === '0000' ? '' : parseInt(year, 10);\n }\n }\n getFieldValue(name) {\n const parts = this.dataValue ? this.dataValue.split('/') : [];\n let val = 0;\n switch (name) {\n case 'month':\n val = parts[this.dayFirst ? 1 : 0];\n break;\n case 'day':\n val = parts[this.dayFirst ? 0 : 1];\n break;\n case 'year':\n val = parts[2];\n break;\n }\n val = parseInt(val, 10);\n return (!lodash_1.default.isNaN(val) && lodash_1.default.isNumber(val)) ? val : 0;\n }\n get parts() {\n return {\n day: this.getFieldValue('day'),\n month: this.getFieldValue('month'),\n year: this.getFieldValue('year'),\n };\n }\n /**\n * Get the format for the value string.\n * @returns {string} - the format for the value string.\n */\n get format() {\n let format = '';\n if (this.component.dayFirst && this.showDay) {\n format += 'D/';\n }\n if (this.showMonth) {\n format += 'M/';\n }\n if (!this.component.dayFirst && this.showDay) {\n format += 'D/';\n }\n if (this.showYear) {\n format += 'YYYY';\n return format;\n }\n else {\n // Trim off the \"/\" from the end of the format string.\n return format.length ? format.substring(0, format.length - 1) : format;\n }\n }\n /**\n * Return the date for this component.\n * @param {any} value - The value to convert to a date.\n * @returns {null|string} - The date string.\n */\n getDate(value) {\n let defaults = [], day, month, year;\n // Map positions to identifiers to get default values for each part of day\n const [DAY, MONTH, YEAR] = this.component.dayFirst ? [0, 1, 2] : [1, 0, 2];\n const defaultValue = value || this.component.defaultValue;\n if (defaultValue) {\n defaults = defaultValue.split('/').map(x => parseInt(x, 10));\n }\n if (this.showDay && this.refs.day) {\n day = parseInt(this.refs.day.value, 10);\n }\n if (day === undefined || lodash_1.default.isNaN(day)) {\n day = defaults[DAY] && !lodash_1.default.isNaN(defaults[DAY]) ? defaults[DAY] : 0;\n }\n if (this.showMonth && this.refs.month) {\n // Months are 0 indexed.\n month = parseInt(this.refs.month.value, 10);\n }\n if (month === undefined || lodash_1.default.isNaN(month)) {\n month = defaults[MONTH] && !lodash_1.default.isNaN(defaults[MONTH]) ? defaults[MONTH] : 0;\n }\n if (this.showYear && this.refs.year) {\n year = parseInt(this.refs.year.value);\n }\n if (year === undefined || lodash_1.default.isNaN(year)) {\n year = defaults[YEAR] && !lodash_1.default.isNaN(defaults[YEAR]) ? defaults[YEAR] : 0;\n }\n let result;\n if (!day && !month && !year) {\n return null;\n }\n // add trailing zeros if the data is showed\n day = this.showDay ? day.toString().padStart(2, 0) : '';\n month = this.showMonth ? month.toString().padStart(2, 0) : '';\n year = this.showYear ? year.toString().padStart(4, 0) : '';\n if (this.component.dayFirst) {\n result = `${day}${this.showDay && this.showMonth || this.showDay && this.showYear ? '/' : ''}${month}${this.showMonth && this.showYear ? '/' : ''}${year}`;\n }\n else {\n result = `${month}${this.showDay && this.showMonth || this.showMonth && this.showYear ? '/' : ''}${day}${this.showDay && this.showYear ? '/' : ''}${year}`;\n }\n return result;\n }\n /**\n * Return the date string for this component.\n * @returns {string|null} - The date string for this component.\n */\n get date() {\n return this.getDate();\n }\n /**\n * Return the raw value.\n * @returns {string} - The raw value of the component.\n */\n get validationValue() {\n return this.dataValue;\n }\n getValue() {\n const result = super.getValue();\n return (!result) ? this.dataValue : result;\n }\n /**\n * Get the value at a specific index.\n * @param {number} index - The index to get the value from.\n * @returns {*} - The value at index.\n */\n getValueAt(index) {\n const date = this.date || this.emptyValue;\n if (date) {\n this.refs.input[index].value = date;\n return this.refs.input[index].value;\n }\n else {\n this.refs.input[index].value = '';\n return null;\n }\n }\n /**\n * Get the input value of the date.\n * @param {any} value - The value to convert to a string.\n * @returns {string|null} - The string value of the date.\n */\n getValueAsString(value) {\n return this.getDate(value) || '';\n }\n focus(field) {\n var _a, _b, _c;\n if (field && typeof field === 'string' && this.refs[field]) {\n this.refs[field].focus();\n }\n else if (this.dayFirst && this.showDay || !this.dayFirst && !this.showMonth && this.showDay) {\n (_a = this.refs.day) === null || _a === void 0 ? void 0 : _a.focus();\n }\n else if (this.dayFirst && !this.showDay && this.showMonth || !this.dayFirst && this.showMonth) {\n (_b = this.refs.month) === null || _b === void 0 ? void 0 : _b.focus();\n }\n else if (!this.showDay && !this.showDay && this.showYear) {\n (_c = this.refs.year) === null || _c === void 0 ? void 0 : _c.focus();\n }\n }\n restoreCaretPosition() {\n var _a;\n if ((_a = this.root) === null || _a === void 0 ? void 0 : _a.currentSelection) {\n const { selection, index } = this.root.currentSelection;\n if (this.refs[index]) {\n const input = this.refs[index];\n const isInputRangeSelectable = (i) => /text|search|password|tel|url/i.test((i === null || i === void 0 ? void 0 : i.type) || '');\n if (isInputRangeSelectable(input)) {\n input.setSelectionRange(...selection);\n }\n }\n }\n }\n isPartialDay(value) {\n if (!value) {\n return false;\n }\n const [DAY, MONTH, YEAR] = this.component.dayFirst ? [0, 1, 2] : [1, 0, 2];\n const values = value.split('/');\n return (values[DAY] === '00' || values[MONTH] === '00' || values[YEAR] === '0000');\n }\n getValidationFormat() {\n return this.dayFirst ? 'DD-MM-YYYY' : 'MM-DD-YYYY';\n }\n}\nexports[\"default\"] = DayComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/day/Day.js?");
|
|
5108
5108
|
|
|
5109
5109
|
/***/ }),
|
|
5110
5110
|
|
|
@@ -5148,7 +5148,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5148
5148
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
5149
5149
|
|
|
5150
5150
|
"use strict";
|
|
5151
|
-
eval("\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst Field_1 = __importDefault(__webpack_require__(/*! ../_classes/field/Field */ \"./lib/cjs/components/_classes/field/Field.js\"));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst downloadjs_1 = __importDefault(__webpack_require__(/*! downloadjs */ \"./node_modules/downloadjs/download.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst fileProcessor_1 = __importDefault(__webpack_require__(/*! ../../providers/processor/fileProcessor */ \"./lib/cjs/providers/processor/fileProcessor.js\"));\nconst browser_md5_file_1 = __importDefault(__webpack_require__(/*! browser-md5-file */ \"./node_modules/browser-md5-file/dist/index.umd.js\"));\nlet Camera;\nlet webViewCamera = 'undefined' !== typeof window ? navigator.camera : Camera;\n// canvas.toBlob polyfill.\nlet htmlCanvasElement;\nif (typeof window !== 'undefined') {\n htmlCanvasElement = window.HTMLCanvasElement;\n}\nelse if (typeof __webpack_require__.g !== 'undefined') {\n htmlCanvasElement = __webpack_require__.g.HTMLCanvasElement;\n}\nif (htmlCanvasElement && !htmlCanvasElement.prototype.toBlob) {\n Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {\n value: function (callback, type, quality) {\n var canvas = this;\n setTimeout(function () {\n var binStr = atob(canvas.toDataURL(type, quality).split(',')[1]), len = binStr.length, arr = new Uint8Array(len);\n for (var i = 0; i < len; i++) {\n arr[i] = binStr.charCodeAt(i);\n }\n callback(new Blob([arr], { type: type || 'image/png' }));\n });\n }\n });\n}\nconst createRandomString = () => Math.random().toString(36).substring(2, 15);\nclass FileComponent extends Field_1.default {\n static schema(...extend) {\n return Field_1.default.schema({\n type: 'file',\n label: 'Upload',\n key: 'file',\n image: false,\n privateDownload: false,\n imageSize: '200',\n filePattern: '*',\n fileMinSize: '0KB',\n fileMaxSize: '1GB',\n uploadOnly: false,\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'File',\n group: 'premium',\n icon: 'file',\n documentation: '/userguide/form-building/premium-components#file',\n weight: 100,\n schema: FileComponent.schema(),\n };\n }\n static get serverConditionSettings() {\n return FileComponent.conditionOperatorsSettings;\n }\n static get conditionOperatorsSettings() {\n return Object.assign(Object.assign({}, super.conditionOperatorsSettings), { operators: ['isEmpty', 'isNotEmpty'] });\n }\n static savedValueTypes(schema) {\n schema = schema || {};\n return (0, utils_1.getComponentSavedTypes)(schema) || [utils_1.componentValueTypes.object];\n }\n init() {\n super.init();\n webViewCamera = navigator.camera || Camera;\n const fileReaderSupported = (typeof FileReader !== 'undefined');\n const formDataSupported = typeof window !== 'undefined' ? Boolean(window.FormData) : false;\n const progressSupported = (typeof window !== 'undefined' && window.XMLHttpRequest) ? ('upload' in new XMLHttpRequest) : false;\n this.support = {\n filereader: fileReaderSupported,\n formdata: formDataSupported,\n hasWarning: !fileReaderSupported || !formDataSupported || !progressSupported,\n progress: progressSupported,\n };\n this.cameraMode = false;\n this.fileDropHidden = false;\n this.filesToSync = {\n filesToUpload: [],\n filesToDelete: [],\n };\n this.isSyncing = false;\n this.abortUploads = [];\n }\n get dataReady() {\n return this.filesReady || Promise.resolve();\n }\n get defaultSchema() {\n return FileComponent.schema();\n }\n loadImage(fileInfo) {\n if (this.component.privateDownload) {\n fileInfo.private = true;\n }\n return this.fileService.downloadFile(fileInfo).then((result) => result.url);\n }\n get emptyValue() {\n return [];\n }\n getValueAsString(value) {\n if (lodash_1.default.isArray(value)) {\n return lodash_1.default.map(value, 'originalName').join(', ');\n }\n return lodash_1.default.get(value, 'originalName', '');\n }\n getValue() {\n return this.dataValue;\n }\n get defaultValue() {\n const value = super.defaultValue;\n return Array.isArray(value) ? value : [];\n }\n get hasTypes() {\n return this.component.fileTypes &&\n Array.isArray(this.component.fileTypes) &&\n this.component.fileTypes.length !== 0 &&\n (this.component.fileTypes[0].label !== '' || this.component.fileTypes[0].value !== '');\n }\n get fileDropHidden() {\n return this._fileBrowseHidden;\n }\n set fileDropHidden(value) {\n if (typeof value !== 'boolean' || this.component.multiple) {\n return;\n }\n this._fileBrowseHidden = value;\n }\n get shouldSyncFiles() {\n return Boolean(this.filesToSync.filesToDelete.length || this.filesToSync.filesToUpload.length);\n }\n get autoSync() {\n return lodash_1.default.get(this, 'component.autoSync', false);\n }\n get columnsSize() {\n const actionsColumn = this.disabled ? 0 : this.autoSync ? 2 : 1;\n const typeColumn = this.hasTypes ? 2 : 0;\n const sizeColumn = 2;\n const nameColumn = 12 - actionsColumn - typeColumn - sizeColumn;\n return {\n name: nameColumn,\n size: sizeColumn,\n type: typeColumn,\n actions: actionsColumn,\n };\n }\n render() {\n const { filesToDelete, filesToUpload } = this.filesToSync;\n return super.render(this.renderTemplate('file', {\n fileSize: this.fileSize,\n files: this.dataValue || [],\n filesToDelete,\n filesToUpload,\n disabled: this.disabled,\n support: this.support,\n fileDropHidden: this.fileDropHidden,\n showSyncButton: this.autoSync && (filesToDelete.length || filesToUpload.length),\n isSyncing: this.isSyncing,\n columns: this.columnsSize,\n }));\n }\n getVideoStream(constraints) {\n return navigator.mediaDevices.getUserMedia({\n video: Object.assign({ width: { min: 640, ideal: 1920 }, height: { min: 360, ideal: 1080 }, aspectRatio: { ideal: 16 / 9 } }, constraints),\n audio: false,\n });\n }\n stopVideoStream(videoStream) {\n videoStream.getVideoTracks().forEach((track) => track.stop());\n }\n getFrame(videoPlayer) {\n return new Promise((resolve) => {\n const canvas = document.createElement('canvas');\n canvas.height = videoPlayer.videoHeight;\n canvas.width = videoPlayer.videoWidth;\n const context = canvas.getContext('2d');\n context.drawImage(videoPlayer, 0, 0);\n canvas.toBlob(resolve);\n });\n }\n startVideo() {\n this.getVideoStream()\n .then((stream) => {\n this.videoStream = stream;\n const { videoPlayer } = this.refs;\n if (!videoPlayer) {\n console.warn('Video player not found in template.');\n this.cameraMode = false;\n this.redraw();\n return;\n }\n videoPlayer.srcObject = stream;\n const width = parseInt(this.component.webcamSize) || 320;\n videoPlayer.setAttribute('width', width);\n videoPlayer.play();\n })\n .catch((err) => {\n console.error(err);\n this.cameraMode = false;\n this.redraw();\n });\n }\n stopVideo() {\n if (this.videoStream) {\n this.stopVideoStream(this.videoStream);\n this.videoStream = null;\n }\n }\n takePicture() {\n const { videoPlayer } = this.refs;\n if (!videoPlayer) {\n console.warn('Video player not found in template.');\n this.cameraMode = false;\n this.redraw();\n return;\n }\n this.getFrame(videoPlayer)\n .then((frame) => {\n frame.name = `photo-${Date.now()}.png`;\n this.handleFilesToUpload([frame]);\n this.cameraMode = false;\n this.redraw();\n });\n }\n browseFiles(attrs = {}) {\n return new Promise((resolve) => {\n const fileInput = this.ce('input', Object.assign({ type: 'file', style: 'height: 0; width: 0; visibility: hidden;', tabindex: '-1' }, attrs));\n document.body.appendChild(fileInput);\n fileInput.addEventListener('change', () => {\n resolve(fileInput.files);\n document.body.removeChild(fileInput);\n }, true);\n // There is no direct way to trigger a file dialog. To work around this, create an input of type file and trigger\n // a click event on it.\n if (typeof fileInput.trigger === 'function') {\n fileInput.trigger('click');\n }\n else {\n fileInput.click();\n }\n });\n }\n set cameraMode(value) {\n this._cameraMode = value;\n if (value) {\n this.startVideo();\n }\n else {\n this.stopVideo();\n }\n }\n get cameraMode() {\n return this._cameraMode;\n }\n get useWebViewCamera() {\n return this.imageUpload && webViewCamera;\n }\n get imageUpload() {\n return Boolean(this.component.image);\n }\n get browseOptions() {\n const options = {};\n if (this.component.multiple) {\n options.multiple = true;\n }\n if (this.component.capture) {\n options.capture = this.component.capture;\n }\n //use \"accept\" attribute only for desktop devices because of its limited support by mobile browsers\n const filePattern = this.component.filePattern.trim() || '';\n if (!this.isMobile.any) {\n const imagesPattern = 'image/*';\n if (this.imageUpload && (!filePattern || filePattern === '*')) {\n options.accept = imagesPattern;\n }\n else if (this.imageUpload && !filePattern.includes(imagesPattern)) {\n options.accept = `${imagesPattern},${filePattern}`;\n }\n else {\n options.accept = filePattern;\n }\n }\n // if input capture is set, we need the \"accept\" attribute to determine which device to launch\n else if (this.component.capture) {\n if (filePattern.includes('video')) {\n options.accept = 'video/*';\n }\n else if (filePattern.includes('audio')) {\n options.accept = 'audio/*';\n }\n else {\n options.accept = 'image/*';\n }\n }\n return options;\n }\n get actions() {\n return {\n abort: this.abortRequest.bind(this),\n };\n }\n attach(element) {\n this.loadRefs(element, {\n fileDrop: 'single',\n fileBrowse: 'single',\n galleryButton: 'single',\n cameraButton: 'single',\n takePictureButton: 'single',\n toggleCameraMode: 'single',\n videoPlayer: 'single',\n fileLink: 'multiple',\n removeLink: 'multiple',\n fileToSyncRemove: 'multiple',\n fileImage: 'multiple',\n fileType: 'multiple',\n fileProcessingLoader: 'single',\n syncNow: 'single',\n restoreFile: 'multiple',\n progress: 'multiple',\n });\n // Ensure we have an empty input refs. We need this for the setValue method to redraw the control when it is set.\n this.refs.input = [];\n const superAttach = super.attach(element);\n if (this.refs.fileDrop) {\n // if (!this.statuses.length) {\n // this.refs.fileDrop.removeAttribute('hidden');\n // }\n const _this = this;\n this.addEventListener(this.refs.fileDrop, 'dragover', function (event) {\n this.className = 'fileSelector fileDragOver';\n event.preventDefault();\n });\n this.addEventListener(this.refs.fileDrop, 'dragleave', function (event) {\n this.className = 'fileSelector';\n event.preventDefault();\n });\n this.addEventListener(this.refs.fileDrop, 'drop', function (event) {\n this.className = 'fileSelector';\n event.preventDefault();\n _this.handleFilesToUpload(event.dataTransfer.files);\n });\n }\n this.addEventListener(element, 'click', (event) => {\n this.handleAction(event);\n });\n if (this.refs.fileBrowse) {\n this.addEventListener(this.refs.fileBrowse, 'click', (event) => {\n event.preventDefault();\n this.browseFiles(this.browseOptions)\n .then((files) => {\n this.handleFilesToUpload(files);\n });\n });\n }\n this.refs.fileLink.forEach((fileLink, index) => {\n this.addEventListener(fileLink, 'click', (event) => {\n event.preventDefault();\n this.getFile(this.dataValue[index]);\n });\n });\n this.refs.removeLink.forEach((removeLink, index) => {\n this.addEventListener(removeLink, 'click', (event) => {\n event.preventDefault();\n const fileInfo = this.dataValue[index];\n this.handleFileToRemove(fileInfo);\n });\n });\n this.refs.fileToSyncRemove.forEach((fileToSyncRemove, index) => {\n this.addEventListener(fileToSyncRemove, 'click', (event) => {\n event.preventDefault();\n this.filesToSync.filesToUpload.splice(index, 1);\n this.redraw();\n });\n });\n this.refs.restoreFile.forEach((fileToRestore, index) => {\n this.addEventListener(fileToRestore, 'click', (event) => {\n event.preventDefault();\n const fileInfo = this.filesToSync.filesToDelete[index];\n delete fileInfo.status;\n delete fileInfo.message;\n this.filesToSync.filesToDelete.splice(index, 1);\n this.dataValue.push(fileInfo);\n this.triggerChange();\n this.redraw();\n });\n });\n if (this.refs.galleryButton && webViewCamera) {\n this.addEventListener(this.refs.galleryButton, 'click', (event) => {\n event.preventDefault();\n webViewCamera.getPicture((success) => {\n window.resolveLocalFileSystemURL(success, (fileEntry) => {\n fileEntry.file((file) => {\n const reader = new FileReader();\n reader.onloadend = (evt) => {\n const blob = new Blob([new Uint8Array(evt.target.result)], { type: file.type });\n blob.name = file.name;\n this.handleFilesToUpload([blob]);\n };\n reader.readAsArrayBuffer(file);\n });\n });\n }, (err) => {\n console.error(err);\n }, {\n sourceType: webViewCamera.PictureSourceType.PHOTOLIBRARY,\n });\n });\n }\n if (this.refs.cameraButton && webViewCamera) {\n this.addEventListener(this.refs.cameraButton, 'click', (event) => {\n event.preventDefault();\n webViewCamera.getPicture((success) => {\n window.resolveLocalFileSystemURL(success, (fileEntry) => {\n fileEntry.file((file) => {\n const reader = new FileReader();\n reader.onloadend = (evt) => {\n const blob = new Blob([new Uint8Array(evt.target.result)], { type: file.type });\n blob.name = file.name;\n this.handleFilesToUpload([blob]);\n };\n reader.readAsArrayBuffer(file);\n });\n });\n }, (err) => {\n console.error(err);\n }, {\n sourceType: webViewCamera.PictureSourceType.CAMERA,\n encodingType: webViewCamera.EncodingType.PNG,\n mediaType: webViewCamera.MediaType.PICTURE,\n saveToPhotoAlbum: true,\n correctOrientation: false,\n });\n });\n }\n if (this.refs.takePictureButton) {\n this.addEventListener(this.refs.takePictureButton, 'click', (event) => {\n event.preventDefault();\n this.takePicture();\n });\n }\n if (this.refs.toggleCameraMode) {\n this.addEventListener(this.refs.toggleCameraMode, 'click', (event) => {\n event.preventDefault();\n this.cameraMode = !this.cameraMode;\n this.redraw();\n });\n }\n this.refs.fileType.forEach((fileType, index) => {\n if (!this.dataValue[index]) {\n return;\n }\n this.dataValue[index].fileType = this.dataValue[index].fileType || this.component.fileTypes[0].label;\n this.addEventListener(fileType, 'change', (event) => {\n event.preventDefault();\n const fileType = this.component.fileTypes.find((typeObj) => typeObj.value === event.target.value);\n this.dataValue[index].fileType = fileType.label;\n });\n });\n this.addEventListener(this.refs.syncNow, 'click', (event) => {\n event.preventDefault();\n this.syncFiles();\n });\n const fileService = this.fileService;\n if (fileService) {\n const loadingImages = [];\n this.filesReady = new Promise((resolve, reject) => {\n this.filesReadyResolve = resolve;\n this.filesReadyReject = reject;\n });\n this.refs.fileImage.forEach((image, index) => {\n loadingImages.push(this.loadImage(this.dataValue[index]).then((url) => (image.src = url)));\n });\n if (loadingImages.length) {\n Promise.all(loadingImages).then(() => {\n this.filesReadyResolve();\n }).catch(() => this.filesReadyReject());\n }\n else {\n this.filesReadyResolve();\n }\n }\n return superAttach;\n }\n /* eslint-disable max-len */\n fileSize(a, b, c, d, e) {\n return `${(b = Math, c = b.log, d = 1024, e = c(a) / c(d) | 0, a / b.pow(d, e)).toFixed(2)} ${e ? `${'kMGTPEZY'[--e]}B` : 'Bytes'}`;\n }\n /* eslint-enable max-len */\n /* eslint-disable max-depth */\n globStringToRegex(str) {\n str = str.replace(/\\s/g, '');\n let regexp = '', excludes = [];\n if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {\n regexp = str.substring(1, str.length - 1);\n }\n else {\n const split = str.split(',');\n if (split.length > 1) {\n for (let i = 0; i < split.length; i++) {\n const r = this.globStringToRegex(split[i]);\n if (r.regexp) {\n regexp += `(${r.regexp})`;\n if (i < split.length - 1) {\n regexp += '|';\n }\n }\n else {\n excludes = excludes.concat(r.excludes);\n }\n }\n }\n else {\n if (str.startsWith('!')) {\n excludes.push(`^((?!${this.globStringToRegex(str.substring(1)).regexp}).)*$`);\n }\n else {\n if (str.startsWith('.')) {\n str = `*${str}`;\n }\n regexp = `^${str.replace(new RegExp('[.\\\\\\\\+*?\\\\[\\\\^\\\\]$(){}=!<>|:\\\\-]', 'g'), '\\\\$&')}$`;\n regexp = regexp.replace(/\\\\\\*/g, '.*').replace(/\\\\\\?/g, '.');\n }\n }\n }\n return { regexp, excludes };\n }\n /* eslint-enable max-depth */\n translateScalars(str) {\n if (typeof str === 'string') {\n if (str.search(/kb/i) === str.length - 2) {\n return parseFloat(str.substring(0, str.length - 2) * 1024);\n }\n if (str.search(/mb/i) === str.length - 2) {\n return parseFloat(str.substring(0, str.length - 2) * 1024 * 1024);\n }\n if (str.search(/gb/i) === str.length - 2) {\n return parseFloat(str.substring(0, str.length - 2) * 1024 * 1024 * 1024);\n }\n if (str.search(/b/i) === str.length - 1) {\n return parseFloat(str.substring(0, str.length - 1));\n }\n if (str.search(/s/i) === str.length - 1) {\n return parseFloat(str.substring(0, str.length - 1));\n }\n if (str.search(/m/i) === str.length - 1) {\n return parseFloat(str.substring(0, str.length - 1) * 60);\n }\n if (str.search(/h/i) === str.length - 1) {\n return parseFloat(str.substring(0, str.length - 1) * 3600);\n }\n }\n return str;\n }\n validatePattern(file, val) {\n if (!val) {\n return true;\n }\n const pattern = this.globStringToRegex(val);\n let valid = true;\n if (pattern.regexp && pattern.regexp.length) {\n const regexp = new RegExp(pattern.regexp, 'i');\n valid = (!lodash_1.default.isNil(file.type) && regexp.test(file.type)) ||\n (!lodash_1.default.isNil(file.name) && regexp.test(file.name));\n }\n valid = pattern.excludes.reduce((result, excludePattern) => {\n const exclude = new RegExp(excludePattern, 'i');\n return result && (lodash_1.default.isNil(file.type) || exclude.test(file.type)) &&\n (lodash_1.default.isNil(file.name) || exclude.test(file.name));\n }, valid);\n return valid;\n }\n validateMinSize(file, val) {\n return file.size + 0.1 >= this.translateScalars(val);\n }\n validateMaxSize(file, val) {\n return file.size - 0.1 <= this.translateScalars(val);\n }\n abortRequest(id) {\n const abortUpload = this.abortUploads.find(abortUpload => abortUpload.id === id);\n if (abortUpload) {\n abortUpload.abort();\n }\n }\n handleAction(event) {\n const target = event.target;\n if (!target.id) {\n return;\n }\n const [action, id] = target.id.split('-');\n if (!action || !id || !this.actions[action]) {\n return;\n }\n this.actions[action](id);\n }\n getFileName(file) {\n return (0, utils_1.uniqueName)(file.name, this.component.fileNameTemplate, this.evalContext());\n }\n getInitFileToSync(file) {\n const escapedFileName = file.name ? file.name.replaceAll('<', '<').replaceAll('>', '>') : file.name;\n return {\n id: createRandomString(),\n // Get a unique name for this file to keep file collisions from occurring.\n dir: this.interpolate(this.component.dir || ''),\n name: this.getFileName(file),\n originalName: escapedFileName,\n fileKey: this.component.fileKey || 'file',\n storage: this.component.storage,\n options: this.component.options,\n file,\n size: file.size,\n status: 'info',\n message: this.t('Processing file. Please wait...'),\n hash: '',\n };\n }\n handleSubmissionRevisions(file) {\n return __awaiter(this, void 0, void 0, function* () {\n if (this.root.form.submissionRevisions !== 'true') {\n return '';\n }\n const bmf = new browser_md5_file_1.default();\n const hash = yield new Promise((resolve, reject) => {\n this.emit('fileUploadingStart');\n bmf.md5(file, (err, md5) => {\n if (err) {\n return reject(err);\n }\n return resolve(md5);\n });\n });\n this.emit('fileUploadingEnd');\n return hash;\n });\n }\n validateFileName(file) {\n // Check if file with the same name is being uploaded\n const fileWithSameNameUploading = this.filesToSync.filesToUpload\n .some(fileToSync => { var _a; return ((_a = fileToSync.file) === null || _a === void 0 ? void 0 : _a.name) === file.name; });\n const fileWithSameNameUploaded = lodash_1.default.some(this.dataValue, fileStatus => fileStatus.originalName === file.name);\n return fileWithSameNameUploaded || fileWithSameNameUploading\n ? {\n status: 'error',\n message: this.t(`File with the same name is already ${fileWithSameNameUploading ? 'being ' : ''}uploaded`),\n }\n : {};\n }\n validateFileSettings(file) {\n // Check file pattern\n if (this.component.filePattern && !this.validatePattern(file, this.component.filePattern)) {\n return {\n status: 'error',\n message: this.t('File is the wrong type; it must be {{ pattern }}', {\n pattern: this.component.filePattern,\n }),\n };\n }\n // Check file minimum size\n if (this.component.fileMinSize && !this.validateMinSize(file, this.component.fileMinSize)) {\n return {\n status: 'error',\n message: this.t('File is too small; it must be at least {{ size }}', {\n size: this.component.fileMinSize,\n }),\n };\n }\n // Check file maximum size\n if (this.component.fileMaxSize && !this.validateMaxSize(file, this.component.fileMaxSize)) {\n return {\n status: 'error',\n message: this.t('File is too big; it must be at most {{ size }}', {\n size: this.component.fileMaxSize,\n }),\n };\n }\n return {};\n }\n validateFileService() {\n const { fileService } = this;\n return !fileService\n ? {\n status: 'error',\n message: this.t('File Service not provided.'),\n }\n : {};\n }\n validateFile(file) {\n const fileServiceValidation = this.validateFileService();\n if (fileServiceValidation.status === 'error') {\n return fileServiceValidation;\n }\n const fileNameValidation = this.validateFileName(file);\n if (fileNameValidation.status === 'error') {\n return fileNameValidation;\n }\n return this.validateFileSettings(file);\n }\n getGroupPermissions() {\n let groupKey = null;\n let groupPermissions = null;\n //Iterate through form components to find group resource if one exists\n this.root.everyComponent((element) => {\n var _a, _b;\n if (((_a = element.component) === null || _a === void 0 ? void 0 : _a.submissionAccess) || ((_b = element.component) === null || _b === void 0 ? void 0 : _b.defaultPermission)) {\n groupPermissions = !element.component.submissionAccess ? [\n {\n type: element.component.defaultPermission,\n roles: [],\n },\n ] : element.component.submissionAccess;\n groupPermissions.forEach((permission) => {\n groupKey = ['admin', 'write', 'create'].includes(permission.type) ? element.component.key : null;\n });\n }\n });\n return { groupKey, groupPermissions };\n }\n triggerFileProcessor(file) {\n return __awaiter(this, void 0, void 0, function* () {\n let processedFile = null;\n if (this.root.options.fileProcessor) {\n try {\n if (this.refs.fileProcessingLoader) {\n this.refs.fileProcessingLoader.style.display = 'block';\n }\n const fileProcessorHandler = (0, fileProcessor_1.default)(this.fileService, this.root.options.fileProcessor);\n processedFile = yield fileProcessorHandler(file, this.component.properties);\n }\n catch (err) {\n this.fileDropHidden = false;\n return {\n status: 'error',\n message: this.t('File processing has been failed.'),\n };\n }\n finally {\n if (this.refs.fileProcessingLoader) {\n this.refs.fileProcessingLoader.style.display = 'none';\n }\n }\n }\n return {\n file: processedFile,\n };\n });\n }\n prepareFileToUpload(file) {\n return __awaiter(this, void 0, void 0, function* () {\n const fileToSync = this.getInitFileToSync(file);\n fileToSync.hash = yield this.handleSubmissionRevisions(file);\n const { status, message } = this.validateFile(file);\n if (status === 'error') {\n fileToSync.isValidationError = true;\n fileToSync.status = status;\n fileToSync.message = message;\n return this.filesToSync.filesToUpload.push(fileToSync);\n }\n if (this.component.privateDownload) {\n file.private = true;\n }\n const { groupKey, groupPermissions } = this.getGroupPermissions();\n const processedFile = yield this.triggerFileProcessor(file);\n if (processedFile.status === 'error') {\n fileToSync.status === 'error';\n fileToSync.message = processedFile.message;\n return this.filesToSync.filesToUpload.push(fileToSync);\n }\n if (this.autoSync) {\n fileToSync.message = this.t('Ready to be uploaded into storage');\n }\n this.filesToSync.filesToUpload.push(Object.assign(Object.assign({}, fileToSync), { message: fileToSync.message, file: processedFile.file || file, url: this.interpolate(this.component.url, { file: fileToSync }), groupPermissions, groupResourceId: groupKey ? this.currentForm.submission.data[groupKey]._id : null }));\n });\n }\n prepareFilesToUpload(files) {\n return __awaiter(this, void 0, void 0, function* () {\n // Only allow one upload if not multiple.\n if (!this.component.multiple) {\n files = Array.prototype.slice.call(files, 0, 1);\n }\n if (this.component.storage && files && files.length) {\n this.fileDropHidden = true;\n return Promise.all([...files].map((file) => __awaiter(this, void 0, void 0, function* () {\n yield this.prepareFileToUpload(file);\n this.redraw();\n })));\n }\n else {\n return Promise.resolve();\n }\n });\n }\n handleFilesToUpload(files) {\n return __awaiter(this, void 0, void 0, function* () {\n yield this.prepareFilesToUpload(files);\n if (!this.autoSync) {\n yield this.syncFiles();\n }\n });\n }\n prepareFileToDelete(fileInfo) {\n this.filesToSync.filesToDelete.push(Object.assign(Object.assign({}, fileInfo), { status: 'info', message: this.autoSync\n ? this.t('Ready to be removed from storage')\n : this.t('Preparing file to remove') }));\n const index = this.dataValue.findIndex(file => file.name === fileInfo.name);\n this.splice(index);\n this.redraw();\n }\n handleFileToRemove(fileInfo) {\n this.prepareFileToDelete(fileInfo);\n if (!this.autoSync) {\n this.syncFiles();\n }\n }\n deleteFile(fileInfo) {\n return __awaiter(this, void 0, void 0, function* () {\n const { options = {} } = this.component;\n if (fileInfo && (['url', 'indexeddb', 's3', 'azure', 'googledrive'].includes(this.component.storage))) {\n const { fileService } = this;\n if (fileService && typeof fileService.deleteFile === 'function') {\n return yield fileService.deleteFile(fileInfo, options);\n }\n else {\n const formio = this.options.formio || (this.root && this.root.formio);\n if (formio) {\n return yield formio.makeRequest('', fileInfo.url, 'delete');\n }\n }\n }\n });\n }\n delete() {\n return __awaiter(this, void 0, void 0, function* () {\n if (!this.filesToSync.filesToDelete.length) {\n return Promise.resolve();\n }\n return yield Promise.all(this.filesToSync.filesToDelete.map((fileToSync) => __awaiter(this, void 0, void 0, function* () {\n try {\n if (fileToSync.isValidationError) {\n return { fileToSync };\n }\n yield this.deleteFile(fileToSync);\n fileToSync.status = 'success';\n fileToSync.message = this.t('Succefully removed');\n }\n catch (response) {\n fileToSync.status = 'error';\n fileToSync.message = typeof response === 'string' ? response : response.toString();\n }\n finally {\n this.redraw();\n }\n return { fileToSync };\n })));\n });\n }\n updateProgress(fileInfo, progressEvent) {\n fileInfo.progress = parseInt(100.0 * progressEvent.loaded / progressEvent.total);\n if (fileInfo.status !== 'progress') {\n fileInfo.status = 'progress';\n delete fileInfo.message;\n this.redraw();\n }\n else {\n const progress = Array.prototype.find.call(this.refs.progress, progressElement => progressElement.id === fileInfo.id);\n progress.innerHTML = `<span class=\"visually-hidden\">${fileInfo.progress}% ${this.t('Complete')}</span>`;\n progress.style.width = `${fileInfo.progress}%`;\n progress.ariaValueNow = fileInfo.progress.toString();\n }\n }\n getMultipartOptions(fileToSync) {\n let count = 0;\n return this.component.useMultipartUpload && this.component.multipart ? Object.assign(Object.assign({}, this.component.multipart), { progressCallback: (total) => {\n count++;\n fileToSync.status = 'progress';\n fileToSync.progress = parseInt(100 * count / total);\n delete fileToSync.message;\n this.redraw();\n }, changeMessage: (message) => {\n fileToSync.message = message;\n this.redraw();\n } }) : false;\n }\n uploadFile(fileToSync) {\n return __awaiter(this, void 0, void 0, function* () {\n return yield this.fileService.uploadFile(fileToSync.storage, fileToSync.file, fileToSync.name, fileToSync.dir, \n // Progress callback\n this.updateProgress.bind(this, fileToSync), fileToSync.url, fileToSync.options, fileToSync.fileKey, fileToSync.groupPermissions, fileToSync.groupResourceId, () => { }, \n // Abort upload callback\n (abort) => this.abortUploads.push({\n id: fileToSync.id,\n abort,\n }), this.getMultipartOptions(fileToSync));\n });\n }\n upload() {\n return __awaiter(this, void 0, void 0, function* () {\n if (!this.filesToSync.filesToUpload.length) {\n return Promise.resolve();\n }\n return yield Promise.all(this.filesToSync.filesToUpload.map((fileToSync) => __awaiter(this, void 0, void 0, function* () {\n let fileInfo = null;\n try {\n if (fileToSync.isValidationError) {\n return {\n fileToSync,\n fileInfo,\n };\n }\n fileInfo = yield this.uploadFile(fileToSync);\n fileToSync.status = 'success';\n fileToSync.message = this.t('Succefully uploaded');\n fileInfo.originalName = fileToSync.originalName;\n fileInfo.hash = fileToSync.hash;\n }\n catch (response) {\n fileToSync.status = 'error';\n delete fileToSync.progress;\n fileToSync.message = typeof response === 'string'\n ? response\n : response.type === 'abort'\n ? this.t('Request was aborted')\n : response.toString();\n }\n finally {\n delete fileToSync.progress;\n this.redraw();\n }\n return {\n fileToSync,\n fileInfo,\n };\n })));\n });\n }\n syncFiles() {\n return __awaiter(this, void 0, void 0, function* () {\n this.isSyncing = true;\n this.fileDropHidden = true;\n this.redraw();\n try {\n const [filesToDelete = [], filesToUpload = []] = yield Promise.all([this.delete(), this.upload()]);\n this.filesToSync.filesToDelete = filesToDelete\n .filter(file => { var _a; return ((_a = file.fileToSync) === null || _a === void 0 ? void 0 : _a.status) === 'error'; })\n .map(file => file.fileToSync);\n this.filesToSync.filesToUpload = filesToUpload\n .filter(file => { var _a; return ((_a = file.fileToSync) === null || _a === void 0 ? void 0 : _a.status) === 'error'; })\n .map(file => file.fileToSync);\n if (!this.hasValue()) {\n this.dataValue = [];\n }\n const data = filesToUpload\n .filter(file => { var _a; return ((_a = file.fileToSync) === null || _a === void 0 ? void 0 : _a.status) === 'success'; })\n .map(file => file.fileInfo);\n this.dataValue.push(...data);\n this.triggerChange();\n return Promise.resolve();\n }\n catch (err) {\n return Promise.reject();\n }\n finally {\n this.isSyncing = false;\n this.fileDropHidden = false;\n this.abortUploads = [];\n this.redraw();\n }\n });\n }\n getFile(fileInfo) {\n const { options = {} } = this.component;\n const { fileService } = this;\n if (!fileService) {\n return alert('File Service not provided');\n }\n if (this.component.privateDownload) {\n fileInfo.private = true;\n }\n fileService.downloadFile(fileInfo, options).then((file) => {\n if (file) {\n if (['base64', 'indexeddb'].includes(file.storage)) {\n (0, downloadjs_1.default)(file.url, file.originalName || file.name, file.type);\n }\n else {\n window.open(file.url, '_blank');\n }\n }\n })\n .catch((response) => {\n // Is alert the best way to do this?\n // User is expecting an immediate notification due to attempting to download a file.\n alert(response);\n });\n }\n focus() {\n if ('beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n if (this.refs.fileBrowse) {\n this.refs.fileBrowse.focus();\n }\n }\n beforeSubmit() {\n return __awaiter(this, void 0, void 0, function* () {\n try {\n if (!this.autoSync) {\n return Promise.resolve();\n }\n yield this.syncFiles();\n return this.shouldSyncFiles\n ? Promise.reject('Synchronization is failed')\n : Promise.resolve();\n }\n catch (error) {\n return Promise.reject(error.message);\n }\n });\n }\n destroy(all) {\n this.stopVideo();\n super.destroy(all);\n }\n}\nexports[\"default\"] = FileComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/file/File.js?");
|
|
5151
|
+
eval("\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst Field_1 = __importDefault(__webpack_require__(/*! ../_classes/field/Field */ \"./lib/cjs/components/_classes/field/Field.js\"));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst downloadjs_1 = __importDefault(__webpack_require__(/*! downloadjs */ \"./node_modules/downloadjs/download.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst fileProcessor_1 = __importDefault(__webpack_require__(/*! ../../providers/processor/fileProcessor */ \"./lib/cjs/providers/processor/fileProcessor.js\"));\nconst browser_md5_file_1 = __importDefault(__webpack_require__(/*! browser-md5-file */ \"./node_modules/browser-md5-file/dist/index.umd.js\"));\nlet Camera;\nlet webViewCamera = 'undefined' !== typeof window ? navigator.camera : Camera;\n// canvas.toBlob polyfill.\nlet htmlCanvasElement;\nif (typeof window !== 'undefined') {\n htmlCanvasElement = window.HTMLCanvasElement;\n}\nelse if (typeof __webpack_require__.g !== 'undefined') {\n htmlCanvasElement = __webpack_require__.g.HTMLCanvasElement;\n}\nif (htmlCanvasElement && !htmlCanvasElement.prototype.toBlob) {\n Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {\n value: function (callback, type, quality) {\n var canvas = this;\n setTimeout(function () {\n var binStr = atob(canvas.toDataURL(type, quality).split(',')[1]), len = binStr.length, arr = new Uint8Array(len);\n for (var i = 0; i < len; i++) {\n arr[i] = binStr.charCodeAt(i);\n }\n callback(new Blob([arr], { type: type || 'image/png' }));\n });\n }\n });\n}\nconst createRandomString = () => Math.random().toString(36).substring(2, 15);\nclass FileComponent extends Field_1.default {\n static schema(...extend) {\n return Field_1.default.schema({\n type: 'file',\n label: 'Upload',\n key: 'file',\n image: false,\n privateDownload: false,\n imageSize: '200',\n filePattern: '*',\n fileMinSize: '0KB',\n fileMaxSize: '1GB',\n uploadOnly: false,\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'File',\n group: 'premium',\n icon: 'file',\n documentation: '/userguide/form-building/premium-components#file',\n weight: 100,\n schema: FileComponent.schema(),\n };\n }\n static get serverConditionSettings() {\n return FileComponent.conditionOperatorsSettings;\n }\n static get conditionOperatorsSettings() {\n return Object.assign(Object.assign({}, super.conditionOperatorsSettings), { operators: ['isEmpty', 'isNotEmpty'] });\n }\n static savedValueTypes(schema) {\n schema = schema || {};\n return (0, utils_1.getComponentSavedTypes)(schema) || [utils_1.componentValueTypes.object];\n }\n init() {\n super.init();\n webViewCamera = navigator.camera || Camera;\n const fileReaderSupported = (typeof FileReader !== 'undefined');\n const formDataSupported = typeof window !== 'undefined' ? Boolean(window.FormData) : false;\n const progressSupported = (typeof window !== 'undefined' && window.XMLHttpRequest) ? ('upload' in new XMLHttpRequest) : false;\n this.support = {\n filereader: fileReaderSupported,\n formdata: formDataSupported,\n hasWarning: !fileReaderSupported || !formDataSupported || !progressSupported,\n progress: progressSupported,\n };\n this.cameraMode = false;\n this.fileDropHidden = false;\n this.filesToSync = {\n filesToUpload: [],\n filesToDelete: [],\n };\n this.isSyncing = false;\n this.abortUploads = [];\n }\n get dataReady() {\n return this.filesReady || Promise.resolve();\n }\n get defaultSchema() {\n return FileComponent.schema();\n }\n loadImage(fileInfo) {\n if (this.component.privateDownload) {\n fileInfo.private = true;\n }\n return this.fileService.downloadFile(fileInfo).then((result) => result.url);\n }\n get emptyValue() {\n return [];\n }\n getValueAsString(value, options) {\n if ((options === null || options === void 0 ? void 0 : options.review) && !this.component.uploadOnly) {\n return lodash_1.default.map(value, (val, index) => {\n return `<a href=\"${val.url || '#'}\" target=\"_blank\" data-path='${this.path}' data-fileindex='${index}'>${val.originalName}</a>`;\n }).join(', ');\n }\n if (lodash_1.default.isArray(value)) {\n return lodash_1.default.map(value, 'originalName').join(', ');\n }\n return lodash_1.default.get(value, 'originalName', '');\n }\n getValue() {\n return this.dataValue;\n }\n get defaultValue() {\n const value = super.defaultValue;\n return Array.isArray(value) ? value : [];\n }\n get hasTypes() {\n return this.component.fileTypes &&\n Array.isArray(this.component.fileTypes) &&\n this.component.fileTypes.length !== 0 &&\n (this.component.fileTypes[0].label !== '' || this.component.fileTypes[0].value !== '');\n }\n get fileDropHidden() {\n return this._fileBrowseHidden;\n }\n set fileDropHidden(value) {\n if (typeof value !== 'boolean' || this.component.multiple) {\n return;\n }\n this._fileBrowseHidden = value;\n }\n get shouldSyncFiles() {\n return Boolean(this.filesToSync.filesToDelete.length || this.filesToSync.filesToUpload.length);\n }\n get autoSync() {\n return lodash_1.default.get(this, 'component.autoSync', false);\n }\n get columnsSize() {\n const actionsColumn = this.disabled ? 0 : this.autoSync ? 2 : 1;\n const typeColumn = this.hasTypes ? 2 : 0;\n const sizeColumn = 2;\n const nameColumn = 12 - actionsColumn - typeColumn - sizeColumn;\n return {\n name: nameColumn,\n size: sizeColumn,\n type: typeColumn,\n actions: actionsColumn,\n };\n }\n render() {\n const { filesToDelete, filesToUpload } = this.filesToSync;\n return super.render(this.renderTemplate('file', {\n fileSize: this.fileSize,\n files: this.dataValue || [],\n filesToDelete,\n filesToUpload,\n disabled: this.disabled,\n support: this.support,\n fileDropHidden: this.fileDropHidden,\n showSyncButton: this.autoSync && (filesToDelete.length || filesToUpload.length),\n isSyncing: this.isSyncing,\n columns: this.columnsSize,\n }));\n }\n getVideoStream(constraints) {\n return navigator.mediaDevices.getUserMedia({\n video: Object.assign({ width: { min: 640, ideal: 1920 }, height: { min: 360, ideal: 1080 }, aspectRatio: { ideal: 16 / 9 } }, constraints),\n audio: false,\n });\n }\n stopVideoStream(videoStream) {\n videoStream.getVideoTracks().forEach((track) => track.stop());\n }\n getFrame(videoPlayer) {\n return new Promise((resolve) => {\n const canvas = document.createElement('canvas');\n canvas.height = videoPlayer.videoHeight;\n canvas.width = videoPlayer.videoWidth;\n const context = canvas.getContext('2d');\n context.drawImage(videoPlayer, 0, 0);\n canvas.toBlob(resolve);\n });\n }\n startVideo() {\n this.getVideoStream()\n .then((stream) => {\n this.videoStream = stream;\n const { videoPlayer } = this.refs;\n if (!videoPlayer) {\n console.warn('Video player not found in template.');\n this.cameraMode = false;\n this.redraw();\n return;\n }\n videoPlayer.srcObject = stream;\n const width = parseInt(this.component.webcamSize) || 320;\n videoPlayer.setAttribute('width', width);\n videoPlayer.play();\n })\n .catch((err) => {\n console.error(err);\n this.cameraMode = false;\n this.redraw();\n });\n }\n stopVideo() {\n if (this.videoStream) {\n this.stopVideoStream(this.videoStream);\n this.videoStream = null;\n }\n }\n takePicture() {\n const { videoPlayer } = this.refs;\n if (!videoPlayer) {\n console.warn('Video player not found in template.');\n this.cameraMode = false;\n this.redraw();\n return;\n }\n this.getFrame(videoPlayer)\n .then((frame) => {\n frame.name = `photo-${Date.now()}.png`;\n this.handleFilesToUpload([frame]);\n this.cameraMode = false;\n this.redraw();\n });\n }\n browseFiles(attrs = {}) {\n return new Promise((resolve) => {\n const fileInput = this.ce('input', Object.assign({ type: 'file', style: 'height: 0; width: 0; visibility: hidden;', tabindex: '-1' }, attrs));\n document.body.appendChild(fileInput);\n fileInput.addEventListener('change', () => {\n resolve(fileInput.files);\n document.body.removeChild(fileInput);\n }, true);\n // There is no direct way to trigger a file dialog. To work around this, create an input of type file and trigger\n // a click event on it.\n if (typeof fileInput.trigger === 'function') {\n fileInput.trigger('click');\n }\n else {\n fileInput.click();\n }\n });\n }\n set cameraMode(value) {\n this._cameraMode = value;\n if (value) {\n this.startVideo();\n }\n else {\n this.stopVideo();\n }\n }\n get cameraMode() {\n return this._cameraMode;\n }\n get useWebViewCamera() {\n return this.imageUpload && webViewCamera;\n }\n get imageUpload() {\n return Boolean(this.component.image);\n }\n get browseOptions() {\n const options = {};\n if (this.component.multiple) {\n options.multiple = true;\n }\n if (this.component.capture) {\n options.capture = this.component.capture;\n }\n //use \"accept\" attribute only for desktop devices because of its limited support by mobile browsers\n const filePattern = this.component.filePattern.trim() || '';\n if (!this.isMobile.any) {\n const imagesPattern = 'image/*';\n if (this.imageUpload && (!filePattern || filePattern === '*')) {\n options.accept = imagesPattern;\n }\n else if (this.imageUpload && !filePattern.includes(imagesPattern)) {\n options.accept = `${imagesPattern},${filePattern}`;\n }\n else {\n options.accept = filePattern;\n }\n }\n // if input capture is set, we need the \"accept\" attribute to determine which device to launch\n else if (this.component.capture) {\n if (filePattern.includes('video')) {\n options.accept = 'video/*';\n }\n else if (filePattern.includes('audio')) {\n options.accept = 'audio/*';\n }\n else {\n options.accept = 'image/*';\n }\n }\n return options;\n }\n get actions() {\n return {\n abort: this.abortRequest.bind(this),\n };\n }\n attach(element) {\n this.loadRefs(element, {\n fileDrop: 'single',\n fileBrowse: 'single',\n galleryButton: 'single',\n cameraButton: 'single',\n takePictureButton: 'single',\n toggleCameraMode: 'single',\n videoPlayer: 'single',\n fileLink: 'multiple',\n removeLink: 'multiple',\n fileToSyncRemove: 'multiple',\n fileImage: 'multiple',\n fileType: 'multiple',\n fileProcessingLoader: 'single',\n syncNow: 'single',\n restoreFile: 'multiple',\n progress: 'multiple',\n });\n // Ensure we have an empty input refs. We need this for the setValue method to redraw the control when it is set.\n this.refs.input = [];\n const superAttach = super.attach(element);\n if (this.refs.fileDrop) {\n // if (!this.statuses.length) {\n // this.refs.fileDrop.removeAttribute('hidden');\n // }\n const _this = this;\n this.addEventListener(this.refs.fileDrop, 'dragover', function (event) {\n this.className = 'fileSelector fileDragOver';\n event.preventDefault();\n });\n this.addEventListener(this.refs.fileDrop, 'dragleave', function (event) {\n this.className = 'fileSelector';\n event.preventDefault();\n });\n this.addEventListener(this.refs.fileDrop, 'drop', function (event) {\n this.className = 'fileSelector';\n event.preventDefault();\n _this.handleFilesToUpload(event.dataTransfer.files);\n });\n }\n this.addEventListener(element, 'click', (event) => {\n this.handleAction(event);\n });\n if (this.refs.fileBrowse) {\n this.addEventListener(this.refs.fileBrowse, 'click', (event) => {\n event.preventDefault();\n this.browseFiles(this.browseOptions)\n .then((files) => {\n this.handleFilesToUpload(files);\n });\n });\n }\n this.refs.fileLink.forEach((fileLink, index) => {\n this.addEventListener(fileLink, 'click', (event) => {\n event.preventDefault();\n this.getFile(this.dataValue[index]);\n });\n });\n this.refs.removeLink.forEach((removeLink, index) => {\n this.addEventListener(removeLink, 'click', (event) => {\n event.preventDefault();\n const fileInfo = this.dataValue[index];\n this.handleFileToRemove(fileInfo);\n });\n });\n this.refs.fileToSyncRemove.forEach((fileToSyncRemove, index) => {\n this.addEventListener(fileToSyncRemove, 'click', (event) => {\n event.preventDefault();\n this.filesToSync.filesToUpload.splice(index, 1);\n this.redraw();\n });\n });\n this.refs.restoreFile.forEach((fileToRestore, index) => {\n this.addEventListener(fileToRestore, 'click', (event) => {\n event.preventDefault();\n const fileInfo = this.filesToSync.filesToDelete[index];\n delete fileInfo.status;\n delete fileInfo.message;\n this.filesToSync.filesToDelete.splice(index, 1);\n this.dataValue.push(fileInfo);\n this.triggerChange();\n this.redraw();\n });\n });\n if (this.refs.galleryButton && webViewCamera) {\n this.addEventListener(this.refs.galleryButton, 'click', (event) => {\n event.preventDefault();\n webViewCamera.getPicture((success) => {\n window.resolveLocalFileSystemURL(success, (fileEntry) => {\n fileEntry.file((file) => {\n const reader = new FileReader();\n reader.onloadend = (evt) => {\n const blob = new Blob([new Uint8Array(evt.target.result)], { type: file.type });\n blob.name = file.name;\n this.handleFilesToUpload([blob]);\n };\n reader.readAsArrayBuffer(file);\n });\n });\n }, (err) => {\n console.error(err);\n }, {\n sourceType: webViewCamera.PictureSourceType.PHOTOLIBRARY,\n });\n });\n }\n if (this.refs.cameraButton && webViewCamera) {\n this.addEventListener(this.refs.cameraButton, 'click', (event) => {\n event.preventDefault();\n webViewCamera.getPicture((success) => {\n window.resolveLocalFileSystemURL(success, (fileEntry) => {\n fileEntry.file((file) => {\n const reader = new FileReader();\n reader.onloadend = (evt) => {\n const blob = new Blob([new Uint8Array(evt.target.result)], { type: file.type });\n blob.name = file.name;\n this.handleFilesToUpload([blob]);\n };\n reader.readAsArrayBuffer(file);\n });\n });\n }, (err) => {\n console.error(err);\n }, {\n sourceType: webViewCamera.PictureSourceType.CAMERA,\n encodingType: webViewCamera.EncodingType.PNG,\n mediaType: webViewCamera.MediaType.PICTURE,\n saveToPhotoAlbum: true,\n correctOrientation: false,\n });\n });\n }\n if (this.refs.takePictureButton) {\n this.addEventListener(this.refs.takePictureButton, 'click', (event) => {\n event.preventDefault();\n this.takePicture();\n });\n }\n if (this.refs.toggleCameraMode) {\n this.addEventListener(this.refs.toggleCameraMode, 'click', (event) => {\n event.preventDefault();\n this.cameraMode = !this.cameraMode;\n this.redraw();\n });\n }\n this.refs.fileType.forEach((fileType, index) => {\n if (!this.dataValue[index]) {\n return;\n }\n this.dataValue[index].fileType = this.dataValue[index].fileType || this.component.fileTypes[0].label;\n this.addEventListener(fileType, 'change', (event) => {\n event.preventDefault();\n const fileType = this.component.fileTypes.find((typeObj) => typeObj.value === event.target.value);\n this.dataValue[index].fileType = fileType.label;\n });\n });\n this.addEventListener(this.refs.syncNow, 'click', (event) => {\n event.preventDefault();\n this.syncFiles();\n });\n const fileService = this.fileService;\n if (fileService) {\n const loadingImages = [];\n this.filesReady = new Promise((resolve, reject) => {\n this.filesReadyResolve = resolve;\n this.filesReadyReject = reject;\n });\n this.refs.fileImage.forEach((image, index) => {\n loadingImages.push(this.loadImage(this.dataValue[index]).then((url) => (image.src = url)));\n });\n if (loadingImages.length) {\n Promise.all(loadingImages).then(() => {\n this.filesReadyResolve();\n }).catch(() => this.filesReadyReject());\n }\n else {\n this.filesReadyResolve();\n }\n }\n return superAttach;\n }\n /* eslint-disable max-len */\n fileSize(a, b, c, d, e) {\n return `${(b = Math, c = b.log, d = 1024, e = c(a) / c(d) | 0, a / b.pow(d, e)).toFixed(2)} ${e ? `${'kMGTPEZY'[--e]}B` : 'Bytes'}`;\n }\n /* eslint-enable max-len */\n /* eslint-disable max-depth */\n globStringToRegex(str) {\n str = str.replace(/\\s/g, '');\n let regexp = '', excludes = [];\n if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {\n regexp = str.substring(1, str.length - 1);\n }\n else {\n const split = str.split(',');\n if (split.length > 1) {\n for (let i = 0; i < split.length; i++) {\n const r = this.globStringToRegex(split[i]);\n if (r.regexp) {\n regexp += `(${r.regexp})`;\n if (i < split.length - 1) {\n regexp += '|';\n }\n }\n else {\n excludes = excludes.concat(r.excludes);\n }\n }\n }\n else {\n if (str.startsWith('!')) {\n excludes.push(`^((?!${this.globStringToRegex(str.substring(1)).regexp}).)*$`);\n }\n else {\n if (str.startsWith('.')) {\n str = `*${str}`;\n }\n regexp = `^${str.replace(new RegExp('[.\\\\\\\\+*?\\\\[\\\\^\\\\]$(){}=!<>|:\\\\-]', 'g'), '\\\\$&')}$`;\n regexp = regexp.replace(/\\\\\\*/g, '.*').replace(/\\\\\\?/g, '.');\n }\n }\n }\n return { regexp, excludes };\n }\n /* eslint-enable max-depth */\n translateScalars(str) {\n if (typeof str === 'string') {\n if (str.search(/kb/i) === str.length - 2) {\n return parseFloat(str.substring(0, str.length - 2) * 1024);\n }\n if (str.search(/mb/i) === str.length - 2) {\n return parseFloat(str.substring(0, str.length - 2) * 1024 * 1024);\n }\n if (str.search(/gb/i) === str.length - 2) {\n return parseFloat(str.substring(0, str.length - 2) * 1024 * 1024 * 1024);\n }\n if (str.search(/b/i) === str.length - 1) {\n return parseFloat(str.substring(0, str.length - 1));\n }\n if (str.search(/s/i) === str.length - 1) {\n return parseFloat(str.substring(0, str.length - 1));\n }\n if (str.search(/m/i) === str.length - 1) {\n return parseFloat(str.substring(0, str.length - 1) * 60);\n }\n if (str.search(/h/i) === str.length - 1) {\n return parseFloat(str.substring(0, str.length - 1) * 3600);\n }\n }\n return str;\n }\n validatePattern(file, val) {\n if (!val) {\n return true;\n }\n const pattern = this.globStringToRegex(val);\n let valid = true;\n if (pattern.regexp && pattern.regexp.length) {\n const regexp = new RegExp(pattern.regexp, 'i');\n valid = (!lodash_1.default.isNil(file.type) && regexp.test(file.type)) ||\n (!lodash_1.default.isNil(file.name) && regexp.test(file.name));\n }\n valid = pattern.excludes.reduce((result, excludePattern) => {\n const exclude = new RegExp(excludePattern, 'i');\n return result && (lodash_1.default.isNil(file.type) || exclude.test(file.type)) &&\n (lodash_1.default.isNil(file.name) || exclude.test(file.name));\n }, valid);\n return valid;\n }\n validateMinSize(file, val) {\n return file.size + 0.1 >= this.translateScalars(val);\n }\n validateMaxSize(file, val) {\n return file.size - 0.1 <= this.translateScalars(val);\n }\n abortRequest(id) {\n const abortUpload = this.abortUploads.find(abortUpload => abortUpload.id === id);\n if (abortUpload) {\n abortUpload.abort();\n }\n }\n handleAction(event) {\n const target = event.target;\n if (!target.id) {\n return;\n }\n const [action, id] = target.id.split('-');\n if (!action || !id || !this.actions[action]) {\n return;\n }\n this.actions[action](id);\n }\n getFileName(file) {\n return (0, utils_1.uniqueName)(file.name, this.component.fileNameTemplate, this.evalContext());\n }\n getInitFileToSync(file) {\n const escapedFileName = file.name ? file.name.replaceAll('<', '<').replaceAll('>', '>') : file.name;\n return {\n id: createRandomString(),\n // Get a unique name for this file to keep file collisions from occurring.\n dir: this.interpolate(this.component.dir || ''),\n name: this.getFileName(file),\n originalName: escapedFileName,\n fileKey: this.component.fileKey || 'file',\n storage: this.component.storage,\n options: this.component.options,\n file,\n size: file.size,\n status: 'info',\n message: this.t('Processing file. Please wait...'),\n hash: '',\n };\n }\n handleSubmissionRevisions(file) {\n return __awaiter(this, void 0, void 0, function* () {\n if (this.root.form.submissionRevisions !== 'true') {\n return '';\n }\n const bmf = new browser_md5_file_1.default();\n const hash = yield new Promise((resolve, reject) => {\n this.emit('fileUploadingStart');\n bmf.md5(file, (err, md5) => {\n if (err) {\n return reject(err);\n }\n return resolve(md5);\n });\n });\n this.emit('fileUploadingEnd');\n return hash;\n });\n }\n validateFileName(file) {\n // Check if file with the same name is being uploaded\n const fileWithSameNameUploading = this.filesToSync.filesToUpload\n .some(fileToSync => { var _a; return ((_a = fileToSync.file) === null || _a === void 0 ? void 0 : _a.name) === file.name; });\n const fileWithSameNameUploaded = lodash_1.default.some(this.dataValue, fileStatus => fileStatus.originalName === file.name);\n return fileWithSameNameUploaded || fileWithSameNameUploading\n ? {\n status: 'error',\n message: this.t(`File with the same name is already ${fileWithSameNameUploading ? 'being ' : ''}uploaded`),\n }\n : {};\n }\n validateFileSettings(file) {\n // Check file pattern\n if (this.component.filePattern && !this.validatePattern(file, this.component.filePattern)) {\n return {\n status: 'error',\n message: this.t('File is the wrong type; it must be {{ pattern }}', {\n pattern: this.component.filePattern,\n }),\n };\n }\n // Check file minimum size\n if (this.component.fileMinSize && !this.validateMinSize(file, this.component.fileMinSize)) {\n return {\n status: 'error',\n message: this.t('File is too small; it must be at least {{ size }}', {\n size: this.component.fileMinSize,\n }),\n };\n }\n // Check file maximum size\n if (this.component.fileMaxSize && !this.validateMaxSize(file, this.component.fileMaxSize)) {\n return {\n status: 'error',\n message: this.t('File is too big; it must be at most {{ size }}', {\n size: this.component.fileMaxSize,\n }),\n };\n }\n return {};\n }\n validateFileService() {\n const { fileService } = this;\n return !fileService\n ? {\n status: 'error',\n message: this.t('File Service not provided.'),\n }\n : {};\n }\n validateFile(file) {\n const fileServiceValidation = this.validateFileService();\n if (fileServiceValidation.status === 'error') {\n return fileServiceValidation;\n }\n const fileNameValidation = this.validateFileName(file);\n if (fileNameValidation.status === 'error') {\n return fileNameValidation;\n }\n return this.validateFileSettings(file);\n }\n getGroupPermissions() {\n let groupKey = null;\n let groupPermissions = null;\n //Iterate through form components to find group resource if one exists\n this.root.everyComponent((element) => {\n var _a, _b;\n if (((_a = element.component) === null || _a === void 0 ? void 0 : _a.submissionAccess) || ((_b = element.component) === null || _b === void 0 ? void 0 : _b.defaultPermission)) {\n groupPermissions = !element.component.submissionAccess ? [\n {\n type: element.component.defaultPermission,\n roles: [],\n },\n ] : element.component.submissionAccess;\n groupPermissions.forEach((permission) => {\n groupKey = ['admin', 'write', 'create'].includes(permission.type) ? element.component.key : null;\n });\n }\n });\n return { groupKey, groupPermissions };\n }\n triggerFileProcessor(file) {\n return __awaiter(this, void 0, void 0, function* () {\n let processedFile = null;\n if (this.root.options.fileProcessor) {\n try {\n if (this.refs.fileProcessingLoader) {\n this.refs.fileProcessingLoader.style.display = 'block';\n }\n const fileProcessorHandler = (0, fileProcessor_1.default)(this.fileService, this.root.options.fileProcessor);\n processedFile = yield fileProcessorHandler(file, this.component.properties);\n }\n catch (err) {\n this.fileDropHidden = false;\n return {\n status: 'error',\n message: this.t('File processing has been failed.'),\n };\n }\n finally {\n if (this.refs.fileProcessingLoader) {\n this.refs.fileProcessingLoader.style.display = 'none';\n }\n }\n }\n return {\n file: processedFile,\n };\n });\n }\n prepareFileToUpload(file) {\n return __awaiter(this, void 0, void 0, function* () {\n const fileToSync = this.getInitFileToSync(file);\n fileToSync.hash = yield this.handleSubmissionRevisions(file);\n const { status, message } = this.validateFile(file);\n if (status === 'error') {\n fileToSync.isValidationError = true;\n fileToSync.status = status;\n fileToSync.message = message;\n return this.filesToSync.filesToUpload.push(fileToSync);\n }\n if (this.component.privateDownload) {\n file.private = true;\n }\n const { groupKey, groupPermissions } = this.getGroupPermissions();\n const processedFile = yield this.triggerFileProcessor(file);\n if (processedFile.status === 'error') {\n fileToSync.status === 'error';\n fileToSync.message = processedFile.message;\n return this.filesToSync.filesToUpload.push(fileToSync);\n }\n if (this.autoSync) {\n fileToSync.message = this.t('Ready to be uploaded into storage');\n }\n this.filesToSync.filesToUpload.push(Object.assign(Object.assign({}, fileToSync), { message: fileToSync.message, file: processedFile.file || file, url: this.interpolate(this.component.url, { file: fileToSync }), groupPermissions, groupResourceId: groupKey ? this.currentForm.submission.data[groupKey]._id : null }));\n });\n }\n prepareFilesToUpload(files) {\n return __awaiter(this, void 0, void 0, function* () {\n // Only allow one upload if not multiple.\n if (!this.component.multiple) {\n files = Array.prototype.slice.call(files, 0, 1);\n }\n if (this.component.storage && files && files.length) {\n this.fileDropHidden = true;\n return Promise.all([...files].map((file) => __awaiter(this, void 0, void 0, function* () {\n yield this.prepareFileToUpload(file);\n this.redraw();\n })));\n }\n else {\n return Promise.resolve();\n }\n });\n }\n handleFilesToUpload(files) {\n return __awaiter(this, void 0, void 0, function* () {\n yield this.prepareFilesToUpload(files);\n if (!this.autoSync) {\n yield this.syncFiles();\n }\n });\n }\n prepareFileToDelete(fileInfo) {\n this.filesToSync.filesToDelete.push(Object.assign(Object.assign({}, fileInfo), { status: 'info', message: this.autoSync\n ? this.t('Ready to be removed from storage')\n : this.t('Preparing file to remove') }));\n const index = this.dataValue.findIndex(file => file.name === fileInfo.name);\n this.splice(index);\n this.redraw();\n }\n handleFileToRemove(fileInfo) {\n this.prepareFileToDelete(fileInfo);\n if (!this.autoSync) {\n this.syncFiles();\n }\n }\n deleteFile(fileInfo) {\n return __awaiter(this, void 0, void 0, function* () {\n const { options = {} } = this.component;\n if (fileInfo && (['url', 'indexeddb', 's3', 'azure', 'googledrive'].includes(this.component.storage))) {\n const { fileService } = this;\n if (fileService && typeof fileService.deleteFile === 'function') {\n return yield fileService.deleteFile(fileInfo, options);\n }\n else {\n const formio = this.options.formio || (this.root && this.root.formio);\n if (formio) {\n return yield formio.makeRequest('', fileInfo.url, 'delete');\n }\n }\n }\n });\n }\n delete() {\n return __awaiter(this, void 0, void 0, function* () {\n if (!this.filesToSync.filesToDelete.length) {\n return Promise.resolve();\n }\n return yield Promise.all(this.filesToSync.filesToDelete.map((fileToSync) => __awaiter(this, void 0, void 0, function* () {\n try {\n if (fileToSync.isValidationError) {\n return { fileToSync };\n }\n yield this.deleteFile(fileToSync);\n fileToSync.status = 'success';\n fileToSync.message = this.t('Succefully removed');\n }\n catch (response) {\n fileToSync.status = 'error';\n fileToSync.message = typeof response === 'string' ? response : response.toString();\n }\n finally {\n this.redraw();\n }\n return { fileToSync };\n })));\n });\n }\n updateProgress(fileInfo, progressEvent) {\n fileInfo.progress = parseInt(100.0 * progressEvent.loaded / progressEvent.total);\n if (fileInfo.status !== 'progress') {\n fileInfo.status = 'progress';\n delete fileInfo.message;\n this.redraw();\n }\n else {\n const progress = Array.prototype.find.call(this.refs.progress, progressElement => progressElement.id === fileInfo.id);\n progress.innerHTML = `<span class=\"visually-hidden\">${fileInfo.progress}% ${this.t('Complete')}</span>`;\n progress.style.width = `${fileInfo.progress}%`;\n progress.ariaValueNow = fileInfo.progress.toString();\n }\n }\n getMultipartOptions(fileToSync) {\n let count = 0;\n return this.component.useMultipartUpload && this.component.multipart ? Object.assign(Object.assign({}, this.component.multipart), { progressCallback: (total) => {\n count++;\n fileToSync.status = 'progress';\n fileToSync.progress = parseInt(100 * count / total);\n delete fileToSync.message;\n this.redraw();\n }, changeMessage: (message) => {\n fileToSync.message = message;\n this.redraw();\n } }) : false;\n }\n uploadFile(fileToSync) {\n return __awaiter(this, void 0, void 0, function* () {\n return yield this.fileService.uploadFile(fileToSync.storage, fileToSync.file, fileToSync.name, fileToSync.dir, \n // Progress callback\n this.updateProgress.bind(this, fileToSync), fileToSync.url, fileToSync.options, fileToSync.fileKey, fileToSync.groupPermissions, fileToSync.groupResourceId, () => { }, \n // Abort upload callback\n (abort) => this.abortUploads.push({\n id: fileToSync.id,\n abort,\n }), this.getMultipartOptions(fileToSync));\n });\n }\n upload() {\n return __awaiter(this, void 0, void 0, function* () {\n if (!this.filesToSync.filesToUpload.length) {\n return Promise.resolve();\n }\n return yield Promise.all(this.filesToSync.filesToUpload.map((fileToSync) => __awaiter(this, void 0, void 0, function* () {\n let fileInfo = null;\n try {\n if (fileToSync.isValidationError) {\n return {\n fileToSync,\n fileInfo,\n };\n }\n fileInfo = yield this.uploadFile(fileToSync);\n fileToSync.status = 'success';\n fileToSync.message = this.t('Succefully uploaded');\n fileInfo.originalName = fileToSync.originalName;\n fileInfo.hash = fileToSync.hash;\n }\n catch (response) {\n fileToSync.status = 'error';\n delete fileToSync.progress;\n fileToSync.message = typeof response === 'string'\n ? response\n : response.type === 'abort'\n ? this.t('Request was aborted')\n : response.toString();\n this.emit('fileUploadError', {\n fileToSync,\n response,\n });\n }\n finally {\n delete fileToSync.progress;\n this.redraw();\n }\n return {\n fileToSync,\n fileInfo,\n };\n })));\n });\n }\n syncFiles() {\n return __awaiter(this, void 0, void 0, function* () {\n this.isSyncing = true;\n this.fileDropHidden = true;\n this.redraw();\n try {\n const [filesToDelete = [], filesToUpload = []] = yield Promise.all([this.delete(), this.upload()]);\n this.filesToSync.filesToDelete = filesToDelete\n .filter(file => { var _a; return ((_a = file.fileToSync) === null || _a === void 0 ? void 0 : _a.status) === 'error'; })\n .map(file => file.fileToSync);\n this.filesToSync.filesToUpload = filesToUpload\n .filter(file => { var _a; return ((_a = file.fileToSync) === null || _a === void 0 ? void 0 : _a.status) === 'error'; })\n .map(file => file.fileToSync);\n if (!this.hasValue()) {\n this.dataValue = [];\n }\n const data = filesToUpload\n .filter(file => { var _a; return ((_a = file.fileToSync) === null || _a === void 0 ? void 0 : _a.status) === 'success'; })\n .map(file => file.fileInfo);\n this.dataValue.push(...data);\n this.triggerChange();\n return Promise.resolve();\n }\n catch (err) {\n return Promise.reject();\n }\n finally {\n this.isSyncing = false;\n this.fileDropHidden = false;\n this.abortUploads = [];\n this.redraw();\n }\n });\n }\n getFile(fileInfo) {\n const { options = {} } = this.component;\n const { fileService } = this;\n if (!fileService) {\n return alert('File Service not provided');\n }\n if (this.component.privateDownload) {\n fileInfo.private = true;\n }\n fileService.downloadFile(fileInfo, options).then((file) => {\n if (file) {\n if (['base64', 'indexeddb'].includes(file.storage)) {\n (0, downloadjs_1.default)(file.url, file.originalName || file.name, file.type);\n }\n else {\n window.open(file.url, '_blank');\n }\n }\n })\n .catch((response) => {\n // Is alert the best way to do this?\n // User is expecting an immediate notification due to attempting to download a file.\n alert(response);\n });\n }\n focus() {\n if ('beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n if (this.refs.fileBrowse) {\n this.refs.fileBrowse.focus();\n }\n }\n beforeSubmit() {\n return __awaiter(this, void 0, void 0, function* () {\n try {\n if (!this.autoSync) {\n return Promise.resolve();\n }\n yield this.syncFiles();\n return this.shouldSyncFiles\n ? Promise.reject('Synchronization is failed')\n : Promise.resolve();\n }\n catch (error) {\n return Promise.reject(error.message);\n }\n });\n }\n destroy(all) {\n this.stopVideo();\n super.destroy(all);\n }\n}\nexports[\"default\"] = FileComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/file/File.js?");
|
|
5152
5152
|
|
|
5153
5153
|
/***/ }),
|
|
5154
5154
|
|
|
@@ -5720,7 +5720,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5720
5720
|
/***/ (function(__unused_webpack_module, exports) {
|
|
5721
5721
|
|
|
5722
5722
|
"use strict";
|
|
5723
|
-
eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports[\"default\"] = {\n unsavedRowsError: 'Please save all rows before proceeding.',\n invalidRowsError: 'Please correct invalid rows before proceeding.',\n invalidRowError: 'Invalid row. Please correct it or delete.',\n invalidOption: '{{field}} is an invalid value.',\n invalidDay: '{{field}} is not a valid day.',\n alertMessageWithLabel: '{{label}}: {{message}}',\n alertMessage: '{{message}}',\n complete: 'Submission Complete',\n error: 'Please fix the following errors before submitting.',\n errorListHotkey: 'Press Ctrl + Alt + X to go back to the error list.',\n errorsListNavigationMessage: 'Click to navigate to the field with following error.',\n submitError: 'Please check the form and correct all errors before submitting.',\n required: '{{field}} is required',\n unique: '{{field}} must be unique',\n array: '{{field}} must be an array',\n array_nonempty: '{{field}} must be a non-empty array', // eslint-disable-line camelcase\n nonarray: '{{field}} must not be an array',\n select: '{{field}} contains an invalid selection',\n pattern: '{{field}} does not match the pattern {{pattern}}',\n minLength: '{{field}} must have at least {{length}} characters.',\n maxLength: '{{field}} must have no more than {{length}} characters.',\n minWords: '{{field}} must have at least {{length}} words.',\n maxWords: '{{field}} must have no more than {{length}} words.',\n min: '{{field}} cannot be less than {{min}}.',\n max: '{{field}} cannot be greater than {{max}}.',\n maxDate: '{{field}} should not contain date after {{- maxDate}}',\n minDate: '{{field}} should not contain date before {{- minDate}}',\n maxYear: '{{field}} should not contain year greater than {{maxYear}}',\n minYear: '{{field}} should not contain year less than {{minYear}}',\n minSelectedCount: 'You must select at least {{minCount}} items',\n maxSelectedCount: 'You may only select up to {{maxCount}} items',\n invalid_email: '{{field}} must be a valid email.', // eslint-disable-line camelcase\n invalid_url: '{{field}} must be a valid url.', // eslint-disable-line camelcase\n invalid_regex: '{{field}} does not match the pattern {{regex}}.', // eslint-disable-line camelcase\n invalid_date: '{{field}} is not a valid date.', // eslint-disable-line camelcase\n invalid_day: '{{field}} is not a valid day.', // eslint-disable-line camelcase\n invalidValueProperty: 'Invalid Value Property',\n mask: '{{field}} does not match the mask.',\n valueIsNotAvailable: '{{ field }} is an invalid value.',\n stripe: '{{stripe}}',\n month: 'Month',\n day: 'Day',\n year: 'Year',\n january: 'January',\n february: 'February',\n march: 'March',\n april: 'April',\n may: 'May',\n june: 'June',\n july: 'July',\n august: 'August',\n september: 'September',\n october: 'October',\n november: 'November',\n december: 'December',\n next: 'Next',\n previous: 'Previous',\n cancel: 'Cancel',\n submit: 'Submit Form',\n confirmCancel: 'Are you sure you want to cancel?',\n saveDraftInstanceError: 'Cannot save draft because there is no formio instance.',\n saveDraftAuthError: 'Cannot save draft unless a user is authenticated.',\n restoreDraftInstanceError: 'Cannot restore draft because there is no formio instance.',\n saveDraftError: 'Unable to save draft.',\n restoreDraftError: 'Unable to restore draft.',\n time: 'Invalid time',\n cancelButtonAriaLabel: 'Cancel button. Click to reset the form',\n previousButtonAriaLabel: 'Previous button. Click to go back to the previous tab',\n nextButtonAriaLabel: 'Next button. Click to go to the next tab',\n submitButtonAriaLabel: 'Submit Form button. Click to submit the form',\n reCaptchaTokenValidationError: 'ReCAPTCHA: Token validation error',\n reCaptchaTokenNotSpecifiedError: 'ReCAPTCHA: Token is not specified in submission',\n apiKey: 'API Key is not unique: {{key}}',\n typeRemaining: '{{ remaining }} {{ type }} remaining.',\n typeCount: '{{ count }} {{ type }}',\n requiredDayField: '{{ field }} is required',\n
|
|
5723
|
+
eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports[\"default\"] = {\n unsavedRowsError: 'Please save all rows before proceeding.',\n invalidRowsError: 'Please correct invalid rows before proceeding.',\n invalidRowError: 'Invalid row. Please correct it or delete.',\n invalidOption: '{{field}} is an invalid value.',\n invalidDay: '{{field}} is not a valid day.',\n alertMessageWithLabel: '{{label}}: {{message}}',\n alertMessage: '{{message}}',\n complete: 'Submission Complete',\n error: 'Please fix the following errors before submitting.',\n errorListHotkey: 'Press Ctrl + Alt + X to go back to the error list.',\n errorsListNavigationMessage: 'Click to navigate to the field with following error.',\n submitError: 'Please check the form and correct all errors before submitting.',\n required: '{{field}} is required',\n unique: '{{field}} must be unique',\n array: '{{field}} must be an array',\n array_nonempty: '{{field}} must be a non-empty array', // eslint-disable-line camelcase\n nonarray: '{{field}} must not be an array',\n select: '{{field}} contains an invalid selection',\n pattern: '{{field}} does not match the pattern {{pattern}}',\n minLength: '{{field}} must have at least {{length}} characters.',\n maxLength: '{{field}} must have no more than {{length}} characters.',\n minWords: '{{field}} must have at least {{length}} words.',\n maxWords: '{{field}} must have no more than {{length}} words.',\n min: '{{field}} cannot be less than {{min}}.',\n max: '{{field}} cannot be greater than {{max}}.',\n maxDate: '{{field}} should not contain date after {{- maxDate}}',\n minDate: '{{field}} should not contain date before {{- minDate}}',\n maxYear: '{{field}} should not contain year greater than {{maxYear}}',\n minYear: '{{field}} should not contain year less than {{minYear}}',\n minSelectedCount: 'You must select at least {{minCount}} items',\n maxSelectedCount: 'You may only select up to {{maxCount}} items',\n invalid_email: '{{field}} must be a valid email.', // eslint-disable-line camelcase\n invalid_url: '{{field}} must be a valid url.', // eslint-disable-line camelcase\n invalid_regex: '{{field}} does not match the pattern {{regex}}.', // eslint-disable-line camelcase\n invalid_date: '{{field}} is not a valid date.', // eslint-disable-line camelcase\n invalid_day: '{{field}} is not a valid day.', // eslint-disable-line camelcase\n invalidValueProperty: 'Invalid Value Property',\n mask: '{{field}} does not match the mask.',\n valueIsNotAvailable: '{{ field }} is an invalid value.',\n stripe: '{{stripe}}',\n month: 'Month',\n day: 'Day',\n year: 'Year',\n january: 'January',\n february: 'February',\n march: 'March',\n april: 'April',\n may: 'May',\n june: 'June',\n july: 'July',\n august: 'August',\n september: 'September',\n october: 'October',\n november: 'November',\n december: 'December',\n next: 'Next',\n previous: 'Previous',\n cancel: 'Cancel',\n submit: 'Submit Form',\n confirmCancel: 'Are you sure you want to cancel?',\n saveDraftInstanceError: 'Cannot save draft because there is no formio instance.',\n saveDraftAuthError: 'Cannot save draft unless a user is authenticated.',\n restoreDraftInstanceError: 'Cannot restore draft because there is no formio instance.',\n saveDraftError: 'Unable to save draft.',\n restoreDraftError: 'Unable to restore draft.',\n time: 'Invalid time',\n cancelButtonAriaLabel: 'Cancel button. Click to reset the form',\n previousButtonAriaLabel: 'Previous button. Click to go back to the previous tab',\n nextButtonAriaLabel: 'Next button. Click to go to the next tab',\n submitButtonAriaLabel: 'Submit Form button. Click to submit the form',\n reCaptchaTokenValidationError: 'ReCAPTCHA: Token validation error',\n reCaptchaTokenNotSpecifiedError: 'ReCAPTCHA: Token is not specified in submission',\n apiKey: 'API Key is not unique: {{key}}',\n typeRemaining: '{{ remaining }} {{ type }} remaining.',\n typeCount: '{{ count }} {{ type }}',\n requiredDayField: '{{ field }} is required',\n requiredMonthField: '{{ field }} is required',\n requiredYearField: '{{ field }} is required'\n};\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/translations/en.js?");
|
|
5724
5724
|
|
|
5725
5725
|
/***/ }),
|
|
5726
5726
|
|