Skip to content

Commit

Permalink
# This is a combination of 4 commits.
Browse files Browse the repository at this point in the history
# This is the 1st commit message:

Adding new chunking-fileuploader template

(cherry picked from commit 517072f)
Change-Id: I9f80d24959a725c8a4765de7759b8114be808460

# This is the commit message #2:

pop up modal close and upload job progress UI changes

(cherry picked from commit f2fb733)

# This is the commit message #3:

Fix - drag and drop functionality - the drop zone will automatically hide when the file is moved out of the dropzone area ,
fix file upload popup css styling,
name of the file uploading will be displayed instead of static text failed.

(cherry picked from commit 7d9737b)

# This is the commit message #4:

chunksize and max number of concurrent connections config support

(cherry picked from commit 2cf8b98)
Change-Id: I285da6c2267281d6458af30f2a1682aec63b2a85
  • Loading branch information
ranade1 authored and Athithyaa Selvam committed Oct 30, 2023
1 parent 962ae05 commit d30de64
Show file tree
Hide file tree
Showing 10 changed files with 7,952 additions and 90 deletions.
12 changes: 12 additions & 0 deletions apps/filebrowser/src/filebrowser/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@
default=None,
type=str)

FILE_UPLOAD_CHUNK_SIZE = Config(
key="file_upload_chunk_size",
default=5000000,
type=int,
help=_('Configure chunk size of the chunked file uploader. Default chunk size is set to 5MB.'))

CONCURRENT_MAX_CONNECTIONS = Config(
key="concurrent_max_connections",
default=5,
type=int,
help=_('Configure the maximum number of concurrent connections(chunks) for file uploads using the chunked file uploader.'))

