UNPKG

devextreme

Version:

JavaScript/TypeScript Component Suite for Responsive Web Development

386 lines (385 loc) • 16.9 kB
/** * DevExtreme (esm/__internal/ui/file_manager/ui.file_manager.file_uploader.js) * Version: 25.2.7 * Build date: Tue May 05 2026 * * Copyright (c) 2012 - 2026 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ import Guid from "../../../core/guid"; import $ from "../../../core/renderer"; import { Deferred } from "../../../core/utils/deferred"; import { getInnerHeight, setHeight, setWidth } from "../../../core/utils/size"; import { hasWindow } from "../../../core/utils/window"; import FileUploader from "../../../ui/file_uploader"; import Widget from "../../core/widget/widget"; import { whenSome } from "../../ui/file_manager/ui.file_manager.common"; const FILE_MANAGER_FILE_UPLOADER_CLASS = "dx-filemanager-fileuploader"; const FILE_MANAGER_FILE_UPLOADER_DROPZONE_PLACEHOLDER_CLASS = "dx-filemanager-fileuploader-dropzone-placeholder"; class FileManagerFileUploader extends Widget { _initMarkup() { this._initActions(); this.$element().addClass("dx-filemanager-fileuploader"); this._uploaderInfos = []; this._createInternalFileUploader(); this._createDropZonePlaceholder(); this._setDropZonePlaceholderVisible(false); super._initMarkup() } _createInternalFileUploader() { const { chunkSize: chunkSize } = this._getController(); const $fileUploader = $("<div>").appendTo(this.$element()); const fileUploader = this._createComponent($fileUploader, FileUploader, { name: "file", multiple: true, showFileList: false, activeStateEnabled: false, focusStateEnabled: false, hoverStateEnabled: false, labelText: "", readyToUploadMessage: "", accept: "*", chunkSize: chunkSize, dropZone: this.option("dropZone"), onValueChanged: e => this._onFileUploaderValueChanged(e), onProgress: e => this._onFileUploaderProgress(e), onUploaded: e => this._onFileUploaderUploaded(e), onFilesUploaded: e => this._onFileUploaderAllFilesUploaded(e), onUploadAborted: e => this._onFileUploaderUploadAborted(e), onUploadError: e => this._onFileUploaderUploadError(e), onDropZoneEnter: () => this._setDropZonePlaceholderVisible(true), onDropZoneLeave: () => this._setDropZonePlaceholderVisible(false) }); fileUploader.option({ uploadChunk: (file, chunksData) => this._fileUploaderUploadChunk(fileUploader, file, chunksData), abortUpload: (file, chunksData) => this._fileUploaderAbortUpload(fileUploader, file, chunksData) }); fileUploader._shouldRaiseDragLeaveBase = fileUploader._shouldRaiseDragLeave; fileUploader._shouldRaiseDragLeave = e => this._shouldRaiseDragLeave(e, fileUploader); const uploaderInfo = { fileUploader: fileUploader }; this._uploaderInfos.push(uploaderInfo) } tryUpload() { const info = this._findAndUpdateAvailableUploaderInfo(); if (info) { info.fileUploader._selectFileDialogClickHandler() } } cancelUpload(sessionId) { this._cancelUpload(sessionId) } cancelFileUpload(sessionId, fileIndex) { this._cancelUpload(sessionId, fileIndex) } _cancelUpload(sessionId, fileIndex) { const { fileUploader: fileUploader } = this._findUploaderInfoBySessionId(sessionId); fileUploader.abortUpload(fileIndex) } _fileUploaderUploadChunk(fileUploader, file, chunksInfo) { const { session: session, fileIndex: fileIndex } = this._findSessionByFile(fileUploader, file); const { controller: controller } = session; chunksInfo.fileIndex = fileIndex; return controller.uploadFileChunk(file, chunksInfo) } _fileUploaderAbortUpload(fileUploader, file, chunksInfo) { const { session: session, fileIndex: fileIndex } = this._findSessionByFile(fileUploader, file); const { controller: controller } = session; chunksInfo.fileIndex = fileIndex; return controller.abortFileUpload(file, chunksInfo) } _onFileUploaderValueChanged(_ref) { let { component: component, value: value } = _ref; if (0 === value.length) { return } const files = value.slice(); const uploaderInfo = this._findUploaderInfo(component); this._uploadFiles(uploaderInfo, files); setTimeout(() => { if (!this._findAndUpdateAvailableUploaderInfo()) { this._createInternalFileUploader() } }) } _onFileUploaderProgress(_ref2) { let { component: component, file: file, bytesLoaded: bytesLoaded, bytesTotal: bytesTotal } = _ref2; const { session: session, fileIndex: fileIndex } = this._findSessionByFile(component, file); const fileValue = 0 !== bytesTotal ? bytesLoaded / bytesTotal : 1; const commonValue = component.option("progress") / 100; const args = { sessionId: session.id, fileIndex: fileIndex, commonValue: commonValue, fileValue: fileValue }; this._raiseUploadProgress(args) } _onFileUploaderAllFilesUploaded(_ref3) { let { component: component } = _ref3; const { session: session } = this._findSessionByFile(component, component._files[0].value); this._raiseUploadFinished({ sessionId: session.id, commonValue: component.option("progress") / 100 }) } _onFileUploaderUploaded(_ref4) { let { component: component, file: file } = _ref4; const deferred = this._getDeferredForFile(component, file); deferred.resolve() } _onFileUploaderUploadAborted(_ref5) { let { component: component, file: file } = _ref5; const deferred = this._getDeferredForFile(component, file); deferred.resolve({ canceled: true }) } _onFileUploaderUploadError(_ref6) { let { component: component, file: file, error: error } = _ref6; const deferred = this._getDeferredForFile(component, file); deferred.reject(error) } _createDropZonePlaceholder() { const { dropZonePlaceholderContainer: dropZonePlaceholderContainer } = this.option(); this._$dropZonePlaceholder = $("<div>").addClass("dx-filemanager-fileuploader-dropzone-placeholder").appendTo($(dropZonePlaceholderContainer)) } _adjustDropZonePlaceholder() { var _this$_$dropZonePlace, _this$_$dropZonePlace2, _this$_$dropZonePlace3; const { dropZone: dropZone } = this.option(); const $dropZoneTarget = dropZone; if (!hasWindow() || 0 === (null === $dropZoneTarget || void 0 === $dropZoneTarget ? void 0 : $dropZoneTarget.length)) { return } const placeholderBorderTopWidth = parseFloat((null === (_this$_$dropZonePlace = this._$dropZonePlaceholder) || void 0 === _this$_$dropZonePlace ? void 0 : _this$_$dropZonePlace.css("borderTopWidth")) ?? ""); const placeholderBorderLeftWidth = parseFloat((null === (_this$_$dropZonePlace2 = this._$dropZonePlaceholder) || void 0 === _this$_$dropZonePlace2 ? void 0 : _this$_$dropZonePlace2.css("borderLeftWidth")) ?? ""); const { dropZonePlaceholderContainer: dropZonePlaceholderContainer } = this.option(); const $placeholderContainer = dropZonePlaceholderContainer; const containerBorderBottomWidth = parseFloat((null === $placeholderContainer || void 0 === $placeholderContainer ? void 0 : $placeholderContainer.css("borderBottomWidth")) ?? ""); const containerBorderLeftWidth = parseFloat((null === $placeholderContainer || void 0 === $placeholderContainer ? void 0 : $placeholderContainer.css("borderLeftWidth")) ?? ""); const containerHeight = getInnerHeight($placeholderContainer); const containerOffset = null === $placeholderContainer || void 0 === $placeholderContainer ? void 0 : $placeholderContainer.offset(); const dropZoneOffset = null === $dropZoneTarget || void 0 === $dropZoneTarget ? void 0 : $dropZoneTarget.offset(); null === (_this$_$dropZonePlace3 = this._$dropZonePlaceholder) || void 0 === _this$_$dropZonePlace3 || _this$_$dropZonePlace3.css({ top: (null === dropZoneOffset || void 0 === dropZoneOffset ? void 0 : dropZoneOffset.top) - (null === containerOffset || void 0 === containerOffset ? void 0 : containerOffset.top) - containerHeight - containerBorderBottomWidth, left: (null === dropZoneOffset || void 0 === dropZoneOffset ? void 0 : dropZoneOffset.left) - (null === containerOffset || void 0 === containerOffset ? void 0 : containerOffset.left) - containerBorderLeftWidth }); setHeight(this._$dropZonePlaceholder, (null === $dropZoneTarget || void 0 === $dropZoneTarget ? void 0 : $dropZoneTarget.get(0).offsetHeight) - 2 * placeholderBorderTopWidth); setWidth(this._$dropZonePlaceholder, (null === $dropZoneTarget || void 0 === $dropZoneTarget ? void 0 : $dropZoneTarget.get(0).offsetWidth) - 2 * placeholderBorderLeftWidth) } _setDropZonePlaceholderVisible(visible) { if (visible) { var _this$_$dropZonePlace4; this._adjustDropZonePlaceholder(); null === (_this$_$dropZonePlace4 = this._$dropZonePlaceholder) || void 0 === _this$_$dropZonePlace4 || _this$_$dropZonePlace4.css("display", "") } else { var _this$_$dropZonePlace5; null === (_this$_$dropZonePlace5 = this._$dropZonePlaceholder) || void 0 === _this$_$dropZonePlace5 || _this$_$dropZonePlace5.css("display", "none") } } _shouldRaiseDragLeave(e, uploaderInstance) { return uploaderInstance.isMouseOverElement(e, this.option("splitterElement")) || uploaderInstance._shouldRaiseDragLeaveBase(e, true) } _uploadFiles(uploaderInfo, files) { this._setDropZonePlaceholderVisible(false); const sessionId = (new Guid).toString(); const controller = this._getController(); const deferreds = files.map(() => new Deferred); uploaderInfo.session = { id: sessionId, controller: controller, files: files, deferreds: deferreds }; const sessionInfo = { sessionId: sessionId, deferreds: deferreds, files: files }; this._raiseUploadSessionStarted(sessionInfo); return whenSome(deferreds).always(() => setTimeout(() => { uploaderInfo.fileUploader.clear(); uploaderInfo.session = null })) } _getDeferredForFile(fileUploader, file) { const { session: session, fileIndex: fileIndex } = this._findSessionByFile(fileUploader, file); return session.deferreds[fileIndex] } _findSessionByFile(fileUploader, file) { const uploaderInfo = this._findUploaderInfo(fileUploader); const { session: session } = uploaderInfo; const fileIndex = session.files.indexOf(file); return { session: session, fileIndex: fileIndex } } _findUploaderInfoBySessionId(sessionId) { for (let i = 0; i < (null === (_this$_uploaderInfos = this._uploaderInfos) || void 0 === _this$_uploaderInfos ? void 0 : _this$_uploaderInfos.length); i += 1) { var _this$_uploaderInfos; const uploaderInfo = this._uploaderInfos[i]; const { session: session } = uploaderInfo; if (session && session.id === sessionId) { return uploaderInfo } } return null } _findAndUpdateAvailableUploaderInfo() { var _info; let info = null; for (let i = 0; i < (null === (_this$_uploaderInfos2 = this._uploaderInfos) || void 0 === _this$_uploaderInfos2 ? void 0 : _this$_uploaderInfos2.length); i += 1) { var _this$_uploaderInfos2; const currentInfo = this._uploaderInfos[i]; currentInfo.fileUploader.option("dropZone", ""); if (!info && !currentInfo.session) { info = currentInfo } } const { dropZone: dropZone } = this.option(); null === (_info = info) || void 0 === _info || _info.fileUploader.option("dropZone", dropZone); return info } _findUploaderInfo(fileUploader) { for (let i = 0; i < (null === (_this$_uploaderInfos3 = this._uploaderInfos) || void 0 === _this$_uploaderInfos3 ? void 0 : _this$_uploaderInfos3.length); i += 1) { var _this$_uploaderInfos3; const info = this._uploaderInfos[i]; if (info.fileUploader === fileUploader) { return info } } return null } _getController() { const { getController: controllerGetter } = this.option(); return null === controllerGetter || void 0 === controllerGetter ? void 0 : controllerGetter() } _raiseUploadSessionStarted(sessionInfo) { var _this$_actions$onUplo, _this$_actions; null === (_this$_actions$onUplo = (_this$_actions = this._actions).onUploadSessionStarted) || void 0 === _this$_actions$onUplo || _this$_actions$onUplo.call(_this$_actions, { sessionInfo: sessionInfo }) } _raiseUploadProgress(args) { var _this$_actions$onUplo2, _this$_actions2; null === (_this$_actions$onUplo2 = (_this$_actions2 = this._actions).onUploadProgress) || void 0 === _this$_actions$onUplo2 || _this$_actions$onUplo2.call(_this$_actions2, args) } _raiseUploadFinished(args) { var _this$_actions$onUplo3, _this$_actions3; null === (_this$_actions$onUplo3 = (_this$_actions3 = this._actions).onUploadFinished) || void 0 === _this$_actions$onUplo3 || _this$_actions$onUplo3.call(_this$_actions3, args) } _initActions() { this._actions = { onUploadSessionStarted: this._createActionByOption("onUploadSessionStarted"), onUploadProgress: this._createActionByOption("onUploadProgress"), onUploadFinished: this._createActionByOption("onUploadFinished") } } _getDefaultOptions() { return Object.assign({}, super._getDefaultOptions(), { getController: void 0, onUploadSessionStarted: void 0, onUploadProgress: void 0, onUploadFinished: void 0, splitterElement: void 0 }) } _optionChanged(args) { var _this$_$dropZonePlace6, _this$_$dropZonePlace7; const { name: name, value: value } = args; switch (name) { case "getController": this.repaint(); break; case "onUploadSessionStarted": case "onUploadProgress": case "onUploadFinished": this._actions[name] = this._createActionByOption(name); break; case "dropZone": this._findAndUpdateAvailableUploaderInfo(); this._adjustDropZonePlaceholder(); break; case "dropZonePlaceholderContainer": null === (_this$_$dropZonePlace6 = this._$dropZonePlaceholder) || void 0 === _this$_$dropZonePlace6 || _this$_$dropZonePlace6.detach(); null === (_this$_$dropZonePlace7 = this._$dropZonePlaceholder) || void 0 === _this$_$dropZonePlace7 || _this$_$dropZonePlace7.appendTo(value); break; case "splitterElement": break; default: super._optionChanged(args) } } } export default FileManagerFileUploader;