Merge branch 'devel-2.4.5' into webdav_project_tree
This commit is contained in:
commit
119330836e
@ -1,6 +1,9 @@
|
||||
Changelog for Redmine DMSF
|
||||
==========================
|
||||
|
||||
2.4.5 *????-??-??*
|
||||
------------------
|
||||
|
||||
2.4.4 *2020-07-10*
|
||||
------------------
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
Redmine DMSF Plugin
|
||||
===================
|
||||
|
||||
The current version of Redmine DMSF is **2.4.4** [](https://travis-ci.org/danmunn/redmine_dmsf)
|
||||
The current version of Redmine DMSF is **2.4.5 devel** [](https://travis-ci.org/danmunn/redmine_dmsf)
|
||||
|
||||
Redmine DMSF is Document Management System Features plugin for Redmine issue tracking system; It is aimed to replace current Redmine's Documents module.
|
||||
|
||||
|
||||
@ -67,8 +67,8 @@ def dmsf_init
|
||||
pmap.permission :file_manipulation,
|
||||
{ dmsf_files: [:create_revision, :lock, :unlock, :delete_revision, :obsolete_revision,
|
||||
:notify_activate, :notify_deactivate, :restore],
|
||||
dmsf_upload: [:upload_files, :upload_file, :upload, :commit_files, :commit,
|
||||
:delete_dmsf_attachment, :delete_dmsf_link_attachment, :multi_upload],
|
||||
dmsf_upload: [:upload_files, :upload, :commit_files, :commit, :delete_dmsf_attachment,
|
||||
:delete_dmsf_link_attachment, :multi_upload],
|
||||
dmsf_links: [:new, :create, :destroy, :restore, :autocomplete_for_project,
|
||||
:autocomplete_for_folder],
|
||||
dmsf_files_copy: [:new, :copy, :move],
|
||||
|
||||
@ -392,6 +392,7 @@ class DmsfController < ApplicationController
|
||||
# Move the dragged object to the given destination
|
||||
def drop
|
||||
result = false
|
||||
object = nil
|
||||
if params[:dmsf_folder].present? && params[:dmsf_folder][:drag_id].present? && params[:dmsf_folder][:drop_id].present?
|
||||
if params[:dmsf_folder][:drag_id] =~ /(.+)-(\d+)/
|
||||
type = $1
|
||||
@ -399,22 +400,20 @@ class DmsfController < ApplicationController
|
||||
if params[:dmsf_folder][:drop_id] =~ /^folder.*-(\d+)/
|
||||
case type
|
||||
when 'file'
|
||||
dmsf_file = DmsfFile.find_by(id: id)
|
||||
dmsf_folder = DmsfFolder.find_by(id: $1)
|
||||
if dmsf_file && dmsf_folder
|
||||
result = dmsf_file.move_to(dmsf_file.project, dmsf_folder)
|
||||
end
|
||||
object = DmsfFile.find_by(id: id)
|
||||
when 'folder'
|
||||
dmsf_folder = DmsfFolder.find_by(id: id)
|
||||
if dmsf_folder
|
||||
dmsf_folder.dmsf_folder_id = $1
|
||||
result = dmsf_folder.save
|
||||
end
|
||||
object = DmsfFolder.find_by(id: id)
|
||||
when 'file-link', 'folder-link', 'url-link'
|
||||
dmsf_link = DmsfLink.find_by(id: id)
|
||||
if dmsf_link
|
||||
dmsf_link.dmsf_folder_id = $1
|
||||
result = dmsf_link.save
|
||||
object = DmsfLink.find_by(id: id)
|
||||
end
|
||||
dmsf_folder = DmsfFolder.find_by(id: $1)
|
||||
if object && dmsf_folder
|
||||
if dmsf_folder == object.dmsf_folder
|
||||
object.errors[:base] << l(:error_target_folder_same)
|
||||
elsif object.dmsf_folder.locked_for_user?
|
||||
object.errors[:base] << l(:error_folder_is_locked)
|
||||
else
|
||||
result = object.move_to(dmsf_folder.project, dmsf_folder)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -424,7 +423,13 @@ class DmsfController < ApplicationController
|
||||
if result
|
||||
format.js { head 200 }
|
||||
else
|
||||
format.js { head 422 }
|
||||
format.js {
|
||||
if object
|
||||
flash.now[:error] = object.errors.full_messages.to_sentence
|
||||
else
|
||||
head 422
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -128,17 +128,11 @@ class DmsfFilesController < ApplicationController
|
||||
revision.size = upload.size
|
||||
revision.disk_filename = revision.new_storage_filename
|
||||
revision.mime_type = upload.mime_type
|
||||
revision.digest = DmsfFileRevision.create_digest upload.tempfile_path
|
||||
end
|
||||
else
|
||||
revision.size = last_revision.size
|
||||
revision.disk_filename = last_revision.disk_filename
|
||||
revision.mime_type = last_revision.mime_type
|
||||
if last_revision.digest.blank?
|
||||
revision.digest = DmsfFileRevision.create_digest last_revision.disk_file
|
||||
else
|
||||
revision.digest = last_revision.digest
|
||||
end
|
||||
end
|
||||
|
||||
# Custom fields
|
||||
|
||||
@ -27,10 +27,8 @@ class DmsfUploadController < ApplicationController
|
||||
before_action :find_project, except: [:upload, :delete_dmsf_attachment, :delete_dmsf_link_attachment]
|
||||
before_action :authorize, except: [:upload, :delete_dmsf_attachment, :delete_dmsf_link_attachment]
|
||||
before_action :authorize_global, only: [:upload, :delete_dmsf_attachment, :delete_dmsf_link_attachment]
|
||||
before_action :find_folder, except: [:upload_file, :upload, :commit, :delete_dmsf_attachment,
|
||||
:delete_dmsf_link_attachment]
|
||||
before_action :permissions, except: [:upload_file, :upload, :commit, :delete_dmsf_attachment,
|
||||
:delete_dmsf_link_attachment]
|
||||
before_action :find_folder, except: [:upload, :commit, :delete_dmsf_attachment, :delete_dmsf_link_attachment]
|
||||
before_action :permissions, except: [:upload, :commit, :delete_dmsf_attachment, :delete_dmsf_link_attachment]
|
||||
|
||||
helper :all
|
||||
helper :dmsf_workflows
|
||||
@ -57,27 +55,6 @@ class DmsfUploadController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
# async single file upload handling
|
||||
def upload_file
|
||||
@tempfile = params[:file]
|
||||
unless @tempfile.original_filename
|
||||
render_404
|
||||
return
|
||||
end
|
||||
@disk_filename = DmsfHelper.temp_filename(@tempfile.original_filename)
|
||||
@tempfile_path = DmsfHelper.temp_dir.join(@disk_filename).to_s
|
||||
File.open(@tempfile_path, 'wb') do |f|
|
||||
if params[:file].respond_to?(:read)
|
||||
while (buffer = @tempfile.read(8192))
|
||||
f.write(buffer)
|
||||
end
|
||||
else
|
||||
f.write(@tempfile)
|
||||
end
|
||||
end
|
||||
render layout: false
|
||||
end
|
||||
|
||||
# REST API and Redmine attachment form
|
||||
def upload
|
||||
unless request.content_type == 'application/octet-stream'
|
||||
@ -85,7 +62,7 @@ class DmsfUploadController < ApplicationController
|
||||
return
|
||||
end
|
||||
|
||||
@attachment = Attachment.new(file: request.raw_post)
|
||||
@attachment = Attachment.new(file: request.body)
|
||||
@attachment.author = User.current
|
||||
@attachment.filename = params[:filename].presence || Redmine::Utils.random_hex(16)
|
||||
@attachment.content_type = params[:content_type].presence
|
||||
@ -124,6 +101,7 @@ class DmsfUploadController < ApplicationController
|
||||
uploaded_file[:disk_filename] = upload.disk_filename
|
||||
uploaded_file[:tempfile_path] = upload.tempfile_path
|
||||
uploaded_file[:size] = upload.size
|
||||
uploaded_file[:digest] = upload.digest
|
||||
end
|
||||
end
|
||||
commit_files_internal uploaded_files
|
||||
|
||||
@ -80,7 +80,7 @@ module DmsfUploadHelper
|
||||
end
|
||||
new_revision.mime_type = commited_file[:mime_type]
|
||||
new_revision.size = commited_file[:size]
|
||||
new_revision.digest = DmsfFileRevision.create_digest commited_file[:tempfile_path]
|
||||
new_revision.digest = commited_file[:digest]
|
||||
|
||||
if commited_file[:custom_field_values].present?
|
||||
i = 0
|
||||
@ -96,12 +96,12 @@ module DmsfUploadHelper
|
||||
new_revision.disk_filename = new_revision.new_storage_filename
|
||||
else
|
||||
Rails.logger.error (new_revision.errors.full_messages + file.errors.full_messages).to_sentence
|
||||
failed_uploads.push(commited_file)
|
||||
failed_uploads.push commited_file
|
||||
next
|
||||
end
|
||||
|
||||
if new_revision.save
|
||||
new_revision.assign_workflow(commited_file[:dmsf_workflow_id])
|
||||
new_revision.assign_workflow commited_file[:dmsf_workflow_id]
|
||||
begin
|
||||
FileUtils.mv commited_file[:tempfile_path], new_revision.disk_file(false)
|
||||
FileUtils.chmod 'u=wr,g=r', new_revision.disk_file(false)
|
||||
|
||||
@ -240,10 +240,12 @@ class DmsfFile < ActiveRecord::Base
|
||||
def move_to(project, folder)
|
||||
if locked_for_user?
|
||||
errors[:base] << l(:error_file_is_locked)
|
||||
Rails.logger.error l(:error_file_is_locked)
|
||||
return false
|
||||
end
|
||||
unless last_revision
|
||||
errors[:base] << l(:error_at_least_one_revision_must_be_present)
|
||||
Rails.logger.error l(:error_at_least_one_revision_must_be_present)
|
||||
return false
|
||||
end
|
||||
source = "#{project.identifier}:#{dmsf_path_str}"
|
||||
|
||||
@ -268,11 +268,19 @@ class DmsfFileRevision < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def copy_file_content(open_file)
|
||||
sha = Digest::SHA256.new
|
||||
File.open(disk_file(false), 'wb') do |f|
|
||||
while (buffer = open_file.read(8192))
|
||||
f.write(buffer)
|
||||
if open_file.respond_to?(:read)
|
||||
while (buffer = open_file.read(8192))
|
||||
f.write buffer
|
||||
sha.update buffer
|
||||
end
|
||||
else
|
||||
f.write open_file
|
||||
sha.update open_file
|
||||
end
|
||||
end
|
||||
self.digest = sha.hexdigest
|
||||
end
|
||||
|
||||
# Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields
|
||||
@ -304,19 +312,6 @@ class DmsfFileRevision < ActiveRecord::Base
|
||||
format2
|
||||
end
|
||||
|
||||
def self.create_digest(path)
|
||||
begin
|
||||
Digest::SHA256.file(path).hexdigest
|
||||
rescue => e
|
||||
Rails.logger.error e.message
|
||||
0
|
||||
end
|
||||
end
|
||||
|
||||
def create_digest
|
||||
self.digest = DmsfFileRevision.create_digest(disk_file)
|
||||
end
|
||||
|
||||
# Returns either MD5 or SHA256 depending on the way self.digest was computed
|
||||
def digest_type
|
||||
digest.size < 64 ? 'MD5' : 'SHA256' if digest.present?
|
||||
|
||||
@ -35,6 +35,7 @@ class DmsfUpload
|
||||
attr_accessor :workflow
|
||||
attr_accessor :custom_values
|
||||
attr_accessor :tempfile_path
|
||||
attr_accessor :digest
|
||||
|
||||
def disk_file
|
||||
DmsfHelper.temp_dir.join(disk_filename).to_s
|
||||
@ -48,7 +49,8 @@ class DmsfUpload
|
||||
content_type: a.content_type,
|
||||
original_filename: a.filename,
|
||||
comment: uploaded_file[:description],
|
||||
tempfile_path: a.diskfile
|
||||
tempfile_path: a.diskfile,
|
||||
digest: a.digest
|
||||
}
|
||||
DmsfUpload.new project, folder, uploaded
|
||||
else
|
||||
@ -74,6 +76,7 @@ class DmsfUpload
|
||||
Rails.logger.error "Cannot find #{uploaded[:tempfile_path]}"
|
||||
end
|
||||
@tempfile_path = uploaded[:tempfile_path]
|
||||
@digest = uploaded[:digest]
|
||||
|
||||
if file.nil? || file.last_revision.nil?
|
||||
@title = DmsfFileRevision.filename_to_title(@name)
|
||||
|
||||
@ -70,7 +70,7 @@
|
||||
dataType: 'script',
|
||||
data: data,
|
||||
error: function(jqXHR, textStatus, errorThrown){
|
||||
alert(textStatus + " " + jqXHR.status);
|
||||
alert(errorThrown);
|
||||
ui.draggable.animate(ui.draggable.data("ui-draggable").originalPosition, "slow");
|
||||
},
|
||||
complete: function(jqXHR, textStatus, errorThrown){
|
||||
@ -85,6 +85,7 @@
|
||||
}
|
||||
ui.draggable.remove();
|
||||
}
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
23
app/views/dmsf/drop.js.erb
Normal file
23
app/views/dmsf/drop.js.erb
Normal file
@ -0,0 +1,23 @@
|
||||
<%
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Redmine plugin for Document Management System "Features"
|
||||
#
|
||||
# Copyright © 2011-20 Karel Pičman <karel.picman@kontron.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
%>
|
||||
|
||||
throw new Error("<%= j flash[:error] %>");
|
||||
@ -73,11 +73,7 @@
|
||||
|
||||
<%= form_tag(dmsf_folder_path(id: @project, folder_id: @folder), method: :get, id: 'query_form', class: 'dmsf-query-form') do %>
|
||||
<%= hidden_field_tag('folder_id', @folder.id) if @folder %>
|
||||
<% if defined?(EasyExtensions) %>
|
||||
<%= render partial: 'dmsf_queries/query_form' %>
|
||||
<% else %>
|
||||
<%= render partial: 'queries/query_form' %>
|
||||
<% end %>
|
||||
<%= render partial: 'queries/query_form' %>
|
||||
<% end %>
|
||||
<% if @query.valid? %>
|
||||
<% if @dmsf_count == 0 %>
|
||||
|
||||
@ -1,89 +0,0 @@
|
||||
<%= hidden_field_tag 'set_filter', '1' %>
|
||||
<%= hidden_field_tag 'type', @query.type, :disabled => true, :id => 'query_type' %>
|
||||
<%= query_hidden_sort_tag(@query) %>
|
||||
|
||||
<div id="query_form_with_buttons" class="hide-when-print">
|
||||
<div id="query_form_content">
|
||||
<fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>">
|
||||
<legend onclick="toggleFieldset(this);" class="icon icon-<%= @query.new_record? ? "expended" : "collapsed" %>"><%= l(:label_filter_plural) %></legend>
|
||||
<div style="<%= @query.new_record? ? "" : "display: none;" %>">
|
||||
<%= render :partial => 'queries/filters', :locals => {:query => @query} %>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<% if @query.available_columns.any? %>
|
||||
<fieldset id="options" class="collapsible collapsed">
|
||||
<legend onclick="toggleFieldset(this);" class="icon icon-collapsed"><%= l(:label_options) %></legend>
|
||||
<div class="hidden">
|
||||
<% if @query.available_display_types.size > 1 %>
|
||||
<div>
|
||||
<span class="field"><label for='display_type'><%= l(:label_display_type) %></label></span>
|
||||
<%= available_display_types_tags(@query) %>
|
||||
</div>
|
||||
<% end %>
|
||||
<table id="list-definition" class="<%= 'hidden' if (@query.display_type != 'list') %>">
|
||||
<% if @query.available_columns.any? %>
|
||||
<tr>
|
||||
<td class="field"><%= l(:field_column_names) %></td>
|
||||
<td><%= render_query_columns_selection(@query) %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% if @query.groupable_columns.any? %>
|
||||
<tr>
|
||||
<td class="field"><label for='group_by'><%= l(:field_group_by) %></label></td>
|
||||
<td><%= group_by_column_select_tag(@query) %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% if @query.available_block_columns.any? %>
|
||||
<tr>
|
||||
<td class="field"><%= l(:button_show) %></td>
|
||||
<td><%= available_block_columns_tags(@query) %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% if @query.available_totalable_columns.any? %>
|
||||
<tr>
|
||||
<td><%= l(:label_total_plural) %></td>
|
||||
<td><%= available_totalable_columns_tags(@query) %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
</div>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<p class="buttons">
|
||||
<%= link_to_function l(:button_apply), '$("#query_form").submit()', :class => 'icon icon-checked' %>
|
||||
<%= link_to l(:button_clear), { :set_filter => 1, :sort => '', :project_id => @project }, :class => 'icon icon-reload' %>
|
||||
<% if @query.new_record? %>
|
||||
<% if User.current.allowed_to?(:save_queries, @project, :global => true) %>
|
||||
<%= link_to_function l(:button_save),
|
||||
"$('#query_type').prop('disabled',false);$('#query_form').attr('action', '#{ @project ? new_project_query_path(@project) : new_query_path }').submit()",
|
||||
:class => 'icon icon-save' %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<% if @query.editable_by?(User.current) %>
|
||||
<%= link_to l(:button_edit), edit_query_path(@query), :class => 'icon icon-edit' %>
|
||||
<%= delete_link query_path(@query) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<%= error_messages_for @query %>
|
||||
<%# DMS modification do %>
|
||||
<%#= javascript_tag do %>
|
||||
<%= late_javascript_tag do %>
|
||||
<%# end %>
|
||||
$(function ($) {
|
||||
$('input[name=display_type]').change(function (e) {
|
||||
if ($("#display_type_list").is(':checked')) {
|
||||
$('table#list-definition').show();
|
||||
} else {
|
||||
$('table#list-definition').hide();
|
||||
}
|
||||
|
||||
})
|
||||
});
|
||||
|
||||
<% end %>
|
||||
@ -22,11 +22,12 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
%>
|
||||
|
||||
<div class="box tabular" style="padding-top: 10px">
|
||||
<div class="box tabular dmfs-box-tabular">
|
||||
<%= hidden_field_tag "commited_files[#{i}][disk_filename]", upload.disk_filename %>
|
||||
<%= hidden_field_tag "commited_files[#{i}][tempfile_path]", upload.tempfile_path %>
|
||||
<%= hidden_field_tag "commited_files[#{i}][size]", upload.size %>
|
||||
<%= hidden_field_tag "commited_files[#{i}][mime_type]", upload.mime_type %>
|
||||
<%= hidden_field_tag "commited_files[#{i}][digest]", upload.digest %>
|
||||
<div class="clear">
|
||||
<div class="splitcontentleft">
|
||||
<p>
|
||||
|
||||
@ -22,12 +22,13 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
%>
|
||||
|
||||
<div class="box tabular" style="padding-top: 10px">
|
||||
<div class="box tabular dmfs-box-tabular">
|
||||
<%= hidden_field_tag "commited_files[#{i}][disk_filename]", upload.disk_filename %>
|
||||
<%= hidden_field_tag "commited_files[#{i}][tempfile_path]", upload.tempfile_path %>
|
||||
<%= hidden_field_tag "commited_files[#{i}][size]", upload.size %>
|
||||
<%= hidden_field_tag "commited_files[#{i}][mime_type]", upload.mime_type %>
|
||||
<%= hidden_field_tag "commited_files[#{i}][name]", upload.name %>
|
||||
<%= hidden_field_tag "commited_files[#{i}][digest]", upload.digest %>
|
||||
<p class="warning"><%= l(:info_file_locked) %></p>
|
||||
<div class="clear">
|
||||
<div class="splitcontentleft">
|
||||
|
||||
@ -1 +1,23 @@
|
||||
<%
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Redmine plugin for Document Management System "Features"
|
||||
#
|
||||
# Copyright © 2011-20 Karel Pičman <karel.picman@kontron.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
%>
|
||||
|
||||
$('#dmsf_attachments_<%= j params[:attachment_id] %>').remove();
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
<%= render partial: '/dmsf/path',
|
||||
locals: { folder: @folder, filename: nil, title: l(:label_attachment_new) } %>
|
||||
<%= form_tag({ controller: 'dmsf_upload', action: 'upload_files', id: @project, folder_id: @folder },
|
||||
id: 'uploadform', method: :post, multipart: true) do %>
|
||||
{ id: 'uploadform', multipart: true }) do %>
|
||||
<div class="box tabular">
|
||||
<span class="dmsf-uploader">
|
||||
<%= render partial: 'dmsf_upload/form',
|
||||
|
||||
@ -27,4 +27,5 @@
|
||||
"content_type": "<%= @tempfile.content_type.gsub('"', '').html_safe %>",
|
||||
"disk_filename": "<%= @disk_filename.html_safe %>",
|
||||
"tempfile_path": "<%= @tempfile_path.html_safe %>"
|
||||
"digest": "<%= @digest.html_safe %>"
|
||||
}
|
||||
|
||||
@ -113,7 +113,7 @@ function dmsfAjaxUpload(file, attachmentId, fileSpan, inputEl) {
|
||||
|
||||
function onProgress(e) {
|
||||
if(e.lengthComputable) {
|
||||
this.progressbar( 'value', e.loaded * 100 / e.total );
|
||||
this.progressbar('value', e.loaded * 100 / e.total);
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,11 +132,11 @@ function dmsfAjaxUpload(file, attachmentId, fileSpan, inputEl) {
|
||||
.fail(function(result) {
|
||||
progressSpan.text(result.statusText);
|
||||
}).always(function() {
|
||||
dmsfAjaxUpload.uploading--;
|
||||
fileSpan.removeClass('ajax-loading');
|
||||
let form = fileSpan.parents('form');
|
||||
if ((form.queue('upload').length == 0) && (dmsfAjaxUpload.uploading == 0)) {
|
||||
$('input:submit', form).removeAttr('disabled');
|
||||
dmsfAjaxUpload.uploading--;
|
||||
fileSpan.removeClass('ajax-loading');
|
||||
let form = fileSpan.parents('form');
|
||||
if ((form.queue('upload').length == 0) && (dmsfAjaxUpload.uploading == 0)) {
|
||||
$('input:submit', form).removeAttr('disabled');
|
||||
}
|
||||
form.dequeue('upload');
|
||||
});
|
||||
@ -163,13 +163,6 @@ function dmsfRemoveFileLbl() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*function dmsfRemoveFile() {
|
||||
|
||||
$(this).parent('span').parent('span').remove();
|
||||
|
||||
return false;
|
||||
}*/
|
||||
|
||||
function dmsfUploadBlob(blob, uploadUrl, attachmentId, options) {
|
||||
|
||||
let actualOptions = $.extend({
|
||||
|
||||
@ -66,12 +66,6 @@ table.dmsf a.sort.asc.icon.icon-sorted-desc {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#query_form.dmsf-query-form .add-filter {
|
||||
float: right;
|
||||
text-align: right;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#query_form.dmsf-query-form td.values span:first-child {
|
||||
#query_form.dmsf-query-form td.values span[style]:first-child {
|
||||
display: inline !important;
|
||||
}
|
||||
|
||||
@ -319,6 +319,10 @@ div[id*="revision_access_"] {
|
||||
padding-left: 18px;
|
||||
}
|
||||
|
||||
.dmfs-box-tabular {
|
||||
padding-top: 10px
|
||||
}
|
||||
|
||||
/* New link form */
|
||||
#dmsf_link_target_file_id, #dmsf_link_target_folder_id, #dmsf_link_target_project_id, #dmsf_link_name{
|
||||
min-width: 40%;
|
||||
|
||||
@ -73,7 +73,6 @@ if Redmine::Plugin.installed? :redmine_dmsf
|
||||
get '/projects/:id/dmsf/upload/multi_upload', controller: 'dmsf_upload', action: 'multi_upload', as: 'multi_dmsf_upload'
|
||||
post '/projects/:id/dmsf/upload/files', controller: 'dmsf_upload', action: 'upload_files'
|
||||
get '/projects/:id/dmsf/upload/files', controller: 'dmsf_upload', action: 'upload_files'
|
||||
post '/projects/:id/dmsf/upload/file', controller: 'dmsf_upload', action: 'upload_file'
|
||||
post '/projects/:id/dmsf/upload', controller: 'dmsf_upload', action: 'upload'
|
||||
post '/projects/:id/dmsf/upload/commit', controller: 'dmsf_upload', action: 'commit_files'
|
||||
post '/projects/:id/dmsf/commit', controller: 'dmsf_upload', action: 'commit'
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
#!/bin/bash
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Redmine plugin for Document Management System "Features"
|
||||
@ -18,8 +19,6 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
# Authentication as input parameters either as login + password or the API key
|
||||
# -u ${1}:${2}
|
||||
# -H "X-Redmine-API-Key: ${1}"
|
||||
|
||||
2
init.rb
2
init.rb
@ -33,7 +33,7 @@ Redmine::Plugin.register :redmine_dmsf do
|
||||
end
|
||||
author 'Vít Jonáš / Daniel Munn / Karel Pičman'
|
||||
description 'Document Management System Features'
|
||||
version '2.4.4 devel'
|
||||
version '2.4.5 devel'
|
||||
|
||||
requires_redmine version_or_higher: '4.0.0'
|
||||
|
||||
|
||||
@ -139,6 +139,7 @@ module RedmineDmsf
|
||||
uploaded_file[:size] = upload.size
|
||||
uploaded_file[:mime_type] = upload.mime_type
|
||||
uploaded_file[:tempfile_path] = upload.tempfile_path
|
||||
uploaded_file[:digest] = upload.digest
|
||||
if params[:dmsf_attachments_wfs].present? && params[:dmsf_attachments_wfs][key].present?
|
||||
uploaded_file[:workflow_id] = params[:dmsf_attachments_wfs][key].to_i
|
||||
end
|
||||
|
||||
@ -25,7 +25,7 @@ module RedmineDmsf
|
||||
class DmsfViewListener < Redmine::Hook::ViewListener
|
||||
|
||||
def view_layouts_base_html_head(context={})
|
||||
return unless /^(Dmsf|Projects|Issues)/.match?(context[:controller].class.name)
|
||||
return unless /^(Dmsf|Projects|Issues|Queries)/.match?(context[:controller].class.name)
|
||||
meta = "\n".html_safe + stylesheet_link_tag('redmine_dmsf.css', plugin: :redmine_dmsf) +
|
||||
"\n".html_safe + stylesheet_link_tag('select2.min.css', plugin: :redmine_dmsf) +
|
||||
"\n".html_safe + javascript_include_tag('select2.min.js', plugin: :redmine_dmsf, defer: true) +
|
||||
|
||||
@ -603,9 +603,9 @@ module RedmineDmsf
|
||||
# Phusion passenger does not have a method "length" in its model
|
||||
# however, includes a size method - so we instead use reflection
|
||||
# to determine best approach to problem
|
||||
if request.body.respond_to? 'length'
|
||||
if request.body.respond_to?(:length)
|
||||
new_revision.size = request.body.length
|
||||
elsif request.body.respond_to? 'size'
|
||||
elsif request.body.respond_to?(:size)
|
||||
new_revision.size = request.body.size
|
||||
else
|
||||
new_revision.size = request.content_length # Bad Guess
|
||||
@ -616,11 +616,10 @@ module RedmineDmsf
|
||||
new_revision.disk_filename = new_revision.new_storage_filename unless reuse_revision
|
||||
|
||||
if new_revision.save
|
||||
new_revision.copy_file_content(request.body)
|
||||
new_revision.create_digest
|
||||
new_revision.copy_file_content request.body
|
||||
new_revision.save
|
||||
# Notifications
|
||||
DmsfMailer.deliver_files_updated(project, [f])
|
||||
DmsfMailer.deliver_files_updated project, [f]
|
||||
else
|
||||
raise InternalServerError
|
||||
end
|
||||
|
||||
@ -35,25 +35,38 @@ END_DESC
|
||||
|
||||
namespace :redmine do
|
||||
task :dmsf_create_digests => :environment do
|
||||
m = DmsfDigest.new
|
||||
m.create_digests
|
||||
m = DmsfCreateDigest.new
|
||||
m.dmsf_create_digests
|
||||
end
|
||||
end
|
||||
|
||||
class DmsfDigest
|
||||
class DmsfCreateDigest
|
||||
|
||||
def initialize
|
||||
@dry_run = ENV['dry_run']
|
||||
@force_sha256 = ENV['forceSHA256']
|
||||
end
|
||||
|
||||
def create_digests
|
||||
def dmsf_create_digests
|
||||
revisions = DmsfFileRevision.where(['digest IS NULL OR length(digest) < ?', @force_sha256 ? 64 : 32])
|
||||
count = revisions.count
|
||||
n = 0
|
||||
revisions.each_with_index do |rev, i|
|
||||
rev.create_digest
|
||||
rev.save unless @dry_run
|
||||
if File.exist?(rev.disk_file)
|
||||
sha = Digest::SHA256.new
|
||||
file = File.new rev.disk_file, 'r'
|
||||
if file.respond_to?(:read)
|
||||
while (buffer = file.read(8192))
|
||||
sha.update buffer
|
||||
end
|
||||
else
|
||||
sha.update @temp_file
|
||||
end
|
||||
rev.digest = sha.hexdigest
|
||||
rev.save unless @dry_run
|
||||
else
|
||||
puts "#{rev.disk_file} not found"
|
||||
end
|
||||
n += 1
|
||||
# Progress bar
|
||||
print "\r#{i * 100 / count}%"
|
||||
|
||||
@ -77,18 +77,9 @@ class DmsfFileRevisionTest < RedmineDmsf::Test::UnitTest
|
||||
assert_nil DmsfFileRevision.find_by(id: @revision5.id)
|
||||
end
|
||||
|
||||
def test_create_digest
|
||||
@revision1.create_digest
|
||||
assert_equal 'SHA256', @revision1.digest_type
|
||||
assert_equal @revision8.create_digest, 0, 'Digest should be 0, if the file is missing'
|
||||
end
|
||||
|
||||
def test_digest_type
|
||||
# Old type MD5
|
||||
assert_equal 'MD5', @revision1.digest_type
|
||||
# New type SHA256
|
||||
@revision1.create_digest
|
||||
assert_equal 'SHA256', @revision1.digest_type
|
||||
end
|
||||
|
||||
def test_new_storage_filename
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user