#48 Attached documents available in the DMS view

This commit is contained in:
Karel Picman 2017-04-26 12:08:53 +02:00
parent 208b8b1ae7
commit c1a5939c7c
56 changed files with 400 additions and 274 deletions

View File

@ -38,7 +38,7 @@ class DmsfController < ApplicationController
helper :dmsf_folder_permissions helper :dmsf_folder_permissions
def permissions def permissions
render_403 unless DmsfFolder.permissions(@folder) render_403 unless DmsfFolder.permissions?(@folder)
true true
end end
@ -80,7 +80,7 @@ class DmsfController < ApplicationController
@file_manipulation_allowed = User.current.allowed_to? :file_manipulation, @project @file_manipulation_allowed = User.current.allowed_to? :file_manipulation, @project
@file_delete_allowed = User.current.allowed_to? :file_delete, @project @file_delete_allowed = User.current.allowed_to? :file_delete, @project
@subfolders = DmsfFolder.deleted.where(:project_id => @project.id) @subfolders = DmsfFolder.deleted.where(:project_id => @project.id)
@files = DmsfFile.deleted.where(:container_id => @project.id, :container_type => 'Project') @files = DmsfFile.deleted.where(:project_id => @project.id)
@dir_links = DmsfLink.deleted.where(:project_id => @project.id, :target_type => DmsfFolder.model_name.to_s) @dir_links = DmsfLink.deleted.where(:project_id => @project.id, :target_type => DmsfFolder.model_name.to_s)
@file_links = DmsfLink.deleted.where(:project_id => @project.id, :target_type => DmsfFile.model_name.to_s) @file_links = DmsfLink.deleted.where(:project_id => @project.id, :target_type => DmsfFile.model_name.to_s)
@url_links = DmsfLink.deleted.where(:project_id => @project.id, :target_type => 'DmsfUrl') @url_links = DmsfLink.deleted.where(:project_id => @project.id, :target_type => 'DmsfUrl')
@ -643,6 +643,7 @@ class DmsfController < ApplicationController
private private
def get_display_params def get_display_params
@system_folder = @folder && @folder.system
@folder_manipulation_allowed = User.current.allowed_to?(:folder_manipulation, @project) @folder_manipulation_allowed = User.current.allowed_to?(:folder_manipulation, @project)
@file_manipulation_allowed = User.current.allowed_to?(:file_manipulation, @project) @file_manipulation_allowed = User.current.allowed_to?(:file_manipulation, @project)
@file_delete_allowed = User.current.allowed_to?(:file_delete, @project) @file_delete_allowed = User.current.allowed_to?(:file_delete, @project)
@ -658,7 +659,7 @@ class DmsfController < ApplicationController
if tag if tag
@subfolders = [] @subfolders = []
folder_id = @folder.id if @folder folder_id = @folder.id if @folder
DmsfFolder.where(:project_id => @project.id, :dmsf_folder_id => folder_id).visible.each do |f| DmsfFolder.where(:project_id => @project.id, :dmsf_folder_id => folder_id, :system => false).visible.each do |f|
f.custom_field_values.each do |v| f.custom_field_values.each do |v|
if v.custom_field_id == params[:custom_field_id].to_i if v.custom_field_id == params[:custom_field_id].to_i
if v.custom_field.compare_values?(v.value, params[:custom_value]) if v.custom_field.compare_values?(v.value, params[:custom_value])
@ -669,7 +670,7 @@ class DmsfController < ApplicationController
end end
end end
@files = [] @files = []
DmsfFile.where(:container_id => @project.id, :container_type => 'Project', :dmsf_folder_id => folder_id).visible.each do |f| DmsfFile.where(:project_id => @project.id, :dmsf_folder_id => folder_id).visible.each do |f|
r = f.last_revision r = f.last_revision
if r if r
r.custom_field_values.each do |v| r.custom_field_values.each do |v|
@ -733,7 +734,7 @@ class DmsfController < ApplicationController
@trash_visible = @folder_manipulation_allowed && @file_manipulation_allowed && @trash_visible = @folder_manipulation_allowed && @file_manipulation_allowed &&
@file_delete_allowed && !@locked_for_user && !@folder @file_delete_allowed && !@locked_for_user && !@folder
@trash_enabled = DmsfFolder.deleted.where(:project_id => @project.id).any? || @trash_enabled = DmsfFolder.deleted.where(:project_id => @project.id).any? ||
DmsfFile.deleted.where(:container_id => @project.id, :container_type => 'Project').any? || DmsfFile.deleted.where(:project_id => @project.id).any? ||
DmsfLink.deleted.where(:project_id => @project.id).any? DmsfLink.deleted.where(:project_id => @project.id).any?
end end

View File

@ -38,7 +38,7 @@ class DmsfFilesController < ApplicationController
def permissions def permissions
if @file if @file
render_403 unless DmsfFolder.permissions(@file.dmsf_folder) render_403 unless DmsfFolder.permissions?(@file.dmsf_folder)
end end
true true
end end
@ -192,7 +192,7 @@ class DmsfFilesController < ApplicationController
commit = params[:commit] == 'yes' commit = params[:commit] == 'yes'
if @file.delete(commit) if @file.delete(commit)
flash[:notice] = l(:notice_file_deleted) flash[:notice] = l(:notice_file_deleted)
if commit && (@file.container_type == 'Project') if commit
log_activity('deleted') log_activity('deleted')
begin begin
recipients = DmsfMailer.get_notify_users(@project, [@file]) recipients = DmsfMailer.get_notify_users(@project, [@file])

View File

@ -27,7 +27,7 @@ class DmsfFolderPermissionsController < ApplicationController
before_filter :permissions before_filter :permissions
def permissions def permissions
render_403 unless DmsfFolder.permissions(@dmsf_folder) render_403 unless DmsfFolder.permissions?(@dmsf_folder)
true true
end end

View File

@ -26,7 +26,7 @@ class DmsfFoldersCopyController < ApplicationController
before_filter :permissions before_filter :permissions
def permissions def permissions
render_403 unless DmsfFolder.permissions(@folder) render_403 unless DmsfFolder.permissions?(@folder)
true true
end end

View File

@ -29,7 +29,7 @@ class DmsfLinksController < ApplicationController
def permissions def permissions
if @dmsf_link if @dmsf_link
render_403 unless DmsfFolder.permissions(@dmsf_link.dmsf_folder) render_403 unless DmsfFolder.permissions?(@dmsf_link.dmsf_folder)
end end
true true
end end

View File

@ -36,7 +36,7 @@ class DmsfUploadController < ApplicationController
accept_api_auth :upload, :commit accept_api_auth :upload, :commit
def permissions def permissions
render_403 unless DmsfFolder.permissions(@folder) render_403 unless DmsfFolder.permissions?(@folder)
true true
end end

View File

@ -32,7 +32,7 @@ class DmsfWorkflowsController < ApplicationController
def permissions def permissions
revision = DmsfFileRevision.find_by_id params[:dmsf_file_revision_id] if params[:dmsf_file_revision_id].present? revision = DmsfFileRevision.find_by_id params[:dmsf_file_revision_id] if params[:dmsf_file_revision_id].present?
if revision if revision
render_403 unless revision.dmsf_file || DmsfFolder.permissions(revision.dmsf_file.dmsf_folder) render_403 unless revision.dmsf_file || DmsfFolder.permissions?(revision.dmsf_file.dmsf_folder)
end end
true true
end end

View File

@ -21,20 +21,15 @@
module DmsfUploadHelper module DmsfUploadHelper
include Redmine::I18n include Redmine::I18n
def self.commit_files_internal(commited_files, container, folder, controller) def self.commit_files_internal(commited_files, project, folder, controller)
failed_uploads = [] failed_uploads = []
files = [] files = []
if container.is_a?(Project)
project = container
else
project = container.project
end
if commited_files && commited_files.is_a?(Hash) if commited_files && commited_files.is_a?(Hash)
failed_uploads = [] failed_uploads = []
commited_files.each_value do |commited_file| commited_files.each_value do |commited_file|
name = commited_file[:name] name = commited_file[:name]
new_revision = DmsfFileRevision.new new_revision = DmsfFileRevision.new
file = DmsfFile.visible.find_file_by_name(container, folder, name) file = DmsfFile.visible.find_file_by_name(project, folder, name)
unless file unless file
link = DmsfLink.find_link_by_file_name(project, folder, name) link = DmsfLink.find_link_by_file_name(project, folder, name)
file = link.target_file if link file = link.target_file if link
@ -42,8 +37,7 @@ module DmsfUploadHelper
unless file unless file
file = DmsfFile.new file = DmsfFile.new
file.container_type = container.class.name.demodulize file.project_id = project.id
file.container_id = container.id
file.name = name file.name = name
file.dmsf_folder = folder file.dmsf_folder = folder
file.notification = Setting.plugin_redmine_dmsf[:dmsf_default_notifications].present? file.notification = Setting.plugin_redmine_dmsf[:dmsf_default_notifications].present?
@ -119,7 +113,7 @@ module DmsfUploadHelper
failed_uploads.push(commited_file) failed_uploads.push(commited_file)
end end
end end
if container.is_a?(Project) && ((folder && folder.notification?) || (!folder && project.dmsf_notification?)) if ((folder && folder.notification?) || (!folder && project.dmsf_notification?))
begin begin
recipients = DmsfMailer.get_notify_users(project, files) recipients = DmsfMailer.get_notify_users(project, files)
recipients.each do |u| recipients.each do |u|

View File