def get_desktop_enable_download():
"""Get desktop enable_download default"""
return ENABLE_DOWNLOAD.get()
Expand Down
216 changes: 159 additions & 57 deletions apps/filebrowser/src/filebrowser/templates/listdir_components.mako
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ from django.template.defaultfilters import urlencode, stringformat, filesizeform
from desktop.lib.django_util import reverse_with_get, extract_field_data
from django.utils.encoding import smart_str
from filebrowser.conf import ENABLE_EXTRACT_UPLOADED_ARCHIVE
from filebrowser.conf import ENABLE_EXTRACT_UPLOADED_ARCHIVE, FILE_UPLOAD_CHUNK_SIZE, CONCURRENT_MAX_CONNECTIONS
if sys.version_info[0] > 2:
from django.utils.translation import gettext as _
Expand Down Expand Up @@ -698,6 +698,31 @@ else:
<script src="${ static('desktop/ext/js/datatables-paging-0.1.js') }" type="text/javascript" charset="utf-8"></script>
<script type="text/template" id="qq-template">
<div class="qq-uploader-selector" style="margin-left: 10px">
<div class="qq-upload-drop-area-selector" qq-hide-dropzone><span>${_('Drop the files here to upload')}</span></div>
<div class="qq-upload-button-selector qq-no-float">${_('Select files')}</div> &nbsp;
<span class="muted">${_('or drag and drop them here')}</span>
<ul class="qq-upload-list-selector qq-upload-files unstyled qq-no-float" style="margin-right: 0;">
<li>
<span class="qq-upload-spinner-selector hide" style="display:none"></span>
<div class="progress-row dz-processing">
<span class="break-word qq-upload-file-selector"></span>
<div class="pull-right">
<span class="qq-upload-file-selector" style="display:block"></span>
<span class="muted qq-upload-size-selector"></span>&nbsp;&nbsp;
<a href="#" title="${_('Cancel')}" class="complex-layout"><i class="fa fa-fw fa-times qq-upload-cancel-selector"></i></a>
<span class="qq-upload-done-selector" style="display:none"><i class="fa fa-fw fa-check muted"></i></span>
<span class="qq-upload-failed-text">${_('Failed')}</span>
</div>
<div class="progress-row-bar" style="width: 0%;"></div>
</div>
</li>
</ul>
</div>
</script>
<script>
var _dragged;
Expand Down Expand Up @@ -2021,63 +2046,140 @@ else:
};
self.uploadFile = (function () {
self.pendingUploads(0);
var action = "/filebrowser/upload/file";
var uploader = new qq.FileUploader({
element: document.getElementById("fileUploader"),
action: action,
template: '<div class="qq-uploader" style="margin-left: 10px">' +
'<div class="qq-upload-drop-area"><span>${_('Drop the files here to upload')}</span></div>' +
'<div class="qq-upload-button qq-no-float">${_('Select files')}</div> &nbsp; <span class="muted">${_('or drag and drop them here')}</span>' +
'<ul class="qq-upload-list qq-upload-files unstyled qq-no-float" style="margin-right: 0;"></ul>' +
'</div>',
fileTemplate: '<li><span class="qq-upload-file-extended" style="display:none"></span><span class="qq-upload-spinner hide" style="display:none"></span>' +
'<div class="progress-row dz-processing">' +
'<span class="break-word qq-upload-file"></span>' +
'<div class="pull-right">' +
'<span class="muted qq-upload-size"></span>&nbsp;&nbsp;' +
'<a href="#" title="${_('Cancel')}" class="complex-layout"><i class="fa fa-fw fa-times qq-upload-cancel"></i></a>' +
'<span class="qq-upload-done" style="display:none"><i class="fa fa-fw fa-check muted"></i></span>' +
'<span class="qq-upload-failed-text">${_('Failed')}</span>' +
'</div>' +
'<div class="progress-row-bar" style="width: 0%;"></div>' +
'</div></li>',
params: {
dest: self.currentPath(),
fileFieldLabel: "hdfs_file"
},
onProgress: function (id, fileName, loaded, total) {
$('.qq-upload-files').find('li').each(function(){
var listItem = $(this);
if (listItem.find('.qq-upload-file-extended').text() == fileName){
listItem.find('.progress-row-bar').css('width', (loaded/total)*100 + '%');
}
var uploader;
if (window.ENABLE_NEW_FILE_UPLOADER) {
self.pendingUploads(0);
var action = "/filebrowser/uploadchunks/";
uploader = new qq.FileUploader({
element: document.getElementById("fileUploader"),
request: {
endpoint: action,
paramsInBody: false,
params: {
dest: self.currentPath(),
inputName: "hdfs_file"
}
},
maxConnections: window.CONCURRENT_MAX_CONNECTIONS || 5,
chunking: {
enabled: true,
concurrent: {
enabled: true
},
partSize: window.FILE_UPLOAD_CHUNK_SIZE || 5000000,
success: {
endpoint: "/filebrowser/uploaddone/"
},
paramNames: {
partIndex: "qqpartindex",
partByteOffset: "qqpartbyteoffset",
chunkSize: "qqchunksize",
totalFileSize: "qqtotalfilesize",
totalParts: "qqtotalparts"
}
},
template: 'qq-template',
callbacks: {
onProgress: function (id, fileName, loaded, total) {
console.log(loaded);
$('.qq-upload-files').find('li').each(function(){
var listItem = $(this);
if (listItem.find('.qq-upload-file-selector').text() == fileName){
listItem.find('.progress-row-bar').css('width', (loaded/total)*100 + '%');
}
});
},
onComplete: function (id, fileName, response) {
self.pendingUploads(self.pendingUploads() - 1);
if (response.status != 0) {
$(document).trigger('error', "${ _('Error: ') }" + response.data);
}
else {
$(document).trigger('info', response.path + "${ _(' uploaded successfully.') }");
self.filesToHighlight.push(response.path);
}
if (self.pendingUploads() == 0) {
$('#uploadFileModal').modal('hide');
self.retrieveData(true);
}
},
onAllComplete: function(succeeded, failed){
$('#uploadFileModal').modal('hide');
},
onSubmit: function (id, fileName, responseJSON) {
var newPath = "/filebrowser/uploadchunks/file?dest=" + encodeURIComponent(self.currentPath());
this.setEndpoint(newPath);
self.pendingUploads(self.pendingUploads() + 1);
},
onCancel: function (id, fileName) {
self.pendingUploads(self.pendingUploads() - 1);
}
},
debug: false
});
},
onComplete: function (id, fileName, response) {
self.pendingUploads(self.pendingUploads() - 1);
if (response.status != 0) {
$(document).trigger('error', "${ _('Error: ') }" + response.data);
}
else {
$(document).trigger('info', response.path + "${ _(' uploaded successfully.') }");
self.filesToHighlight.push(response.path);
}
if (self.pendingUploads() == 0) {
$('#uploadFileModal').modal('hide');
self.retrieveData(true);
}
},
onSubmit: function (id, fileName, responseJSON) {
self.pendingUploads(self.pendingUploads() + 1);
},
onCancel: function (id, fileName) {
self.pendingUploads(self.pendingUploads() - 1);
},
debug: false
});
}
else {
self.pendingUploads(0);
var action = "/filebrowser/upload/file";
uploader = new fileuploader.FileUploader({
element: document.getElementById("fileUploader"),
action: action,
template: '<div class="qq-uploader" style="margin-left: 10px">' +
'<div class="qq-upload-drop-area"><span>${_('Drop the files here to upload')}</span></div>' +
'<div class="qq-upload-button qq-no-float">${_('Select files')}</div> &nbsp; <span class="muted">${_('or drag and drop them here')}</span>' +
'<ul class="qq-upload-list qq-upload-files unstyled qq-no-float" style="margin-right: 0;"></ul>' +
'</div>',
fileTemplate: '<li><span class="qq-upload-file-extended" style="display:none"></span><span class="qq-upload-spinner hide" style="display:none"></span>' +
'<div class="progress-row dz-processing">' +
'<span class="break-word qq-upload-file"></span>' +
'<div class="pull-right">' +
'<span class="muted qq-upload-size"></span>&nbsp;&nbsp;' +
'<a href="#" title="${_('Cancel')}" class="complex-layout"><i class="fa fa-fw fa-times qq-upload-cancel"></i></a>' +
'<span class="qq-upload-done" style="display:none"><i class="fa fa-fw fa-check muted"></i></span>' +
'<span class="qq-upload-failed-text">${_('Failed')}</span>' +
'</div>' +
'<div class="progress-row-bar" style="width: 0%;"></div>' +
'</div></li>',
params: {
dest: self.currentPath(),
fileFieldLabel: "hdfs_file"
},
onProgress: function (id, fileName, loaded, total) {
$('.qq-upload-files').find('li').each(function(){
var listItem = $(this);
if (listItem.find('.qq-upload-file-extended').text() == fileName){
listItem.find('.progress-row-bar').css('width', (loaded/total)*100 + '%');
}
});
},
onComplete: function (id, fileName, response) {
self.pendingUploads(self.pendingUploads() - 1);
if (response.status != 0) {
$(document).trigger('error', "${ _('Error: ') }" + response.data);
}
else {
$(document).trigger('info', response.path + "${ _(' uploaded successfully.') }");
self.filesToHighlight.push(response.path);
}
if (self.pendingUploads() == 0) {
$('#uploadFileModal').modal('hide');
self.retrieveData(true);
}
},
onSubmit: function (id, fileName, responseJSON) {
self.pendingUploads(self.pendingUploads() + 1);
},
onCancel: function (id, fileName) {
self.pendingUploads(self.pendingUploads() - 1);
},
debug: false
});
}
$("#fileUploader").on('fb:updatePath', function (e, options) {
$("#fileUploader").on('fb:updatePath', function (e, options) {
const uploadingToOzone = self.currentPath().startsWith("ofs://");
const ozoneSizeLimit = Math.min(
...[UPLOAD_CHUNK_SIZE, MAX_FILE_SIZE_UPLOAD_LIMIT].filter(Number.isFinite)
Expand Down Expand Up @@ -2640,7 +2742,7 @@ else:
if (typeof _dropzone != "undefined") {
_dropzone.enable();
}
$(".qq-upload-list").empty();
$(".qq-upload-list-selector").empty();
$(".qq-upload-drop-area").hide();
});
});
Expand Down
5 changes: 3 additions & 2 deletions desktop/core/src/desktop/api2.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@
from beeswax.models import Namespace
from desktop import appmanager
from desktop.auth.backend import is_admin
from desktop.conf import ENABLE_CONNECTORS, ENABLE_GIST_PREVIEW, CUSTOM, get_clusters, ENABLE_SHARING
from desktop.conf import ENABLE_NEW_STORAGE_BROWSER
from desktop.conf import ENABLE_CONNECTORS, ENABLE_GIST_PREVIEW, CUSTOM, get_clusters, IS_K8S_ONLY, ENABLE_SHARING
from desktop.conf import ENABLE_NEW_STORAGE_BROWSER, ENABLE_NEW_FILE_UPLOADER
from desktop.lib.conf import BoundContainer, GLOBAL_CONFIG, is_anonymous
from desktop.lib.django_util import JsonResponse, login_notrequired, render
from desktop.lib.exceptions_renderable import PopupException
Expand Down Expand Up @@ -100,6 +100,7 @@ def get_config(request):
config['hue_config']['is_admin'] = is_admin(request.user)
config['hue_config']['is_yarn_enabled'] = is_yarn()
config['hue_config']['enable_new_storage_browser'] = ENABLE_NEW_STORAGE_BROWSER.get()
config['hue_config']['enable_new_file_uploader'] = ENABLE_NEW_FILE_UPLOADER.get()
config['clusters'] = list(get_clusters(request.user).values())
config['documents'] = {
'types': list(Document2.objects.documents(user=request.user).order_by().values_list('type', flat=True).distinct())
Expand Down
10 changes: 10 additions & 0 deletions desktop/core/src/desktop/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1818,6 +1818,16 @@ def get_instrumentation_default():
default=False
)

def get_chunked_fileuploader():
return ENABLE_NEW_FILE_UPLOADER.get();

ENABLE_NEW_FILE_UPLOADER = Config(
key="enable_new_file_uploader",
help=_("Enable new chunked file uploader."),
type=coerce_bool,
default=False
)

USE_NEW_EDITOR = Config( # To remove in Hue 4
key='',
default=True,
Expand Down
5 changes: 3 additions & 2 deletions desktop/core/src/desktop/js/ext/fileuploader.custom.js
Original file line number Diff line number Diff line change
Expand Up @@ -1259,7 +1259,7 @@ qq.extend(qq.UploadHandlerXhr.prototype, {
}
};

var formData = new FormData();
var formData = new FormData();
formData.append(params.fileFieldLabel, file, file.name.normalize('NFC'));
formData.append('dest', params.dest);

Expand Down Expand Up @@ -1313,4 +1313,5 @@ qq.extend(qq.UploadHandlerXhr.prototype, {
}
});

export default qq;
let fileuploader = qq;
export default fileuploader;
Loading

0 comments on commit d30de64

Please sign in to comment.