diff --git a/cms/djangoapps/contentstore/features/upload.feature b/cms/djangoapps/contentstore/features/upload.feature index 441de597ea..1a2e25fcd3 100644 --- a/cms/djangoapps/contentstore/features/upload.feature +++ b/cms/djangoapps/contentstore/features/upload.feature @@ -10,6 +10,16 @@ Feature: Upload Files Then I should see the file "test" was uploaded And The url for the file "test" is valid + @skip_safari + Scenario: Users can upload multiple files + Given I have opened a new course in studio + And I go to the files and uploads page + When I upload the files "test","test2" + Then I should see the file "test" was uploaded + And I should see the file "test2" was uploaded + And The url for the file "test2" is valid + And The url for the file "test" is valid + # Uploading isn't working on safari with sauce labs @skip_safari Scenario: Users can update files diff --git a/cms/djangoapps/contentstore/features/upload.py b/cms/djangoapps/contentstore/features/upload.py index 882b36e6b2..53b7b679f2 100644 --- a/cms/djangoapps/contentstore/features/upload.py +++ b/cms/djangoapps/contentstore/features/upload.py @@ -26,7 +26,24 @@ def upload_file(_step, file_name): #uploading the file itself path = os.path.join(TEST_ROOT, 'uploads/', file_name) world.browser.execute_script("$('input.file-input').css('display', 'block')") - world.browser.attach_file('file', os.path.abspath(path)) + world.browser.attach_file('files[]', os.path.abspath(path)) + close_css = 'a.close-button' + world.css_click(close_css) + + +@step(u'I upload the files (".*")$') +def upload_file(_step, files_string): + # Turn files_string to a list of file names + files = files_string.split(",") + files = map(lambda x: string.strip(x, ' "\''), files) + + upload_css = 'a.upload-button' + world.css_click(upload_css) + #uploading the files + for f in files: + path = os.path.join(TEST_ROOT, 'uploads/', f) + world.browser.execute_script("$('input.file-input').css('display', 'block')") + world.browser.attach_file('files[]', os.path.abspath(path)) close_css = 'a.close-button' world.css_click(close_css) diff --git a/cms/djangoapps/contentstore/views/assets.py b/cms/djangoapps/contentstore/views/assets.py index 4743622fa8..71e4073ed2 100644 --- a/cms/djangoapps/contentstore/views/assets.py +++ b/cms/djangoapps/contentstore/views/assets.py @@ -149,14 +149,14 @@ def upload_asset(request, org, course, coursename): logging.error('Could not find course' + location) return HttpResponseBadRequest() - if 'file' not in request.FILES: + if 'files[]' not in request.FILES: return HttpResponseBadRequest() # compute a 'filename' which is similar to the location formatting, we're # using the 'filename' nomenclature since we're using a FileSystem paradigm # here. We're just imposing the Location string formatting expectations to # keep things a bit more consistent - upload_file = request.FILES['file'] + upload_file = request.FILES['files[]'] filename = upload_file.name mime_type = upload_file.content_type diff --git a/cms/static/js/views/assets.js b/cms/static/js/views/assets.js index 4b0b97180a..dde2f93962 100644 --- a/cms/static/js/views/assets.js +++ b/cms/static/js/views/assets.js @@ -52,7 +52,29 @@ function removeAsset(e){ function showUploadModal(e) { e.preventDefault(); + resetUploadModal(); $modal = $('.upload-modal').show(); + $('.upload-modal .file-chooser').fileupload({ + dataType: 'json', + type: 'POST', + maxChunkSize: 100 * 1000 * 1000, // 100 MB + autoUpload: true, + progressall: function(e, data) { + var percentComplete = parseInt((100 * data.loaded) / data.total, 10); + showUploadFeedback(e, percentComplete); + }, + maxFileSize: 100 * 1000 * 1000, // 100 MB + maxNumberofFiles: 100, + add: function(e, data) { + data.process().done(function () { + data.submit(); + }); + }, + done: function(e, data) { + displayFinishedUpload(data.result); + } + + }); $('.file-input').bind('change', startUpload); $modalCover.show(); } @@ -69,11 +91,6 @@ function startUpload(e) { $('.upload-modal h1').html(gettext('Uploading…')); $('.upload-modal .file-name').html(files[0].name); - $('.upload-modal .file-chooser').ajaxSubmit({ - beforeSend: resetUploadBar, - uploadProgress: showUploadFeedback, - complete: displayFinishedUpload - }); $('.upload-modal .choose-file-button').hide(); $('.upload-modal .progress-bar').removeClass('loaded').show(); } @@ -84,18 +101,28 @@ function resetUploadBar() { $('.upload-modal .progress-fill').html(percentVal); } -function showUploadFeedback(event, position, total, percentComplete) { +function resetUploadModal() { + // Reset modal so it no longer displays information about previously + // completed uploads. + resetUploadBar(); + $('.upload-modal .file-name').html(''); + $('.upload-modal h1').html(gettext('Upload New File')); + $('.upload-modal .choose-file-button').html(gettext('Choose File')); + $('.upload-modal .embeddable-xml-input').val(''); + $('.upload-modal .embeddable').hide(); +} + +function showUploadFeedback(event, percentComplete) { var percentVal = percentComplete + '%'; $('.upload-modal .progress-fill').width(percentVal); $('.upload-modal .progress-fill').html(percentVal); } -function displayFinishedUpload(xhr) { - if (xhr.status == 200) { +function displayFinishedUpload(resp) { + if (resp.status == 200) { markAsLoaded(); } - var resp = JSON.parse(xhr.responseText); $('.upload-modal .embeddable-xml-input').val(resp.portable_url); $('.upload-modal .embeddable').show(); $('.upload-modal .file-name').hide(); diff --git a/cms/templates/asset_index.html b/cms/templates/asset_index.html index c681cf5058..38cb0928f8 100644 --- a/cms/templates/asset_index.html +++ b/cms/templates/asset_index.html @@ -8,6 +8,8 @@ <%block name="jsextra"> + + %block> <%block name="content"> @@ -40,12 +42,12 @@