@ -32,6 +32,7 @@ class DmsfFile < ActiveRecord::Base
include RedmineDmsf::Lockable include RedmineDmsf::Lockable
belongs_to :project
belongs_to :dmsf_folder belongs_to :dmsf_folder
belongs_to :deleted_by_user, :class_name => 'User', :foreign_key => 'deleted_by_user_id' belongs_to :deleted_by_user, :class_name => 'User', :foreign_key => 'deleted_by_user_id'
@ -58,7 +59,7 @@ class DmsfFile < ActiveRecord::Base
attr_accessible :project, :project_id attr_accessible :project, :project_id
def validates_name_uniqueness def validates_name_uniqueness
existing_file = DmsfFile.visible.findn_file_by_name(self.container_id, self.container_type, self.dmsf_folder, self.name) existing_file = DmsfFile.visible.findn_file_by_name(self.project_id, self.dmsf_folder, self.name)
errors.add(:name, l('activerecord.errors.messages.taken')) unless (existing_file.nil? || existing_file.id == self.id) errors.add(:name, l('activerecord.errors.messages.taken')) unless (existing_file.nil? || existing_file.id == self.id)
end end
@ -120,14 +121,13 @@ class DmsfFile < ActiveRecord::Base
@@storage_path = path @@storage_path = path
end end
def self.find_file_by_name(container, folder, name) def self.find_file_by_name(project, folder, name)
self.findn_file_by_name(container.id, container.class.name.demodulize, folder, name) self.findn_file_by_name(project.id, folder, name)
end end
def self.findn_file_by_name(container_id, container_type, folder, name) def self.findn_file_by_name(project_id, folder, name)
where( where(
:container_id => container_id, :project_id => project_id,
:container_type => container_type,
:dmsf_folder_id => folder ? folder.id : nil, :dmsf_folder_id => folder ? folder.id : nil,
:name => name).visible.first :name => name).visible.first
end end
@ -249,19 +249,17 @@ class DmsfFile < ActiveRecord::Base
projects projects
end end
def move_to(container, folder) def move_to(project, folder)
if self.locked_for_user? if self.locked_for_user?
errors[:base] << l(:error_file_is_locked) errors[:base] << l(:error_file_is_locked)
return false return false
end end
# Must invalidate source parent folder cache before moving # Must invalidate source parent folder cache before moving
RedmineDmsf::Webdav::Cache.invalidate_item(propfind_cache_key) RedmineDmsf::Webdav::Cache.invalidate_item(propfind_cache_key)
self.container_type = self.container_type self.project_id = project.id
self.container_id = container.id
self.dmsf_folder = folder self.dmsf_folder = folder
new_revision = self.last_revision.clone new_revision = self.last_revision.clone
new_revision.dmsf_file = self new_revision.dmsf_file = self
project = container.is_a?(Project) ? container : container.project
new_revision.comment = l(:comment_moved_from, :source => "#{self.project.identifier}:#{self.dmsf_path_str}") new_revision.comment = l(:comment_moved_from, :source => "#{self.project.identifier}:#{self.dmsf_path_str}")
new_revision.custom_values = [] new_revision.custom_values = []
self.last_revision.custom_values.each do |cv| self.last_revision.custom_values.each do |cv|
@ -271,15 +269,14 @@ class DmsfFile < ActiveRecord::Base
self.save && new_revision.save self.save && new_revision.save
end end
def copy_to(container, folder = nil) def copy_to(project, folder = nil)
copy_to_filename(container, folder, self.name) copy_to_filename(project, folder, self.name)
end end
def copy_to_filename(container, folder=nil, filename) def copy_to_filename(project, folder, filename)
file = DmsfFile.new file = DmsfFile.new
file.dmsf_folder = folder file.dmsf_folder = folder
file.container_type = self.container_type file.project_id = project.id
file.container_id = container.id
file.name = filename file.name = filename
file.notification = Setting.plugin_redmine_dmsf['dmsf_default_notifications'].present? file.notification = Setting.plugin_redmine_dmsf['dmsf_default_notifications'].present?
if file.save && self.last_revision if file.save && self.last_revision
@ -289,7 +286,6 @@ class DmsfFile < ActiveRecord::Base
if File.exist? self.last_revision.disk_file if File.exist? self.last_revision.disk_file
FileUtils.cp self.last_revision.disk_file, new_revision.disk_file FileUtils.cp self.last_revision.disk_file, new_revision.disk_file
end end
project = container.is_a?(Project) ? container : container.project
new_revision.comment = l(:comment_copied_from, :source => "#{project.identifier}: #{self.dmsf_path_str}") new_revision.comment = l(:comment_copied_from, :source => "#{project.identifier}: #{self.dmsf_path_str}")
new_revision.custom_values = [] new_revision.custom_values = []
self.last_revision.custom_values.each do |cv| self.last_revision.custom_values.each do |cv|
@ -325,8 +321,7 @@ class DmsfFile < ActiveRecord::Base
project_conditions << Project.allowed_to_condition(user, :view_dmsf_files) project_conditions << Project.allowed_to_condition(user, :view_dmsf_files)
project_conditions << "#{Project.table_name}.id IN (#{project_ids.join(',')})" if project_ids.present? project_conditions << "#{Project.table_name}.id IN (#{project_ids.join(',')})" if project_ids.present?
scope = self.visible.joins(:dmsf_file_revisions).joins( scope = self.visible.joins(:dmsf_file_revision).joins(:project)
"JOIN #{Project.table_name} ON #{DmsfFile.table_name}.container_id = #{Project.table_name}.id AND #{DmsfFile.table_name}.container_type = 'Project'")
scope = scope.limit(options[:limit]) unless options[:limit].blank? scope = scope.limit(options[:limit]) unless options[:limit].blank?
scope = scope.where(limit_options) unless limit_options.blank? scope = scope.where(limit_options) unless limit_options.blank?
scope = scope.where(project_conditions.join(' AND ')) scope = scope.where(project_conditions.join(' AND '))
@ -516,13 +511,11 @@ class DmsfFile < ActiveRecord::Base
end end
def propfind_cache_key def propfind_cache_key
if self.container_type == 'Project' unless dmsf_folder_id
if dmsf_folder_id.nil? # File is in project root
# File is in project root return "PROPFIND/#{self.project_id}"
return "PROPFIND/#{self.container_id}" else
else return "PROPFIND/#{self.project_id}/#{self.dmsf_folder_id}"
return "PROPFIND/#{self.container_id}/#{self.dmsf_folder_id}"
end
end end
end end
@ -606,31 +599,6 @@ class DmsfFile < ActiveRecord::Base
csv csv
end end
def project
unless @project
case self.container_type
when 'Project'
@project = Project.find_by_id(self.container_id)
when 'Issue'
issue = Issue.find_by_id(self.container_id)
@project = issue.project if issue
end
end
@project
end
def container
unless @container
case self.container_type
when 'Project'
@container = Project.find_by_id(self.container_id)
when 'Issue'
@container = Issue.find_by_id(self.container_id)
end
end
@container
end
def thumbnail(options={}) def thumbnail(options={})
if image? if image?
size = options[:size].to_i size = options[:size].to_i
@ -665,4 +633,10 @@ class DmsfFile < ActiveRecord::Base
l(:title_unlock_file) l(:title_unlock_file)
end end
def container
if self.dmsf_folder && self.dmsf_folder.system
Issue.where(:id => self.dmsf_folder.title.to_i).first
end
end
end end

View File

@ -49,10 +49,8 @@ class DmsfFileRevision < ActiveRecord::Base
:timestamp => "#{DmsfFileRevision.table_name}.updated_at", :timestamp => "#{DmsfFileRevision.table_name}.updated_at",
:author_key => "#{DmsfFileRevision.table_name}.user_id", :author_key => "#{DmsfFileRevision.table_name}.user_id",
:permission => :view_dmsf_file_revisions, :permission => :view_dmsf_file_revisions,
:scope => select("#{DmsfFileRevision.table_name}.*"). :scope => select("#{DmsfFileRevision.table_name}.*").joins(:dmsf_file).
joins(:dmsf_file).joins( joins("JOIN #{Project.table_name} ON #{Project.table_name}.id = #{DmsfFile.table_name}.project_id").visible
"LEFT JOIN #{Project.table_name} ON #{DmsfFile.table_name}.container_id = #{Project.table_name}.id").
where("#{DmsfFile.table_name}.container_type = ?", 'Project').visible
validates :title, :presence => true validates :title, :presence => true
validates_format_of :name, :with => DmsfFolder::INVALID_CHARACTERS, validates_format_of :name, :with => DmsfFolder::INVALID_CHARACTERS,

View File

@ -41,8 +41,6 @@ class DmsfFileRevisionAccess < ActiveRecord::Base
:author_key => "#{DmsfFileRevisionAccess.table_name}.user_id", :author_key => "#{DmsfFileRevisionAccess.table_name}.user_id",
:permission => :view_dmsf_file_revision_accesses, :permission => :view_dmsf_file_revision_accesses,
:scope => select("#{DmsfFileRevisionAccess.table_name}.*"). :scope => select("#{DmsfFileRevisionAccess.table_name}.*").
joins(:dmsf_file_revision).joins( joins(:dmsf_file_revision).joins(:dmsf_file).
"LEFT JOIN #{DmsfFile.table_name} ON #{DmsfFileRevision.table_name}.dmsf_file_id = #{DmsfFile.table_name}.id " + where(["#{DmsfFile.table_name}.deleted = ?", DmsfFile::STATUS_ACTIVE])
"LEFT JOIN #{Project.table_name} ON #{DmsfFile.table_name}.container_id = #{Project.table_name}.id").
where("#{DmsfFile.table_name}.deleted = ? AND #{DmsfFile.table_name}.container_type = ?", DmsfFile::STATUS_ACTIVE, 'Project')
end end

View File

