/** * @namespace WORKAREA.directUploads */ WORKAREA.registerModule('directUploads', (function () { 'use strict'; var processingTemplate = JST['workarea/admin/templates/direct_upload_processing'], tableRowTemplate = JST['workarea/admin/templates/direct_upload_table_row'], savingFile = function (type, filename) { return $.post({ url: WORKAREA.routes.admin.directUploadsPath({ type: type, filename: filename }) }); }, uploadingFile = function (type, file, url) { return $.ajax({ url: url, method: 'put', data: file, contentType: file.type, processData: false }); }, gettingUploadEndpoint = function (type, filename) { return $.get({ url: WORKAREA.routes.admin.newDirectUploadsPath({ type: type, filename: filename }) }); }, markTableRow = function(status, file, response) { var $tableBody = file.$element.closest('tbody'); file.$element .addClass('direct-upload__table-row--' + status) .find('[data-direct-upload-file-status]') .text(function () { var defaultMessage = I18n.t( 'workarea.admin.direct_uploads.' + status + '_status' ); if (_.isEmpty((response.responseJSON || {}).error)) { return defaultMessage; } else { return response.responseJSON.error; } }); if (status === 'failure') { file.$element.prependTo($tableBody); } }, incrementCount = function ($dropzone) { var $count = $('[data-direct-upload-count]', $dropzone), count = $count.data('directUploadCount') + 1; $count.text(count).data('directUploadCount', count); }, stopProcessing = function ($dropzone) { $dropzone.removeClass('direct-upload--processing'); WORKAREA.unsavedChanges.reset(); }, scrollToFailures = function ($dropzone) { $('html, body').animate({ scrollTop: $dropzone.offset().top }, 1000); }, updateFailUI = function ($dropzone) { $dropzone .addClass('direct-upload--fail') .find('.direct-upload__heading') .text(I18n.t('workarea.admin.direct_uploads.something_went_wrong')) .end() .find('.direct-upload__info') .text(I18n.t('workarea.admin.direct_uploads.upload_failed')); }, failUI = function ($dropzone) { updateFailUI($dropzone); scrollToFailures($dropzone); }, refresh = function ($dropzone) { var $takeover = $dropzone.closest('.takeover'); _.delay(function () { if (_.isEmpty($takeover)) { window.location.reload(); } else { WORKAREA.takeover.reload(); } }, WORKAREA.config.messages.delay); }, updateSuccessUI = function ($dropzone) { $dropzone .addClass('direct-upload--success') .find('.direct-upload__heading') .text(I18n.t('workarea.admin.direct_uploads.everything_went_great')) .end() .find('.direct-upload__info') .text(I18n.t('workarea.admin.direct_uploads.upload_succeeded')); }, successUI = function ($dropzone) { updateSuccessUI($dropzone); refresh($dropzone); }, uploadFile = function (type, $dropzone, file) { var endpointRequest = WORKAREA.directUploads.gettingUploadEndpoint( type, file.name ), uploadPromise = $.Deferred(), requests = []; requests.push(endpointRequest); endpointRequest.done(function (result) { var uploadRequest = WORKAREA.directUploads.uploadingFile( type, file, result.upload_url ); requests.push(uploadRequest); uploadRequest.done(function () { var saveRequest = WORKAREA.directUploads.savingFile( type, file.name ); requests.push(saveRequest); saveRequest.done(function(response) { uploadPromise.resolve.apply(null, requests); markTableRow('success', file, response); }).fail(function (response) { uploadPromise.reject(requests); markTableRow('failure', file, response); }); }).fail(function (response) { uploadPromise.reject(requests); markTableRow('failure', file, response); }); }).fail(function (response) { uploadPromise.reject(requests); markTableRow('failure', file, response); }).always(_.partial(incrementCount, $dropzone)); return uploadPromise; }, activateUI = function (event) { var $dropzone = $(event.delegateTarget); event.preventDefault(); event.stopPropagation(); $dropzone.addClass('direct-upload--active'); }, prepareFiles = function (event) { var data = (event.originalEvent || {}).dataTransfer, files; if (data.items) { files = _.filter(data.items, function (item) { return item.kind === 'file'; }); files = _.map(files, function (item) { return item.getAsFile(); }); data.items.clear(); } else { files = data.files; data.clearData(); } return _.map(files, function (file) { return Object.defineProperty(file, '$element', { value: $(tableRowTemplate({ fileName: file.name })), writable: false }); }); }, testUnload = function ($dropzone) { if ($dropzone.data('directUploadProcessing')) { WORKAREA.unsavedChanges.set(); } }, processFiles = function ($dropzone, files) { var type = $dropzone.data('directUpload').type, upload = _.partial(uploadFile, type, $dropzone), done = _.partial(successUI, $dropzone), fail = _.partial(failUI, $dropzone), always = _.partial(stopProcessing, $dropzone), requests = _.map(files, upload); $.when.apply($, requests) .done(done) .fail(fail) .always(always); }, processingUI = function ($dropzone, files) { var $tableBody; $dropzone .addClass('direct-upload--processing') .data('directUploadProcessing', true) .find('.direct-upload__content') .empty() .append(processingTemplate({ count: 0, total: files.length })); $tableBody = $('[data-direct-upload-table-body]', $dropzone); _.forEach(files, function (file) { $tableBody.append(file.$element); }); }, thresholdError = function () { WORKAREA.messages.insertMessage( I18n.t( 'workarea.admin.direct_uploads.threshold_error', { count: WORKAREA.config.directUploads.countThreshold, size: WORKAREA.config.directUploads.sizeThreshold } ), 'error' ); }, thresholdExceeded = function (files) { var safeCount = 500, safeSize = 500, countThreshold = WORKAREA.config.directUploads.countThreshold, sizeThreshold = WORKAREA.config.directUploads.sizeThreshold, count = files.length, size = _.reduce(files, function (totalMegabytes, file) { return totalMegabytes + file.size / 1000000; }, 0); if (WORKAREA.environment.isDevelopment && ! WORKAREA.config.directUploads.suppressWarning) { if (countThreshold > safeCount || sizeThreshold > safeSize) { window.console.warn( 'WORKAREA.directUploads.thresholdExceeded: you have ' + 'increased either the file or file size threshold in ' + 'this module\'s configuration. Testing revealed that ' + 'raising this value too far past the default ' + 'thresholds causes instability and random failure ' + 'during the upload process. PROCEED WITH CAUTION!\n\n' + 'To suppress this warning, set the `WORKAREA.config.' + 'directUploads.suppressWarning` equal to `true`.' ); } } return count > countThreshold || size > sizeThreshold; }, processingWarning = function () { WORKAREA.messages.insertMessage( I18n.t('workarea.admin.direct_uploads.processing_warning'), 'warning' ); }, process = function (event) { var $dropzone = $(event.delegateTarget), files; event.preventDefault(); if ($dropzone.is('.direct-upload--processing')) { processingWarning(); } else { files = WORKAREA.directUploads.prepareFiles(event); if (thresholdExceeded(files)) { thresholdError(); } else { processingUI($dropzone, files); processFiles($dropzone, files); testUnload($dropzone); } } }, /** * @method * @name init * @memberof WORKAREA.directUploads */ init = function($scope) { $('[data-direct-upload]', $scope) .on('drop', process) .on('dragover dragenter', activateUI); }; return { init: init, // for testing savingFile: savingFile, prepareFiles: prepareFiles, processFiles: processFiles, uploadingFile: uploadingFile, gettingUploadEndpoint: gettingUploadEndpoint }; }()));