From 943b84ff9a1b76bedf9c2c5434c55985a5debc1f Mon Sep 17 00:00:00 2001 From: hcphat Date: Fri, 3 Oct 2025 17:53:36 +0700 Subject: [PATCH 1/4] =?UTF-8?q?ref=202.1.=E5=B0=8F=E8=A6=8F=E6=A8=A1?= =?UTF-8?q?=E5=A4=A7=E9=87=8F=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E3=82=92?= =?UTF-8?q?=E5=90=AB=E3=82=80=E3=83=95=E3=82=A9=E3=83=AB=E3=83=80=E3=82=A2?= =?UTF-8?q?=E3=83=83=E3=83=97=E3=83=AD=E3=83=BC=E3=83=89=E6=80=A7=E8=83=BD?= =?UTF-8?q?=E6=94=B9=E5=96=84=E3=81=AB=E3=81=8B=E3=81=8B=E3=82=8B=E9=96=8B?= =?UTF-8?q?=E7=99=BA:=20Commit=20code=20improve=20upload=20multiple=20smal?= =?UTF-8?q?l=20files?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- website/static/js/fangorn.js | 249 ++++++++++++++++-- .../en/LC_MESSAGES/js_messages.po | 3 + .../ja/LC_MESSAGES/js_messages.po | 3 + website/translations/js_messages.pot | 3 + 4 files changed, 235 insertions(+), 23 deletions(-) diff --git a/website/static/js/fangorn.js b/website/static/js/fangorn.js index f0141258731..9423ca207f1 100644 --- a/website/static/js/fangorn.js +++ b/website/static/js/fangorn.js @@ -97,6 +97,108 @@ var COMMAND_KEYS = [224, 17, 91, 93]; var ESCAPE_KEY = 27; var ENTER_KEY = 13; +var PROVIDER_SETTINGS = new Map([ + // ['providerName', { parallelNum: , fileSizeThreshold: }] + // Bulk mount institution storage settings + ['osfstorage', { parallelNum: 4, fileSizeThreshold: 128000000 }], // 128 MB + + // Addon institution storage settings) + ['onedrivebusiness', { parallelNum: 4, fileSizeThreshold: 128000000 }], + ['nextcloudinstitutions', { parallelNum: 4, fileSizeThreshold: 128000000 }], + ['s3compatinstitutions', { parallelNum: 4, fileSizeThreshold: 128000000 }], + ['dropboxbusiness', { parallelNum: 4, fileSizeThreshold: 128000000 }], + + // Extend storage settings + ['s3', { parallelNum: 4, fileSizeThreshold: 128000000 }], + ['s3compat', { parallelNum: 4, fileSizeThreshold: 128000000 }], + ['box', { parallelNum: 4, fileSizeThreshold: 128000000 }], + ['googledrive', { parallelNum: 4, fileSizeThreshold: 128000000 }], + ['nextcloud', { parallelNum: 4, fileSizeThreshold: 128000000 }], + ['onedrive', { parallelNum: 4, fileSizeThreshold: 128000000 }], + ['dropbox', { parallelNum: 4, fileSizeThreshold: 128000000 }], + ['s3compatb3', { parallelNum: 4, fileSizeThreshold: 128000000 }], +]); + +// Monkey-patch Dropzone.processQueue here (must run before any Dropzone instances are created) +(function() { + if (typeof Dropzone === 'undefined' || !Dropzone.prototype) { + return; + } + var _origProcessQueue = Dropzone.prototype.processQueue; + + Dropzone.prototype.processQueue = function() { + var parallelUploads = this.options.parallelUploads; + var processingLength = this.getUploadingFiles().length; + // Start processing from the current number of uploading files + var uploadIndex = processingLength; + if (processingLength >= parallelUploads) { + return; + } + var queuedFiles = this.getQueuedFiles(); + if (!(queuedFiles.length > 0)) { + return; + } + + var threshold = this.options.fileSizeThreshold || this.options.largeFileSize || this.options.largeFileThreshold; + // If a large file is already uploading, do not start new uploads + if (threshold) { + var uploading = this.getUploadingFiles(); + for (var j = 0; j < uploading.length; j++) { + var uploadingFile = uploading[j]; + var fsize = (typeof uploadingFile.size === 'number') ? uploadingFile.size : (uploadingFile.upload && uploadingFile.upload.total ? uploadingFile.upload.total : 0); + if (fsize > threshold) { + return; + } + } + } + + if (this.options.uploadMultiple) { + // reuse original behavior but limit to available slots + return _origProcessQueue.apply(this, arguments); + } else { + var self = this; + while (uploadIndex < parallelUploads) { + if (!queuedFiles.length) { + return; + } + var next = queuedFiles[0]; + var nextSize = (typeof next.size === 'number') ? next.size : (next.upload && next.upload.total ? next.upload.total : 0); + // start the next file + this.processFile(queuedFiles.shift()); + + // If the started file is "large", attach a one-time resume when it completes, + // then stop starting further parallel uploads until resume. + if (threshold && nextSize > threshold) { + var onComplete = function(file) { + if (file !== next) return; + // detach listener (support once()/off() APIs) + try { + if (self.off) { self.off('complete', onComplete); } + } catch (e) {} + // slight delay to allow Dropzone internal state update, then resume + setTimeout(function() { + if (self.options.autoProcessQueue) { + self.processQueue(); + } + }, 0); + }; + if (this.once) { + this.once('complete', onComplete); + } else { + this.on('complete', onComplete); + } + return; + } + uploadIndex++; + } + } + }; +})(); + +function getProviderSettings(provider) { + return PROVIDER_SETTINGS.get(provider) || null; +} + function findByTempID(parent, tmpID) { var child; var item; @@ -941,6 +1043,51 @@ function _fangornDragOver(treebeard, event) { function _fangornDropzoneDrop(treebeard, event) { var dropzoneHoverClass = 'fangorn-dz-hover'; treebeard.select('.tb-row').removeClass(dropzoneHoverClass); + var files = event.dataTransfer.files; + var totalFilesSize = 0; + for (var i = 0; i < files.length; i++) { + totalFilesSize += files[i].size; + } + + var item = treebeard.dropzoneItemCache; + var provider = "unknown" + if (item && item.data) { + provider = item.data.provider; + } + + // check upload quota for upload folder + if (provider === 'osfstorage' || provider === 's3compatinstitutions') { + // call api get used quota and max quota + var quota = $.ajax({ + async: false, + method: 'GET', + url: item.data.nodeApiUrl + 'get_creator_quota/', + }); + + if (!quota.responseJSON) { + $osf.growl('Error', sprintf(gettext('Cannot get quota information.'), + formatProperUnit(totalFilesSize)), + 'danger', 5000); + treebeard.dropzone.options.limitQuota = true; + return; + } + + quota = quota.responseJSON; + if (parseFloat(quota.used) + parseFloat(totalFilesSize) > quota.max) { + $osf.growl('Error', sprintf(gettext('Not enough quota to upload. The total size of all files is %1$s.'), + formatProperUnit(totalFilesSize)), + 'danger', 5000); + treebeard.dropzone.options.limitQuota = true; + return; + } + } + // Set Dropzone settings for upload multiple file + var providerSettings = getProviderSettings(treebeard.dropzoneItemCache.data.provider); + if (providerSettings && providerSettings.parallelNum && providerSettings.fileSizeThreshold) { + treebeard.dropzone.options.parallelUploads = providerSettings.parallelNum; + treebeard.dropzone.options.fileSizeThreshold = providerSettings.fileSizeThreshold; + treebeard.dropzone.options.limitQuota = false; + } } /** * Runs when Dropzone's complete hook is run after upload is completed. @@ -1112,6 +1259,27 @@ function _fangornDropzoneError(treebeard, file, message, xhr) { */ function _uploadEvent(event, item, col) { var self = this; // jshint ignore:line + // clear cache of input before upload new folder + if (self.dropzone.hiddenFileInput) { + document.body.removeChild(self.dropzone.hiddenFileInput); + } + + self.dropzone.hiddenFileInput = document.createElement('input'); + self.dropzone.hiddenFileInput.setAttribute('type', 'file'); + if (self.dropzone.options.maxFiles == null || self.dropzone.options.maxFiles > 1) { + self.dropzone.hiddenFileInput.setAttribute('multiple', 'multiple'); + } + if (self.dropzone.options.acceptedFiles != null) { + self.dropzone.hiddenFileInput.setAttribute('accept', self.dropzone.options.acceptedFiles); + } + self.dropzone.hiddenFileInput.style.visibility = 'hidden'; + self.dropzone.hiddenFileInput.style.position = 'absolute'; + self.dropzone.hiddenFileInput.style.top = '0'; + self.dropzone.hiddenFileInput.style.left = '0'; + self.dropzone.hiddenFileInput.style.height = '0'; + self.dropzone.hiddenFileInput.style.width = '0'; + document.body.appendChild(self.dropzone.hiddenFileInput); + try { event.stopPropagation(); } catch (e) { @@ -1128,6 +1296,50 @@ function _uploadEvent(event, item, col) { function _onchange() { var files = self.dropzone.hiddenFileInput.files || []; + var totalFilesSize = 0; + for (var i = 0; i < files.length; i++) { + totalFilesSize += files[i].size; + } + + var provider = "unknown" + if (item && item.data) { + provider = item.data.provider; + } + + // check upload quota for upload folder + if (provider === 'osfstorage' || provider === 's3compatinstitutions') { + // call api get used quota and max quota + var quota = $.ajax({ + async: false, + method: 'GET', + url: item.data.nodeApiUrl + 'get_creator_quota/', + }); + + if (!quota.responseJSON) { + self.dropzone.options.limitQuota = true; + return; + } + + quota = quota.responseJSON; + + if (parseFloat(quota.used) + parseFloat(totalFilesSize) > quota.max) { + $osf.growl('Error', sprintf(gettext('Not enough quota to upload. The total size of all files is %1$s.'), + formatProperUnit(totalFilesSize)), + 'danger', 5000); + self.uploadStates = []; + return; + } + } + // Set Dropzone settings for upload multiple file + var providerSettings = getProviderSettings(provider); + if (providerSettings && providerSettings.parallelNum && providerSettings.fileSizeThreshold) { + self.dropzone.options.parallelUploads = providerSettings.parallelNum; + self.dropzone.options.fileSizeThreshold = providerSettings.fileSizeThreshold; + }else{ + // Default settings + self.dropzone.options.parallelUploads = 1; + } + self.dropzone.options.limitQuota = false; // Add files to Treebeard for (var i = 0; i < files.length; i++) { @@ -1227,6 +1439,14 @@ function _uploadFolderEvent(event, item, mode, col) { return; } } + // Set Dropzone settings for upload folder\ + var providerSettings = getProviderSettings(item.data.provider); + if (providerSettings && providerSettings.parallelNum && providerSettings.fileSizeThreshold) { + tb.dropzone.options.parallelUploads = providerSettings.parallelNum; + tb.dropzone.options.fileSizeThreshold = providerSettings.fileSizeThreshold; + }else{ + tb.dropzone.options.parallelUploads = 1; + } var createdFolders = []; // Start @@ -3929,6 +4149,12 @@ tbOptions = { var msgText; var quota; if (_fangornCanDrop(treebeard, item)) { + var limitQuota = treebeard.dropzone.options.limitQuota || false; + if (limitQuota) { + addFileStatus(treebeard, file, false, msgText, ''); + removeFromUI(file, treebeard); + return false; + } if (item.data.accept && item.data.accept.maxSize) { size = file.size / 1000000; maxSize = item.data.accept.maxSize; @@ -3942,29 +4168,6 @@ tbOptions = { return false; } } - if ((item.data.provider === 'osfstorage' || item.data.provider === 's3compatinstitutions') && !isInUploadFolderProcess) { - quota = $.ajax({ - async: false, - method: 'GET', - url: item.data.nodeApiUrl + 'get_creator_quota/' - }); - if (quota.responseJSON) { - quota = quota.responseJSON; - if (quota.used + file.size > quota.max) { - msgText = gettext('Not enough quota to upload the file.'); - item.notify.update(msgText, 'warning', undefined, 3000); - addFileStatus(treebeard, file, false, msgText, ''); - return false; - } - if (quota.used + file.size > quota.max * window.contextVars.threshold) { - $osf.growl( - gettext('Quota usage alert'), - sprintf(gettext('You have used more than %1$s%% of your quota.'),(window.contextVars.threshold * 100)), - 'warning' - ); - } - } - } return true; } return false; diff --git a/website/translations/en/LC_MESSAGES/js_messages.po b/website/translations/en/LC_MESSAGES/js_messages.po index a1bff9090cb..77f11f0330b 100644 --- a/website/translations/en/LC_MESSAGES/js_messages.po +++ b/website/translations/en/LC_MESSAGES/js_messages.po @@ -9270,3 +9270,6 @@ msgstr "" msgid "The Integrated Admin added ${contributors} as contributor(s) to ${node}" msgstr "" + +msgid "Not enough quota to upload. The total size of all files is %1$s." +msgstr "" diff --git a/website/translations/ja/LC_MESSAGES/js_messages.po b/website/translations/ja/LC_MESSAGES/js_messages.po index 39bcc9e353d..55d9c940df8 100644 --- a/website/translations/ja/LC_MESSAGES/js_messages.po +++ b/website/translations/ja/LC_MESSAGES/js_messages.po @@ -10557,3 +10557,6 @@ msgstr "作成したプロジェクト数が作成可能なプロジェクトの msgid "The Integrated Admin added ${contributors} as contributor(s) to ${node}" msgstr "統合管理者代理アカウントが${contributors}をコントリビューターとして${node}に追加しました" + +msgid "Not enough quota to upload. The total size of all files is %1$s." +msgstr "アップロードするための空き容量が足りません。全ファイルの合計サイズは %1$s です" diff --git a/website/translations/js_messages.pot b/website/translations/js_messages.pot index a05c7aac7ca..8a30df9e6a2 100644 --- a/website/translations/js_messages.pot +++ b/website/translations/js_messages.pot @@ -9223,3 +9223,6 @@ msgstr "" msgid "The Integrated Admin added ${contributors} as contributor(s) to ${node}" msgstr "" + +msgid "Not enough quota to upload. The total size of all files is %1$s." +msgstr "" From 4b81dd9f0581e6f50e55e287e9415e779f3908a2 Mon Sep 17 00:00:00 2001 From: hcphat Date: Wed, 8 Oct 2025 15:57:42 +0700 Subject: [PATCH 2/4] =?UTF-8?q?ref=202.1.=E5=B0=8F=E8=A6=8F=E6=A8=A1?= =?UTF-8?q?=E5=A4=A7=E9=87=8F=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E3=82=92?= =?UTF-8?q?=E5=90=AB=E3=82=80=E3=83=95=E3=82=A9=E3=83=AB=E3=83=80=E3=82=A2?= =?UTF-8?q?=E3=83=83=E3=83=97=E3=83=AD=E3=83=BC=E3=83=89=E6=80=A7=E8=83=BD?= =?UTF-8?q?=E6=94=B9=E5=96=84=E3=81=AB=E3=81=8B=E3=81=8B=E3=82=8B=E9=96=8B?= =?UTF-8?q?=E7=99=BA:=20Update=20supported=20provider=20and=20Change=20fro?= =?UTF-8?q?m=20map=20to=20object?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- website/static/js/fangorn.js | 37 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/website/static/js/fangorn.js b/website/static/js/fangorn.js index 9423ca207f1..4c1f7643306 100644 --- a/website/static/js/fangorn.js +++ b/website/static/js/fangorn.js @@ -97,27 +97,26 @@ var COMMAND_KEYS = [224, 17, 91, 93]; var ESCAPE_KEY = 27; var ENTER_KEY = 13; -var PROVIDER_SETTINGS = new Map([ - // ['providerName', { parallelNum: , fileSizeThreshold: }] +var PROVIDER_SETTINGS = { // Bulk mount institution storage settings - ['osfstorage', { parallelNum: 4, fileSizeThreshold: 128000000 }], // 128 MB - - // Addon institution storage settings) - ['onedrivebusiness', { parallelNum: 4, fileSizeThreshold: 128000000 }], - ['nextcloudinstitutions', { parallelNum: 4, fileSizeThreshold: 128000000 }], - ['s3compatinstitutions', { parallelNum: 4, fileSizeThreshold: 128000000 }], - ['dropboxbusiness', { parallelNum: 4, fileSizeThreshold: 128000000 }], + 'osfstorage': { parallelNum: 4, fileSizeThreshold: 128000000 }, // 128 MB // Extend storage settings - ['s3', { parallelNum: 4, fileSizeThreshold: 128000000 }], - ['s3compat', { parallelNum: 4, fileSizeThreshold: 128000000 }], - ['box', { parallelNum: 4, fileSizeThreshold: 128000000 }], - ['googledrive', { parallelNum: 4, fileSizeThreshold: 128000000 }], - ['nextcloud', { parallelNum: 4, fileSizeThreshold: 128000000 }], - ['onedrive', { parallelNum: 4, fileSizeThreshold: 128000000 }], - ['dropbox', { parallelNum: 4, fileSizeThreshold: 128000000 }], - ['s3compatb3', { parallelNum: 4, fileSizeThreshold: 128000000 }], -]); + 's3': { parallelNum: 4, fileSizeThreshold: 128000000 }, + 's3compat': { parallelNum: 4, fileSizeThreshold: 128000000 }, + 'box': { parallelNum: 4, fileSizeThreshold: 128000000 }, + 'googledrive': { parallelNum: 4, fileSizeThreshold: 128000000 }, + 'nextcloud': { parallelNum: 4, fileSizeThreshold: 128000000 }, + 'onedrive': { parallelNum: 4, fileSizeThreshold: 128000000 }, + 'dropbox': { parallelNum: 1, fileSizeThreshold: null }, + 's3compatb3': { parallelNum: 4, fileSizeThreshold: 128000000 }, + 'azureblobstorage': { parallelNum: 1, fileSizeThreshold: null }, + 'dataverse': { parallelNum: 1, fileSizeThreshold: null }, + 'figshare': { parallelNum: 1, fileSizeThreshold: null }, + 'github': { parallelNum: 1, fileSizeThreshold: null }, + 'swift': { parallelNum: 1, fileSizeThreshold: null }, + 'owncloud': { parallelNum: 1, fileSizeThreshold: null } +}; // Monkey-patch Dropzone.processQueue here (must run before any Dropzone instances are created) (function() { @@ -196,7 +195,7 @@ var PROVIDER_SETTINGS = new Map([ })(); function getProviderSettings(provider) { - return PROVIDER_SETTINGS.get(provider) || null; + return PROVIDER_SETTINGS[provider] || null; } function findByTempID(parent, tmpID) { From 45400765d41c46f80d9b18e08f1a460476a18f24 Mon Sep 17 00:00:00 2001 From: hcphat Date: Thu, 11 Dec 2025 16:27:42 +0700 Subject: [PATCH 3/4] =?UTF-8?q?ref=20[Bug][NII=20Redmine#56752]=E3=83=95?= =?UTF-8?q?=E3=82=A1=E3=82=A4=E3=83=AB=E3=82=A2=E3=83=83=E3=83=97=E3=83=AD?= =?UTF-8?q?=E3=83=BC=E3=83=89=E3=81=AB=E3=82=88=E3=82=8B=E3=82=AF=E3=82=A9?= =?UTF-8?q?=E3=83=BC=E3=82=BF=E8=B6=85=E9=81=8E=E6=99=82=E3=81=AE=E3=82=A8?= =?UTF-8?q?=E3=83=A9=E3=83=BC=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC=E3=82=B8?= =?UTF-8?q?=E3=81=AE=E8=A1=A8=E7=A4=BA=E4=BD=8D=E7=BD=AE=E8=AA=A4=E3=82=8A?= =?UTF-8?q?:=20Update=20logic=20show=20error=20message=20and=20alert=20quo?= =?UTF-8?q?ta=20warning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- website/static/js/fangorn.js | 55 +++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/website/static/js/fangorn.js b/website/static/js/fangorn.js index 4c1f7643306..e873ee772e8 100644 --- a/website/static/js/fangorn.js +++ b/website/static/js/fangorn.js @@ -1044,8 +1044,12 @@ function _fangornDropzoneDrop(treebeard, event) { treebeard.select('.tb-row').removeClass(dropzoneHoverClass); var files = event.dataTransfer.files; var totalFilesSize = 0; + var lastFile; for (var i = 0; i < files.length; i++) { totalFilesSize += files[i].size; + if (i === files.length-1) { + lastFile = files[i]; + } } var item = treebeard.dropzoneItemCache; @@ -1055,6 +1059,7 @@ function _fangornDropzoneDrop(treebeard, event) { } // check upload quota for upload folder + treebeard.dropzone.options.limitQuota = false; if (provider === 'osfstorage' || provider === 's3compatinstitutions') { // call api get used quota and max quota var quota = $.ajax({ @@ -1062,22 +1067,20 @@ function _fangornDropzoneDrop(treebeard, event) { method: 'GET', url: item.data.nodeApiUrl + 'get_creator_quota/', }); - - if (!quota.responseJSON) { - $osf.growl('Error', sprintf(gettext('Cannot get quota information.'), - formatProperUnit(totalFilesSize)), - 'danger', 5000); - treebeard.dropzone.options.limitQuota = true; + if (!quota.responseJSON){ return; } - quota = quota.responseJSON; if (parseFloat(quota.used) + parseFloat(totalFilesSize) > quota.max) { - $osf.growl('Error', sprintf(gettext('Not enough quota to upload. The total size of all files is %1$s.'), - formatProperUnit(totalFilesSize)), - 'danger', 5000); treebeard.dropzone.options.limitQuota = true; + treebeard.dropzone.options.lastFile = lastFile; return; + } else if (parseFloat(quota.used) + parseFloat(totalFilesSize) > quota.max * window.contextVars.threshold) { + $osf.growl( + gettext('Quota usage alert'), + sprintf(gettext('You have used more than %1$s%% of your quota.'),(window.contextVars.threshold * 100)), + 'warning' + ); } } // Set Dropzone settings for upload multiple file @@ -1085,7 +1088,6 @@ function _fangornDropzoneDrop(treebeard, event) { if (providerSettings && providerSettings.parallelNum && providerSettings.fileSizeThreshold) { treebeard.dropzone.options.parallelUploads = providerSettings.parallelNum; treebeard.dropzone.options.fileSizeThreshold = providerSettings.fileSizeThreshold; - treebeard.dropzone.options.limitQuota = false; } } /** @@ -1306,6 +1308,7 @@ function _uploadEvent(event, item, col) { } // check upload quota for upload folder + self.dropzone.options.limitQuota = false; if (provider === 'osfstorage' || provider === 's3compatinstitutions') { // call api get used quota and max quota var quota = $.ajax({ @@ -1313,20 +1316,23 @@ function _uploadEvent(event, item, col) { method: 'GET', url: item.data.nodeApiUrl + 'get_creator_quota/', }); - - if (!quota.responseJSON) { - self.dropzone.options.limitQuota = true; + if (!quota.responseJSON){ return; } - quota = quota.responseJSON; if (parseFloat(quota.used) + parseFloat(totalFilesSize) > quota.max) { - $osf.growl('Error', sprintf(gettext('Not enough quota to upload. The total size of all files is %1$s.'), - formatProperUnit(totalFilesSize)), - 'danger', 5000); + self.dropzone.options.limitQuota = true; + var msgText = gettext('Not enough quota to upload the file.'); + item.notify.update(msgText, 'warning', undefined, 3000); self.uploadStates = []; return; + } else if (parseFloat(quota.used) + parseFloat(totalFilesSize) > quota.max * window.contextVars.threshold) { + $osf.growl( + gettext('Quota usage alert'), + sprintf(gettext('You have used more than %1$s%% of your quota.'),(window.contextVars.threshold * 100)), + 'warning' + ); } } // Set Dropzone settings for upload multiple file @@ -1338,7 +1344,6 @@ function _uploadEvent(event, item, col) { // Default settings self.dropzone.options.parallelUploads = 1; } - self.dropzone.options.limitQuota = false; // Add files to Treebeard for (var i = 0; i < files.length; i++) { @@ -1437,6 +1442,13 @@ function _uploadFolderEvent(event, item, mode, col) { 'danger', 5000); return; } + if (parseFloat(quota.used) + parseFloat(totalFilesSize) > quota.max * window.contextVars.threshold) { + $osf.growl( + gettext('Quota usage alert'), + sprintf(gettext('You have used more than %1$s%% of your quota.'),(window.contextVars.threshold * 100)), + 'warning' + ); + } } // Set Dropzone settings for upload folder\ var providerSettings = getProviderSettings(item.data.provider); @@ -4150,10 +4162,15 @@ tbOptions = { if (_fangornCanDrop(treebeard, item)) { var limitQuota = treebeard.dropzone.options.limitQuota || false; if (limitQuota) { + if (file === treebeard.dropzone.options.lastFile) { + msgText = gettext('Not enough quota to upload the file.'); + item.notify.update(msgText, 'warning', undefined, 3000); + } addFileStatus(treebeard, file, false, msgText, ''); removeFromUI(file, treebeard); return false; } + if (item.data.accept && item.data.accept.maxSize) { size = file.size / 1000000; maxSize = item.data.accept.maxSize; From 44f3f152d2b8d3d95cfe6d46233ce80f1e262dd4 Mon Sep 17 00:00:00 2001 From: hcphat Date: Wed, 31 Dec 2025 13:08:42 +0700 Subject: [PATCH 4/4] =?UTF-8?q?ref=20[Bug][NII=20Redmine#56752]=E3=83=95?= =?UTF-8?q?=E3=82=A1=E3=82=A4=E3=83=AB=E3=82=A2=E3=83=83=E3=83=97=E3=83=AD?= =?UTF-8?q?=E3=83=BC=E3=83=89=E3=81=AB=E3=82=88=E3=82=8B=E3=82=AF=E3=82=A9?= =?UTF-8?q?=E3=83=BC=E3=82=BF=E8=B6=85=E9=81=8E=E6=99=82=E3=81=AE=E3=82=A8?= =?UTF-8?q?=E3=83=A9=E3=83=BC=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC=E3=82=B8?= =?UTF-8?q?=E3=81=AE=E8=A1=A8=E7=A4=BA=E4=BD=8D=E7=BD=AE=E8=AA=A4=E3=82=8A?= =?UTF-8?q?:=20Fix=20travis=20error=20when=20merge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- website/static/js/fangorn.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/website/static/js/fangorn.js b/website/static/js/fangorn.js index e873ee772e8..c0b8a1d2d8b 100644 --- a/website/static/js/fangorn.js +++ b/website/static/js/fangorn.js @@ -134,7 +134,7 @@ var PROVIDER_SETTINGS = { return; } var queuedFiles = this.getQueuedFiles(); - if (!(queuedFiles.length > 0)) { + if (queuedFiles.length === 0) { return; } @@ -1053,7 +1053,7 @@ function _fangornDropzoneDrop(treebeard, event) { } var item = treebeard.dropzoneItemCache; - var provider = "unknown" + var provider = 'unknown'; if (item && item.data) { provider = item.data.provider; } @@ -1302,7 +1302,7 @@ function _uploadEvent(event, item, col) { totalFilesSize += files[i].size; } - var provider = "unknown" + var provider = 'unknown'; if (item && item.data) { provider = item.data.provider; } @@ -1346,8 +1346,8 @@ function _uploadEvent(event, item, col) { } // Add files to Treebeard - for (var i = 0; i < files.length; i++) { - self.dropzone.addFile(files[i]); + for (var j = 0; j < files.length; j++) { + self.dropzone.addFile(files[j]); } } }