mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-11-11 18:21:04 +08:00
894e201e1b
* Fix big file issue in step atachments * Fix markup
585 lines
19 KiB
Text
585 lines
19 KiB
Text
(function(global) {
|
|
'use strict';
|
|
// Copy from clipboard
|
|
global.copyFromClipboard = (function() {
|
|
var UPLOADED_IMAGE = {};
|
|
var LOCATION = '';
|
|
function init(location) {
|
|
LOCATION = location;
|
|
global.addEventListener('paste', _listener, false);
|
|
$.initTooltips();
|
|
};
|
|
|
|
function destroy() {
|
|
global.removeEventListener('paste', _listener, false);
|
|
}
|
|
|
|
function _listener(pasteEvent) {
|
|
_retrieveImageFromClipboardAsBlob(pasteEvent, function(imageBlob) {
|
|
if(imageBlob){
|
|
_clipboardPasteModal().promise().done(function() {
|
|
var canvas = document.getElementById('clipboardPreview');
|
|
var ctx = canvas.getContext('2d');
|
|
var img = new Image();
|
|
img.onload = function() {
|
|
canvas.width = this.width;
|
|
canvas.height = this.height;
|
|
ctx.drawImage(img, 0, 0);
|
|
};
|
|
var URLObj = window.URL || window.webkitURL;
|
|
img.src = URLObj.createObjectURL(imageBlob);
|
|
var extension = imageBlob.name.slice(
|
|
(Math.max(0, imageBlob.name.lastIndexOf(".")) || Infinity) + 1
|
|
);
|
|
$('#image-name').html('.' + extension); // add extension near file name
|
|
// temporary store image blob
|
|
UPLOADED_IMAGE = imageBlob
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
function _retrieveImageFromClipboardAsBlob(pasteEvent, callback){
|
|
if(pasteEvent.clipboardData == false) {
|
|
if(typeof(callback) == "function"){
|
|
callback(undefined);
|
|
}
|
|
};
|
|
|
|
var items = pasteEvent.clipboardData.items;
|
|
if(items == undefined){
|
|
if(typeof(callback) == "function"){
|
|
callback(undefined);
|
|
}
|
|
};
|
|
|
|
for (var i = 0; i < items.length; i++) {
|
|
if (items[i].type.indexOf("image") == -1) continue;
|
|
var blob = items[i].getAsFile();
|
|
|
|
if(typeof(callback) == "function") {
|
|
callback(blob);
|
|
}
|
|
}
|
|
};
|
|
|
|
// removes modal from dom
|
|
function _destroyModalCallback() {
|
|
var modal = $('#clipboardPreviewModal');
|
|
modal.on('hidden.bs.modal', function() {
|
|
modal.modal('hide').promise().done(function() {
|
|
modal.remove();
|
|
});
|
|
UPLOADED_IMAGE = {};
|
|
});
|
|
}
|
|
|
|
function _closeModal() {
|
|
_hideModalForGood();
|
|
$("#clipboardPreviewModal").remove();
|
|
}
|
|
|
|
// $(..).modal('hide') don't work properly so here we manually remove the
|
|
// displayed modal
|
|
function _hideModalForGood(){
|
|
$("#clipboardPreviewModal").removeClass("in");
|
|
$(".modal-backdrop").remove();
|
|
$('body').removeClass('modal-open');
|
|
$('body').css('padding-right', '');
|
|
$("#clipboardPreviewModal").hide();
|
|
}
|
|
|
|
function _addImageCallback() {
|
|
$('[data-action="addImageFormClipboard"]').on('click', function() {
|
|
var inputArray = [];
|
|
var newName = $('#clipboardImageName').val();
|
|
// check if the name is set
|
|
if( newName && newName.length > 0 ) {
|
|
var extension = UPLOADED_IMAGE.name.slice(
|
|
(Math.max(0, UPLOADED_IMAGE.name.lastIndexOf(".")) || Infinity) + 1
|
|
);
|
|
// hack to inject custom name in File object
|
|
var name = newName + '.' + extension;
|
|
var blob = UPLOADED_IMAGE.slice(0, UPLOADED_IMAGE.size, UPLOADED_IMAGE.type);
|
|
// make new blob with the correct name;
|
|
var newFile = new File([blob], name, { type: UPLOADED_IMAGE.type });
|
|
inputArray.push(newFile);
|
|
} else { // return the default name
|
|
inputArray.push(UPLOADED_IMAGE);
|
|
}
|
|
|
|
// close modal
|
|
_closeModal();
|
|
// reuse file upload from drag'n drop :)
|
|
if(LOCATION === 'steps') {
|
|
DragNDropSteps.init(inputArray);
|
|
} else {
|
|
DragNDropResults.init(inputArray);
|
|
}
|
|
// clear all uploaded images
|
|
UPLOADED_IMAGE = {};
|
|
});
|
|
}
|
|
|
|
// Generate modal html and hook callbacks
|
|
function _clipboardPasteModal() {
|
|
var html = '<div id="clipboardPreviewModal" class="modal fade" ';
|
|
html += 'tabindex="-1" role="dialog" aria-hidden="true">';
|
|
html += '<div class="modal-dialog" role="document">';
|
|
html += '<div class="modal-content"><div class="modal-header">';
|
|
html += '<button type="button" class="close" data-dismiss="modal"';
|
|
html += ' aria-label="Close"><span aria-hidden="true">×</span>';
|
|
html += '</button><h4 class="modal-title"><%= I18n.t('assets.from_clipboard.modal_title') %></h4>';
|
|
html += '</div><div class="modal-body"><p><strong><%= I18n.t('assets.from_clipboard.image_preview') %></strong></p>';
|
|
html += '<canvas style="border:1px solid grey;max-width:400px;max-height:300px" id="clipboardPreview" />';
|
|
html += '<p><strong><%= I18n.t('assets.from_clipboard.file_name') %></strong></p>';
|
|
html += '<div class="input-group">';
|
|
html += '<input id="clipboardImageName" type="text" class="form-control" ';
|
|
html += 'placeholder="<%= I18n.t('assets.from_clipboard.file_name_placeholder') %>" aria-describedby="image-name">';
|
|
html += '<span class="input-group-addon" id="image-name"></span></div>';
|
|
html += '</div><div class="modal-footer">';
|
|
html += '<button type="button" class="btn btn-default" data-dismiss="modal"><%= I18n.t('general.cancel') %></button>';
|
|
html += '<button type="button" class="btn btn-success" data-action="addImageFormClipboard"><%= I18n.t('assets.from_clipboard.add_image') %></button>';
|
|
html += '</div></div></div></div><!-- /.modal -->';
|
|
return $(html).appendTo($('body')).promise().done(function() {
|
|
// display modal
|
|
$('#clipboardPreviewModal').modal('show');
|
|
// add callback to remove modal from DOM
|
|
_destroyModalCallback();
|
|
// add callback on image submit
|
|
_addImageCallback();
|
|
});
|
|
}
|
|
|
|
return Object.freeze({
|
|
init: init,
|
|
destroy: destroy
|
|
});
|
|
})();
|
|
|
|
// Module to handle file uploading in Steps
|
|
global.DragNDropSteps = (function() {
|
|
var droppedFiles = [];
|
|
var filesValid = true;
|
|
var totalSize = 0;
|
|
var fileMaxSizeMb;
|
|
var fileMaxSize;
|
|
|
|
function checkErrors() {
|
|
// Check for error
|
|
var errors = $('.attachments.edit').find('.dnd-error').length;
|
|
if (errors > 0){
|
|
$('#new-step-assets-tab').addClass('has-error');
|
|
} else {
|
|
$('#new-step-assets-tab').removeClass('has-error');
|
|
filesValid = true;
|
|
}
|
|
}
|
|
|
|
function init(files) {
|
|
fileMaxSizeMb = $(document.body).data('file-max-size-mb');
|
|
fileMaxSize = fileMaxSizeMb * 1024 * 1024;
|
|
for(var i = 0; i < files.length; i++) {
|
|
droppedFiles.push(files[i]);
|
|
}
|
|
listItems();
|
|
|
|
checkErrors();
|
|
$('.attachments.edit').find('.remove-icon .fa-trash').click(() => {
|
|
setTimeout(() => {checkErrors()}, 0);
|
|
})
|
|
}
|
|
|
|
// return the status of files if they are ready to submit
|
|
function filesStatus() {
|
|
return filesValid;
|
|
}
|
|
|
|
function clearFiles() {
|
|
droppedFiles = [];
|
|
}
|
|
|
|
// loops through a list of files and display each file in a separate panel
|
|
function listItems() {
|
|
totalSize = 0;
|
|
_enableSubmitButton();
|
|
$('.attachment-placeholder.new').remove();
|
|
_dragNdropAssetsOff();
|
|
for(var i = 0; i < droppedFiles.length; i++) {
|
|
$('.attachments.edit')
|
|
.append(_uploadedAssetPreview(droppedFiles[i], i))
|
|
.promise()
|
|
.done(function() {
|
|
_removeItemHandler(i);
|
|
});
|
|
}
|
|
_validateTotalSize();
|
|
dragNdropAssetsInit('steps');
|
|
}
|
|
|
|
// append the files to the form before submit
|
|
function appendFilesToForm(ev) {
|
|
var regex = /step\[assets_attributes\]\[[0-9]*\]\[id\]/;
|
|
var prevEls = $('input').filter(function() {
|
|
return this.name.match(regex);
|
|
});
|
|
var fd = new FormData($(ev.target).closest('form').get(0));
|
|
for(var i = 0; i < droppedFiles.length; i++) {
|
|
var index = i + prevEls.length;
|
|
var name = 'step[assets_attributes][' + index + '][file]';
|
|
fd.append(name, droppedFiles[i]);
|
|
}
|
|
|
|
filesValid = true;
|
|
totalSize = 0;
|
|
_dragNdropAssetsOff();
|
|
return fd;
|
|
}
|
|
|
|
function _disableSubmitButton() {
|
|
$('.step-save').prop('disabled', true);
|
|
}
|
|
|
|
function _enableSubmitButton() {
|
|
$('.step-save').prop('disabled', false);
|
|
}
|
|
|
|
function _filerAndCheckFiles() {
|
|
for(var i = 0; i < droppedFiles.length; i++) {
|
|
if(droppedFiles[i].isValid == false) {
|
|
return false;
|
|
}
|
|
}
|
|
return (droppedFiles.length > 0);
|
|
}
|
|
|
|
function _validateFilesSize(file) {
|
|
var fileSize = file.size;
|
|
totalSize += parseInt(fileSize);
|
|
if(fileSize > fileMaxSize) {
|
|
file.isValid = false;
|
|
_disableSubmitButton();
|
|
return "<p class='dnd-error'>" + I18n.t('general.file.size_exceeded', { file_size: fileMaxSizeMb }) + '</p>';
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function _validateTotalSize() {
|
|
if(totalSize > fileMaxSize) {
|
|
filesValid = false;
|
|
_disableSubmitButton();
|
|
$.each($('.panel-step-attachment-new'), function() {
|
|
if(!$(this).find('p').hasClass('dnd-total-error')) {
|
|
$(this)
|
|
.find('.panel-body')
|
|
.append("<p class='dnd-total-error'>" + I18n.t('general.file.total_size', { size: fileMaxSizeMb }) + '</p>');
|
|
}
|
|
});
|
|
} else {
|
|
$('.dnd-total-error').remove();
|
|
if(_filerAndCheckFiles()) {
|
|
filesValid = true;
|
|
_enableSubmitButton();
|
|
}
|
|
}
|
|
}
|
|
|
|
function _uploadedAssetPreview(asset, i) {
|
|
var html = '<div class="attachment-placeholder pull-left new">';
|
|
html +='<div class="attachment-thumbnail no-shadow %>">';
|
|
html +='<i class="fas fa-image"></i>';
|
|
html +='</div>';
|
|
html +='<div class="attachment-label">' + truncateLongString(asset.name, <%= Constants::FILENAME_TRUNCATION_LENGTH %>);
|
|
html += '</div>';
|
|
html +='<div class="spencer-bonnet-modif">';
|
|
html +='</div>';
|
|
html +='<div class="remove-icon pull-right">';
|
|
html +='<a data-item-id="' + i + '" href="#">';
|
|
html +='<span class="fas fa-trash"></span>';
|
|
html +='</a> </div>';
|
|
html += _validateFilesSize(asset);
|
|
html +='</div>';
|
|
|
|
return html;
|
|
}
|
|
|
|
function _removeItemHandler(id) {
|
|
$('[data-item-id="' + id +'"]').off('click').on('click', function(e) {
|
|
e.preventDefault();
|
|
e.stopImmediatePropagation();
|
|
e.stopPropagation();
|
|
var $el = $(this);
|
|
var index = $el.data('item-id');
|
|
totalSize -= parseInt(droppedFiles[index].size);
|
|
droppedFiles.splice(index, 1);
|
|
listItems();
|
|
});
|
|
}
|
|
|
|
function _dragNdropAssetsOff() {
|
|
$('body').off('drag dragstart dragend dragover dragenter dragleave drop');
|
|
$('.is-dragover').hide();
|
|
// remove listeners for clipboard images
|
|
copyFromClipboard.destroy();
|
|
}
|
|
|
|
return Object.freeze({
|
|
init: init,
|
|
appendFilesToForm: appendFilesToForm,
|
|
listItems: listItems,
|
|
filesStatus: filesStatus,
|
|
clearFiles: clearFiles,
|
|
checkErrors: checkErrors
|
|
});
|
|
})();
|
|
|
|
// Module to handle file uploading in Results
|
|
global.DragNDropResults = (function() {
|
|
var droppedFiles = [];
|
|
var isValid = true;
|
|
var totalSize = 0;
|
|
var fileMaxSizeMb;
|
|
var fileMaxSize;
|
|
|
|
function init(files) {
|
|
fileMaxSizeMb = $(document.body).data('file-max-size-mb');
|
|
fileMaxSize = fileMaxSizeMb * 1024 * 1024;
|
|
for(var i = 0; i < files.length; i++) {
|
|
droppedFiles.push(files[i]);
|
|
}
|
|
listItems();
|
|
}
|
|
|
|
// return the status of files if they are ready to submit
|
|
function filesStatus() {
|
|
return isValid;
|
|
}
|
|
|
|
// loops through a list of files and display each file in a separate panel
|
|
function listItems() {
|
|
totalSize = 0;
|
|
$('.panel-result-attachment-new').remove();
|
|
if(droppedFiles.length < 1) {
|
|
_disableSubmitButton();
|
|
} else {
|
|
_dragNdropAssetsOff();
|
|
for(var i = 0; i < droppedFiles.length; i++) {
|
|
$('#new-result-assets-select')
|
|
.after(_uploadedAssetPreview(droppedFiles[i], i))
|
|
.promise()
|
|
.done(function() {
|
|
_removeItemHandler(i);
|
|
});
|
|
}
|
|
_validateTotalSize();
|
|
dragNdropAssetsInit('results');
|
|
}
|
|
}
|
|
|
|
// appent the files to the form before submit
|
|
function _appendFilesToForm() {
|
|
var regex = /result\[assets_attributes\]\[[0-9]*\]\[id\]/;
|
|
var prevEls = $('input').filter(function() {
|
|
return this.name.match(regex);
|
|
});
|
|
|
|
var fd = new FormData();
|
|
var result_names = [];
|
|
$.each($('input[rel="results[name]"]'), function() {
|
|
result_names.push($(this).val());
|
|
});
|
|
result_names.reverse();
|
|
for(var i = 0; i < droppedFiles.length; i++) {
|
|
var index = i + prevEls.length;
|
|
var file_name = 'results_files[' + index + ']';
|
|
fd.append(file_name, droppedFiles[i]);
|
|
fd.append('results_names[' + i + ']', result_names[i]);
|
|
}
|
|
destroyAll();
|
|
return fd;
|
|
}
|
|
|
|
function _disableSubmitButton() {
|
|
$('.save-result').prop('disabled', true);
|
|
}
|
|
|
|
function _enableSubmitButton() {
|
|
$('.save-result').prop('disabled', false);
|
|
}
|
|
|
|
function _filerAndCheckFiles() {
|
|
for(var i = 0; i < droppedFiles.length; i++) {
|
|
if(droppedFiles[i].isValid == false) {
|
|
return false;
|
|
}
|
|
}
|
|
return (droppedFiles.length > 0);
|
|
}
|
|
|
|
function _validateFilesSize(file) {
|
|
var fileSize = file.size;
|
|
totalSize += parseInt(fileSize);
|
|
if(fileSize > fileMaxSize) {
|
|
file.isValid = false;
|
|
_disableSubmitButton();
|
|
return "<p class='dnd-error'>" + I18n.t('general.file.size_exceeded', { file_size: fileMaxSizeMb }) + '</p>';
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function _validateTotalSize() {
|
|
if(totalSize > fileMaxSize) {
|
|
isValid = false;
|
|
_disableSubmitButton();
|
|
$.each($('.panel-result-attachment-new'), function() {
|
|
if(!$(this).find('p').hasClass('dnd-total-error')) {
|
|
$(this)
|
|
.find('.panel-body')
|
|
.append("<p class='dnd-total-error'>" + I18n.t('general.file.total_size', { size: fileMaxSizeMb }) + '</p>');
|
|
}
|
|
});
|
|
} else {
|
|
$('.dnd-total-error').remove();
|
|
if(_filerAndCheckFiles()) {
|
|
isValid = true;
|
|
_enableSubmitButton();
|
|
}
|
|
}
|
|
}
|
|
|
|
function validateTextSize(input) {
|
|
if(input.value.length > <%= Constants::NAME_MAX_LENGTH %>) {
|
|
$(input).parent().find('.dnd-error').remove();
|
|
$(input).after("<p class='dnd-error'><%= I18n.t('general.text.length_too_long', max_length: Constants::NAME_MAX_LENGTH) %></p>");
|
|
isValid = false;
|
|
} else {
|
|
$(input).parent().find('.dnd-error').remove();
|
|
isValid = true;
|
|
}
|
|
}
|
|
|
|
function _uploadedAssetPreview(asset, i) {
|
|
var html = '<div class="panel panel-default panel-result-attachment-new">';
|
|
html += '<div class="panel-heading">';
|
|
html += '<span class="fas fa-paperclip"></span>';
|
|
html += '<%= I18n.t 'assets.drag_n_drop.file_label' %>';
|
|
html += '<div class="pull-right">';
|
|
html += '<a data-item-id="' + i + '" href="#">';
|
|
html += '<span class="fas fa-times"></span></a></div></div>';
|
|
html += '<div class="panel-body"><div class="form-group">';
|
|
html += '<label class="control-label">Name</label>';
|
|
html += '<input type="text" class="form-control" ';
|
|
html += 'onChange="DragNDropResults.validateTextSize(this)"';
|
|
html += ' rel="results[name]" name="results[name][' + i + ']">';
|
|
html += '</div><div class="form-group"><label class="control-label">';
|
|
html += '<%= I18n.t 'assets.drag_n_drop.file_label' %>:</label> ';
|
|
html += truncateLongString(asset.name,
|
|
<%= Constants::FILENAME_TRUNCATION_LENGTH %>);
|
|
html += _validateFilesSize(asset);
|
|
html += '</div></div>';
|
|
return html;
|
|
}
|
|
|
|
function _removeItemHandler(id) {
|
|
$('[data-item-id="' + id +'"]').off('click').on('click', function(e) {
|
|
e.preventDefault();
|
|
e.stopImmediatePropagation();
|
|
e.stopPropagation();
|
|
var $el = $(this);
|
|
var index = $el.data('item-id');
|
|
totalSize -= parseInt(droppedFiles[index].size);
|
|
droppedFiles.splice(index, 1);
|
|
listItems();
|
|
});
|
|
}
|
|
|
|
function processResult(button) {
|
|
if(isValid && _filerAndCheckFiles()) {
|
|
animateSpinner();
|
|
$.ajax({
|
|
url: $(button).attr('data-href'),
|
|
method: 'POST',
|
|
data: _appendFilesToForm(),
|
|
contentType: false,
|
|
processData: false,
|
|
success: function(data) {
|
|
animateSpinner(null, false);
|
|
$('#new-result-assets-select').parent().remove();
|
|
$(data.html).prependTo('#results').promise().done(function() {
|
|
$.each($('[data-container="new-reports"]').find('.result'),
|
|
function() {
|
|
initFormSubmitLinks($(this));
|
|
ResutlAssets.applyEditResultAssetCallback();
|
|
Results.applyCollapseLinkCallBack();
|
|
Results.toggleResultEditButtons(true);
|
|
FilePreviewModal.init();
|
|
Comments.init();
|
|
ResutlAssets.initNewResultAsset();
|
|
Results.expandResult($(this));
|
|
});
|
|
|
|
});
|
|
$('#results-toolbar').show();
|
|
},
|
|
error: function() {
|
|
animateSpinner();
|
|
location.reload();
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
function destroyAll() {
|
|
_dragNdropAssetsOff();
|
|
droppedFiles = [];
|
|
isValid = true;
|
|
totalSize = 0;
|
|
}
|
|
|
|
function _dragNdropAssetsOff() {
|
|
$('body').off('drag dragstart dragend dragover dragenter dragleave drop');
|
|
$('.is-dragover').hide();
|
|
}
|
|
|
|
return Object.freeze({
|
|
init: init,
|
|
listItems: listItems,
|
|
destroyAll: destroyAll,
|
|
filesStatus: filesStatus,
|
|
validateTextSize: validateTextSize,
|
|
processResult: processResult
|
|
});
|
|
})();
|
|
|
|
global.dragNdropAssetsInit = function(location) {
|
|
var in_window = true;
|
|
|
|
$('body').on('drag dragstart dragend dragover dragenter dragleave drop',
|
|
function(e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
}).on('dragover', function() {
|
|
in_window = true;
|
|
$('.is-dragover').show();
|
|
}).on('dragleave', function() {
|
|
in_window = false;
|
|
setTimeout(function() {
|
|
if(!in_window) {
|
|
$('.is-dragover').hide();
|
|
}
|
|
}, 5000);
|
|
|
|
}).on('drop', function(e) {
|
|
$('.is-dragover').hide();
|
|
var files = e.originalEvent.dataTransfer.files;
|
|
if(location === 'steps') {
|
|
DragNDropSteps.init(files);
|
|
} else {
|
|
DragNDropResults.init(files);
|
|
}
|
|
});
|
|
|
|
copyFromClipboard.init(location);
|
|
}
|
|
|
|
})(window);
|