diff --git a/app/controllers/dmsf_files_controller.rb b/app/controllers/dmsf_files_controller.rb index 6a5b6a7e..e6037bd2 100644 --- a/app/controllers/dmsf_files_controller.rb +++ b/app/controllers/dmsf_files_controller.rb @@ -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 diff --git a/app/models/dmsf_file.rb b/app/models/dmsf_file.rb index bd8b2a3c..f126943c 100644 --- a/app/models/dmsf_file.rb +++ b/app/models/dmsf_file.rb @@ -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 diff --git a/app/views/dmsf_files/_file_new_revision.html.erb b/app/views/dmsf_files/_file_new_revision.html.erb index 27b38162..4e0875de 100644 --- a/app/views/dmsf_files/_file_new_revision.html.erb +++ b/app/views/dmsf_files/_file_new_revision.html.erb @@ -46,6 +46,13 @@ <%= f.text_area(:description, :rows => 6, :class => 'wiki-edit') %>

+
+
+ <% @revision.custom_field_values.each do |value| %> +

<%= custom_field_tag_with_label(:dmsf_file_revision, value) %>

+ <% end %> +
+

<%= 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) %> -

-
-
-

- <%= label_tag('file_upload', l(:label_new_content)) %> - - <%= 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) %>) -

-
-
- <% @revision.custom_field_values.each do |value| %> -

<%= custom_field_tag_with_label(:dmsf_file_revision, value) %>

- <% end %> -
+ +
+

+ <%= label_tag('file_upload', l(:label_new_content)) %> + <%= render :partial => 'upload_form' %> +

+

<%= f.text_area(:comment, :rows => 2, :label => l(:label_comment)) %>

@@ -99,4 +87,4 @@ -<%= wikitoolbar_for 'dmsf_file_revision_description' %> \ No newline at end of file +<%= wikitoolbar_for 'dmsf_file_revision_description' %> diff --git a/app/views/dmsf_files/_upload_form.html.erb b/app/views/dmsf_files/_upload_form.html.erb new file mode 100644 index 00000000..df4d6954 --- /dev/null +++ b/app/views/dmsf_files/_upload_form.html.erb @@ -0,0 +1,36 @@ +<% hide = false %> + + +<% if defined?(container) && container && container.saved_attachments %> + <% container.saved_attachments.each_with_index do |attachment, i| %> + + <%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename') %> + <%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %> + <% hide = true %> + + <% end %> +<% end %> + + +<% unless hide %> + + <%= 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) %>) + +<% end %> + +<% content_for :header_tags do %> + <%= javascript_include_tag 'attachments_dmsf', :plugin => 'redmine_dmsf' %> +<% end %> diff --git a/assets/javascripts/attachments_dmsf.js b/assets/javascripts/attachments_dmsf.js new file mode 100644 index 00000000..6589bcee --- /dev/null +++ b/assets/javascripts/attachments_dmsf.js @@ -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 = $('', { id: 'attachments_' + attachmentId }); + + fileSpan.append( + $('', { 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 = $('
').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); diff --git a/config/locales/cs.yml b/config/locales/cs.yml index b77796b9..73f77152 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -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(ů)." diff --git a/config/locales/de.yml b/config/locales/de.yml index 3cfa3576..53f5bc79 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -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." diff --git a/config/locales/en.yml b/config/locales/en.yml index 74e5db07..3979ce52 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -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." diff --git a/config/locales/es.yml b/config/locales/es.yml index 30fc5fd6..6318ba58 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -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." diff --git a/config/locales/fr.yml b/config/locales/fr.yml index c8e9fee6..9c237a59 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -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." diff --git a/config/locales/it.yml b/config/locales/it.yml index 83af58d2..edc9d38c 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -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." diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 5f8b1733..a50e53a6 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -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." diff --git a/config/locales/pl.yml b/config/locales/pl.yml index f69ae385..38f66ac3 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -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." diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 288e5a56..03881324 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -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." diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 6d66880d..9005d33b 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -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." diff --git a/config/locales/sl.yml b/config/locales/sl.yml index d6684b1e..a66b2420 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -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." diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index ecb62914..4a75e501 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -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." diff --git a/config/locales/zh.yml b/config/locales/zh.yml index 5bb0ff1b..547dd2a5 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -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."