drag/drop feature for new content #443
This commit is contained in:
parent
7626815961
commit
cfbae13b56
@ -135,7 +135,8 @@ class DmsfFilesController < ApplicationController
|
||||
else
|
||||
revision.increase_version(version)
|
||||
end
|
||||
file_upload = params[:file_upload]
|
||||
#file_upload = params[:file_upload]
|
||||
file_upload = params[:attachments]['1'] if params[:attachments].present?
|
||||
unless file_upload
|
||||
revision.size = last_revision.size
|
||||
revision.disk_filename = last_revision.disk_filename
|
||||
@ -146,10 +147,11 @@ class DmsfFilesController < ApplicationController
|
||||
revision.digest = last_revision.digest
|
||||
end
|
||||
else
|
||||
upload = DmsfUpload.create_from_uploaded_attachment(@project, @folder, file_upload)
|
||||
revision.size = file_upload.size
|
||||
revision.disk_filename = revision.new_storage_filename
|
||||
revision.mime_type = Redmine::MimeType.of(file_upload.original_filename)
|
||||
revision.digest = DmsfFileRevision.create_digest file_upload.path
|
||||
revision.mime_type = upload.mime_type
|
||||
revision.digest = DmsfFileRevision.create_digest upload.disk_file
|
||||
end
|
||||
|
||||
# Custom fields
|
||||
@ -163,8 +165,8 @@ class DmsfFilesController < ApplicationController
|
||||
|
||||
if revision.save
|
||||
revision.assign_workflow(params[:dmsf_workflow_id])
|
||||
if file_upload
|
||||
revision.copy_file_content(file_upload)
|
||||
if upload
|
||||
FileUtils.mv(upload.disk_file, revision.disk_file)
|
||||
end
|
||||
if @file.locked? && !@file.locks.empty?
|
||||
begin
|
||||
|
||||
@ -201,7 +201,7 @@ class DmsfFile < ActiveRecord::Base
|
||||
|
||||
def notify?
|
||||
return true if self.notification
|
||||
return true if self.dmsf_folder && delf.dmsf_folder.notify?
|
||||
return true if self.dmsf_folder && self.dmsf_folder.notify?
|
||||
return true if !self.dmsf_folder && self.project.dmsf_notification
|
||||
return false
|
||||
end
|
||||
|
||||
@ -46,6 +46,13 @@
|
||||
<%= f.text_area(:description, :rows => 6, :class => 'wiki-edit') %>
|
||||
</p>
|
||||
<div class="clear">
|
||||
<div class="splitcontentright">
|
||||
<div class="custom_fields">
|
||||
<% @revision.custom_field_values.each do |value| %>
|
||||
<p><%= custom_field_tag_with_label(:dmsf_file_revision, value) %></p>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="splitcontentleft">
|
||||
<p>
|
||||
<%= label_tag('version_0', l(:label_dmsf_version)) %>
|
||||
@ -62,34 +69,15 @@
|
||||
<%= select_tag 'custom_version_major', options_for_select(0..99, @file.last_revision.major_version + 2), :onchange => '$("#version_3").prop("checked", true)' %>.
|
||||
<%= select_tag 'custom_version_minor', options_for_select(0..99, @file.last_revision.minor_version + 1), :onchange => '$("#version_3").prop("checked", true)' %>
|
||||
<%= l(:option_version_custom) %>
|
||||
</p>
|
||||
</div>
|
||||
<div class="splitcontentright">
|
||||
<p>
|
||||
<%= label_tag('file_upload', l(:label_new_content)) %>
|
||||
<span class="add_attachment">
|
||||
<%= file_field_tag 'file_upload',
|
||||
:id => 'file_upload',
|
||||
:class => 'file_selector',
|
||||
:multiple => false,
|
||||
:onchange => "$('#dmsf_file_revision_name').val(this.files[0].name)",
|
||||
:data => {
|
||||
:max_file_size => Setting.attachment_max_size.to_i.kilobytes,
|
||||
:max_file_size_message => l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)),
|
||||
:max_concurrent_uploads => 1,
|
||||
:upload_path => uploads_path(:format => 'js')
|
||||
}
|
||||
%>
|
||||
(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="custom_fields">
|
||||
<% @revision.custom_field_values.each do |value| %>
|
||||
<p><%= custom_field_tag_with_label(:dmsf_file_revision, value) %></p>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<p>
|
||||
<%= label_tag('file_upload', l(:label_new_content)) %>
|
||||
<%= render :partial => 'upload_form' %>
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
<%= f.text_area(:comment, :rows => 2, :label => l(:label_comment)) %>
|
||||
</p>
|
||||
@ -99,4 +87,4 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= wikitoolbar_for 'dmsf_file_revision_description' %>
|
||||
<%= wikitoolbar_for 'dmsf_file_revision_description' %>
|
||||
|
||||
36
app/views/dmsf_files/_upload_form.html.erb
Normal file
36
app/views/dmsf_files/_upload_form.html.erb
Normal file
@ -0,0 +1,36 @@
|
||||
<% hide = false %>
|
||||
|
||||
<span id="attachments_fields">
|
||||
<% if defined?(container) && container && container.saved_attachments %>
|
||||
<% container.saved_attachments.each_with_index do |attachment, i| %>
|
||||
<span id="attachments_p<%= i %>">
|
||||
<%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename') %>
|
||||
<%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %>
|
||||
<% hide = true %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</span>
|
||||
|
||||
<% unless hide %>
|
||||
<span class="add_attachment">
|
||||
<%= file_field_tag 'attachments[dummy][file]',
|
||||
:id => nil,
|
||||
:class => 'file_selector',
|
||||
:multiple => false,
|
||||
:onchange => 'addInputFile(this);',
|
||||
:data => {
|
||||
:max_file_size => Setting.attachment_max_size.to_i.kilobytes,
|
||||
:max_file_size_message => l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)),
|
||||
:max_file_count_message => l(:error_maximum_upload_filecount, :filecount => 1),
|
||||
:max_concurrent_uploads => Redmine::Configuration['max_concurrent_ajax_uploads'].to_i,
|
||||
:upload_path => uploads_path(:format => 'js'),
|
||||
:description_placeholder => l(:label_optional_description)
|
||||
} %>
|
||||
(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)
|
||||
</span>
|
||||
<% end %>
|
||||
|
||||
<% content_for :header_tags do %>
|
||||
<%= javascript_include_tag 'attachments_dmsf', :plugin => 'redmine_dmsf' %>
|
||||
<% end %>
|
||||
206
assets/javascripts/attachments_dmsf.js
Normal file
206
assets/javascripts/attachments_dmsf.js
Normal file
@ -0,0 +1,206 @@
|
||||
/* Redmine - project management software
|
||||
Copyright (C) 2006-2016 Jean-Philippe Lang */
|
||||
|
||||
function addFile(inputEl, file, eagerUpload) {
|
||||
|
||||
if ($('#attachments_fields').children().length < 10) {
|
||||
|
||||
var attachmentId = addFile.nextAttachmentId++;
|
||||
|
||||
var fileSpan = $('<span>', { id: 'attachments_' + attachmentId });
|
||||
|
||||
fileSpan.append(
|
||||
$('<input>', { type: 'text', 'class': 'filename readonly', name: 'attachments[' + attachmentId + '][filename]', readonly: 'readonly'} ).val(file.name)
|
||||
).appendTo('#attachments_fields');
|
||||
|
||||
if(eagerUpload) {
|
||||
ajaxUpload(file, attachmentId, fileSpan, inputEl);
|
||||
}
|
||||
|
||||
toggleFileAdding(false);
|
||||
$('#dmsf_file_revision_name').val(file.name);
|
||||
|
||||
return attachmentId;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
addFile.nextAttachmentId = 1;
|
||||
|
||||
function ajaxUpload(file, attachmentId, fileSpan, inputEl) {
|
||||
|
||||
function onLoadstart(e) {
|
||||
fileSpan.removeClass('ajax-waiting');
|
||||
fileSpan.addClass('ajax-loading');
|
||||
$('input:submit', $(this).parents('form')).attr('disabled', 'disabled');
|
||||
}
|
||||
|
||||
function onProgress(e) {
|
||||
if(e.lengthComputable) {
|
||||
this.progressbar( 'value', e.loaded * 100 / e.total );
|
||||
}
|
||||
}
|
||||
|
||||
function actualUpload(file, attachmentId, fileSpan, inputEl) {
|
||||
|
||||
ajaxUpload.uploading++;
|
||||
|
||||
uploadBlob(file, $(inputEl).data('upload-path'), attachmentId, {
|
||||
loadstartEventHandler: onLoadstart.bind(progressSpan),
|
||||
progressEventHandler: onProgress.bind(progressSpan)
|
||||
})
|
||||
.done(function(result) {
|
||||
progressSpan.progressbar( 'value', 100 ).remove();
|
||||
fileSpan.find('input.description, a').css('display', 'inline-block');
|
||||
})
|
||||
.fail(function(result) {
|
||||
progressSpan.text(result.statusText);
|
||||
}).always(function() {
|
||||
ajaxUpload.uploading--;
|
||||
fileSpan.removeClass('ajax-loading');
|
||||
var form = fileSpan.parents('form');
|
||||
if (form.queue('upload').length == 0 && ajaxUpload.uploading == 0) {
|
||||
$('input:submit', form).removeAttr('disabled');
|
||||
}
|
||||
form.dequeue('upload');
|
||||
});
|
||||
}
|
||||
|
||||
var progressSpan = $('<div>').insertAfter(fileSpan.find('input.filename'));
|
||||
progressSpan.progressbar();
|
||||
fileSpan.addClass('ajax-waiting');
|
||||
|
||||
var maxSyncUpload = $(inputEl).data('max-concurrent-uploads');
|
||||
|
||||
if(maxSyncUpload == null || maxSyncUpload <= 0 || ajaxUpload.uploading < maxSyncUpload)
|
||||
actualUpload(file, attachmentId, fileSpan, inputEl);
|
||||
else
|
||||
$(inputEl).parents('form').queue('upload', actualUpload.bind(this, file, attachmentId, fileSpan, inputEl));
|
||||
}
|
||||
|
||||
ajaxUpload.uploading = 0;
|
||||
|
||||
function removeFile() {
|
||||
|
||||
$(this).parent('span').remove();
|
||||
toggleFileAdding(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
function uploadBlob(blob, uploadUrl, attachmentId, options) {
|
||||
|
||||
var actualOptions = $.extend({
|
||||
loadstartEventHandler: $.noop,
|
||||
progressEventHandler: $.noop
|
||||
}, options);
|
||||
|
||||
uploadUrl = uploadUrl + '?attachment_id=' + attachmentId;
|
||||
if (blob instanceof window.File) {
|
||||
uploadUrl += '&filename=' + encodeURIComponent(blob.name);
|
||||
uploadUrl += '&content_type=' + encodeURIComponent(blob.type);
|
||||
}
|
||||
|
||||
return $.ajax(uploadUrl, {
|
||||
type: 'POST',
|
||||
contentType: 'application/octet-stream',
|
||||
beforeSend: function(jqXhr, settings) {
|
||||
jqXhr.setRequestHeader('Accept', 'application/js');
|
||||
// attach proper File object
|
||||
settings.data = blob;
|
||||
},
|
||||
xhr: function() {
|
||||
var xhr = $.ajaxSettings.xhr();
|
||||
xhr.upload.onloadstart = actualOptions.loadstartEventHandler;
|
||||
xhr.upload.onprogress = actualOptions.progressEventHandler;
|
||||
return xhr;
|
||||
},
|
||||
data: blob,
|
||||
cache: false,
|
||||
processData: false
|
||||
});
|
||||
}
|
||||
|
||||
function addInputFile(inputEl) {
|
||||
var clearedFileInput = $(inputEl).clone().val('');
|
||||
|
||||
if ($.ajaxSettings.xhr().upload && inputEl.files) {
|
||||
// upload files using ajax
|
||||
uploadAndAttachFiles(inputEl.files, inputEl);
|
||||
$(inputEl).remove();
|
||||
} else {
|
||||
// browser not supporting the file API, upload on form submission
|
||||
var attachmentId;
|
||||
var aFilename = inputEl.value.split(/\/|\\/);
|
||||
attachmentId = addFile(inputEl, { name: aFilename[ aFilename.length - 1 ] }, false);
|
||||
if (attachmentId) {
|
||||
$(inputEl).attr({ name: 'attachments[' + attachmentId + '][file]', style: 'display:none;' }).appendTo('#attachments_' + attachmentId);
|
||||
}
|
||||
}
|
||||
|
||||
clearedFileInput.insertAfter('#attachments_fields');
|
||||
|
||||
toggleFileAdding(false);
|
||||
}
|
||||
|
||||
function uploadAndAttachFiles(files, inputEl) {
|
||||
|
||||
var maxFileSize = $(inputEl).data('max-file-size');
|
||||
var maxFileSizeExceeded = $(inputEl).data('max-file-size-message');
|
||||
var maxFileCountExceeded = $(inputEl).data('max-file-count-message');
|
||||
|
||||
var sizeExceeded = false;
|
||||
$.each(files, function() {
|
||||
if (this.size && maxFileSize != null && this.size > parseInt(maxFileSize)) {sizeExceeded=true;}
|
||||
});
|
||||
if((files.length > 1) || (!$('input.file_selector').is(':visible'))){
|
||||
window.alert(maxFileCountExceeded);
|
||||
}
|
||||
else if (sizeExceeded) {
|
||||
window.alert(maxFileSizeExceeded);
|
||||
} else {
|
||||
$.each(files, function() {addFile(inputEl, this, true);});
|
||||
}
|
||||
}
|
||||
|
||||
function toggleFileAdding(toggle){
|
||||
|
||||
$('input.file_selector').toggle(toggle);
|
||||
$('span.add_attachment').toggle(toggle);
|
||||
}
|
||||
|
||||
function handleFileDropEvent(e) {
|
||||
|
||||
$(this).removeClass('fileover');
|
||||
blockEventPropagation(e);
|
||||
|
||||
if ($.inArray('Files', e.dataTransfer.types) > -1) {
|
||||
uploadAndAttachFiles(e.dataTransfer.files, $('input:file.file_selector'));
|
||||
}
|
||||
}
|
||||
|
||||
function dragOverHandler(e) {
|
||||
$(this).addClass('fileover');
|
||||
blockEventPropagation(e);
|
||||
}
|
||||
|
||||
function dragOutHandler(e) {
|
||||
$(this).removeClass('fileover');
|
||||
blockEventPropagation(e);
|
||||
}
|
||||
|
||||
function setupFileDrop() {
|
||||
if (window.File && window.FileList && window.ProgressEvent && window.FormData) {
|
||||
|
||||
$.event.fixHooks.drop = { props: [ 'dataTransfer' ] };
|
||||
|
||||
$('form div.box').has('input:file').each(function() {
|
||||
$(this).on({
|
||||
dragover: dragOverHandler,
|
||||
dragleave: dragOutHandler,
|
||||
drop: handleFileDropEvent
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(setupFileDrop);
|
||||
@ -330,4 +330,6 @@ cs:
|
||||
label_maximum_ajax_upload_filesize: Maximální velikost souboru nahratelná přes AJAX
|
||||
note_maximum_ajax_upload_filesize: Omezuje velikost souboru, který může být nahrán přes standardní rozhraní AJAX, jinak se použije standardní rozhraní Redminu. Číslo je v MB.
|
||||
label_classic: Klasický
|
||||
label_drag_drop: "Drag&Drop"
|
||||
label_drag_drop: Moderní
|
||||
|
||||
error_maximum_upload_filecount: "Nelze nahrát více než %{filecount} soubor(ů)."
|
||||
|
||||
@ -330,4 +330,6 @@ de:
|
||||
label_maximum_ajax_upload_filesize: Maximale Dateigröße für den Upload via AJAX
|
||||
note_maximum_ajax_upload_filesize: Maximale Dateigröße für den Upload über die AJAX-Schnittstelle. Für größere Dateien muss der Standard-Uploader von Redmine verwendet werden. Angabe in MB.
|
||||
label_classic: Klassisch
|
||||
label_drag_drop: "Drag&Drop"
|
||||
label_drag_drop: Modern
|
||||
|
||||
error_maximum_upload_filecount: "Nicht mehr als %{filecount} Datai(en) kann man hochladen."
|
||||
|
||||
@ -330,4 +330,6 @@ en:
|
||||
label_maximum_ajax_upload_filesize: Maximum file size uploadable via AJAX
|
||||
note_maximum_ajax_upload_filesize: Limits maximum file size that can uploaded via standard AJAX interface otherwise Redmine standard upload form must be used. Number is in MB.
|
||||
label_classic: Classic
|
||||
label_drag_drop: "Drag&Drop"
|
||||
label_drag_drop: Modern
|
||||
|
||||
error_maximum_upload_filecount: "No more than %{filecount} file(s) can be uploaded."
|
||||
|
||||
@ -330,4 +330,6 @@ es:
|
||||
label_maximum_ajax_upload_filesize: "El máximo tamaño de archivo para subir por AJAX"
|
||||
note_maximum_ajax_upload_filesize: "El límite máximo de tamaño de archivo que puede ser subido por la interfaz AJAX estandar, de lo contrario se debe utilizar el formulario estandar de Redmine. El número es en MB."
|
||||
label_classic: Classic
|
||||
label_drag_drop: "Drag&Drop"
|
||||
label_drag_drop: Modern
|
||||
|
||||
error_maximum_upload_filecount: "No more than %{filecount} file(s) can be uploaded."
|
||||
|
||||
@ -330,4 +330,6 @@ fr:
|
||||
label_maximum_ajax_upload_filesize: Taille maximale de fichier pour téléversement via AJAX
|
||||
note_maximum_ajax_upload_filesize: "Taille maximale, en méga octets, de fichier pour téléversement via l'interface standard AJAX. Sinon l'interface standard de Redmine doit être utilisée."
|
||||
label_classic: Classic
|
||||
label_drag_drop: "Drag&Drop"
|
||||
label_drag_drop: Modern
|
||||
|
||||
error_maximum_upload_filecount: "No more than %{filecount} file(s) can be uploaded."
|
||||
|
||||
@ -330,4 +330,6 @@ it: # Italian strings thx 2 Matteo Arceci!
|
||||
label_maximum_ajax_upload_filesize: Dimensione massima dei documenti caricabili tramite AJAX
|
||||
note_maximum_ajax_upload_filesize: Limita la dimensione massima dei documenti che possono essere caricati tramite interfaccia standard AJAX altrimenti sarà necessario utilizzare il modulo standard di Redmine. Il numero è espresso in MB.
|
||||
label_classic: Classic
|
||||
label_drag_drop: "Drag&Drop"
|
||||
label_drag_drop: Modern
|
||||
|
||||
error_maximum_upload_filecount: "No more than %{filecount} file(s) can be uploaded."
|
||||
|
||||
@ -330,4 +330,6 @@ ja:
|
||||
label_maximum_ajax_upload_filesize: アップロードファイルサイズ上限
|
||||
note_maximum_ajax_upload_filesize: アップロード可能なファイルサイズの上限。AjaxおよびRedmineの仕様に制限される(2ギガバイト程度までは確認済み)単位はMB。
|
||||
label_classic: Classic
|
||||
label_drag_drop: "Drag&Drop"
|
||||
label_drag_drop: Modern
|
||||
|
||||
error_maximum_upload_filecount: "No more than %{filecount} file(s) can be uploaded."
|
||||
|
||||
@ -330,4 +330,6 @@ pl:
|
||||
label_maximum_ajax_upload_filesize: Maximum file size uploadable via AJAX
|
||||
note_maximum_ajax_upload_filesize: Limits maximum file size that can uploaded via standard AJAX interface otherwise Redmine standard upload form must be used. Number is in MB.
|
||||
label_classic: Classic
|
||||
label_drag_drop: "Drag&Drop"
|
||||
label_drag_drop: Modern
|
||||
|
||||
error_maximum_upload_filecount: "No more than %{filecount} file(s) can be uploaded."
|
||||
|
||||
@ -330,4 +330,6 @@ pt-BR:
|
||||
label_maximum_ajax_upload_filesize: Maximum file size uploadable via AJAX
|
||||
note_maximum_ajax_upload_filesize: Limits maximum file size that can uploaded via standard AJAX interface otherwise Redmine standard upload form must be used. Number is in MB.
|
||||
label_classic: Classic
|
||||
label_drag_drop: "Drag&Drop"
|
||||
label_drag_drop: Modern
|
||||
|
||||
error_maximum_upload_filecount: "No more than %{filecount} file(s) can be uploaded."
|
||||
|
||||
@ -330,4 +330,6 @@ ru:
|
||||
label_maximum_ajax_upload_filesize: Максимальный размер файла, загружаемого посредством AJAX
|
||||
note_maximum_ajax_upload_filesize: Превышает максимальный размер файла, загружаемого посредством интерфейса AJAX, для загрузки можно использовать стандартную форму Redmine. Размер указан в MB.
|
||||
label_classic: Classic
|
||||
label_drag_drop: "Drag&Drop"
|
||||
label_drag_drop: Modern
|
||||
|
||||
error_maximum_upload_filecount: "No more than %{filecount} file(s) can be uploaded."
|
||||
|
||||
@ -330,4 +330,6 @@ sl:
|
||||
label_maximum_ajax_upload_filesize: Maximum file size uploadable via AJAX
|
||||
note_maximum_ajax_upload_filesize: Limits maximum file size that can uploaded via standard AJAX interface otherwise Redmine standard upload form must be used. Number is in MB.
|
||||
label_classic: Classic
|
||||
label_drag_drop: "Drag&Drop"
|
||||
label_drag_drop: Modern
|
||||
|
||||
error_maximum_upload_filecount: "No more than %{filecount} file(s) can be uploaded."
|
||||
|
||||
@ -330,4 +330,6 @@ zh-TW:
|
||||
label_maximum_ajax_upload_filesize: Maximum file size uploadable via AJAX
|
||||
note_maximum_ajax_upload_filesize: Limits maximum file size that can uploaded via standard AJAX interface otherwise Redmine standard upload form must be used. Number is in MB.
|
||||
label_classic: Classic
|
||||
label_drag_drop: "Drag&Drop"
|
||||
label_drag_drop: Modern
|
||||
|
||||
error_maximum_upload_filecount: "No more than %{filecount} file(s) can be uploaded."
|
||||
|
||||
@ -330,4 +330,6 @@ zh:
|
||||
label_maximum_ajax_upload_filesize: Maximum file size uploadable via AJAX
|
||||
note_maximum_ajax_upload_filesize: Limits maximum file size that can uploaded via standard AJAX interface otherwise Redmine standard upload form must be used. Number is in MB.
|
||||
label_classic: Classic
|
||||
label_drag_drop: "Drag&Drop"
|
||||
label_drag_drop: Modern
|
||||
|
||||
error_maximum_upload_filecount: "No more than %{filecount} file(s) can be uploaded."
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user