@ -50,14 +50,15 @@ class DmsfFolder < ActiveRecord::Base
AVAILABLE_COLUMNS = %w(id title extension size modified version workflow author).freeze AVAILABLE_COLUMNS = %w(id title extension size modified version workflow author).freeze
DEFAULT_COLUMNS = %w(title size modified version workflow author).freeze DEFAULT_COLUMNS = %w(title size modified version workflow author).freeze
scope :visible, -> { joins(:project).joins( scope :visible, -> (system=true) { joins(:project).joins(
"LEFT JOIN #{DmsfFolderPermission.table_name} ON #{DmsfFolder.table_name}.id = #{DmsfFolderPermission.table_name}.dmsf_folder_id").where( "LEFT JOIN #{DmsfFolderPermission.table_name} ON #{DmsfFolder.table_name}.id = #{DmsfFolderPermission.table_name}.dmsf_folder_id").where(
:deleted => STATUS_ACTIVE).where(DmsfFolder.visible_condition).distinct :deleted => STATUS_ACTIVE).where(DmsfFolder.visible_condition(system)).distinct
} }
scope :deleted, -> { joins(:project).joins( scope :deleted, -> { joins(:project).joins(
"LEFT JOIN #{DmsfFolderPermission.table_name} ON #{DmsfFolder.table_name}.id = #{DmsfFolderPermission.table_name}.dmsf_folder_id").where( "LEFT JOIN #{DmsfFolderPermission.table_name} ON #{DmsfFolder.table_name}.id = #{DmsfFolderPermission.table_name}.dmsf_folder_id").where(
:deleted => STATUS_DELETED).where(DmsfFolder.visible_condition).distinct :deleted => STATUS_DELETED).where(DmsfFolder.visible_condition).distinct
} }
scope :system, -> { where(:system => true) }
acts_as_customizable acts_as_customizable
@ -83,8 +84,8 @@ class DmsfFolder < ActiveRecord::Base
before_create :default_values before_create :default_values
def self.visible_condition def self.visible_condition(system=true)
Project.allowed_to_condition(User.current, :view_dmsf_folders) do |role, user| sql = Project.allowed_to_condition(User.current, :view_dmsf_folders) do |role, user|
if user.id && user.logged? if user.id && user.logged?
%{ %{
(#{DmsfFolderPermission.table_name}.object_id IS NULL) OR (#{DmsfFolderPermission.table_name}.object_id IS NULL) OR
@ -92,14 +93,16 @@ class DmsfFolder < ActiveRecord::Base
(#{DmsfFolderPermission.table_name}.object_id = #{user.id} AND #{DmsfFolderPermission.table_name}.object_type = 'User') (#{DmsfFolderPermission.table_name}.object_id = #{user.id} AND #{DmsfFolderPermission.table_name}.object_type = 'User')
} }
else else
'0=1' '0 = 1'
end end
end end
"#{sql} AND (#{DmsfFolder.table_name}.system = 0 OR 1 = #{(system && Setting.plugin_redmine_dmsf['dmsf_show_system_folders']) ? 1 : 0})"
end end
def self.permissions(folder) def self.permissions?(folder, allow_system = true)
return false if folder && folder.system && (!allow_system || !Setting.plugin_redmine_dmsf['dmsf_show_system_folders'])
return true if (User.current.admin? || folder.nil?) return true if (User.current.admin? || folder.nil?)
if !folder.dmsf_folder || permissions(folder.dmsf_folder) if !folder.dmsf_folder || permissions?(folder.dmsf_folder, allow_system)
if folder.dmsf_folder_permissions.any? if folder.dmsf_folder_permissions.any?
role_ids = User.current.roles_for_project(folder.project).map{ |r| r.id } role_ids = User.current.roles_for_project(folder.project).map{ |r| r.id }
role_permission_ids = folder.dmsf_folder_permissions.roles.map{ |p| p.object_id } role_permission_ids = folder.dmsf_folder_permissions.roles.map{ |p| p.object_id }
@ -205,7 +208,7 @@ class DmsfFolder < ActiveRecord::Base
def self.directory_tree(project, current_folder = nil) def self.directory_tree(project, current_folder = nil)
tree = [[l(:link_documents), nil]] tree = [[l(:link_documents), nil]]
project.dmsf_folders.visible.each do |folder| project.dmsf_folders.visible(false).each do |folder|
unless folder == current_folder unless folder == current_folder
tree.push(["...#{folder.title}", folder.id]) tree.push(["...#{folder.title}", folder.id])
directory_subtree(tree, folder, 2, current_folder) directory_subtree(tree, folder, 2, current_folder)
@ -316,8 +319,8 @@ class DmsfFolder < ActiveRecord::Base
self.project_id, self.id, last_update]).maximum(:updated_at) self.project_id, self.id, last_update]).maximum(:updated_at)
last_update = time if time last_update = time if time
time = DmsfFile.where( time = DmsfFile.where(
['container_id = ? AND container_type = ? AND dmsf_folder_id = ? AND updated_at > ?', ['project_id = ? AND dmsf_folder_id = ? AND updated_at > ?',
self.project_id, 'Project', self.id, last_update]).maximum(:updated_at) self.project_id, self.id, last_update]).maximum(:updated_at)
last_update = time if time last_update = time if time
time = DmsfLink.where( time = DmsfLink.where(
['project_id = ? AND dmsf_folder_id = ? AND updated_at > ?', ['project_id = ? AND dmsf_folder_id = ? AND updated_at > ?',
@ -329,7 +332,7 @@ class DmsfFolder < ActiveRecord::Base
# Number of items in the folder # Number of items in the folder
def items def items
dmsf_folders.visible.where(:project_id => self.project_id).count + dmsf_folders.visible.where(:project_id => self.project_id).count +
dmsf_files.visible.where(:container_id => self.project_id).count + dmsf_files.visible.where(:project_id => self.project_id).count +
dmsf_links.visible.where(:project_id => self.project_id).count dmsf_links.visible.where(:project_id => self.project_id).count
end end
@ -351,6 +354,10 @@ class DmsfFolder < ActiveRecord::Base
end end
def self.get_column_position(column) def self.get_column_position(column)
unless @@dmsf_columns
@@dmsf_columns = Setting.plugin_redmine_dmsf['dmsf_columns']
@@dmsf_columns = DmsfFolder::DEFAULT_COLUMNS unless columns
end
pos = 0 pos = 0
# 0 - checkbox # 0 - checkbox
# 1 - id # 1 - id
@ -517,7 +524,7 @@ class DmsfFolder < ActiveRecord::Base
private private
def self.directory_subtree(tree, folder, level, current_folder) def self.directory_subtree(tree, folder, level, current_folder)
folder.dmsf_folders.visible.each do |subfolder| folder.dmsf_folders.visible(false).each do |subfolder|
unless subfolder == current_folder unless subfolder == current_folder
tree.push(["#{'...' * level}#{subfolder.title}", subfolder.id]) tree.push(["#{'...' * level}#{subfolder.title}", subfolder.id])
directory_subtree(tree, subfolder, level + 1, current_folder) directory_subtree(tree, subfolder, level + 1, current_folder)

View File

@ -76,8 +76,7 @@ class DmsfUpload
@minor_version = 0 @minor_version = 0
@workflow = nil @workflow = nil
file = DmsfFile.new file = DmsfFile.new
file.container_type = 'Project' file.project_id = project.id
file.container_id = project.id
revision = DmsfFileRevision.new revision = DmsfFileRevision.new
revision.dmsf_file = file revision.dmsf_file = file
@custom_values = revision.custom_field_values @custom_values = revision.custom_field_values

View File

@ -106,8 +106,8 @@ class DmsfWorkflow < ActiveRecord::Base
def delegates(q, dmsf_workflow_step_assignment_id, dmsf_file_revision_id) def delegates(q, dmsf_workflow_step_assignment_id, dmsf_file_revision_id)
if dmsf_workflow_step_assignment_id && dmsf_file_revision_id if dmsf_workflow_step_assignment_id && dmsf_file_revision_id
sql = [ sql = [
'id NOT IN (SELECT a.user_id FROM dmsf_workflow_step_assignments a WHERE id = ?) AND id IN (SELECT m.user_id FROM members m JOIN dmsf_files f ON f.container_id = m.project_id JOIN dmsf_file_revisions r ON r.dmsf_file_id = f.id WHERE r.id = ? AND container_type = ?)', 'id NOT IN (SELECT a.user_id FROM dmsf_workflow_step_assignments a WHERE id = ?) AND id IN (SELECT m.user_id FROM members m JOIN dmsf_files f ON f.project_id = m.project_id JOIN dmsf_file_revisions r ON r.dmsf_file_id = f.id WHERE r.id = ?)',
dmsf_workflow_step_assignment_id, dmsf_file_revision_id, 'Project'] dmsf_workflow_step_assignment_id, dmsf_file_revision_id]
elsif project elsif project
sql = ['id IN (SELECT user_id FROM members WHERE project_id = ?)', project.id] sql = ['id IN (SELECT user_id FROM members WHERE project_id = ?)', project.id]
else else

View File

@ -20,8 +20,11 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
%> %>
<td class="dmsf_checkbox"><%= check_box_tag(name, id, false, <td class="dmsf_checkbox">
:title => l(:title_check_for_zip_download_or_email), :id => "subfolder_#{id}") %></td> <% unless (subfolder && subfolder.system) %>
<%= check_box_tag(name, id, false, :title => l(:title_check_for_zip_download_or_email), :id => "subfolder_#{id}") %>
<% end %>
</td>
<% if DmsfFolder.is_column_on?('id') %> <% if DmsfFolder.is_column_on?('id') %>
<td class="id"><%= link_to(subfolder.id, edit_dmsf_path(:id => project, :folder_id => subfolder)) %></td> <td class="id"><%= link_to(subfolder.id, edit_dmsf_path(:id => project, :folder_id => subfolder)) %></td>
<% end %> <% end %>
@ -68,7 +71,7 @@
<% end %> <% end %>
<% end %> <% end %>
<td class="dmsf_buttons"> <td class="dmsf_buttons">
<% if @folder_manipulation_allowed %> <% if @folder_manipulation_allowed && !(subfolder && subfolder.system) %>
<% if subfolder && subfolder.locked? %> <% if subfolder && subfolder.locked? %>
<span class="icon"></span> <span class="icon"></span>
<% if subfolder.unlockable? && (!subfolder.locked_for_user? || @force_file_unlock_allowed) %> <% if subfolder.unlockable? && (!subfolder.locked_for_user? || @force_file_unlock_allowed) %>

View File

@ -19,6 +19,7 @@
<% end %> <% end %>
<% if obj.is_a? DmsfFolder %> <% if obj.is_a? DmsfFolder %>
<% classes << ' dmsf_system' if obj.system %>
<tr <%= id %> class="dir <%= classes %>"> <tr <%= id %> class="dir <%= classes %>">
<%= render(:partial => 'dir', <%= render(:partial => 'dir',
:locals => { :locals => {

View File

@ -133,46 +133,9 @@
<span class="icon"></span> <span class="icon"></span>
<% end %> <% end %>
<% end %> <% end %>
<% if @file_approval_allowed %> <%= render(:partial => 'dmsf_files/approval_workflow_button',
<% case file.last_revision.workflow %> :locals => {:file => file, :file_approval_allowed => @file_approval_allowed,
<% when DmsfWorkflow::STATE_WAITING_FOR_APPROVAL %> :workflows_available => @workflows_available, :project => project, :wf => wf }) %>
<% if wf %>
<% assignments = wf.next_assignments(file.last_revision.id) %>
<% index = assignments.find_index{|assignment| assignment.user_id == User.current.id} if assignments %>
<% if index %>
<%= link_to('',
action_dmsf_workflow_path(
:project_id => project.id,
:id => wf.id,
:dmsf_workflow_step_assignment_id => assignments[index].id,
:dmsf_file_revision_id => file.last_revision.id),
:title => l(:title_waiting_for_approval),
:remote => true,
:class => 'icon icon-wf-waiting') %>
<% end %>
<% end %>
<% when DmsfWorkflow::STATE_ASSIGNED %>
<% if User.current && (file.last_revision.dmsf_workflow_assigned_by == User.current.id) && wf %>
<%= link_to('',
start_dmsf_workflow_path(
:id => file.last_revision.dmsf_workflow_id,
:dmsf_file_revision_id => file.last_revision.id),
:title => l(:label_dmsf_wokflow_action_start),
:class => 'icon icon-wf-assigned') %>
<% end %>
<% when DmsfWorkflow::STATE_APPROVED, DmsfWorkflow::STATE_REJECTED %>
<% else %>
<% if @workflows_available %>
<%= link_to('',
assign_dmsf_workflow_path(
:project_id => project.id,
:dmsf_file_revision_id => file.last_revision.id),
:title => l(:label_dmsf_wokflow_action_assign),
:remote => true,
:class => 'icon icon-wf-none') %>
<% end %>
<% end %>
<% end %>
</td> </td>
<td class="hol"><%= position %></td> <td class="hol"><%= position %></td>
<td class="hol"><%= file.last_revision.size %></td> <td class="hol"><%= file.last_revision.size %></td>

View File

@ -65,7 +65,7 @@
</thead> </thead>
<tbody> <tbody>
<% @subfolders.each do |subfolder| %> <% @subfolders.each do |subfolder| %>
<tr class="dir"> <tr class="dir <%= 'dmsf_system' if subfolder.system %>">
<%= render(:partial => 'dir', <%= render(:partial => 'dir',
:locals => { :locals => {
:project => @project, :project => @project,

View File

@ -25,7 +25,7 @@
<% html_title(l(:dmsf)) %> <% html_title(l(:dmsf)) %>
<div class="contextual"> <div class="contextual">
<% if !@folder.new_record? && User.current.allowed_to?(:folder_manipulation, @project) %> <% if !@folder.new_record? && User.current.allowed_to?(:folder_manipulation, @project) && !@folder.system %>
<% unless @folder.locked? %> <% unless @folder.locked? %>
<%= link_to(l(:button_lock), lock_dmsf_path(:id => @project, :folder_id => @folder), <%= link_to(l(:button_lock), lock_dmsf_path(:id => @project, :folder_id => @folder),
:title => l(:title_lock_file), :class => 'icon icon-lock') %> :title => l(:title_lock_file), :class => 'icon icon-lock') %>

View File

@ -24,7 +24,7 @@
<% html_title l(:dmsf) %> <% html_title l(:dmsf) %>
<div class="contextual"> <div class="contextual">
<% if @folder_manipulation_allowed %> <% if @folder_manipulation_allowed && !@system_folder %>
<% if @folder.nil? %> <% if @folder.nil? %>
<%= link_to(l(:button_edit), edit_root_dmsf_path(:id => @project), <%= link_to(l(:button_edit), edit_root_dmsf_path(:id => @project),
:title => l(:link_edit, :title => l(:link_documents)), :title => l(:link_edit, :title => l(:link_documents)),
@ -92,16 +92,18 @@
<%= submit_tag(l(:button_delete), :title => l(:title_delete_checked), :name => 'delete_entries') if @file_delete_allowed %> <%= submit_tag(l(:button_delete), :title => l(:title_delete_checked), :name => 'delete_entries') if @file_delete_allowed %>
<% end %> <% end %>
</div> </div>
<% values = @folder ? @folder.custom_field_values : DmsfFolder.new.custom_field_values %> <% unless @system_folder %>
<% unless values.empty? %> <% values = @folder ? @folder.custom_field_values : DmsfFolder.new.custom_field_values %>
<div id="dmsf_tag" class="dmsf_controls" style="float: right"> <% unless values.empty? %>
<% custom_value = values.first %> <div id="dmsf_tag" class="dmsf_controls" style="float: right">
<% custom_value.custom_field.is_required = false %> <% custom_value = values.first %>
<% custom_value.value = params[:custom_value].present? ? params[:custom_value] : '' %> <% custom_value.custom_field.is_required = false %>
<% name = :dmsf_folder %> <% custom_value.value = params[:custom_value].present? ? params[:custom_value] : '' %>
<%= content_tag('label', custom_field_name_tag(custom_value.custom_field), <% name = :dmsf_folder %>
:for => "#{name}_custom_field_values_#{custom_value.custom_field.id}") + ': ' + custom_field_tag(name, custom_value) %> <%= content_tag('label', custom_field_name_tag(custom_value.custom_field),
</div> :for => "#{name}_custom_field_values_#{custom_value.custom_field.id}") + ': ' + custom_field_tag(name, custom_value) %>
</div>
<% end %>
<% end %> <% end %>
<div class="autoscroll"> <div class="autoscroll">
<% if @tree_view %> <% if @tree_view %>
@ -181,7 +183,7 @@
<% if @folder %> <% if @folder %>
return "<%= "#{l(:label_number_of_folders)}: #{@folder.deep_folder_count} #{l(:label_number_of_documents)}: #{@folder.deep_file_count}" %>"; return "<%= "#{l(:label_number_of_folders)}: #{@folder.deep_folder_count} #{l(:label_number_of_documents)}: #{@folder.deep_file_count}" %>";
<% else %> <% else %>
return "<%= "#{l(:label_number_of_folders)}: #{DmsfFolder.visible.where(:project_id => @project.id).count + DmsfLink.visible.where(:project_id => @project.id, :target_type => 'DmsfFolder').count}, #{l(:label_number_of_documents)}: #{DmsfFile.visible.where(:container_id => @project.id, :container_type => 'Project').count + DmsfLink.visible.where(:project_id => @project.id, :target_type => 'DmsfFile').count + DmsfLink.visible.where(:project_id => @project.id, :target_type => 'DmsfUrl').count}" %>"; return "<%= "#{l(:label_number_of_folders)}: #{DmsfFolder.visible.where(:project_id => @project.id).count + DmsfLink.visible.where(:project_id => @project.id, :target_type => 'DmsfFolder').count}, #{l(:label_number_of_documents)}: #{DmsfFile.visible.where(:project_id => @project.id).count + DmsfLink.visible.where(:project_id => @project.id, :target_type => ['DmsfFile', 'DmsfUrl']).count}" %>";
<% end %> <% end %>
<% else %> <% else %>
return "<%= "#{l(:label_number_of_folders)}: #{@subfolders.count + @dir_links.count}, #{l(:label_number_of_documents)}: #{@files.count + @file_links.count + @url_links.count}" %>"; return "<%= "#{l(:label_number_of_folders)}: #{@subfolders.count + @dir_links.count}, #{l(:label_number_of_documents)}: #{@files.count + @file_links.count + @url_links.count}" %>";
@ -207,12 +209,14 @@
</script> </script>
<% end %> <% end %>
<% if (@file_manipulation_allowed && !@locked_for_user) %> <% if (@file_manipulation_allowed && !@locked_for_user && !@system_folder) %>
<%= render(:partial => 'dmsf_upload/multi_upload') %> <%= render(:partial => 'dmsf_upload/multi_upload') %>
<% end %> <% end %>
<% other_formats_links do |f| %> <% unless @system_folder %>
<% other_formats_links do |f| %>
<%= f.link_to 'CSV', :url => params, :onclick => "showModal('csv-export-options', '350px'); return false;" %> <%= f.link_to 'CSV', :url => params, :onclick => "showModal('csv-export-options', '350px'); return false;" %>
<% end %>
<% end %> <% end %>
<div id="csv-export-options" style="display:none;"> <div id="csv-export-options" style="display:none;">

View File

@ -0,0 +1,62 @@
<%
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-17 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.
%>
<% if file_approval_allowed %>
<% case file.last_revision.workflow %>
<% when DmsfWorkflow::STATE_WAITING_FOR_APPROVAL %>
<% if wf %>
<% assignments = wf.next_assignments(file.last_revision.id) %>
<% index = assignments.find_index{|assignment| assignment.user_id == User.current.id} if assignments %>
<% if index %>
<%= link_to('',
action_dmsf_workflow_path(
:project_id => project.id,
:id => wf.id,
:dmsf_workflow_step_assignment_id => assignments[index].id,
:dmsf_file_revision_id => file.last_revision.id),
:title => l(:title_waiting_for_approval),
:remote => true,
:class => 'icon icon-wf-waiting') %>
<% end %>
<% end %>
<% when DmsfWorkflow::STATE_ASSIGNED %>
<% if User.current && (file.last_revision.dmsf_workflow_assigned_by == User.current.id) && wf %>
<%= link_to('',
start_dmsf_workflow_path(
:id => file.last_revision.dmsf_workflow_id,
:dmsf_file_revision_id => file.last_revision.id),
:title => l(:label_dmsf_wokflow_action_start),
:class => 'icon icon-wf-assigned') %>
<% end %>
<% when DmsfWorkflow::STATE_APPROVED, DmsfWorkflow::STATE_REJECTED %>
<% else %>
<% if workflows_available %>
<%= link_to('',
assign_dmsf_workflow_path(
:project_id => project.id,
:dmsf_file_revision_id => file.last_revision.id),
:title => l(:label_dmsf_wokflow_action_assign),
:remote => true,
:class => 'icon icon-wf-none') %>
<% end %>
<% end %>
<% end %>

View File

@ -22,7 +22,7 @@
<% if dmsf_files.present? %> <% if dmsf_files.present? %>
<hr/> <hr/>
<div class="attachments"> <div class="attachments dmsf_parent_container">
<% for dmsf_file in dmsf_files %> <% for dmsf_file in dmsf_files %>
<% if dmsf_file.last_revision %> <% if dmsf_file.last_revision %>
<p> <p>
@ -50,6 +50,14 @@
:class => 'icon icon-del') %> :class => 'icon icon-del') %>
<% end %> <% end %>
<span class="author"><%= dmsf_file.last_revision.user %>, <%= format_time(dmsf_file.last_revision.updated_at) %></span> <span class="author"><%= dmsf_file.last_revision.user %>, <%= format_time(dmsf_file.last_revision.updated_at) %></span>
<span class="dmsf_upload_select">
<% wf = DmsfWorkflow.find_by_id(dmsf_file.last_revision.dmsf_workflow_id) if dmsf_file.last_revision.dmsf_workflow_id %>
<%= render(:partial => 'dmsf_files/approval_workflow_button',
:locals => {:file => dmsf_file,
:file_approval_allowed => User.current.allowed_to?(:file_approval, dmsf_file.project),
:workflows_available => DmsfWorkflow.where(['project_id = ? OR project_id IS NULL', dmsf_file.project.id]).exists?,
:project => dmsf_file.project, :wf => wf }) %>
</span>
</p> </p>
<% end %> <% end %>
<% end %> <% end %>

View File

@ -1,8 +1,7 @@
api.dmsf_file do api.dmsf_file do
api.id @file.id api.id @file.id
api.name @file.name api.name @file.name
api.container_id @file.container_id api.project_id @file.project_id
api.container_type @file.container_type
api.dmsf_folder_id @file.folder if @file.dmsf_folder_id api.dmsf_folder_id @file.folder if @file.dmsf_folder_id
api.version "#{@file.last_revision.major_version}.#{@file.last_revision.minor_version}" if @file.last_revision api.version "#{@file.last_revision.major_version}.#{@file.last_revision.minor_version}" if @file.last_revision
api.content_url url_for(:controller => :dmsf_files, :action => 'show', :download => '', :id => @file) api.content_url url_for(:controller => :dmsf_files, :action => 'show', :download => '', :id => @file)

View File

@ -152,10 +152,8 @@
<div class="status attribute"> <div class="status attribute">
<%= content_tag :div, l(:label_file), :class => 'label' %> <%= content_tag :div, l(:label_file), :class => 'label' %>
<div class="value"> <div class="value">
<% if revision.dmsf_file.dmsf_folder %> <% path = "#{revision.dmsf_file.dmsf_folder.dmsf_path_str}/" if revision.dmsf_file.dmsf_folder %>
<%= (h("#{revision.dmsf_file.dmsf_folder.dmsf_path_str}/")) %> <%= h("#{path}#{revision.name}") %>
<% end %>
<%= h(revision.name) %>
</div> </div>
</div> </div>
<div class="status attribute"> <div class="status attribute">

View File

@ -137,6 +137,15 @@
</em> </em>
</p> </p>
<p>
<%= content_tag(:label, l(:label_show_system_folders)) %>
<%= check_box_tag('settings[dmsf_show_system_folders]', true, @settings['dmsf_show_system_folders']) %>
<em class="info">
<%= l(:note_dmsf_show_system_folders) %><br/>
<%= l(:label_default)%>: <%= l(:general_text_No)%>
</em>
</p>
<hr/> <hr/>
<em class="info"> <em class="info">
<%= l(:menu_dmsf) %> <%= l(:field_column_names) %> <%= l(:menu_dmsf) %> <%= l(:field_column_names) %>

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

View File

@ -194,6 +194,7 @@ div.dmsf_revision_inner_box .attribute .label {
/* File types */ /* File types */
.dmsf_gray .icon-folder { background-image: url(../images/folder_gray.png); } .dmsf_gray .icon-folder { background-image: url(../images/folder_gray.png); }
.dmsf_system .icon-folder { background-image: url(../images/folder_system.png); }
.icon-file.filetype-doc, .icon-file.filetype-docx { background-image: url(../images/filetypes/doc.png); } .icon-file.filetype-doc, .icon-file.filetype-docx { background-image: url(../images/filetypes/doc.png); }
.icon-file.filetype-xls, .icon-file.filetype-xlsx { background-image: url(../images/filetypes/xls.png); } .icon-file.filetype-xls, .icon-file.filetype-xlsx { background-image: url(../images/filetypes/xls.png); }
@ -240,6 +241,10 @@ div.dmsf_revision_inner_box .attribute .label {
.dmsf_gray { color: #AAA } .dmsf_gray { color: #AAA }
.dmsf_gray a, .dmsf_gray a:link, .dmsf_gray a:visited{ color: #484848; text-decoration: none; } .dmsf_gray a, .dmsf_gray a:link, .dmsf_gray a:visited{ color: #484848; text-decoration: none; }
/* System folders */
.dmsf_system { color: #5C82AD }
.dmsf_system a, .dmsf_gray a:link, .dmsf_gray a:visited{ color: #484848; text-decoration: none; }
/* Search results */ /* Search results */
.dmsf-file { background-image: url(../../../images/document.png); } .dmsf-file { background-image: url(../../../images/document.png); }
.dmsf-folder { background-image: url(../../../images/folder.png); } .dmsf-folder { background-image: url(../../../images/folder.png); }

View File

@ -363,5 +363,7 @@ cs:
label_act_as_attachable: Jako příloha label_act_as_attachable: Jako příloha
note_dmsf_act_as_attachable: Umožní přikládat dokumenty k objektům např. úkolům. note_dmsf_act_as_attachable: Umožní přikládat dokumenty k objektům např. úkolům.
label_show_system_folders: Zobrazit systémové složky
note_dmsf_show_system_folders: Systémové složky jsou složky se specifickým určením, např. pro dokumenty nahrané k úkolům.
label_user_search_add: Vyhledej uživatele pro přidání label_user_search_add: Vyhledej uživatele pro přidání

View File

@ -360,5 +360,7 @@ de:
label_act_as_attachable: Act as attachable label_act_as_attachable: Act as attachable
note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues. note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues.
label_show_system_folders: Show system folders
note_dmsf_show_system_folders: System folders are folders with a specifics purpose, e.g. for documents attached to issues.
label_user_search_add: Search for user to add label_user_search_add: Search for user to add

View File

@ -363,5 +363,7 @@ en:
label_act_as_attachable: Act as attachable label_act_as_attachable: Act as attachable
note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues. note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues.
label_show_system_folders: Show system folders
note_dmsf_show_system_folders: System folders are folders with a specifics purpose, e.g. for documents attached to issues.
label_user_search_add: Search for user to add label_user_search_add: Search for user to add

View File

@ -363,5 +363,7 @@ es:
label_act_as_attachable: Act as attachable label_act_as_attachable: Act as attachable
note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues. note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues.
label_show_system_folders: Show system folders
note_dmsf_show_system_folders: System folders are folders with a specifics purpose, e.g. for documents attached to issues.
label_user_search_add: Search for user to add label_user_search_add: Search for user to add

View File

@ -363,5 +363,7 @@ fr:
label_act_as_attachable: Act as attachable label_act_as_attachable: Act as attachable
note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues. note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues.
label_show_system_folders: Show system folders
note_dmsf_show_system_folders: System folders are folders with a specifics purpose, e.g. for documents attached to issues.
label_user_search_add: Search for user to add label_user_search_add: Search for user to add

View File

@ -362,5 +362,7 @@ hu:
label_act_as_attachable: Act as attachable label_act_as_attachable: Act as attachable
note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues. note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues.
label_show_system_folders: Show system folders
note_dmsf_show_system_folders: System folders are folders with a specifics purpose, e.g. for documents attached to issues.
label_user_search_add: Search for user to add label_user_search_add: Search for user to add

View File

@ -363,5 +363,7 @@ it: # Italian strings thx 2 Matteo Arceci!
label_act_as_attachable: Act as attachable label_act_as_attachable: Act as attachable
note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues. note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues.
label_show_system_folders: Show system folders
note_dmsf_show_system_folders: System folders are folders with a specifics purpose, e.g. for documents attached to issues.
label_user_search_add: Search for user to add label_user_search_add: Search for user to add

View File

@ -363,5 +363,7 @@ ja:
label_act_as_attachable: Act as attachable label_act_as_attachable: Act as attachable
note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues. note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues.
label_show_system_folders: Show system folders
note_dmsf_show_system_folders: System folders are folders with a specifics purpose, e.g. for documents attached to issues.
label_user_search_add: Search for user to add label_user_search_add: Search for user to add

View File

@ -363,5 +363,7 @@ pl:
label_act_as_attachable: Act as attachable label_act_as_attachable: Act as attachable
note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues. note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues.
label_show_system_folders: Show system folders
note_dmsf_show_system_folders: System folders are folders with a specifics purpose, e.g. for documents attached to issues.
label_user_search_add: Search for user to add label_user_search_add: Search for user to add

View File

@ -363,5 +363,7 @@ pt-BR:
label_act_as_attachable: Act as attachable label_act_as_attachable: Act as attachable
note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues. note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues.
label_show_system_folders: Show system folders
note_dmsf_show_system_folders: System folders are folders with a specifics purpose, e.g. for documents attached to issues.
label_user_search_add: Search for user to add label_user_search_add: Search for user to add

View File

@ -363,5 +363,7 @@ ru:
label_act_as_attachable: Act as attachable label_act_as_attachable: Act as attachable
note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues. note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues.
label_show_system_folders: Show system folders
note_dmsf_show_system_folders: System folders are folders with a specifics purpose, e.g. for documents attached to issues.
label_user_search_add: Search for user to add label_user_search_add: Search for user to add

View File

@ -363,5 +363,7 @@ sl:
label_act_as_attachable: Act as attachable label_act_as_attachable: Act as attachable
note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues. note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues.
label_show_system_folders: Show system folders
note_dmsf_show_system_folders: System folders are folders with a specifics purpose, e.g. for documents attached to issues.
label_user_search_add: Search for user to add label_user_search_add: Search for user to add

View File

@ -363,5 +363,7 @@ zh-TW:
label_act_as_attachable: Act as attachable label_act_as_attachable: Act as attachable
note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues. note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues.
label_show_system_folders: Show system folders
note_dmsf_show_system_folders: System folders are folders with a specifics purpose, e.g. for documents attached to issues.
label_user_search_add: Search for user to add label_user_search_add: Search for user to add

View File

@ -363,5 +363,7 @@ zh:
label_act_as_attachable: Act as attachable label_act_as_attachable: Act as attachable
note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues. note_dmsf_act_as_attachable: Allows to attach documents to objects e.g. issues.
label_show_system_folders: Show system folders
note_dmsf_show_system_folders: System folders are folders with a specifics purpose, e.g. for documents attached to issues.
label_user_search_add: Search for user to add label_user_search_add: Search for user to add

View File

@ -0,0 +1,85 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-17 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.
class DmsfFileContainerRollback < ActiveRecord::Migration
def up
# Create necessary folders
new_folder_ids = []
description = 'Documents assigned to issues'
DmsfFile.where(:container_type => 'Issue').each do |file|
issue = Issue.find_by_id file.container_id
unless issue
Rails.logger.error "Issue ##{file.container_id} not found"
next
end
# Parent folder
parent = DmsfFolder.where(:project_id => issue.project.id, :title => '.Issues', :description => description).first
unless parent
parent = DmsfFolder.new
parent.project_id = issue.project.id
parent.title = '.Issues'
parent.description = description
parent.user_id = User.anonymous.id
parent.save
new_folder_ids << parent.id
end
# Issue folder
folder = DmsfFolder.new
folder.project_id = issue.project.id
folder.dmsf_folder_id = parent.id
folder.title = "#{issue.id} - #{issue.subject}"
folder.user_id = User.anonymous.id
folder.save
new_folder_ids << folder.id
# Move the file into the new folder
file.dmsf_folder_id = folder.id
file.save
end
# Make DB changes in dmsf_files
remove_index :dmsf_files, [:container_id, :container_type]
remove_column :dmsf_files, :container_type
rename_column :dmsf_files, :container_id, :project_id
add_index :dmsf_files, :project_id
# Add system folder_flag to dmsf_folders
add_column :dmsf_folders, :system, :boolean, :null => false, :default => false
DmsfFolder.where(:id => new_folder_ids).update_all(:system => true)
end
def down
# dmsf_files
file_folder_ids = DmsfFile.joins(:dmsf_folder).where('dmsf_folders.system = 1').pluck('dmsf_files.id, cast(dmsf_folders.title as unsigned)')
remove_index :dmsf_files, :project_id
rename_column :dmsf_files, :project_id, :container_id
add_column :dmsf_files, :container_type, :string, :limit => 30, :null => false, :default => 'Project'
DmsfFile.update_all(:container_type => 'Project')
file_folder_ids.each do |id, container_id|
file = DmsfFile.find_by_id(id)
if file
file.container_id = container_id
file.container_type = 'Issue'
file.save
end
end
add_index :dmsf_files, [:container_id, :container_type]
# dmsf_folders
DmsfFolder.where(:system => true).delete_all
remove_column :dmsf_folders, :system
end
end

View File

@ -52,7 +52,8 @@ Redmine::Plugin.register :redmine_dmsf do
'dmsf_webdav_ignore' => '^(\._|\.DS_Store$|Thumbs.db$)', 'dmsf_webdav_ignore' => '^(\._|\.DS_Store$|Thumbs.db$)',
'dmsf_webdav_disable_versioning' => '^\~\$|\.tmp$', 'dmsf_webdav_disable_versioning' => '^\~\$|\.tmp$',
'dmsf_keep_documents_locked' => false, 'dmsf_keep_documents_locked' => false,
'dmsf_act_as_attachable' => false 'dmsf_act_as_attachable' => false,
'dmsf_show_system_folders' => false
} }
menu :project_menu, :dmsf, { :controller => 'dmsf', :action => 'show' }, :caption => :menu_dmsf, :before => :documents, :param => :id menu :project_menu, :dmsf, { :controller => 'dmsf', :action => 'show' }, :caption => :menu_dmsf, :before => :documents, :param => :id

View File

@ -33,8 +33,8 @@ module RedmineDmsf
copied_from = Issue.find_by_id(params[:copy_from]) if params[:copy_from].present? copied_from = Issue.find_by_id(params[:copy_from]) if params[:copy_from].present?
# Save documents # Save documents
if copied_from if copied_from
issue.dmsf_files = copied_from.dmsf_files.map do |dmsf_file| copied_from.dmsf_files.each do |dmsf_file|
dmsf_file.copy_to(issue) dmsf_file.copy_to(issue.project, issue.system_folder(true))
end end
end end
end end
@ -53,14 +53,15 @@ module RedmineDmsf
params = context[:params] params = context[:params]
uploaded_files = params[:dmsf_attachments] uploaded_files = params[:dmsf_attachments]
if uploaded_files && uploaded_files.is_a?(Hash) if uploaded_files && uploaded_files.is_a?(Hash)
# standard file input uploads system_folder = issue.system_folder(true)
uploaded_files.each_value do |uploaded_file| uploaded_files.each_value do |uploaded_file|
upload = DmsfUpload.create_from_uploaded_attachment(issue.project, nil, uploaded_file) upload = DmsfUpload.create_from_uploaded_attachment(issue.project, system_folder, uploaded_file)
uploaded_file[:disk_filename] = upload.disk_filename uploaded_file[:disk_filename] = upload.disk_filename
uploaded_file[:name] = upload.name uploaded_file[:name] = upload.name
uploaded_file[:title] = upload.title uploaded_file[:title] = upload.title
end end
DmsfUploadHelper.commit_files_internal uploaded_files, issue, nil, context[:controller] DmsfUploadHelper.commit_files_internal uploaded_files, issue.project, system_folder,
context[:controller]
end end
end end
end end

View File

@ -26,20 +26,47 @@ module RedmineDmsf
base.send(:include, InstanceMethods) base.send(:include, InstanceMethods)
base.class_eval do base.class_eval do
unloadable unloadable
alias_method_chain :copy_from, :dmsf_copy_from before_destroy :delete_system_folder
has_many :dmsf_files, -> { where(dmsf_folder_id: nil, container_type: 'Issue').order(:name) },
:class_name => 'DmsfFile', :foreign_key => 'container_id', :dependent => :destroy
end end
end end
module InstanceMethods module InstanceMethods
def copy_from_with_dmsf_copy_from(arg, options={}) def system_folder(create = false)
copy_from_without_dmsf_copy_from(arg, options) parent = DmsfFolder.system.where(:project_id => self.project_id, :title => '.Issues').first
# issue = @copied_from if create && !parent
# self.dmsf_files = issue.dmsf_files.map do |dmsf_file| parent = DmsfFolder.new
# dmsf_file.copy_to(self) parent.project_id = self.project_id
# end parent.title = '.Issues'
parent.description = 'Documents assigned to issues'
parent.user_id = User.anonymous.id
parent.system = true
parent.save
end
if parent
folder = DmsfFolder.system.where(['project_id = ? AND dmsf_folder_id = ? AND CAST(title AS UNSIGNED) = ?',
self.project_id, parent.id, self.id]).first
if create && !folder
folder = DmsfFolder.new
folder.dmsf_folder_id = parent.id
folder.project_id = self.project_id
folder.title = "#{self.id} - #{self.subject}"
folder.user_id = User.anonymous.id
folder.system = true
folder.save
end
end
folder
end
def dmsf_files
folder = self.system_folder
folder.dmsf_files if folder
end
def delete_system_folder
folder = self.system_folder
folder.destroy if folder
end end
def dmsf_file_added(dmsf_file) def dmsf_file_added(dmsf_file)

View File

@ -31,11 +31,10 @@ module RedmineDmsf
unloadable unloadable
alias_method_chain :copy, :dmsf alias_method_chain :copy, :dmsf
has_many :dmsf_files, -> { where(dmsf_folder_id: nil, container_type: 'Project').order(:name) }, has_many :dmsf_files, -> { where(dmsf_folder_id: nil).order(:name) },
:class_name => 'DmsfFile', :foreign_key => 'container_id', :dependent => :destroy :class_name => 'DmsfFile', :foreign_key => 'project_id', :dependent => :destroy
has_many :dmsf_folders, -> { where(dmsf_folder_id: nil).order(:title) }, has_many :dmsf_folders, ->{ where(:dmsf_folder_id => nil).order(:title) },
:class_name => 'DmsfFolder', :foreign_key => 'project_id', :class_name => 'DmsfFolder', :foreign_key => 'project_id', :dependent => :destroy
:dependent => :destroy
has_many :dmsf_workflows, :dependent => :destroy has_many :dmsf_workflows, :dependent => :destroy
has_many :folder_links, -> { where dmsf_folder_id: nil, target_type: 'DmsfFolder' }, has_many :folder_links, -> { where dmsf_folder_id: nil, target_type: 'DmsfFolder' },
:class_name => 'DmsfLink', :foreign_key => 'project_id', :dependent => :destroy :class_name => 'DmsfLink', :foreign_key => 'project_id', :dependent => :destroy

View File

@ -210,10 +210,10 @@ module RedmineDmsf
# File # File
# Use file.id & file.last_revision.id as key # Use file.id & file.last_revision.id as key
# When revision changes then the key will change and the old cached item will eventually be evicted # When revision changes then the key will change and the old cached item will eventually be evicted
propstats_key = "PROPSTATS/#{resource.resource.file.id}-#{resource.resource.file.last_revision.id}" propstats_key = "PROPSTATS/#{resource.resource.file.id}-#{resource.resource.file.last_revision.id}" if resource.resource.file
end end
xml_str = RedmineDmsf::Webdav::Cache.read(propstats_key) xml_str = RedmineDmsf::Webdav::Cache.read(propstats_key) if propstats_key
if xml_str.nil? if xml_str.nil?
# Create the complete PROPSTATS response # Create the complete PROPSTATS response
propstats_builder = Nokogiri::XML::Builder.new do |propstats_xml| propstats_builder = Nokogiri::XML::Builder.new do |propstats_xml|
@ -238,7 +238,7 @@ module RedmineDmsf
# Add PROPSTATS to cache # Add PROPSTATS to cache
# Caching the PROPSTATS response as xml text string. # Caching the PROPSTATS response as xml text string.
RedmineDmsf::Webdav::Cache.write(propstats_key, xml_str) RedmineDmsf::Webdav::Cache.write(propstats_key, xml_str) if propstats_key
end end
xml << xml_str xml << xml_str
end end

View File

@ -88,50 +88,21 @@ module RedmineDmsf
# Check if current entity is a folder and return DmsfFolder object if found (nil if not) # Check if current entity is a folder and return DmsfFolder object if found (nil if not)
def folder def folder
unless @folder unless @folder
return nil unless project # If the project doesn't exist, this entity can't exist return nil unless project
# Note: Folder is searched for as a generic search to prevent SQL queries being generated: f = parent.folder
# if we were to look within parent, we'd have to go all the way up the chain as part of the @folder = DmsfFolder.visible.where(:project_id => project.id, :title => basename,
# existence check, and although I'm sure we'd love to access the hierarchy, I can't yet :dmsf_folder_id => parent.folder ? parent.folder.id : nil).first
# see a practical need for it
folders = DmsfFolder.visible.where(:project_id => project.id, :title => basename).order('title ASC').to_a
return nil unless folders.length > 0
if (folders.length > 1)
folders.delete_if { |x| '/' + x.dmsf_path_str != projectless_path }
return nil unless folders.length > 0
@folder = folders[0]
else
if (('/' + folders[0].dmsf_path_str) == projectless_path)
@folder = folders[0]
end
end
end end
@folder @folder
end end
# Check if current entity exists as a file (DmsfFile), and returns corresponding object if found (nil otherwise) # Check if current entity exists as a file (DmsfFile), and returns corresponding object if found (nil otherwise)
# Currently has a dual search approach (depending on if parent can be determined)
def file def file
unless @file unless @file
return nil unless project # Again if entity project is nil, it cannot exist in context of this object return nil unless project # Again if entity project is nil, it cannot exist in context of this object
# Hunt for files parent path @file = DmsfFile.visible.joins('JOIN dmsf_file_revisions ON dmsf_files.id = dmsf_file_revisions.dmsf_file_id').where(
f = false ["dmsf_files.project_id = ? AND dmsf_files.dmsf_folder_id #{parent.folder ? '=' : 'IS'} ? AND dmsf_file_revisions.name = ?",
if (parent.projectless_path != '/') project.id, parent.folder ? parent.folder.id : nil, basename]).first
f = parent.folder if parent.folder
else
f = nil
end
if f || f.nil?
# f has a value other than false? - lets use traditional
# DMSF file search by name.
@file = DmsfFile.visible.find_file_by_name(project, f, basename)
else
# If folder is false, means it couldn't pick up parent,
# as such its probably fine to bail out, however we'll
# perform a search in this scenario
files = DmsfFile.visible.where(:container_id => project.id, :container_type => 'Project', :name => basename).order('name ASC').to_a
files.delete_if { |x| File.dirname('/' + x.dmsf_path_str) != File.dirname(projectless_path) }
@file = files[0] if files.length > 0
end
end end
@file @file
end end
@ -189,6 +160,7 @@ module RedmineDmsf
## ##
def get(request, response) def get(request, response)
raise NotFound unless exist? raise NotFound unless exist?
raise Forbidden unless (!parent.exist? || !parent.folder || DmsfFolder.permissions?(parent.folder))
if collection? if collection?
html_display html_display
response['Content-Length'] = response.body.bytesize.to_s response['Content-Length'] = response.body.bytesize.to_s
@ -207,6 +179,7 @@ module RedmineDmsf
if request.body.read.to_s.empty? if request.body.read.to_s.empty?
raise NotFound unless project && project.module_enabled?('dmsf') raise NotFound unless project && project.module_enabled?('dmsf')
raise Forbidden unless User.current.admin? || User.current.allowed_to?(:folder_manipulation, project) raise Forbidden unless User.current.admin? || User.current.allowed_to?(:folder_manipulation, project)
raise Forbidden unless (!parent.exist? || !parent.folder || DmsfFolder.permissions?(parent.folder, false))
return MethodNotAllowed if exist? # If we already exist, why waste the time trying to save? return MethodNotAllowed if exist? # If we already exist, why waste the time trying to save?
parent_folder = nil parent_folder = nil
if (parent.projectless_path != '/') if (parent.projectless_path != '/')
@ -231,7 +204,7 @@ module RedmineDmsf
def delete def delete
if file if file
raise Forbidden unless User.current.admin? || User.current.allowed_to?(:file_delete, project) raise Forbidden unless User.current.admin? || User.current.allowed_to?(:file_delete, project)
raise Forbidden unless (!parent.exist? || !parent.folder || DmsfFolder.permissions?(parent.folder, false))
pattern = Setting.plugin_redmine_dmsf['dmsf_webdav_disable_versioning'] pattern = Setting.plugin_redmine_dmsf['dmsf_webdav_disable_versioning']
if !pattern.blank? && basename.match(pattern) if !pattern.blank? && basename.match(pattern)
# Files that are not versioned should be destroyed # Files that are not versioned should be destroyed
@ -253,6 +226,7 @@ module RedmineDmsf
end end
elsif folder elsif folder
raise Forbidden unless User.current.admin? || User.current.allowed_to?(:folder_manipulation, project) raise Forbidden unless User.current.admin? || User.current.allowed_to?(:folder_manipulation, project)
raise Forbidden unless DmsfFolder.permissions?(folder, false)
folder.delete(false) ? NoContent : Conflict folder.delete(false) ? NoContent : Conflict
else else
MethodNotAllowed MethodNotAllowed
@ -271,11 +245,13 @@ module RedmineDmsf
return PreconditionFailed if !resource.is_a?(DmsfResource) || resource.project.nil? return PreconditionFailed if !resource.is_a?(DmsfResource) || resource.project.nil?
parent = resource.parent parent = resource.parent
raise Forbidden unless (!parent.exist? || !parent.folder || DmsfFolder.permissions?(parent.folder, false))
if collection? if collection?
# At the moment we don't support cross project destinations # At the moment we don't support cross project destinations
return MethodNotImplemented unless (project.id == resource.project.id) return MethodNotImplemented unless (project.id == resource.project.id)
raise Forbidden unless User.current.admin? || User.current.allowed_to?(:folder_manipulation, project) raise Forbidden unless User.current.admin? || User.current.allowed_to?(:folder_manipulation, project)
raise Forbidden unless DmsfFolder.permissions?(folder, false)
# Current object is a folder, so now we need to figure out information about Destination # Current object is a folder, so now we need to figure out information about Destination
if dest.exist? if dest.exist?
@ -386,6 +362,7 @@ module RedmineDmsf
return PreconditionFailed if !resource.is_a?(DmsfResource) || resource.project.nil? return PreconditionFailed if !resource.is_a?(DmsfResource) || resource.project.nil?
parent = resource.parent parent = resource.parent
raise Forbidden unless (!parent.exist? || !parent.folder || DmsfFolder.permissions?(parent.folder, false))
if collection? if collection?
# Current object is a folder, so now we need to figure out information about Destination # Current object is a folder, so now we need to figure out information about Destination
@ -402,6 +379,7 @@ module RedmineDmsf
User.current.allowed_to?(:view_dmsf_folders, resource.project) && User.current.allowed_to?(:view_dmsf_folders, resource.project) &&
User.current.allowed_to?(:view_dmsf_files, project) && User.current.allowed_to?(:view_dmsf_files, project) &&
User.current.allowed_to?(:view_dmsf_folders, project)) User.current.allowed_to?(:view_dmsf_folders, project))
raise Forbidden unless DmsfFolder.permissions?(folder, false)
return PreconditionFailed if (parent.projectless_path != '/' && !parent.folder) return PreconditionFailed if (parent.projectless_path != '/' && !parent.folder)
folder.title = resource.basename folder.title = resource.basename
@ -552,6 +530,7 @@ module RedmineDmsf
def put(request, response) def put(request, response)
raise BadRequest if collection? raise BadRequest if collection?
raise Forbidden unless User.current.admin? || User.current.allowed_to?(:file_manipulation, project) raise Forbidden unless User.current.admin? || User.current.allowed_to?(:file_manipulation, project)
raise Forbidden unless (!parent.exist? || !parent.folder || DmsfFolder.permissions?(parent.folder, false))
# Ignore file name patterns given in the plugin settings # Ignore file name patterns given in the plugin settings
pattern = Setting.plugin_redmine_dmsf['dmsf_webdav_ignore'] pattern = Setting.plugin_redmine_dmsf['dmsf_webdav_ignore']
@ -593,8 +572,7 @@ module RedmineDmsf
else else
raise BadRequest unless (parent.projectless_path == '/' || (parent.exist? && parent.folder)) raise BadRequest unless (parent.projectless_path == '/' || (parent.exist? && parent.folder))
f = DmsfFile.new f = DmsfFile.new
f.container_type = 'Project' f.project_id = project.id
f.container_id = project.id
f.name = basename f.name = basename
f.dmsf_folder = parent.folder f.dmsf_folder = parent.folder
f.notification = !Setting.plugin_redmine_dmsf['dmsf_default_notifications'].blank? f.notification = !Setting.plugin_redmine_dmsf['dmsf_default_notifications'].blank?
@ -677,6 +655,7 @@ module RedmineDmsf
# also best-utilising DAV4Rack's implementation. # also best-utilising DAV4Rack's implementation.
def download def download
raise NotFound unless (file && file.last_revision && file.last_revision.disk_file) raise NotFound unless (file && file.last_revision && file.last_revision.disk_file)
raise Forbidden unless (!parent.exist? || !parent.folder || DmsfFolder.permissions?(parent.folder))
# If there is no range (start of ranged download, or direct download) then we log the # If there is no range (start of ranged download, or direct download) then we log the
# file access, so we can properly keep logged information # file access, so we can properly keep logged information

View File

@ -1,8 +1,7 @@
--- ---
dmsf_files_001: dmsf_files_001:
id: 1 id: 1
container_id: 1 project_id: 1
container_type: "Project"
dmsf_folder_id: NULL dmsf_folder_id: NULL
name: "test.txt" name: "test.txt"
notification: 0 notification: 0
@ -12,8 +11,7 @@ dmsf_files_001:
#file on non-dmsf enabled project #file on non-dmsf enabled project
dmsf_files_002: dmsf_files_002:
id: 2 id: 2
container_id: 2 project_id: 2
container_type: "Project"
dmsf_folder_id: NULL dmsf_folder_id: NULL
name: "test.txt" name: "test.txt"
notification: 0 notification: 0
@ -23,8 +21,7 @@ dmsf_files_002:
#deleted file on dmsf-enabled project #deleted file on dmsf-enabled project
dmsf_files_003: dmsf_files_003:
id: 3 id: 3
container_id: 1 project_id: 1
container_type: "Project"
dmsf_folder_id: NULL dmsf_folder_id: NULL
name: "deleted.txt" name: "deleted.txt"
notification: 0 notification: 0
@ -33,8 +30,7 @@ dmsf_files_003:
dmsf_files_004: dmsf_files_004:
id: 4 id: 4
container_id: 1 project_id: 1
container_type: "Project"
dmsf_folder_id: 2 dmsf_folder_id: 2
name: "test.txt" name: "test.txt"
notification: 0 notification: 0
@ -43,8 +39,7 @@ dmsf_files_004:
dmsf_files_005: dmsf_files_005:
id: 5 id: 5
container_id: 1 project_id: 1
container_type: "Project"
dmsf_folder_id: 5 dmsf_folder_id: 5
name: "test.txt" name: "test.txt"
notification: 0 notification: 0
@ -53,8 +48,7 @@ dmsf_files_005:
dmsf_files_006: dmsf_files_006:
id: 6 id: 6
container_id: 1 project_id: 1
container_type: "Project"
dmsf_folder_id: 3 dmsf_folder_id: 3
name: "test.txt" name: "test.txt"
notification: 0 notification: 0
@ -63,9 +57,8 @@ dmsf_files_006:
dmsf_files_007: dmsf_files_007:
id: 7 id: 7
container_id: 1 project_id: 1
container_type: "Issue" dmsf_folder_id: 8
dmsf_folder_id: NULL
name: "test.gif" name: "test.gif"
notification: 0 notification: 0
deleted: 0 deleted: 0
@ -73,8 +66,7 @@ dmsf_files_007:
dmsf_files_008: dmsf_files_008:
id: 8 id: 8
container_id: 1 project_id: 1
container_type: "Issue"
dmsf_folder_id: NULL dmsf_folder_id: NULL
name: "test.pdf" name: "test.pdf"
notification: 0 notification: 0
@ -83,8 +75,7 @@ dmsf_files_008:
dmsf_files_009: dmsf_files_009:
id: 9 id: 9
container_id: 1 project_id: 1
container_type: "Project"
dmsf_folder_id: NULL dmsf_folder_id: NULL
name: "myfile.txt" name: "myfile.txt"
notification: 0 notification: 0
@ -93,8 +84,7 @@ dmsf_files_009:
dmsf_files_010: dmsf_files_010:
id: 10 id: 10
container_id: 1 project_id: 1
container_type: "Project"
dmsf_folder_id: NULL dmsf_folder_id: NULL
name: "zero.txt" name: "zero.txt"
notification: 0 notification: 0

View File

@ -46,4 +46,12 @@ dmsf_folders_007:
title: folder7 title: folder7
project_id: 1 project_id: 1
dmsf_folder_id: NULL dmsf_folder_id: NULL
user_id: 1 user_id: 1
dmsf_folders_008:
id: 8
title: .Issues
project_id: 1
dmsf_folder_id: NULL
user_id: 1
system: true

View File

@ -63,15 +63,13 @@ class DmsfFileApiTest < RedmineDmsf::Test::IntegrationTest
# <dmsf_file> # <dmsf_file>
# <id>1</id> # <id>1</id>
# <name>test.txt</name> # <name>test.txt</name>
# <container_id>1</container_id> # <project_id>1</project_id>
# <container_type>Project</container_type>
# <version>1.0</version> # <version>1.0</version>
# <content_url>/dmsf/files/1/download</content_url> # <content_url>/dmsf/files/1/download</content_url>
# </dmsf_file> # </dmsf_file>
assert_select 'dmsf_file > id', :text => @file1.id.to_s assert_select 'dmsf_file > id', :text => @file1.id.to_s
assert_select 'dmsf_file > name', :text => @file1.name assert_select 'dmsf_file > name', :text => @file1.name
assert_select 'dmsf_file > container_id', :text => @file1.container_id.to_s assert_select 'dmsf_file > project_id', :text => @file1.project_id.to_s
assert_select 'dmsf_file > container_type', :text => @file1.container_type.to_s
assert_select 'dmsf_file > version', :text => "#{@file1.last_revision.major_version}.#{@file1.last_revision.minor_version}" assert_select 'dmsf_file > version', :text => "#{@file1.last_revision.major_version}.#{@file1.last_revision.minor_version}"
assert_select 'dmsf_file > content_url', :text => "/dmsf/files/#{@file1.id}/download" assert_select 'dmsf_file > content_url', :text => "/dmsf/files/#{@file1.id}/download"
#curl -v -H "Content-Type: application/octet-stream" -X GET -u ${1}:${2} http://localhost:3000/dmsf/files/41532/download > file.txt #curl -v -H "Content-Type: application/octet-stream" -X GET -u ${1}:${2} http://localhost:3000/dmsf/files/41532/download > file.txt

View File

@ -322,7 +322,7 @@ class DmsfWebdavPropfindTest < RedmineDmsf::Test::IntegrationTest
def test_propfind_depth1_on_project1_for_admin_with_cache def test_propfind_depth1_on_project1_for_admin_with_cache
RedmineDmsf::Webdav::Cache.init_testcache RedmineDmsf::Webdav::Cache.init_testcache
assert_difference 'RedmineDmsf::Webdav::Cache.cache.instance_variable_get(:@data).count', +8 do assert_difference 'RedmineDmsf::Webdav::Cache.cache.instance_variable_get(:@data).count', +9 do
xml_http_request :propfind, "/dmsf/webdav/#{@project1.identifier}", nil, xml_http_request :propfind, "/dmsf/webdav/#{@project1.identifier}", nil,
@admin.merge!({:HTTP_DEPTH => '1'}) @admin.merge!({:HTTP_DEPTH => '1'})
assert_response 207 # MultiStatus assert_response 207 # MultiStatus
@ -376,7 +376,7 @@ class DmsfWebdavPropfindTest < RedmineDmsf::Test::IntegrationTest
log_user 'admin', 'admin' # login as admin log_user 'admin', 'admin' # login as admin
assert !User.current.anonymous?, 'Current user is anonymous' assert !User.current.anonymous?, 'Current user is anonymous'
assert_difference 'RedmineDmsf::Webdav::Cache.cache.instance_variable_get(:@data).count', +8 do assert_difference 'RedmineDmsf::Webdav::Cache.cache.instance_variable_get(:@data).count', +9 do
xml_http_request :propfind, "/dmsf/webdav/#{@project1.identifier}", nil, xml_http_request :propfind, "/dmsf/webdav/#{@project1.identifier}", nil,
@admin.merge!({:HTTP_DEPTH => '1'}) @admin.merge!({:HTTP_DEPTH => '1'})
assert_response 207 # MultiStatus assert_response 207 # MultiStatus

View File

@ -60,9 +60,8 @@ class DmsfFileRevisionTest < RedmineDmsf::Test::UnitTest
def test_new_storage_filename def test_new_storage_filename
# Create a file. # Create a file.
f = DmsfFile.new f = DmsfFile.new
f.container_type = 'Project' f.project_id = 1
f.container_id = 1 f.name = 'Testfile.txt'
f.name = "Testfile.txt"
f.dmsf_folder = nil f.dmsf_folder = nil
f.notification = !Setting.plugin_redmine_dmsf['dmsf_default_notifications'].blank? f.notification = !Setting.plugin_redmine_dmsf['dmsf_default_notifications'].blank?
f.save f.save
@ -74,7 +73,7 @@ class DmsfFileRevisionTest < RedmineDmsf::Test::UnitTest
r1.dmsf_file = f r1.dmsf_file = f
r1.user = User.current r1.user = User.current
r1.name = "Testfile.txt" r1.name = "Testfile.txt"
r1.title = DmsfFileRevision.filename_to_title("Testfile.txt") r1.title = DmsfFileRevision.filename_to_title('Testfile.txt')
r1.description = nil r1.description = nil
r1.comment = nil r1.comment = nil
r1.mime_type = nil r1.mime_type = nil

View File

@ -208,18 +208,6 @@ class DmsfFileTest < RedmineDmsf::Test::UnitTest
RedmineDmsf::Webdav::Cache.init_nullcache RedmineDmsf::Webdav::Cache.init_nullcache
end end
def test_container_project
container = @file1.container
assert_not_nil container
assert container.is_a?(Project)
end
def test_container_issue
container = @file7.container
assert_not_nil container
assert container.is_a?(Issue)
end
def test_project_project def test_project_project
project = @file1.project project = @file1.project
assert_not_nil project assert_not_nil project

View File

@ -53,7 +53,7 @@ class DmsfFolderTest < RedmineDmsf::Test::UnitTest
def test_visiblity def test_visiblity
# The role has got permissions # The role has got permissions
User.current = @manager User.current = @manager
assert_equal 5, DmsfFolder.where(:project_id => 1).count assert_equal 6, DmsfFolder.where(:project_id => 1).count
assert_equal 5, DmsfFolder.visible.where(:project_id => 1).count assert_equal 5, DmsfFolder.visible.where(:project_id => 1).count
# The user has got permissions # The user has got permissions
User.current = @developer User.current = @developer
@ -65,10 +65,10 @@ class DmsfFolderTest < RedmineDmsf::Test::UnitTest
def test_permissions def test_permissions
User.current = @developer User.current = @developer
assert DmsfFolder.permissions(@folder7) assert DmsfFolder.permissions?(@folder7)
@folder7.dmsf_folder_permissions.where(:object_type => 'User').delete_all @folder7.dmsf_folder_permissions.where(:object_type => 'User').delete_all
@folder7.reload @folder7.reload
assert !DmsfFolder.permissions(@folder7) assert !DmsfFolder.permissions?(@folder7)
end end
def test_delete def test_delete

View File

@ -67,7 +67,7 @@ class ProjectPatchTest < RedmineDmsf::Test::UnitTest
def test_dmsf_count def test_dmsf_count
hash = @project1.dmsf_count hash = @project1.dmsf_count
assert_equal 7, hash[:files] assert_equal 8, hash[:files]
assert_equal 6, hash[:folders] assert_equal 6, hash[:folders]
end end
@ -79,7 +79,7 @@ class ProjectPatchTest < RedmineDmsf::Test::UnitTest
end end
def test_copy_dmsf def test_copy_dmsf
assert_equal 3, @project1.dmsf_files.visible.count assert_equal 4, @project1.dmsf_files.visible.count
assert_equal 3, @project1.dmsf_folders.visible.count assert_equal 3, @project1.dmsf_folders.visible.count
assert_equal 1, @project1.file_links.visible.count assert_equal 1, @project1.file_links.visible.count
assert_equal 1, @project1.folder_links.visible.count assert_equal 1, @project1.folder_links.visible.count
@ -90,7 +90,7 @@ class ProjectPatchTest < RedmineDmsf::Test::UnitTest
assert_equal 0, @project3.folder_links.visible.count assert_equal 0, @project3.folder_links.visible.count
assert_equal 0, @project3.url_links.visible.count assert_equal 0, @project3.url_links.visible.count
@project3.copy_dmsf(@project1) @project3.copy_dmsf(@project1)
assert_equal 3, @project3.dmsf_files.visible.count assert_equal 4, @project3.dmsf_files.visible.count
assert_equal 3, @project3.dmsf_folders.count assert_equal 3, @project3.dmsf_folders.count
assert_equal 1, @project3.file_links.visible.count assert_equal 1, @project3.file_links.visible.count
assert_equal 1, @project3.folder_links.visible.count assert_equal 1, @project3.folder_links.visible.count