UNPKG

@pinuts/bsr-uikit-relaunch

Version:

BSR UI-KIT Relaunch

280 lines (275 loc) 12.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _propTypes = _interopRequireDefault(require("prop-types")); var _react = _interopRequireWildcard(require("react")); var _reactDropzone = require("react-dropzone"); var _formBuilder = require("@pinuts/form-builder"); var _reactI18next = require("react-i18next"); var _FormFieldChildPropTypes = _interopRequireDefault(require("../FormFieldWrapper/FormFieldChildPropTypes.jsx")); var _FormFieldWrapper = _interopRequireDefault(require("../FormFieldWrapper/FormFieldWrapper.jsx")); var _withFieldGroup = _interopRequireDefault(require("../../hooks/withFieldGroup.jsx")); var _Icon = _interopRequireDefault(require("../Icon/Icon.jsx")); var _PictureUploadRowFieldModule = _interopRequireDefault(require("./PictureUploadRowField.module.scss")); var _acceptedUploadTypeMapping = require("./acceptedUploadTypeMapping.js"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } // form-builder const { useField, useFormikContext } = _formBuilder.formik; const { getClassNames } = _formBuilder.utils; //accept-prop needs an object mit mimeType as keys and an array of file extensions as values const getFormattedAcceptesFileTypes = acceptedFileTypes => acceptedFileTypes?.reduce((newObj, type) => _acceptedUploadTypeMapping.ACCEPTED_UPLOAD_TYPE_MAPPING?.[type] ? { ...newObj, [type]: _acceptedUploadTypeMapping.ACCEPTED_UPLOAD_TYPE_MAPPING[type] || [] } : newObj, {}); const PictureUploadRowField = _ref => { let { viewMode, field, ariaAttributes, isInvalid, readOnly, disabled, fieldIds, uploadConfig } = _ref; // eslint-disable-next-line no-unused-vars const [formikField, _meta, helpers] = useField(field.name); const [t] = (0, _reactI18next.useTranslation)(); const usedViewMode = (0, _react.useMemo)(() => readOnly || disabled || viewMode, [readOnly, disabled, viewMode]); const { status, setStatus } = useFormikContext(); const [previewFiles, setPreviewFiles] = (0, _react.useState)([]); // State to hold the files and previews (0, _react.useEffect)(() => { if (formikField.value && formikField.value.length > 0 && previewFiles.length === 0) { const initFiles = formikField.value.map(file => Object.assign(file, { preview: URL.createObjectURL(file) })); setPreviewFiles(initFiles); } }, [formikField.value, previewFiles.length]); const uploadFilesToUM = (0, _react.useCallback)(async uploadFiles => { const successfulUploads = []; for (const file of uploadFiles) { const formData = new FormData(); formData.append(file.name, file); if (uploadConfig) { formData.append('uploadConfig', JSON.stringify(uploadConfig)); } try { // eslint-disable-next-line no-await-in-loop const response = await fetch(uploadConfig.uploadPath, { method: 'POST', body: formData, headers: { 'X-CSRF-Safe': 'Yes' } }); if (response.ok) { // eslint-disable-next-line no-await-in-loop const data = await response.json(); if (data && data.success && data.files && data.files.length > 0) { successfulUploads.push(...data.files); } } } catch (error) { console.error('Upload error for file:', file.name, error); } } return successfulUploads; }, [uploadConfig]); const onChange = (0, _react.useCallback)(async acceptedFiles => { const uploadableFiles = [...previewFiles, ...acceptedFiles.map(file => Object.assign(file, { preview: URL.createObjectURL(file) }))]; const uploadedFiles = await uploadFilesToUM(uploadableFiles); if (uploadedFiles) { const filteredUploadableFiles = uploadableFiles.map(uploadableFile => { const found = uploadedFiles.find(uploadedFile => uploadedFile.name === uploadableFile.name); if (found) { const mergedObject = uploadableFile; mergedObject.uuid = found.uuid; return mergedObject; } return uploadableFile; }).filter(uploadableFile => { return uploadedFiles.some(uploadedFile => uploadedFile.name === uploadableFile.name); }); setPreviewFiles(filteredUploadableFiles); helpers.setTouched(true); helpers.setValue(filteredUploadableFiles); setStatus({ ...status, [formikField.name]: uploadedFiles }); } }, [previewFiles, formikField.name, helpers, setStatus, status, uploadFilesToUM]); const onDrop = (0, _react.useCallback)(acceptedFiles => { onChange(acceptedFiles); }, [onChange]); const { fileRejections, getRootProps, getInputProps } = (0, _reactDropzone.useDropzone)({ onDrop: !usedViewMode ? onDrop : () => {}, noClick: usedViewMode || previewFiles.length >= uploadConfig.maxFiles, // Disable click if view mode is used or maxFiles limit is reached noKeyboard: usedViewMode, accept: getFormattedAcceptesFileTypes(uploadConfig.acceptedFileTypes || []) || {}, maxFiles: uploadConfig.maxFiles, maxSize: uploadConfig.maxSize }); const removeFile = async (e, index, uuid) => { e.preventDefault(); e.stopPropagation(); try { const response = await fetch(`${uploadConfig.deletePath}/${uuid}`, { method: 'DELETE', headers: { 'X-CSRF-Safe': 'Yes' } }); if (response.ok) { const data = await response.json(); if (data && data.success) { setPreviewFiles(previewFiles.filter((file, i) => i !== index)); helpers.setTouched(true); if (status[formikField.name]) { setStatus({ ...status, [formikField.name]: null }); } else { helpers.setValue(''); } } } } catch (error) { console.error('Error removing file by uuid:', uuid, error); } }; const fileRejectionItems = fileRejections.map(_ref2 => { let { file, errors } = _ref2; return /*#__PURE__*/_react.default.createElement("li", { key: file.path, className: 'filename' }, file.name, ' ', "-", Math.floor(file.size / 1024), ' ', "kb", /*#__PURE__*/_react.default.createElement("ul", null, errors.map(e => /*#__PURE__*/_react.default.createElement("li", { key: e.code, className: 'errorMsg' }, t(`bsrItems.DropzoneUploadField.${e.code}`, { maxFiles: uploadConfig.maxFiles, maxFileSize: uploadConfig.maxSize / 1000000 }))))); }); const createThumbs = () => { if (viewMode && field.value.length > 0) { const uuids = field.value.map(file => file.uuid); return uuids.map(uuid => { return /*#__PURE__*/_react.default.createElement("div", { className: _PictureUploadRowFieldModule.default.thumb, key: uuid }, /*#__PURE__*/_react.default.createElement("div", { className: _PictureUploadRowFieldModule.default.thumbInner }, /*#__PURE__*/_react.default.createElement("img", { src: uploadConfig.previewPath.replace(':uuid', uuid), alt: '', className: _PictureUploadRowFieldModule.default.img }))); }); } return previewFiles.map((file, index) => { return /*#__PURE__*/_react.default.createElement("div", { className: _PictureUploadRowFieldModule.default.thumb, key: file.name }, /*#__PURE__*/_react.default.createElement("div", { className: _PictureUploadRowFieldModule.default.thumbInner }, /*#__PURE__*/_react.default.createElement("img", { src: file.preview, alt: '', className: _PictureUploadRowFieldModule.default.img, onLoad: () => { URL.revokeObjectURL(file.preview); } }), /*#__PURE__*/_react.default.createElement("button", { type: "button", "aria-label": 'Ausgewählte Datei entfernen', className: `${_PictureUploadRowFieldModule.default.deleteBtn}`, onClick: e => removeFile(e, index, file.uuid) }, /*#__PURE__*/_react.default.createElement(_Icon.default, { icon: "trash", height: "12", width: "12", stroke: '#fff' })))); }); }; // Cleanup previews on unmount (0, _react.useEffect)(() => { return () => previewFiles.forEach(file => URL.revokeObjectURL(file.preview)); }, [previewFiles]); return /*#__PURE__*/_react.default.createElement("section", { className: getClassNames(['container-fluid', _PictureUploadRowFieldModule.default.dropZoneWrapper, isInvalid && _PictureUploadRowFieldModule.default.isInvalid // usedViewMode && styles.disabled, ]), "aria-labelledby": fieldIds.label }, /*#__PURE__*/_react.default.createElement("div", { className: "d-flex justify-content-between" }, /*#__PURE__*/_react.default.createElement("div", getRootProps({ onDrop, className: getClassNames(['dropzone', 'flex-fill', _PictureUploadRowFieldModule.default.fakeButton]), role: 'button', 'aria-disabled': usedViewMode || previewFiles.length >= uploadConfig.maxFiles, // Reflect disabled state in ARIA attributes tabIndex: usedViewMode ? '-1' : '0', ...ariaAttributes, 'aria-controls': fieldIds.fieldId, 'aria-labelledby': '' }), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("input", _extends({}, getInputProps({ id: fieldIds.fieldId }), { accept: uploadConfig.acceptedFileTypes?.join(',') })), /*#__PURE__*/_react.default.createElement("aside", { className: `${_PictureUploadRowFieldModule.default.thumbsContainer} d-flex` }, createThumbs(), previewFiles.length < uploadConfig.maxFiles && /*#__PURE__*/_react.default.createElement("div", { className: _PictureUploadRowFieldModule.default.addBtnContainer }, /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_Icon.default, { icon: usedViewMode ? 'lock' : 'circlePlus', height: "24", width: "24", className: "" }))))))), /*#__PURE__*/_react.default.createElement("ul", null, fileRejectionItems)); }; PictureUploadRowField.propTypes = { ..._FormFieldChildPropTypes.default, acceptedFileTypes: _propTypes.default.arrayOf(_propTypes.default.string), localeRejected: _propTypes.default.string, onChange: _propTypes.default.func, key: _propTypes.default.string, maxFiles: _propTypes.default.number }; PictureUploadRowField.formFieldConfig = { labelIsLegend: true, isFieldset: true }; const HigherOrderDropzoneUploadField = (0, _withFieldGroup.default)(PictureUploadRowField); // wrap the field label, error message help text and more const WrappedPictureUploadRowField = props => { return /*#__PURE__*/_react.default.createElement(_FormFieldWrapper.default, props, /*#__PURE__*/_react.default.createElement(HigherOrderDropzoneUploadField, props)); }; (0, _formBuilder.registerComponent)('PictureUploadRowField', WrappedPictureUploadRowField); (0, _formBuilder.registerComponent)('PictureUploadRowFieldBasic', HigherOrderDropzoneUploadField); var _default = exports.default = HigherOrderDropzoneUploadField;