diff --git a/app/controllers/dmsf_controller.rb b/app/controllers/dmsf_controller.rb index d929af8e..a6cf2e40 100644 --- a/app/controllers/dmsf_controller.rb +++ b/app/controllers/dmsf_controller.rb @@ -26,13 +26,13 @@ class DmsfController < ApplicationController before_filter :find_project before_filter :authorize before_filter :find_folder, :except => [:new, :create, :edit_root, :save_root] - before_filter :find_parent, :only => [:new, :create] - + before_filter :find_parent, :only => [:new, :create] + accept_api_auth :show, :create helper :all - def show + def show @folder_manipulation_allowed = User.current.allowed_to?(:folder_manipulation, @project) @file_manipulation_allowed = User.current.allowed_to?(:file_manipulation, @project) @file_delete_allowed = User.current.allowed_to?(:file_delete, @project) @@ -40,112 +40,117 @@ class DmsfController < ApplicationController @force_file_unlock_allowed = User.current.allowed_to?(:force_file_unlock, @project) @workflows_available = DmsfWorkflow.where(['project_id = ? OR project_id IS NULL', @project.id]).count > 0 @file_approval_allowed = User.current.allowed_to?(:file_approval, @project) + @tree_view = (User.current.pref[:dmsf_tree_view] == '1') && (!%w(atom xml json).include?(params[:format])) - unless @folder - if params[:custom_field_id].present? && params[:custom_value].present? - @subfolders = [] - DmsfFolder.where(:project_id => @project.id).visible.each do |f| - f.custom_field_values.each do |v| - if v.custom_field_id == params[:custom_field_id].to_i - if v.custom_field.compare_values?(v.value, params[:custom_value]) - @subfolders << f - break - end - end - end - end - @files = [] - DmsfFile.where(:project_id => @project.id).visible.each do |f| - r = f.last_revision - if r - r.custom_field_values.each do |v| - if v.custom_field_id == params[:custom_field_id].to_i - if v.custom_field.compare_values?(v.value, params[:custom_value]) - @files << f - break - end - end - end - end - end - @dir_links = [] - DmsfLink.where(:project_id => @project.id, :target_type => DmsfFolder.model_name.to_s).visible.each do |l| - l.target_folder.custom_field_values.each do |v| - if v.custom_field_id == params[:custom_field_id].to_i - if v.custom_field.compare_values?(v.value, params[:custom_value]) - @dir_links << l - break - end - end - end - end - @file_links = [] - DmsfLink.where(:project_id => @project.id, :target_type => DmsfFile.model_name.to_s).visible.each do |l| - r = l.target_file.last_revision if l.target_file - if r - r.custom_field_values.each do |v| - if v.custom_field_id == params[:custom_field_id].to_i - if v.custom_field.compare_values?(v.value, params[:custom_value]) - @file_links << l - break - end - end - end - end - end - @url_links = [] - DmsfLink.where(:project_id => @project.id, :target_type => 'DmsfUrl').visible.each do |l| - r = l.target_file.last_revision if l.target_file - if r - r.custom_field_values.each do |v| - if v.custom_field_id == params[:custom_field_id].to_i - if v.custom_field.compare_values?(v.value, params[:custom_value]) - @file_links << l - break - end - end - end - end - end - else - @subfolders = @project.dmsf_folders.visible - @files = @project.dmsf_files.visible - @dir_links = @project.folder_links.visible - @file_links = @project.file_links.visible - @url_links = @project.url_links.visible - end + if @tree_view @locked_for_user = false else - - if @folder.deleted? - render_404 - return - end - - @subfolders = @folder.subfolders.visible - @files = @folder.files.visible - @dir_links = @folder.folder_links.visible - @file_links = @folder.file_links.visible - @url_links = @folder.url_links.visible - @locked_for_user = @folder.locked_for_user? + unless @folder + if params[:custom_field_id].present? && params[:custom_value].present? + @subfolders = [] + DmsfFolder.where(:project_id => @project.id).visible.each do |f| + f.custom_field_values.each do |v| + if v.custom_field_id == params[:custom_field_id].to_i + if v.custom_field.compare_values?(v.value, params[:custom_value]) + @subfolders << f + break + end + end + end + end + @files = [] + DmsfFile.where(:project_id => @project.id).visible.each do |f| + r = f.last_revision + if r + r.custom_field_values.each do |v| + if v.custom_field_id == params[:custom_field_id].to_i + if v.custom_field.compare_values?(v.value, params[:custom_value]) + @files << f + break + end + end + end + end + end + @dir_links = [] + DmsfLink.where(:project_id => @project.id, :target_type => DmsfFolder.model_name.to_s).visible.each do |l| + l.target_folder.custom_field_values.each do |v| + if v.custom_field_id == params[:custom_field_id].to_i + if v.custom_field.compare_values?(v.value, params[:custom_value]) + @dir_links << l + break + end + end + end + end + @file_links = [] + DmsfLink.where(:project_id => @project.id, :target_type => DmsfFile.model_name.to_s).visible.each do |l| + r = l.target_file.last_revision if l.target_file + if r + r.custom_field_values.each do |v| + if v.custom_field_id == params[:custom_field_id].to_i + if v.custom_field.compare_values?(v.value, params[:custom_value]) + @file_links << l + break + end + end + end + end + end + @url_links = [] + DmsfLink.where(:project_id => @project.id, :target_type => 'DmsfUrl').visible.each do |l| + r = l.target_file.last_revision if l.target_file + if r + r.custom_field_values.each do |v| + if v.custom_field_id == params[:custom_field_id].to_i + if v.custom_field.compare_values?(v.value, params[:custom_value]) + @file_links << l + break + end + end + end + end + end + else + @subfolders = @project.dmsf_folders.visible + @files = @project.dmsf_files.visible + @dir_links = @project.folder_links.visible + @file_links = @project.file_links.visible + @url_links = @project.url_links.visible + end + @locked_for_user = false + else + + if @folder.deleted? + render_404 + return + end + + @subfolders = @folder.dmsf_folders.visible + @files = @folder.dmsf_files.visible + @dir_links = @folder.folder_links.visible + @file_links = @folder.file_links.visible + @url_links = @folder.url_links.visible + @locked_for_user = @folder.locked_for_user? + end end @ajax_upload_size = Setting.plugin_redmine_dmsf['dmsf_max_ajax_upload_filesize'].present? ? Setting.plugin_redmine_dmsf['dmsf_max_ajax_upload_filesize'] : 100 # Trash - @trash_visible = @folder_manipulation_allowed && @file_manipulation_allowed && + @trash_visible = @folder_manipulation_allowed && @file_manipulation_allowed && @file_delete_allowed && !@locked_for_user && !@folder @trash_enabled = DmsfFolder.deleted.where(:project_id => @project.id).any? || DmsfFile.deleted.where(:project_id => @project.id).any? || DmsfLink.deleted.where(:project_id => @project.id).any? - + respond_to do |format| format.html { render :layout => !request.xhr? } format.api end - end + end def trash @folder_manipulation_allowed = User.current.allowed_to? :folder_manipulation, @project @@ -188,7 +193,7 @@ class DmsfController < ApplicationController (params[:email_entries].present? || params[:download_entries].present?) selected_dir_links.each do |id| link = DmsfLink.find_by_id id - selected_folders << link.target_id if link && !selected_folders.include?(link.target_id.to_s) + selected_folders << link.target_id if link && !selected_folders.include?(link.target_id.to_s) end end @@ -196,10 +201,10 @@ class DmsfController < ApplicationController (params[:email_entries].present? || params[:download_entries].present?) selected_file_links.each do |id| link = DmsfLink.find_by_id id - selected_files << link.target_id if link && !selected_files.include?(link.target_id.to_s) + selected_files << link.target_id if link && !selected_files.include?(link.target_id.to_s) end end - + if params[:email_entries].present? email_entries(selected_folders, selected_files) elsif params[:restore_entries].present? @@ -213,7 +218,7 @@ class DmsfController < ApplicationController redirect_to :back else download_entries(selected_folders, selected_files) - end + end rescue FileNotFound render_404 rescue DmsfAccessError @@ -221,7 +226,7 @@ class DmsfController < ApplicationController rescue Exception => e flash[:error] = e.message Rails.logger.error e.message - redirect_to :back + redirect_to :back end def tag_changed @@ -236,7 +241,7 @@ class DmsfController < ApplicationController end end - def entries_email + def entries_email if params[:email][:to].strip.blank? flash.now[:error] = l(:error_email_to_must_be_entered) render :action => 'email_entries' @@ -255,68 +260,68 @@ class DmsfController < ApplicationController render :action => 'edit' end - def create + def create @folder = DmsfFolder.new @folder.title = params[:dmsf_folder][:title].strip @folder.description = params[:dmsf_folder][:description].strip @folder.dmsf_folder_id = params[:dmsf_folder][:dmsf_folder_id] @folder.project = @project @folder.user = User.current - + # Custom fields if params[:dmsf_folder][:custom_field_values].present? params[:dmsf_folder][:custom_field_values].each_with_index do |v, i| @folder.custom_field_values[i].value = v[1] end end - + saved = @folder.save - + respond_to do |format| format.js - format.api { - unless saved - render_validation_errors(@folder) - end + format.api { + unless saved + render_validation_errors(@folder) + end } - format.html { + format.html { if saved - flash[:notice] = l(:notice_folder_created) + flash[:notice] = l(:notice_folder_created) redirect_to dmsf_folder_path(:id => @project, :folder_id => @folder) else @pathfolder = @parent render :action => 'edit' end } - end - + end + end def edit - @parent = @folder.folder + @parent = @folder.dmsf_folder @pathfolder = copy_folder(@folder) @force_file_unlock_allowed = User.current.allowed_to?(:force_file_unlock, @project) end def save - unless params[:dmsf_folder] + unless params[:dmsf_folder] redirect_to dmsf_folder_path(:id => @project, :folder_id => @folder) return end - @pathfolder = copy_folder(@folder) + @pathfolder = copy_folder(@folder) @folder.title = params[:dmsf_folder][:title].strip @folder.description = params[:dmsf_folder][:description].strip @folder.dmsf_folder_id = params[:dmsf_folder][:dmsf_folder_id] - + # Custom fields if params[:dmsf_folder][:custom_field_values].present? params[:dmsf_folder][:custom_field_values].each_with_index do |v, i| @folder.custom_field_values[i].value = v[1] end end - + if @folder.save - flash[:notice] = l(:notice_folder_details_were_saved) + flash[:notice] = l(:notice_folder_details_were_saved) redirect_to dmsf_folder_path(:id => @project, :folder_id => @folder) else render :action => 'edit' @@ -333,7 +338,7 @@ class DmsfController < ApplicationController if commit redirect_to :back else - redirect_to dmsf_folder_path(:id => @project, :folder_id => @folder.folder) + redirect_to dmsf_folder_path(:id => @project, :folder_id => @folder.dmsf_folder) end end @@ -353,7 +358,7 @@ class DmsfController < ApplicationController if params[:project] @project.dmsf_description = params[:project][:dmsf_description] if @project.save - flash[:notice] = l(:notice_folder_details_were_saved) + flash[:notice] = l(:notice_folder_details_were_saved) else flash[:error] = @project.errors.full_messages.to_sentence end @@ -445,11 +450,11 @@ class DmsfController < ApplicationController end zip.files.each do |f| - log_activity(f, 'emailing zip') + log_activity(f, 'emailing zip') audit = DmsfFileRevisionAccess.new audit.user = User.current - audit.revision = f.last_revision - audit.action = DmsfFileRevisionAccess::EmailAction + audit.dmsf_file_revision = f.last_revision + audit.action = DmsfFileRevisionAccess::EmailAction audit.save! end @@ -472,11 +477,11 @@ class DmsfController < ApplicationController zip_entries(zip, selected_folders, selected_files) zip.files.each do |f| - log_activity(f, 'download zip') + log_activity(f, 'download zip') audit = DmsfFileRevisionAccess.new audit.user = User.current - audit.revision = f.last_revision - audit.action = DmsfFileRevisionAccess::DownloadAction + audit.dmsf_file_revision = f.last_revision + audit.action = DmsfFileRevisionAccess::DownloadAction audit.save! end @@ -484,7 +489,7 @@ class DmsfController < ApplicationController :filename => filename_for_content_disposition("#{@project.name}-#{DateTime.now.strftime('%y%m%d%H%M%S')}.zip"), :type => 'application/zip', :disposition => 'attachment') - rescue Exception + rescue Exception raise ensure zip.close if zip @@ -497,7 +502,7 @@ class DmsfController < ApplicationController selected_folders.each do |selected_folder_id| folder = DmsfFolder.visible.find_by_id selected_folder_id if folder - zip.add_folder(folder, member, (folder.folder.dmsf_path_str if folder.folder)) + zip.add_folder(folder, member, (folder.dmsf_folder.dmsf_path_str if folder.dmsf_folder)) else raise FileNotFound end @@ -505,14 +510,14 @@ class DmsfController < ApplicationController end if selected_files && selected_files.is_a?(Array) selected_files.each do |selected_file_id| - file = DmsfFile.visible.find_by_id selected_file_id + file = DmsfFile.visible.find_by_id selected_file_id unless file && file.last_revision && File.exists?(file.last_revision.disk_file) raise FileNotFound end unless (file.project == @project) || User.current.allowed_to?(:view_dmsf_files, file.project) raise DmsfAccessError end - zip.add_file(file, member, (file.folder.dmsf_path_str if file.folder)) if file + zip.add_file(file, member, (file.dmsf_folder.dmsf_path_str if file.dmsf_folder)) if file end end max_files = Setting.plugin_redmine_dmsf['dmsf_max_file_download'].to_i @@ -565,6 +570,7 @@ class DmsfController < ApplicationController if folder unless folder.delete commit flash[:error] = folder.errors.full_messages.to_sentence + return end elsif !commit raise FileNotFound @@ -624,7 +630,7 @@ class DmsfController < ApplicationController rescue DmsfAccessError render_403 rescue ActiveRecord::RecordNotFound - render_404 + render_404 end def find_parent @@ -648,5 +654,5 @@ class DmsfController < ApplicationController :to, :zipped_content, :email, :cc, :subject, :zipped_content => [], :files => []) end - + end \ No newline at end of file diff --git a/app/controllers/dmsf_files_controller.rb b/app/controllers/dmsf_files_controller.rb index 213ecdf1..a7135962 100644 --- a/app/controllers/dmsf_files_controller.rb +++ b/app/controllers/dmsf_files_controller.rb @@ -39,14 +39,14 @@ class DmsfFilesController < ApplicationController @revision = @file.last_revision else @revision = DmsfFileRevision.find(params[:download].to_i) - raise DmsfAccessError if @revision.file != @file + raise DmsfAccessError if @revision.dmsf_file != @file end - check_project(@revision.file) + check_project(@revision.dmsf_file) raise ActionController::MissingFile if @file.deleted? log_activity('downloaded') access = DmsfFileRevisionAccess.new access.user = User.current - access.revision = @revision + access.dmsf_file_revision = @revision access.action = DmsfFileRevisionAccess::DownloadAction access.save! member = Member.where(:user_id => User.current.id, :project_id => @file.project.id).first @@ -71,14 +71,14 @@ class DmsfFilesController < ApplicationController @revision = @file.last_revision else @revision = DmsfFileRevision.find(params[:download].to_i) - raise DmsfAccessError if @revision.file != @file + raise DmsfAccessError if @revision.dmsf_file != @file end - check_project(@revision.file) - raise ActionController::MissingFile if @revision.file.deleted? + check_project(@revision.dmsf_file) + raise ActionController::MissingFile if @revision.dmsf_file.deleted? log_activity('downloaded') access = DmsfFileRevisionAccess.new access.user = User.current - access.revision = @revision + access.dmsf_file_revision = @revision access.action = DmsfFileRevisionAccess::DownloadAction access.save! member = Member.where(:user_id => User.current.id, :project_id => @file.project.id).first @@ -99,7 +99,7 @@ class DmsfFilesController < ApplicationController @revision = @file.last_revision @file_delete_allowed = User.current.allowed_to?(:file_delete, @project) @file_manipulation_allowed = User.current.allowed_to?(:file_manipulation, @project) - @revision_pages = Paginator.new @file.revisions.visible.count, params['per_page'] ? params['per_page'].to_i : 25, params['page'] + @revision_pages = Paginator.new @file.dmsf_file_revisions.visible.count, params['per_page'] ? params['per_page'].to_i : 25, params['page'] respond_to do |format| format.html { @@ -120,7 +120,7 @@ class DmsfFilesController < ApplicationController revision.description = params[:dmsf_file_revision][:description] revision.comment = params[:dmsf_file_revision][:comment] - revision.file = @file + revision.dmsf_file = @file last_revision = @file.last_revision revision.source_revision = last_revision revision.user = User.current @@ -233,7 +233,7 @@ class DmsfFilesController < ApplicationController if commit redirect_to :back else - redirect_to dmsf_folder_path(:id => @project, :folder_id => @file.folder) + redirect_to dmsf_folder_path(:id => @project, :folder_id => @file.dmsf_folder) end end @@ -318,7 +318,7 @@ class DmsfFilesController < ApplicationController def find_revision @revision = DmsfFileRevision.visible.find params[:id] - @file = @revision.file + @file = @revision.dmsf_file @project = @file.project rescue ActiveRecord::RecordNotFound render_404 diff --git a/app/controllers/dmsf_files_copy_controller.rb b/app/controllers/dmsf_files_copy_controller.rb index 85b8af9b..85d2c60a 100644 --- a/app/controllers/dmsf_files_copy_controller.rb +++ b/app/controllers/dmsf_files_copy_controller.rb @@ -18,9 +18,9 @@ class DmsfFilesCopyController < ApplicationController unloadable - + menu_item :dmsf - + before_filter :find_file before_filter :authorize @@ -34,13 +34,13 @@ class DmsfFilesCopyController < ApplicationController else @target_project ||= DmsfFile.allowed_target_projects_on_copy[0] end - + @target_folder = DmsfFolder.visible.find(params[:target_folder_id]) unless params[:target_folder_id].blank? - @target_folder ||= @file.folder if @target_project == @project - + @target_folder ||= @file.dmsf_folder if @target_project == @project + render :layout => !request.xhr? end - + def create @target_project = DmsfFile.allowed_target_projects_on_copy.detect {|p| p.id.to_s == params[:target_project_id]} if params[:target_project_id] unless @target_project @@ -49,18 +49,18 @@ class DmsfFilesCopyController < ApplicationController end @target_folder = DmsfFolder.visible.find_by_id(params[:target_folder_id]) unless params[:target_folder_id].blank? if @target_folder && (@target_folder.project != @target_project) - raise DmsfAccessError, l(:error_entry_project_does_not_match_current_project) + raise DmsfAccessError, l(:error_entry_project_does_not_match_current_project) end - if (@target_folder && @target_folder == @file.folder) || - (@target_folder.nil? && @file.folder.nil? && @target_project == @file.project) + if (@target_folder && @target_folder == @file.dmsf_folder) || + (@target_folder.nil? && @file.dmsf_folder.nil? && @target_project == @file.project) flash[:error] = l(:error_target_folder_same) redirect_to :action => 'new', :id => @file, :target_project_id => @target_project, :target_folder_id => @target_folder return end new_file = @file.copy_to(@target_project, @target_folder) - + unless new_file.errors.empty? flash[:error] = "#{l(:error_file_cannot_be_copied)}: #{new_file.errors.full_messages.join(', ')}" redirect_to :action => 'new', :id => @file, :target_project_id => @target_project, :target_folder_id => @target_folder @@ -68,8 +68,8 @@ class DmsfFilesCopyController < ApplicationController end flash[:notice] = l(:notice_file_copied) - log_activity(new_file, 'was copied (is copy)') - + log_activity(new_file, 'was copied (is copy)') + redirect_to dmsf_file_path(new_file) end @@ -81,11 +81,11 @@ class DmsfFilesCopyController < ApplicationController end @target_folder = DmsfFolder.visible.find(params[:target_folder_id]) unless params[:target_folder_id].blank? if @target_folder && @target_folder.project != @target_project - raise DmsfAccessError, l(:error_entry_project_does_not_match_current_project) + raise DmsfAccessError, l(:error_entry_project_does_not_match_current_project) end - if (@target_folder && @target_folder == @file.folder) || - (@target_folder.nil? && @file.folder.nil? && @target_project == @file.project) + if (@target_folder && @target_folder == @file.dmsf_folder) || + (@target_folder.nil? && @file.dmsf_folder.nil? && @target_project == @file.project) flash[:error] = l(:error_target_folder_same) redirect_to :action => 'new', :id => @file, :target_project_id => @target_project, :target_folder_id => @target_folder return @@ -98,15 +98,15 @@ class DmsfFilesCopyController < ApplicationController end @file.reload - + flash[:notice] = l(:notice_file_moved) - log_activity(@file, 'was moved (is copy)') - + log_activity(@file, 'was moved (is copy)') + redirect_to dmsf_file_path(@file) - end + end private - + def log_activity(file, action) Rails.logger.info "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} #{User.current.login}@#{request.remote_ip}/#{request.env['HTTP_X_FORWARDED_FOR']}: #{action} dmsf://#{file.project.identifier}/#{file.id}/#{file.last_revision.id}" end @@ -115,5 +115,5 @@ private @file = DmsfFile.visible.find(params[:id]) @project = @file.project end - + end diff --git a/app/controllers/dmsf_folders_copy_controller.rb b/app/controllers/dmsf_folders_copy_controller.rb index 3b53ae82..e3d685bd 100644 --- a/app/controllers/dmsf_folders_copy_controller.rb +++ b/app/controllers/dmsf_folders_copy_controller.rb @@ -18,9 +18,9 @@ class DmsfFoldersCopyController < ApplicationController unloadable - + menu_item :dmsf - + before_filter :find_folder before_filter :authorize @@ -32,10 +32,10 @@ class DmsfFoldersCopyController < ApplicationController else @target_project ||= DmsfFolder.allowed_target_projects_on_copy[0] end - + @target_folder = DmsfFolder.visible.find(params[:target_folder_id]) unless params[:target_folder_id].blank? - @target_folder ||= @folder.folder if @target_project == @project - + @target_folder ||= @folder.dmsf_folder if @target_project == @project + render :layout => !request.xhr? end @@ -47,18 +47,18 @@ class DmsfFoldersCopyController < ApplicationController end @target_folder = DmsfFolder.visible.find(params[:target_folder_id]) unless params[:target_folder_id].blank? if !@target_folder.nil? && @target_folder.project != @target_project - raise DmsfAccessError, l(:error_entry_project_does_not_match_current_project) + raise DmsfAccessError, l(:error_entry_project_does_not_match_current_project) end - if (@target_folder && @target_folder == @folder.folder) || - (@target_folder.nil? && @folder.folder.nil? && @target_project == @folder.project) + if (@target_folder && @target_folder == @folder.dmsf_folder) || + (@target_folder.nil? && @folder.dmsf_folder.nil? && @target_project == @folder.project) flash[:error] = l(:error_target_folder_same) redirect_to :action => 'new', :id => @folder, :target_project_id => @target_project, :target_folder_id => @target_folder return end new_folder = @folder.copy_to(@target_project, @target_folder) - + unless new_folder.errors.empty? flash[:error] = "#{l(:error_folder_cannot_be_copied)}: #{new_folder.errors.full_messages.join(', ')}" redirect_to :action => 'new', :id => @folder, :target_project_id => @target_project, :target_folder_id => @target_folder @@ -66,10 +66,10 @@ class DmsfFoldersCopyController < ApplicationController end new_folder.reload - + flash[:notice] = l(:notice_folder_copied) log_activity(new_folder, 'was copied (is copy)') - + redirect_to dmsf_folder_path(:id => @target_project, :folder_id => new_folder) end @@ -83,5 +83,5 @@ class DmsfFoldersCopyController < ApplicationController @folder = DmsfFolder.visible.find(params[:id]) @project = @folder.project end - + end diff --git a/app/controllers/dmsf_links_controller.rb b/app/controllers/dmsf_links_controller.rb index ca03b680..519a57f6 100644 --- a/app/controllers/dmsf_links_controller.rb +++ b/app/controllers/dmsf_links_controller.rb @@ -26,12 +26,12 @@ class DmsfLinksController < ApplicationController before_filter :find_link_project before_filter :authorize - def new + def new @dmsf_link = DmsfLink.new @dmsf_link.project_id = params[:project_id] if params[:dmsf_link].present? - # Reload + # Reload @dmsf_link.dmsf_folder_id = params[:dmsf_link][:dmsf_folder_id] @dmsf_file_id = params[:dmsf_link][:dmsf_file_id] @type = params[:dmsf_link][:type] @@ -53,7 +53,7 @@ class DmsfLinksController < ApplicationController if file folder = DmsfFolder.find_by_id params[:dmsf_link][:target_folder_id] - if (folder && (folder.project_id == @dmsf_link.target_project_id) && folder.files.include?(file)) || folder.nil? + if (folder && (folder.project_id == @dmsf_link.target_project_id) && folder.dmsf_files.include?(file)) || folder.nil? @dmsf_link.name = file.title end end @@ -111,7 +111,7 @@ class DmsfLinksController < ApplicationController @dmsf_link.target_type = DmsfFolder.model_name.to_s end @dmsf_link.name = params[:dmsf_link][:name] - + if @dmsf_link.save flash[:notice] = l(:notice_successful_create) redirect_to dmsf_folder_path(:id => @project.id, :folder_id => @dmsf_link.dmsf_folder_id) diff --git a/app/controllers/dmsf_upload_controller.rb b/app/controllers/dmsf_upload_controller.rb index f472fdb5..ef32c92c 100644 --- a/app/controllers/dmsf_upload_controller.rb +++ b/app/controllers/dmsf_upload_controller.rb @@ -149,7 +149,7 @@ class DmsfUploadController < ApplicationController file = DmsfFile.new file.project = @project file.name = name - file.folder = @folder + file.dmsf_folder = @folder file.notification = Setting.plugin_redmine_dmsf[:dmsf_default_notifications].present? new_revision.minor_version = 0 new_revision.major_version = 0 @@ -172,7 +172,7 @@ class DmsfUploadController < ApplicationController commited_disk_filepath = "#{DmsfHelper.temp_dir}/#{commited_file[:disk_filename].gsub(/[\/\\]/,'')}" - new_revision.file = file + new_revision.dmsf_file = file new_revision.user = User.current new_revision.name = name new_revision.title = commited_file[:title] diff --git a/app/controllers/dmsf_workflows_controller.rb b/app/controllers/dmsf_workflows_controller.rb index b22f570a..d2f2d9f1 100644 --- a/app/controllers/dmsf_workflows_controller.rb +++ b/app/controllers/dmsf_workflows_controller.rb @@ -47,10 +47,9 @@ class DmsfWorkflowsController < ApplicationController revision = DmsfFileRevision.find_by_id params[:dmsf_file_revision_id] if revision if @dmsf_workflow.try_finish revision, action, (params[:step_action].to_i / 10) - file = DmsfFile.joins(:revisions).where(:dmsf_file_revisions => {:id => revision.id}).first - if file + if revision.dmsf_file begin - file.unlock! true + revision.dmsf_file.unlock! true rescue DmsfLockError => e flash[:info] = e.message end @@ -389,7 +388,7 @@ private @project = @dmsf_workflow.project else # Global workflow revision = DmsfFileRevision.find_by_id params[:dmsf_file_revision_id] - @project = revision.file.project if revision && revision.file + @project = revision.dmsf_file.project if revision && revision.dmsf_file end else if params[:dmsf_workflow] diff --git a/app/helpers/dmsf_helper.rb b/app/helpers/dmsf_helper.rb index 8d7d66ab..893a6a1a 100644 --- a/app/helpers/dmsf_helper.rb +++ b/app/helpers/dmsf_helper.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -# +# # Redmine plugin for Document Management System "Features" # # Copyright (C) 2011 Vít Jonáš @@ -36,7 +36,7 @@ module DmsfHelper end "#{timestamp}_#{filename}" end - + def self.sanitize_filename(filename) # get only the filename, not the whole path just_filename = File.basename(filename.gsub('\\\\', '/')) @@ -49,10 +49,10 @@ module DmsfHelper extension = $1 if just_filename =~ %r{(\.[a-zA-Z0-9]+)$} just_filename = Digest::MD5.hexdigest(just_filename) << extension end - + just_filename end - + def self.filetype_css(filename) extension = File.extname(filename) extension = extension[1, extension.length-1] @@ -63,20 +63,55 @@ module DmsfHelper end end - def plugin_asset_path(plugin, asset_type, source) - return "#{Redmine::Utils.relative_url_root}/plugin_assets/#{plugin}/#{asset_type}/#{source}" + def plugin_asset_path(plugin, asset_type, source) + return "#{Redmine::Utils.relative_url_root}/plugin_assets/#{plugin}/#{asset_type}/#{source}" end def self.to_time(obj) #Right, enough of bugs, let's try a better approach here. - return if !obj + return unless obj return obj.to_time(ActiveRecord::Base.default_timezone) if obj.is_a?(String) # Why can't Mysql::Time conform to time object? - without a utc? method it breaks redmine's - # rendering method, so we convert it to string, and back into time - not the most efficient + # rendering method, so we convert it to string, and back into time - not the most efficient # of methods - however seems functional. Not sure if MySQL - return obj.to_s.to_time(ActiveRecord::Base.default_timezone) if obj.class.name == 'Mysql::Time' - return obj - end - + (obj.class.name == 'Mysql::Time') ? obj.to_s.to_time(ActiveRecord::Base.default_timezone) : obj + end + + def self.dmsf_tree(parent, obj, tree = nil) + tree ||= [] + # Folders && files && links + nodes = obj.dmsf_folders.visible + obj.dmsf_links.visible + obj.dmsf_files.visible + # Alphabetical and type sort + nodes.sort! do |x, y| + if ((x.is_a?(DmsfFolder) || (x.is_a?(DmsfLink) && x.is_folder?)) && + (y.is_a?(DmsfFile) || (y.is_a?(DmsfLink) && y.is_file?))) + -1 + elsif ((x.is_a?(DmsfFile) || (x.is_a?(DmsfLink) && x.is_file?)) && + (y.is_a?(DmsfFolder) || (y.is_a?(DmsfLink) && y.is_folder?))) + 1 + else + x.title.downcase <=> y.title.downcase + end + end + # Create the tree + nodes.each do |node| + local_parent = node.dmsf_folder + level = 0 + while local_parent && (local_parent != parent) + level += 1 + local_parent = local_parent.dmsf_folder + end + position = tree.size + # Files of the same parent and on the same level have the same position + if position > 0 && tree[-1][1] == level && + (tree[-1][0].is_a?(DmsfFile) || (tree[-1][0].is_a?(DmsfLink) && tree[-1][0].is_file?)) + position = tree[-1][2] + end + tree << [node, level, position] + self.dmsf_tree(parent, node, tree) if node.is_a?(DmsfFolder) + end + tree + end + end diff --git a/app/models/dmsf_file.rb b/app/models/dmsf_file.rb index 7ce97d85..3ac69a4a 100644 --- a/app/models/dmsf_file.rb +++ b/app/models/dmsf_file.rb @@ -33,17 +33,15 @@ class DmsfFile < ActiveRecord::Base include RedmineDmsf::Lockable belongs_to :project - belongs_to :folder, :class_name => 'DmsfFolder', :foreign_key => 'dmsf_folder_id' + belongs_to :dmsf_folder belongs_to :deleted_by_user, :class_name => 'User', :foreign_key => 'deleted_by_user_id' - has_many :revisions, -> { order("#{DmsfFileRevision.table_name}.major_version DESC, #{DmsfFileRevision.table_name}.minor_version DESC, #{DmsfFileRevision.table_name}.updated_at DESC") }, - :class_name => 'DmsfFileRevision', :foreign_key => 'dmsf_file_id', + has_many :dmsf_file_revisions, -> { order("#{DmsfFileRevision.table_name}.major_version DESC, #{DmsfFileRevision.table_name}.minor_version DESC, #{DmsfFileRevision.table_name}.updated_at DESC") }, :dependent => :destroy has_many :locks, -> { where(entity_type: 0).order("#{DmsfLock.table_name}.updated_at DESC") }, :class_name => 'DmsfLock', :foreign_key => 'entity_id', :dependent => :destroy has_many :referenced_links, -> { where target_type: DmsfFile.model_name.to_s}, :class_name => 'DmsfLink', :foreign_key => 'target_id', :dependent => :destroy - accepts_nested_attributes_for :revisions, :locks, :referenced_links, :project STATUS_DELETED = 1 STATUS_ACTIVE = 0 @@ -58,7 +56,7 @@ class DmsfFile < ActiveRecord::Base validate :validates_name_uniqueness def validates_name_uniqueness - existing_file = DmsfFile.visible.find_file_by_name(self.project, self.folder, self.name) + existing_file = DmsfFile.visible.find_file_by_name(self.project, self.dmsf_folder, self.name) errors.add(:name, l('activerecord.errors.messages.taken')) unless existing_file.nil? || existing_file.id == self.id end @@ -96,11 +94,12 @@ class DmsfFile < ActiveRecord::Base @@storage_path = nil def self.storage_path - path = Setting.plugin_redmine_dmsf['dmsf_storage_directory'].strip if Setting.plugin_redmine_dmsf['dmsf_storage_directory'].present? + return @@storage_path if @@storage_path.present? + path = Setting.plugin_redmine_dmsf['dmsf_storage_directory'] path = Pathname(Redmine::Configuration['attachments_storage_path']).join('dmsf') if path.blank? && Redmine::Configuration['attachments_storage_path'].present? path = Rails.root.join('files/dmsf').to_s if path.blank? - DmsfFile.storage_path = path if path != @@storage_path - @@storage_path + path.strip if path + path end # Lets introduce a write for storage path, that way we can also @@ -123,7 +122,7 @@ class DmsfFile < ActiveRecord::Base def last_revision unless @last_revision - @last_revision = self.deleted? ? self.revisions.first : self.revisions.visible.first + @last_revision = self.deleted? ? self.dmsf_file_revisions.first : self.dmsf_file_revisions.visible.first end @last_revision end @@ -144,7 +143,7 @@ class DmsfFile < ActiveRecord::Base end begin # Revisions and links of a deleted file SHOULD be deleted too - self.revisions.each { |r| r.delete(commit, true) } + self.dmsf_file_revisions.each { |r| r.delete(commit, true) } if commit self.destroy else @@ -160,11 +159,11 @@ class DmsfFile < ActiveRecord::Base end def restore - if self.dmsf_folder_id && (self.folder.nil? || self.folder.deleted?) + if self.dmsf_folder_id && (self.dmsf_folder.nil? || self.dmsf_folder.deleted?) errors[:base] << l(:error_parent_folder) return false end - self.revisions.each { |r| r.restore } + self.dmsf_file_revisions.each { |r| r.restore } self.deleted = STATUS_ACTIVE self.deleted_by_user = nil save @@ -191,7 +190,7 @@ class DmsfFile < ActiveRecord::Base end def dmsf_path - path = self.folder.nil? ? [] : self.folder.dmsf_path + path = self.dmsf_folder ? self.dmsf_folder.dmsf_path : [] path.push(self) path end @@ -202,8 +201,8 @@ class DmsfFile < ActiveRecord::Base def notify? return true if self.notification - return true if folder && folder.notify? - return true if !folder && self.project.dmsf_notification + return true if self.dmsf_folder && delf.dmsf_folder.notify? + return true if !self.dmsf_folder && self.project.dmsf_notification return false end @@ -236,7 +235,7 @@ class DmsfFile < ActiveRecord::Base # If the target project differs from the source project we must physically move the disk files if self.project != project - self.revisions.all.each do |rev| + self.dmsf_file_revisions.all.each do |rev| if File.exist? rev.disk_file(self.project) FileUtils.mv rev.disk_file(self.project), rev.disk_file(project) end @@ -244,9 +243,9 @@ class DmsfFile < ActiveRecord::Base end self.project = project - self.folder = folder + self.dmsf_folder = folder new_revision = self.last_revision.clone - new_revision.file = self + new_revision.dmsf_file = self new_revision.comment = l(:comment_moved_from, :source => "#{self.project.identifier}:#{self.dmsf_path_str}") new_revision.custom_values = [] @@ -261,7 +260,7 @@ class DmsfFile < ActiveRecord::Base # If the target project differs from the source project we must physically move the disk files if self.project != project - self.revisions.all.each do |rev| + self.dmsf_file_revisions.all.each do |rev| if File.exist? rev.disk_file(self.project) FileUtils.cp rev.disk_file(self.project), rev.disk_file(project) end @@ -269,14 +268,14 @@ class DmsfFile < ActiveRecord::Base end file = DmsfFile.new - file.folder = folder + file.dmsf_folder = folder file.project = project file.name = self.name file.notification = Setting.plugin_redmine_dmsf['dmsf_default_notifications'].present? if file.save && self.last_revision new_revision = self.last_revision.clone - new_revision.file = file + new_revision.dmsf_file = file new_revision.comment = l(:comment_copied_from, :source => "#{self.project.identifier}: #{self.dmsf_path_str}") new_revision.custom_values = [] diff --git a/app/models/dmsf_file_revision.rb b/app/models/dmsf_file_revision.rb index b11a257b..13d04d8b 100644 --- a/app/models/dmsf_file_revision.rb +++ b/app/models/dmsf_file_revision.rb @@ -21,14 +21,12 @@ class DmsfFileRevision < ActiveRecord::Base unloadable - belongs_to :file, :class_name => 'DmsfFile', :foreign_key => 'dmsf_file_id' + belongs_to :dmsf_file belongs_to :source_revision, :class_name => 'DmsfFileRevision', :foreign_key => 'source_dmsf_file_revision_id' belongs_to :user - belongs_to :folder, :class_name => 'DmsfFolder', :foreign_key => 'dmsf_folder_id' belongs_to :deleted_by_user, :class_name => 'User', :foreign_key => 'deleted_by_user_id' - has_many :access, :class_name => 'DmsfFileRevisionAccess', :foreign_key => 'dmsf_file_revision_id', :dependent => :destroy + has_many :dmsf_file_revision_access, :dependent => :destroy has_many :dmsf_workflow_step_assignment, :dependent => :destroy - accepts_nested_attributes_for :access, :dmsf_workflow_step_assignment, :file, :user STATUS_DELETED = 1 STATUS_ACTIVE = 0 @@ -37,8 +35,8 @@ class DmsfFileRevision < ActiveRecord::Base scope :deleted, -> { where(:deleted => STATUS_DELETED) } acts_as_customizable - acts_as_event :title => Proc.new {|o| "#{l(:label_dmsf_updated)}: #{o.file.dmsf_path_str}"}, - :url => Proc.new {|o| {:controller => 'dmsf_files', :action => 'show', :id => o.file}}, + acts_as_event :title => Proc.new {|o| "#{l(:label_dmsf_updated)}: #{o.dmsf_file.dmsf_path_str}"}, + :url => Proc.new {|o| {:controller => 'dmsf_files', :action => 'show', :id => o.dmsf_file}}, :datetime => Proc.new {|o| o.updated_at }, :description => Proc.new {|o| o.comment }, :author => Proc.new {|o| o.user } @@ -58,11 +56,11 @@ class DmsfFileRevision < ActiveRecord::Base :message => l(:error_contains_invalid_character) def project - self.file.project if self.file + self.dmsf_file.project if self.dmsf_file end def folder - self.file.folder if self.file + self.dmsf_file.dmsf_folder if self.dmsf_file end def self.remove_extension(filename) @@ -74,11 +72,11 @@ class DmsfFileRevision < ActiveRecord::Base end def delete(commit = false, force = true) - if self.file.locked_for_user? + if self.dmsf_file.locked_for_user? errors[:base] << l(:error_file_is_locked) return false end - if !commit && (!force && (self.file.revisions.length <= 1)) + if !commit && (!force && (self.dmsf_file.dmsf_file_revisions.length <= 1)) errors[:base] << l(:error_at_least_one_revision_must_be_present) return false end @@ -122,7 +120,7 @@ class DmsfFileRevision < ActiveRecord::Base # custom SQL into a temporary object # def access_grouped - access.select('user_id, COUNT(*) AS count, MIN(created_at) AS first_at, MAX(created_at) AS last_at').group('user_id') + self.dmsf_file_revision_access.select('user_id, COUNT(*) AS count, MIN(created_at) AS first_at, MAX(created_at) AS last_at').group('user_id') end def version @@ -130,9 +128,9 @@ class DmsfFileRevision < ActiveRecord::Base end def disk_file(project = nil) - project = self.file.project unless project + project = self.dmsf_file.project unless project storage_base = DmsfFile.storage_path.dup - if self.file && project + if self.dmsf_file && project project_base = project.identifier.gsub(/[^\w\.\-]/,'_') storage_base << "/p_#{project_base}" end @@ -149,7 +147,7 @@ class DmsfFileRevision < ActiveRecord::Base def clone new_revision = DmsfFileRevision.new - new_revision.file = self.file + new_revision.dmsf_file = self.dmsf_file new_revision.disk_filename = self.disk_filename new_revision.size = self.size new_revision.mime_type = self.mime_type @@ -223,13 +221,13 @@ class DmsfFileRevision < ActiveRecord::Base end def new_storage_filename - raise DmsfAccessError, 'File id is not set' unless self.file.id + raise DmsfAccessError, 'File id is not set' unless self.dmsf_file.id filename = DmsfHelper.sanitize_filename(self.name) timestamp = DateTime.now.strftime("%y%m%d%H%M%S") - while File.exist?(File.join(DmsfFile.storage_path, "#{timestamp}_#{self.file.id}_#{filename}")) + while File.exist?(File.join(DmsfFile.storage_path, "#{timestamp}_#{self.dmsf_file.id}_#{filename}")) timestamp.succ! end - "#{timestamp}_#{self.file.id}_#{filename}" + "#{timestamp}_#{self.dmsf_file.id}_#{filename}" end def copy_file_content(open_file) @@ -262,7 +260,7 @@ class DmsfFileRevision < ActiveRecord::Base format.sub!('%f', filename) format.sub!('%d', self.updated_at.strftime('%Y%m%d%H%M%S')) format.sub!('%v', self.version) - format.sub!('%i', self.file.id.to_s) + format.sub!('%i', self.dmsf_file.id.to_s) format.sub!('%r', self.id.to_s) format + ext end diff --git a/app/models/dmsf_file_revision_access.rb b/app/models/dmsf_file_revision_access.rb index 0136fa78..bdaf493e 100644 --- a/app/models/dmsf_file_revision_access.rb +++ b/app/models/dmsf_file_revision_access.rb @@ -1,3 +1,5 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # # Copyright (C) 2011 Vít Jonáš @@ -18,22 +20,22 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class DmsfFileRevisionAccess < ActiveRecord::Base + unloadable - belongs_to :revision, :class_name => 'DmsfFileRevision', :foreign_key => 'dmsf_file_revision_id' + belongs_to :dmsf_file_revision belongs_to :user delegate :project, :to => :revision, :allow_nil => false - delegate :file, :to => :revision, :allow_nil => false - accepts_nested_attributes_for :user, :revision + delegate :file, :to => :revision, :allow_nil => false DownloadAction = 0 EmailAction = 1 - acts_as_event :title => Proc.new {|o| "#{l(:label_dmsf_downloaded)}: #{o.file.dmsf_path_str}"}, - :url => Proc.new {|o| {:controller => 'dmsf_files', :action => 'show', :id => o.file}}, + acts_as_event :title => Proc.new {|o| "#{l(:label_dmsf_downloaded)}: #{o.dmsf_file.dmsf_path_str}"}, + :url => Proc.new {|o| {:controller => 'dmsf_files', :action => 'show', :id => o.dmsf_file}}, :datetime => Proc.new {|o| o.updated_at }, - :description => Proc.new {|o| o.revision.comment }, - :author => Proc.new {|o| o.user } - + :description => Proc.new {|o| o.dmsf_file_revision.comment }, + :author => Proc.new {|o| o.user } + acts_as_activity_provider :type => 'dmsf_file_revision_accesses', :timestamp => "#{DmsfFileRevisionAccess.table_name}.updated_at", :author_key => "#{DmsfFileRevisionAccess.table_name}.user_id", @@ -43,6 +45,6 @@ class DmsfFileRevisionAccess < ActiveRecord::Base "INNER JOIN #{DmsfFileRevision.table_name} ON #{DmsfFileRevisionAccess.table_name}.dmsf_file_revision_id = #{DmsfFileRevision.table_name}.id " + "INNER JOIN #{DmsfFile.table_name} ON #{DmsfFileRevision.table_name}.dmsf_file_id = #{DmsfFile.table_name}.id " + "INNER JOIN #{Project.table_name} ON #{DmsfFile.table_name}.project_id = #{Project.table_name}.id"). - where("#{DmsfFile.table_name}.deleted = ?", DmsfFile::STATUS_ACTIVE) + where("#{DmsfFile.table_name}.deleted = ?", DmsfFile::STATUS_ACTIVE) end diff --git a/app/models/dmsf_file_revision_custom_field.rb b/app/models/dmsf_file_revision_custom_field.rb index 2793b424..e9a12d8f 100644 --- a/app/models/dmsf_file_revision_custom_field.rb +++ b/app/models/dmsf_file_revision_custom_field.rb @@ -1,7 +1,9 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2011 Vít Jonáš -# Copyright (C) 2013 Karel Picman +# Copyright (C) 2011 Vít Jonáš +# Copyright (C) 2011-16 Karel Pičman # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -17,18 +19,18 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -class DmsfFileRevisionCustomField < CustomField - +class DmsfFileRevisionCustomField < CustomField + def type_name :menu_dmsf end - + def compare_values?(x, y) if x.is_a?(Array) && y.is_a?(Array) && !y.empty? - x.include? y[0] - else + x.include? y[0] + else x == y - end + end end - + end \ No newline at end of file diff --git a/app/models/dmsf_folder.rb b/app/models/dmsf_folder.rb index 484bd4f4..4c68e0a2 100644 --- a/app/models/dmsf_folder.rb +++ b/app/models/dmsf_folder.rb @@ -25,43 +25,41 @@ class DmsfFolder < ActiveRecord::Base include RedmineDmsf::Lockable cattr_reader :invalid_characters - @@invalid_characters = /\A[^\/\\\?":<>]*\z/ + @@invalid_characters = /\A[^\/\\\?":<>]*\z/ belongs_to :project - belongs_to :folder, :class_name => 'DmsfFolder', :foreign_key => 'dmsf_folder_id' + belongs_to :dmsf_folder belongs_to :deleted_by_user, :class_name => 'User', :foreign_key => 'deleted_by_user_id' belongs_to :user - has_many :subfolders, :class_name => 'DmsfFolder', :foreign_key => 'dmsf_folder_id', - :dependent => :destroy - has_many :files, :class_name => 'DmsfFile', :foreign_key => 'dmsf_folder_id', - :dependent => :destroy + has_many :dmsf_folders, :dependent => :destroy + has_many :dmsf_files, :dependent => :destroy has_many :folder_links, -> { where :target_type => 'DmsfFolder' }, :class_name => 'DmsfLink', :foreign_key => 'dmsf_folder_id', :dependent => :destroy has_many :file_links, -> { where :target_type => 'DmsfFile' }, :class_name => 'DmsfLink', :foreign_key => 'dmsf_folder_id', :dependent => :destroy has_many :url_links, -> { where :target_type => 'DmsfUrl' }, :class_name => 'DmsfLink', :foreign_key => 'dmsf_folder_id', :dependent => :destroy + has_many :dmsf_links, :dependent => :destroy has_many :referenced_links, -> { where :target_type => 'DmsfFolder' }, :class_name => 'DmsfLink', :foreign_key => 'target_id', :dependent => :destroy has_many :locks, -> { where(entity_type: 1).order("#{DmsfLock.table_name}.updated_at DESC") }, :class_name => 'DmsfLock', :foreign_key => 'entity_id', :dependent => :destroy - accepts_nested_attributes_for :user, :project, :folder, :subfolders, :files, :folder_links, :file_links, :url_links, :referenced_links, :locks - + STATUS_DELETED = 1 STATUS_ACTIVE = 0 - + scope :visible, -> { where(:deleted => STATUS_ACTIVE) } scope :deleted, -> { where(:deleted => STATUS_DELETED) } acts_as_customizable - + acts_as_searchable :columns => ["#{self.table_name}.title", "#{self.table_name}.description"], :project_key => 'project_id', :date_column => 'updated_at', :permission => :view_dmsf_files, - :scope => self.joins(:project) - + :scope => self.joins(:project) + acts_as_event :title => Proc.new {|o| o.title}, :description => Proc.new {|o| o.description }, :url => Proc.new {|o| {:controller => 'dmsf', :action => 'show', :id => o.project, :folder_id => o}}, @@ -69,11 +67,11 @@ class DmsfFolder < ActiveRecord::Base :author => Proc.new {|o| o.user } validates :title, :presence => true - validates_uniqueness_of :title, :scope => [:dmsf_folder_id, :project_id, :deleted], + validates_uniqueness_of :title, :scope => [:dmsf_folder_id, :project_id, :deleted], conditions: -> { where(:deleted => STATUS_ACTIVE) } validates_format_of :title, :with => @@invalid_characters, :message => l(:error_contains_invalid_character) - validate :check_cycle + validate :check_cycle before_create :default_values def default_values @@ -87,13 +85,13 @@ class DmsfFolder < ActiveRecord::Base def check_cycle folders = [] - self.subfolders.each {|f| folders.push(f)} - folders.each do |folder| - if folder == self.folder + self.dmsf_folders.each {|f| folders.push(f)} + self.dmsf_folders.each do |folder| + if folder == self.dmsf_folder errors.add(:folder, l(:error_create_cycle_in_folder_dependency)) return false end - folder.subfolders.each {|f| folders.push(f)} + folder.dmsf_folders.each {|f| folders.push(f)} end return true end @@ -110,10 +108,10 @@ class DmsfFolder < ActiveRecord::Base if self.locked? errors[:base] << l(:error_folder_is_locked) return false - elsif !self.subfolders.visible.empty? || !self.files.visible.empty? + elsif !self.dmsf_folders.visible.empty? || !self.dmsf_files.visible.empty? errors[:base] << l(:error_folder_is_not_empty) return false - end + end if commit self.destroy else @@ -122,16 +120,16 @@ class DmsfFolder < ActiveRecord::Base self.save end end - + def deleted? self.deleted == STATUS_DELETED end def restore - if self.dmsf_folder_id && (self.folder.nil? || self.folder.deleted?) + if self.dmsf_folder_id && (self.dmsf_folder.nil? || self.dmsf_folder.deleted?) errors[:base] << l(:error_parent_folder) return false - end + end self.deleted = STATUS_ACTIVE self.deleted_by_user = nil self.save @@ -142,7 +140,7 @@ class DmsfFolder < ActiveRecord::Base path = [] while folder path.unshift(folder) - folder = folder.folder + folder = folder.dmsf_folder end path end @@ -155,8 +153,8 @@ class DmsfFolder < ActiveRecord::Base def notify? return true if self.notification - return true if folder && folder.notify? - return true if !folder && self.project.dmsf_notification + return true if self.dmsf_folder && self.dmsf_folder.notify? + return true if !self.dmsf_folder && self.project.dmsf_notification return false end @@ -197,21 +195,21 @@ class DmsfFolder < ActiveRecord::Base end def deep_file_count - file_count = self.files.visible.count - self.subfolders.visible.each {|subfolder| file_count += subfolder.deep_file_count} - file_count + self.file_links.visible.count + file_count = self.dmsf_files.visible.count + self.dmsf_folders.visible.each { |subfolder| file_count += subfolder.deep_file_count } + file_count + self.file_links.visible.count + self.url_links.visible.count end def deep_folder_count - folder_count = self.subfolders.visible.count - self.subfolders.visible.each {|subfolder| folder_count += subfolder.deep_folder_count} + folder_count = self.dmsf_folders.visible.count + self.dmsf_folders.visible.each { |subfolder| folder_count += subfolder.deep_folder_count } folder_count + self.folder_links.visible.count end def deep_size size = 0 - self.files.visible.each {|file| size += file.size} - self.subfolders.visible.each {|subfolder| size += subfolder.deep_size} + self.dmsf_files.visible.each {|file| size += file.size} + self.dmsf_folders.visible.each {|subfolder| size += subfolder.deep_size} size end @@ -228,7 +226,7 @@ class DmsfFolder < ActiveRecord::Base def copy_to(project, folder) new_folder = DmsfFolder.new - new_folder.folder = folder ? folder : nil + new_folder.dmsf_folder = folder ? folder : nil new_folder.project = folder ? folder.project : project new_folder.title = self.title new_folder.description = self.description @@ -241,11 +239,11 @@ class DmsfFolder < ActiveRecord::Base return new_folder unless new_folder.save - self.files.visible.each do |f| + self.dmsf_files.visible.each do |f| f.copy_to project, new_folder end - self.subfolders.visible.each do |s| + self.dmsf_folders.visible.each do |s| s.copy_to project, new_folder end @@ -268,13 +266,13 @@ class DmsfFolder < ActiveRecord::Base def available_custom_fields DmsfFileRevisionCustomField.all end - + def modified last_update = updated_at - subfolders.each do |subfolder| + dmsf_folders.each do |subfolder| last_update = subfolder.updated_at if subfolder.updated_at > last_update end - files.each do |file| + dmsf_files.each do |file| last_update = file.updated_at if file.updated_at > last_update end folder_links.each do |folder_link| @@ -288,20 +286,20 @@ class DmsfFolder < ActiveRecord::Base end last_update end - + # Number of items in the folder def items - subfolders.visible.count + - files.visible.count + + dmsf_folders.visible.count + + dmsf_files.visible.count + folder_links.visible.count + file_links.visible.count + url_links.visible.count - end - + end + private def self.directory_subtree(tree, folder, level, current_folder) - folder.subfolders.visible.each do |subfolder| + folder.dmsf_folders.visible.each do |subfolder| unless subfolder == current_folder tree.push(["#{'...' * level}#{subfolder.title}", subfolder.id]) directory_subtree(tree, subfolder, level + 1, current_folder) diff --git a/app/models/dmsf_link.rb b/app/models/dmsf_link.rb index d0fa4152..1e67e143 100644 --- a/app/models/dmsf_link.rb +++ b/app/models/dmsf_link.rb @@ -29,9 +29,9 @@ class DmsfLink < ActiveRecord::Base validates :name, :presence => true validates_length_of :name, :maximum => 255 - validates_length_of :external_url, :maximum => 255 + validates_length_of :external_url, :maximum => 255 validate :validate_url - + def validate_url if self.target_type == 'DmsfUrl' begin @@ -40,17 +40,17 @@ class DmsfLink < ActiveRecord::Base else errors.add :external_url, :invalid end - rescue URI::InvalidURIError + rescue URI::InvalidURIError errors.add :external_url, :invalid - end + end end end - + STATUS_DELETED = 1 STATUS_ACTIVE = 0 - + scope :visible, -> { where(:deleted => STATUS_ACTIVE) } - scope :deleted, -> { where(:deleted => STATUS_DELETED) } + scope :deleted, -> { where(:deleted => STATUS_DELETED) } def target_folder_id if self.target_type == DmsfFolder.model_name.to_s @@ -97,9 +97,9 @@ class DmsfLink < ActiveRecord::Base end def path - if self.target_type == DmsfFile.model_name.to_s + if self.target_type == DmsfFile.model_name.to_s path = self.target_file.dmsf_path.map { |element| element.is_a?(DmsfFile) ? element.name : element.title }.join('/') if self.target_file - else + else path = self.target_folder ? self.target_folder.dmsf_path_str : '' end path.insert(0, "#{self.target_project.name}:") if self.project_id != self.target_project_id @@ -133,7 +133,7 @@ class DmsfLink < ActiveRecord::Base end def restore - if self.dmsf_folder_id && (self.folder.nil? || self.folder.deleted?) + if self.dmsf_folder_id && (self.dmsf_folder.nil? || self.dmsf_folder.deleted?) errors[:base] << l(:error_parent_folder) return false end @@ -142,4 +142,12 @@ class DmsfLink < ActiveRecord::Base save(:validate => false) end + def is_folder? + self.target_type == 'DmsfFolder' + end + + def is_file? + !is_folder? + end + end \ No newline at end of file diff --git a/app/models/dmsf_lock.rb b/app/models/dmsf_lock.rb index e1873c7d..13bc6b8c 100644 --- a/app/models/dmsf_lock.rb +++ b/app/models/dmsf_lock.rb @@ -29,10 +29,9 @@ class DmsfLock < ActiveRecord::Base belongs_to :user # At the moment apparently we're only supporting a write lock? - as_enum :lock_type, [:type_write, :type_other] as_enum :lock_scope, [:scope_exclusive, :scope_shared] - + # We really loosely bind the value in the belongs_to above # here we just ensure the data internal to the model is correct # to ensure everything lists fine - it's the same as a join @@ -73,5 +72,5 @@ class DmsfLock < ActiveRecord::Base def self.find_by_param(*args) self.find(*args) end - + end \ No newline at end of file diff --git a/app/models/dmsf_mailer.rb b/app/models/dmsf_mailer.rb index 500f4362..666cc3b7 100644 --- a/app/models/dmsf_mailer.rb +++ b/app/models/dmsf_mailer.rb @@ -23,74 +23,74 @@ require 'mailer' class DmsfMailer < Mailer layout 'mailer' - + def files_updated(user, project, files) - if user && project && files.count > 0 + if user && project && files.count > 0 files = files.select { |file| file.notify? } - redmine_headers 'Project' => project.identifier if project + redmine_headers 'Project' => project.identifier if project @files = files @project = project message_id project set_language_if_valid user.language - mail :to => user.mail, + mail :to => user.mail, :subject => "[#{@project.name} - #{l(:menu_dmsf)}] #{l(:text_email_doc_updated_subject)}" end end - + def files_deleted(user, project, files) - if user && files.count > 0 + if user && files.count > 0 files = files.select { |file| file.notify? } - redmine_headers 'Project' => project.identifier if project + redmine_headers 'Project' => project.identifier if project @files = files @project = project message_id project set_language_if_valid user.language - mail :to => user.mail, + mail :to => user.mail, :subject => "[#{@project.name} - #{l(:menu_dmsf)}] #{l(:text_email_doc_deleted_subject)}" end end - - def send_documents(project, user, email_params) - zipped_content_data = open(email_params[:zipped_content], 'rb') { |io| io.read } + + def send_documents(project, user, email_params) + zipped_content_data = open(email_params[:zipped_content], 'rb') { |io| io.read } redmine_headers 'Project' => project.identifier if project @body = email_params[:body] @links_only = email_params[:links_only] @folders = email_params[:folders] - @files = email_params[:files] + @files = email_params[:files] unless @links_only == '1' attachments['Documents.zip'] = { :content_type => 'application/zip', :content => zipped_content_data } - end - mail :to => email_params[:to], :cc => email_params[:cc], + end + mail :to => email_params[:to], :cc => email_params[:cc], :subject => email_params[:subject], :from => user.mail end - + def workflow_notification(user, workflow, revision, subject_id, text1_id, text2_id, notice = nil) if user && workflow && revision - if revision.file && revision.file.project - @project = revision.file.project + if revision.dmsf_file && revision.dmsf_file.project + @project = revision.dmsf_file.project redmine_headers 'Project' => @project.identifier end set_language_if_valid user.language @user = user message_id workflow @workflow = workflow - @revision = revision - @text1 = l(text1_id, :name => workflow.name, :filename => revision.file.name, :notice => notice) + @revision = revision + @text1 = l(text1_id, :name => workflow.name, :filename => revision.dmsf_file.name, :notice => notice) @text2 = l(text2_id) @notice = notice - mail :to => user.mail, + mail :to => user.mail, :subject => "[#{@project.name} - #{l(:field_label_dmsf_workflow)}] #{@workflow.name} #{l(subject_id)}" end - end - + end + def self.get_notify_users(project, files = nil) if files notify_files = files.select { |file| file.notify? } return [] if notify_files.empty? - end + end notify_members = project.members notify_members = notify_members.select do |notify_member| - notify_user = notify_member.user + notify_user = notify_member.user if notify_user == User.current && notify_user.pref.no_self_notified false else @@ -105,13 +105,13 @@ class DmsfMailer < Mailer else false end - else + else notify_member.dmsf_mail_notification end end - end + end notify_members.collect { |m| m.user }.uniq end - + end \ No newline at end of file diff --git a/app/models/dmsf_upload.rb b/app/models/dmsf_upload.rb index a151de50..ff1efd06 100644 --- a/app/models/dmsf_upload.rb +++ b/app/models/dmsf_upload.rb @@ -1,8 +1,10 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # # Copyright (C) 2011 Vít Jonáš # Copyright (C) 2012 Daniel Munn -# Copyright (C) 2011-14 Karel Pičman +# Copyright (C) 2011-16 Karel Pičman # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -19,63 +21,67 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class DmsfUpload - attr_accessor :name + attr_accessor :name attr_accessor :disk_filename attr_reader :size attr_accessor :mime_type attr_accessor :title - attr_accessor :description + attr_accessor :description attr_accessor :comment attr_accessor :major_version attr_accessor :minor_version - attr_accessor :locked + attr_accessor :locked attr_accessor :workflow - attr_accessor :custom_values - + attr_accessor :custom_values + def disk_file "#{DmsfHelper.temp_dir}/#{self.disk_filename}" - end - - def self.create_from_uploaded_attachment(project, folder, uploaded_file) - a = Attachment.find_by_token(uploaded_file[:token]) + end + + def self.create_from_uploaded_attachment(project, folder, uploaded_file) + a = Attachment.find_by_token(uploaded_file[:token]) if a uploaded = { :disk_filename => DmsfHelper.temp_filename(a.filename), :content_type => a.content_type, :original_filename => a.filename, :comment => uploaded_file[:description] - } + } FileUtils.mv(a.diskfile, "#{DmsfHelper.temp_dir}/#{uploaded[:disk_filename]}") - a.destroy + a.destroy upload = DmsfUpload.new(project, folder, uploaded) else - Rails.logger.error "An attachment not found by its token: #{uploaded_file[:token]}" + Rails.logger.error "An attachment not found by its token: #{uploaded_file[:token]}" end upload end - + def initialize(project, folder, uploaded) @name = uploaded[:original_filename] - + file = DmsfFile.find_file_by_name(project, folder, @name) unless file link = DmsfLink.find_link_by_file_name(project, folder, @name) file = link.target_file if link end - + @disk_filename = uploaded[:disk_filename] @mime_type = uploaded[:content_type] - @size = File.size(disk_file) - + @size = File.size(disk_file) + if file.nil? || file.last_revision.nil? @title = DmsfFileRevision.filename_to_title(@name) @description = uploaded[:comment] @major_version = 0 @minor_version = 0 - @workflow = nil - @custom_values = DmsfFileRevision.new(:file => DmsfFile.new(:project => @project)).custom_field_values + @workflow = nil + file = DmsfFile.new + file.project = @project + revision = DmsfFileRevision.new + revision.dmsf_file = file + @custom_values = revision.custom_field_values else - last_revision = file.last_revision + last_revision = file.last_revision @title = last_revision.title if last_revision.description.present? @description = last_revision.description @@ -86,7 +92,7 @@ class DmsfUpload @major_version = last_revision.major_version @minor_version = last_revision.minor_version @workflow = last_revision.workflow - @custom_values = Array.new(file.last_revision.custom_values) + @custom_values = Array.new(file.last_revision.custom_values) # Add default value for CFs not existing present_custom_fields = file.last_revision.custom_values.collect(&:custom_field).uniq @@ -96,8 +102,8 @@ class DmsfUpload end end end - + @locked = file && file.locked_for_user? end - + end \ No newline at end of file diff --git a/app/models/dmsf_workflow_step.rb b/app/models/dmsf_workflow_step.rb index 8ce5c857..63e903ad 100644 --- a/app/models/dmsf_workflow_step.rb +++ b/app/models/dmsf_workflow_step.rb @@ -2,7 +2,7 @@ # # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2011-15 Karel Pičman +# Copyright (C) 2011-16 Karel Pičman # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -25,8 +25,8 @@ class DmsfWorkflowStep < ActiveRecord::Base validates :step, :presence => true validates :user_id, :presence => true validates :operator, :presence => true - validates_uniqueness_of :user_id, :scope => [:dmsf_workflow_id, :step] - + validates_uniqueness_of :user_id, :scope => [:dmsf_workflow_id, :step] + OPERATOR_OR = 0 OPERATOR_AND = 1 @@ -37,7 +37,7 @@ class DmsfWorkflowStep < ActiveRecord::Base def user User.find(user_id) end - + def assign(dmsf_file_revision_id) step_assignment = DmsfWorkflowStepAssignment.new( :dmsf_workflow_step_id => id, @@ -45,20 +45,20 @@ class DmsfWorkflowStep < ActiveRecord::Base :dmsf_file_revision_id => dmsf_file_revision_id) step_assignment.save end - + def is_finished?(dmsf_file_revision_id) self.dmsf_workflow_step_assignments.each do |assignment| if assignment.dmsf_file_revision_id == dmsf_file_revision_id - if assignment.dmsf_workflow_step_actions.empty? + if assignment.dmsf_workflow_step_actions.empty? return false - end - assignment.dmsf_workflow_step_actions.each do |act| - return false unless act.is_finished? end - end - end + assignment.dmsf_workflow_step_actions.each do |act| + return false unless act.is_finished? + end + end + end end - + def copy_to(workflow) new_step = self.dup new_step.dmsf_workflow_id = workflow.id diff --git a/app/models/dmsf_workflow_step_action.rb b/app/models/dmsf_workflow_step_action.rb index f5d8c69e..0725c362 100644 --- a/app/models/dmsf_workflow_step_action.rb +++ b/app/models/dmsf_workflow_step_action.rb @@ -2,7 +2,7 @@ # # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2011-15 Karel Pičman +# Copyright (C) 2011-16 Karel Pičman # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -19,37 +19,35 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class DmsfWorkflowStepAction < ActiveRecord::Base - - belongs_to :dmsf_workflow_step_assignment + + belongs_to :dmsf_workflow_step_assignment validates :dmsf_workflow_step_assignment_id, :presence => true validates :action, :presence => true validates :note, :presence => true, :unless => lambda { self.action == DmsfWorkflowStepAction::ACTION_APPROVE } validates :author_id, :presence => true - validates_uniqueness_of :dmsf_workflow_step_assignment_id, :scope => [:action], :unless => lambda {self.action == DmsfWorkflowStepAction::ACTION_DELEGATE} - - attr_accessible :dmsf_workflow_step_assignment_id, :action, :note - + validates_uniqueness_of :dmsf_workflow_step_assignment_id, :scope => [:action], :unless => lambda {self.action == DmsfWorkflowStepAction::ACTION_DELEGATE} + ACTION_APPROVE = 1 ACTION_REJECT = 2 ACTION_DELEGATE = 3 ACTION_ASSIGN = 4 ACTION_START = 5 - + def initialize(*args) super - self.author_id = User.current.id if User.current + self.author_id = User.current.id if User.current end - + def self.is_finished?(action) action == DmsfWorkflowStepAction::ACTION_APPROVE || action == DmsfWorkflowStepAction::ACTION_REJECT end - + def is_finished? DmsfWorkflowStepAction.is_finished? self.action end - + def self.action_str(action) if action case action.to_i @@ -66,7 +64,7 @@ class DmsfWorkflowStepAction < ActiveRecord::Base end end end - + def self.action_type_str(action) if action case action.to_i @@ -83,12 +81,12 @@ class DmsfWorkflowStepAction < ActiveRecord::Base end end end - + def self.workflow_str(action) if action - case action.to_i + case action.to_i when ACTION_REJECT - l(:title_rejected) + l(:title_rejected) when ACTION_ASSIGN l(:title_assigned) when ACTION_START, ACTION_DELEGATE, ACTION_APPROVE @@ -98,5 +96,5 @@ class DmsfWorkflowStepAction < ActiveRecord::Base end end end - + end \ No newline at end of file diff --git a/app/models/dmsf_workflow_step_assignment.rb b/app/models/dmsf_workflow_step_assignment.rb index cda7d8f3..30ffbcd5 100644 --- a/app/models/dmsf_workflow_step_assignment.rb +++ b/app/models/dmsf_workflow_step_assignment.rb @@ -2,7 +2,7 @@ # # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2011-15 Karel Pičman +# Copyright (C) 2011-16 Karel Pičman # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -22,17 +22,15 @@ class DmsfWorkflowStepAssignment < ActiveRecord::Base belongs_to :dmsf_workflow_step belongs_to :user belongs_to :dmsf_file_revision - has_many :dmsf_workflow_step_actions, :dependent => :destroy - validates :dmsf_workflow_step_id, :dmsf_file_revision_id, :presence => true + has_many :dmsf_workflow_step_actions, :dependent => :destroy + validates :dmsf_workflow_step_id, :dmsf_file_revision_id, :presence => true validates_uniqueness_of :dmsf_workflow_step_id, :scope => [:dmsf_file_revision_id] - - attr_accessible :dmsf_workflow_step_id, :user_id, :dmsf_file_revision_id - + def add?(dmsf_file_revision_id) if self.dmsf_file_revision_id == dmsf_file_revision_id add = true self.dmsf_workflow_step_actions.each do |action| - if action.is_finished? + if action.is_finished? add = false break end diff --git a/app/views/dmsf/_dir.html.erb b/app/views/dmsf/_dir.html.erb index 56da2dbc..2a12f9a0 100644 --- a/app/views/dmsf/_dir.html.erb +++ b/app/views/dmsf/_dir.html.erb @@ -21,12 +21,15 @@ %> <% locked_for_user = subfolder && subfolder.locked_for_user? %> -<% locked = subfolder && subfolder.locked? %> +<% locked = subfolder && subfolder.locked? %> -<%= check_box_tag(name, id, false, +<%= check_box_tag(name, id, false, :title => l(:title_check_for_zip_download_or_email), :id => "subfolder_#{id}") %> - - <%= link_to(h(title), + + <% if @tree_view %> + > + <% end %> + <%= link_to(h(title), dmsf_folder_path(:id => project, :folder_id => subfolder), :class => 'icon icon-folder') %> <% if link %> @@ -34,22 +37,22 @@ <% else %>
[<%= subfolder.items %>]
<% end %> - + -<%= format_time(subfolder.modified) if subfolder %> +<%= format_time(subfolder.modified) if subfolder %> <% if locked_for_user %> - <% if subfolder.lock.reverse[0].user %> + <% if subfolder.lock.reverse[0].user %> <%= link_to(image_tag(link ? 'locked_gray.png' : 'locked.png', :plugin => 'redmine_dmsf'), user_path(subfolder.lock.reverse[0].user), :title => l(:title_locked_by_user, :user => subfolder.lock.reverse[0].user)) %> - <% else %> - <%= content_tag(:span, image_tag(link ? 'locked_gray.png' : 'locked.png', :plugin => 'redmine_dmsf'), + <% else %> + <%= content_tag(:span, image_tag(link ? 'locked_gray.png' : 'locked.png', :plugin => 'redmine_dmsf'), :title => l(:notice_account_unknown_email)) %> <% end %> - <% elsif locked %> - <%= content_tag(:span, image_tag(link ? 'lockedbycurrent_gray.png' : 'lockedbycurrent.png', :plugin => 'redmine_dmsf'), + <% elsif locked %> + <%= content_tag(:span, image_tag(link ? 'lockedbycurrent_gray.png' : 'lockedbycurrent.png', :plugin => 'redmine_dmsf'), :title => l(:title_locked_by_you)) %> - <% end %> + <% end %> @@ -65,7 +68,7 @@ <% if subfolder.unlockable? %> <%= link_to(image_tag('unlock.png', :plugin => 'redmine_dmsf'), unlock_dmsf_path(:id => project, :folder_id => subfolder), - :title => l(:title_unlock_file)) %> + :title => l(:title_unlock_file)) %> <% else %> <% end %> @@ -77,11 +80,11 @@ <% else %> <% end %> - <% if (subfolder && subfolder.notification) || (!subfolder && project.dmsf_notification) %> + <% if (subfolder && subfolder.notification) || (!subfolder && project.dmsf_notification) %> <%= link_to(image_tag('notify.png', :plugin => 'redmine_dmsf'), notify_deactivate_dmsf_path(:id => project, :folder_id => subfolder), :title => l(:title_notifications_active_deactivate)) %> - <% else %> + <% else %> <%= link_to(image_tag('notifynot.png', :plugin => 'redmine_dmsf'), notify_activate_dmsf_path(:id => project, :folder_id => subfolder), :title => l(:title_notifications_not_active_activate)) %> @@ -89,24 +92,24 @@ <% if link %> <%= link_to(image_tag('delete.png'), dmsf_link_path(link), :data => {:confirm => l(:text_are_you_sure)}, - :method => :delete, :title => l(:title_delete)) %> + :method => :delete, :title => l(:title_delete)) %> <% else %> <%= link_to(image_tag('delete.png'), delete_dmsf_path(:id => project, :folder_id => subfolder), - :data => {:confirm => l(:text_are_you_sure)}, - :title => l(:title_delete)) %> - <% end %> - <% else %> + :data => {:confirm => l(:text_are_you_sure)}, + :title => l(:title_delete)) %> + <% end %> + <% else %> <% if (!locked_for_user || @force_file_unlock_allowed) && subfolder.unlockable? %> <%= link_to(image_tag('unlock.png', :plugin => 'redmine_dmsf'), unlock_dmsf_path(:id => project, :folder_id => subfolder), - :title => l(:title_unlock_file)) %> - <% end %> - <% end %> + :title => l(:title_unlock_file)) %> + <% end %> + <% end %> <% end %> -0 +<%= position %> 0 <%= subfolder.modified.to_i if subfolder %> -0 \ No newline at end of file +0 diff --git a/app/views/dmsf/_file.html.erb b/app/views/dmsf/_file.html.erb index 84d6341e..c39fceaf 100644 --- a/app/views/dmsf/_file.html.erb +++ b/app/views/dmsf/_file.html.erb @@ -22,9 +22,12 @@ <% wf = DmsfWorkflow.find_by_id(file.last_revision.dmsf_workflow_id) %> -<%= check_box_tag(name, id, false, +<%= check_box_tag(name, id, false, :title => l(:title_check_for_zip_download_or_email), :id => "file_#{id}") %> + <% if @tree_view %> + > + <% end %> <% file_view_url = url_for({:controller => :dmsf_files, :action => 'view', :id => file}) %> <%= link_to(h(title), file_view_url, @@ -33,32 +36,33 @@ :title => l(:title_title_version_version_download, :title => h(file.title), :version => file.version), 'data-downloadurl' => "#{file.last_revision.detect_content_type}:#{h(file.name)}:#{file_view_url}") %>
<%= h(link ? link.path : file.display_name) %>
+ <%= ''.html_safe if @tree_view %> <%= number_to_human_size(file.last_revision.size) %> <%= format_time(file.last_revision.updated_at) %> <% if file.locked_for_user? %> - <% if file.lock.reverse[0].user %> + <% if file.lock.reverse[0].user %> <%= link_to(image_tag(link ? 'locked_gray.png' : 'locked.png', :plugin => 'redmine_dmsf'), user_path(file.lock.reverse[0].user), :title => l(:title_locked_by_user, :user => file.lock.reverse[0].user)) %> - <% else %> - <%= content_tag(:span, image_tag(link ? 'locked_gray.png' : 'locked.png', :plugin => 'redmine_dmsf'), + <% else %> + <%= content_tag(:span, image_tag(link ? 'locked_gray.png' : 'locked.png', :plugin => 'redmine_dmsf'), :title => l(:notice_account_unknown_email)) %> <% end %> - <% elsif file.locked? %> - <%= content_tag(:span, image_tag(link ? 'lockedbycurrent_gray.png' : 'lockedbycurrent.png', :plugin => 'redmine_dmsf'), + <% elsif file.locked? %> + <%= content_tag(:span, image_tag(link ? 'lockedbycurrent_gray.png' : 'lockedbycurrent.png', :plugin => 'redmine_dmsf'), :title => l(:title_locked_by_you)) %> <% end %> <%= file.last_revision.version %> - + <% if wf && @file_approval_allowed %> <%= link_to( file.last_revision.workflow_str(false), log_dmsf_workflow_path( - :project_id => project.id, - :id => wf.id, + :project_id => project.id, + :id => wf.id, :dmsf_file_revision_id => file.last_revision.id), :title => DmsfWorkflow.assignments_to_users_str(wf.next_assignments(file.last_revision.id)), :remote => true) %> @@ -67,7 +71,7 @@ <% end %> <%= h(file.last_revision.user) %> - + <% if @file_manipulation_allowed %> <%= link_to(image_tag('filedetails.png', :plugin => 'redmine_dmsf'), dmsf_file_path(:id => file), @@ -76,7 +80,7 @@ <% if !file.locked? %> <%= link_to(image_tag('lock.png', :plugin => 'redmine_dmsf'), lock_dmsf_files_path(:id => file), - :title => l(:title_lock_file)) %> + :title => l(:title_lock_file)) %> <% elsif file.unlockable? %> <%= link_to(image_tag('unlock.png', :plugin => 'redmine_dmsf'), unlock_dmsf_files_path(:id => file), @@ -84,97 +88,97 @@ <% else %> <% end %> - <% if file.notification %> + <% if file.notification %> <%= link_to(image_tag('notify.png', :plugin => 'redmine_dmsf'), notify_deactivate_dmsf_files_path(:id => file), :title => l(:title_notifications_active_deactivate)) %> - <% else %> + <% else %> <%= link_to(image_tag('notifynot.png', :plugin => 'redmine_dmsf'), notify_activate_dmsf_files_path(:id => file), :title => l(:title_notifications_not_active_activate)) %> <% end %> <% if link %> - <%= link_to(image_tag('delete.png'), - dmsf_link_path(link), - :data => {:confirm => l(:text_are_you_sure)}, + <%= link_to(image_tag('delete.png'), + dmsf_link_path(link), + :data => {:confirm => l(:text_are_you_sure)}, :method => :delete, :title => l(:title_delete)) %> <% else %> - <% if @file_delete_allowed %> - <%= link_to(image_tag('delete.png'), - dmsf_file_path(:id => file), - :data => {:confirm => l(:text_are_you_sure)}, + <% if @file_delete_allowed %> + <%= link_to(image_tag('delete.png'), + dmsf_file_path(:id => file), + :data => {:confirm => l(:text_are_you_sure)}, :method => :delete, :title => l(:title_delete)) unless file.locked_for_user? %> <% else %> <% end %> - <% end %> - <% else %> + <% end %> + <% else %> <% if @force_file_unlock_allowed && file.unlockable? %> <%= link_to(image_tag('unlock.png', :plugin => 'redmine_dmsf'), unlock_dmsf_files_path(:id => file), :title => l(:title_unlock_file))%> <% else %> - <% end %> + <% end %> <% end %> <% end %> <% if @file_approval_allowed %> <% case file.last_revision.workflow %> - <% when DmsfWorkflow::STATE_WAITING_FOR_APPROVAL %> + <% 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(image_tag('waiting_for_approval.png', :plugin => 'redmine_dmsf'), action_dmsf_workflow_path( - :project_id => project.id, - :id => wf.id, + :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), + :title => l(:title_waiting_for_approval), :remote => true) %> <% else %> <%= content_tag(:span, image_tag('waiting_for_approval.png', :plugin => 'redmine_dmsf'), :title => "#{l(:label_dmsf_wokflow_action_approve)} #{l(:label_dmsf_wokflow_action_reject)} #{l(:label_dmsf_wokflow_action_delegate)}") %> <% end %> - <% else %> + <% else %> <%= content_tag(:span, image_tag('waiting_for_approval.png', :plugin => 'redmine_dmsf'), :title => "#{l(:label_dmsf_wokflow_action_approve)} #{l(:label_dmsf_wokflow_action_reject)} #{l(:label_dmsf_wokflow_action_delegate)}") %> <% end %> - <% when DmsfWorkflow::STATE_APPROVED %> - <%= content_tag(:span, image_tag('approved.png', :plugin => 'redmine_dmsf'), + <% when DmsfWorkflow::STATE_APPROVED %> + <%= content_tag(:span, image_tag('approved.png', :plugin => 'redmine_dmsf'), :title => l(:title_approved)) %> <% when DmsfWorkflow::STATE_ASSIGNED %> - <% if User.current && (file.last_revision.dmsf_workflow_assigned_by == User.current.id) && wf %> + <% if User.current && (file.last_revision.dmsf_workflow_assigned_by == User.current.id) && wf %> <%= link_to(image_tag('assigned.png', :plugin => 'redmine_dmsf'), - start_dmsf_workflow_path( - :id => file.last_revision.dmsf_workflow_id, + 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)) %> - <% else %> - <%= content_tag(:span, image_tag('assigned.png', :plugin => 'redmine_dmsf'), + <% else %> + <%= content_tag(:span, image_tag('assigned.png', :plugin => 'redmine_dmsf'), title => l(:label_dmsf_wokflow_action_start)) %> <% end %> - <% when DmsfWorkflow::STATE_REJECTED %> - <%= content_tag(:span, image_tag('rejected.png', :plugin => 'redmine_dmsf'), + <% when DmsfWorkflow::STATE_REJECTED %> + <%= content_tag(:span, image_tag('rejected.png', :plugin => 'redmine_dmsf'), :title => l(:title_rejected)) %> <% else %> <% if @workflows_available && !file.locked_for_user? %> <%= link_to(image_tag('none.png', :plugin => 'redmine_dmsf'), assign_dmsf_workflow_path( - :project_id => project.id, + :project_id => project.id, :dmsf_file_revision_id => file.last_revision.id), - :title => l(:label_dmsf_wokflow_action_assign), - :remote => true) %> + :title => l(:label_dmsf_wokflow_action_assign), + :remote => true) %> <% end %> - <% end %> + <% end %> <% end %> -1 +<%= position %> <%= file.last_revision.size %> <%= file.last_revision.updated_at.to_i %> -<%= file.last_revision.iversion %> \ No newline at end of file +<%= file.last_revision.iversion %> diff --git a/app/views/dmsf/_list_view.erb b/app/views/dmsf/_list_view.erb new file mode 100644 index 00000000..6ef48f67 --- /dev/null +++ b/app/views/dmsf/_list_view.erb @@ -0,0 +1,118 @@ +<% +# encoding: utf-8 +# +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2011-16 Karel Pičman +# +# 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. +%> + + + + + + + + + + + + + + + + + + + + <% @subfolders.each do |subfolder| %> + + <%= render(:partial => 'dir', + :locals => { + :project => @project, + :subfolder => subfolder, + :link => nil, + :id => subfolder.id, + :name => 'subfolders[]', + :title => subfolder.title, + :position => 0 }) %> + + <% end %> + <% @dir_links.each do |link| %> + <% unless link.target_project %> + <% Rails.logger.error "Error: dmsf_link id #{link.id} has no target!" %> + <% next %> + <% end %> + + <%= render(:partial => 'dir', + :locals => { + :project => link.target_project, + :subfolder => link.target_folder, + :link => link, + :id => link.id, + :name => 'dir_links[]', + :title => link.name, + :position => 0}) %> + + <% end %> + <% @files.each do |file| %> + <% unless file.last_revision %> + <% Rails.logger.error "Error: dmsf_file id #{file.id} has no revision!" %> + <% next %> + <% end %> + + <%= render(:partial => 'file', :locals => { + :project => @project, + :file => file, + :link => nil, + :id => file.id, + :name => 'files[]', + :title => file.title, + :position => 1 }) %> + + <% end %> + <% @file_links.each do |link| %> + <% unless link.target_file.last_revision %> + <% Rails.logger.error "Error: dmsf_file id #{link.target_id} has no revision!" %> + <% next %> + <% end %> + + <%= render(:partial => 'file', :locals => { + :project => link.target_project, + :file => link.target_file, + :link => link, + :id => link.id, + :name => 'file_links[]', + :title => link.name, + :position => 1}) %> + + <% end %> + <% @url_links.each do |link| %> + + <%= render(:partial => 'url', :locals => { + :project => link.target_project, + :file => link.target_file, + :link => link, + :id => link.id, + :name => 'file_links[]', + :title => link.name, + :position => 1}) %> + + <% end %> + +
+ + <%= l(:link_title) %><%= l(:link_size) %><%= l(:link_modified) %><%= l(:link_ver) %><%= l(:link_workflow) %><%= l(:link_author) %>
diff --git a/app/views/dmsf/_tree_view.erb b/app/views/dmsf/_tree_view.erb new file mode 100644 index 00000000..8949ad52 --- /dev/null +++ b/app/views/dmsf/_tree_view.erb @@ -0,0 +1,138 @@ +<% +# encoding: utf-8 +# +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2011-16 Karel Pičman +# +# 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. +%> + + + + + + + + + + + + + + + + + + + + <% parent = @folder ? @folder : @project %> + <% DmsfHelper.dmsf_tree(parent, parent).each do |obj, level, position| %> + <% classes = "dmsf_tree idnt-#{level}" %> + <% if obj.is_a?(DmsfFolder) && ((obj.dmsf_folders.visible.count > 0) || (obj.dmsf_files.visible.count > 0) || (obj.dmsf_links.visible.count > 0)) %> + <% classes += ' idnt dmsf_collapsed' %> + <% id = "id='#{obj.id}span'".html_safe %> + <% onclick = "onclick=\"dmsf_toggle('#{obj.id}','#{obj.id}span')\"" %> + <% else %> + <% classes += ' dmsf_child' %> + <% onclick = '' %> + <% end %> + <% classes += ' dmsf_hidden' if obj.dmsf_folder && obj.dmsf_folder != @folder %> + <% parent = obj.dmsf_folder %> + <% while parent %> + <% classes += " #{parent.id}" %> + <% parent = parent.dmsf_folder %> + <% end %> + + <% if obj.is_a? DmsfFolder %> + class="dir <%= classes %>"> + <%= render(:partial => 'dir', + :locals => { + :project => @project, + :subfolder => obj, + :link => nil, + :id => obj.id, + :name => 'subfolders[]', + :title => obj.title, + :onclick => onclick, + :position => position}) %> + + <% elsif obj.is_a?(DmsfLink) && (obj.target_type == 'DmsfFolder') %> + <% unless obj.target_project %> + <% Rails.logger.error "Error: dmsf_link id #{obj.id} has no target!" %> + <% next %> + <% end %> + class="dmsf_gray <%= classes %>"> + <%= render(:partial => 'dir', + :locals => { + :project => obj.target_project, + :subfolder => obj.target_folder, + :link => obj, + :id => obj.id, + :name => 'dir_links[]', + :title => obj.name, + :onclick => onclick, + :position => position}) %> + + <% elsif obj.is_a?(DmsfFile) %> + <% unless obj.last_revision %> + <% Rails.logger.error "Error: dmsf_file id #{obj.id} has no revision!" %> + <% next %> + <% end %> + class="file <%= classes %>"> + <%= render(:partial => 'file', :locals => { + :project => @project, + :file => obj, + :link => nil, + :id => obj.id, + :name => 'files[]', + :title => obj.title, + :onclick => onclick, + :position => position}) %> + + <% elsif obj.is_a?(DmsfLink) && (obj.target_type == 'DmsfFile') %> + <% unless obj.target_file.last_revision %> + <% Rails.logger.error "Error: dmsf_file id #{obj.target_id} has no revision!" %> + <% next %> + <% end %> + class="dmsf_gray <%= classes %>"> + <%= render(:partial => 'file', :locals => { + :project => obj.target_project, + :file => obj.target_file, + :link => obj, + :id => obj.id, + :name => 'file_links[]', + :title => obj.name, + :onclick => onclick, + :position => position}) %> + + <% elsif obj.is_a?(DmsfLink) && (obj.target_type == 'DmsfUrl') %> + class="dmsf_gray <%= classes %>"> + <%= render(:partial => 'url', :locals => { + :project => obj.target_project, + :file => obj.target_file, + :link => obj, + :id => obj.id, + :name => 'file_links[]', + :title => obj.name, + :onclick => onclick, + :position => position}) %> + + <% end %> + <% end %> + +
+ + <%= l(:link_title) %><%= l(:link_size) %><%= l(:link_modified) %><%= l(:link_ver) %><%= l(:link_workflow) %><%= l(:link_author) %>
diff --git a/app/views/dmsf/_url.html.erb b/app/views/dmsf/_url.html.erb index 7816bab0..cafab4a4 100644 --- a/app/views/dmsf/_url.html.erb +++ b/app/views/dmsf/_url.html.erb @@ -22,13 +22,17 @@ + <% if @tree_view %> + > + <% end %> <%= link_to(h(title), link.external_url, :target => '_blank', :class => 'icon dmsf_icon-link') %> -
+
<%= link.external_url %>
+ <%= ''.html_safe if @tree_view %> <%= format_time(link.updated_at) %> @@ -39,17 +43,17 @@ - <% if @file_manipulation_allowed %> - <%= link_to(image_tag('delete.png'), + <% if @file_manipulation_allowed %> + <%= link_to(image_tag('delete.png'), dmsf_link_path(link), :data => {:confirm => l(:text_are_you_sure)}, :method => :delete, :title => l(:title_delete)) %> - <% else %> + <% else %> - <% end %> + <% end %> -1 +<%= position %> link.updated_at.to_i - \ No newline at end of file + diff --git a/app/views/dmsf/show.html.erb b/app/views/dmsf/show.html.erb index c218b2c8..190945f5 100644 --- a/app/views/dmsf/show.html.erb +++ b/app/views/dmsf/show.html.erb @@ -101,97 +101,11 @@
<% end %>
- - - - - - - - - - - - - - - - - - - <% @subfolders.each do |subfolder| %> - - <%= render(:partial => 'dir', - :locals => { - :project => @project, - :subfolder => subfolder, - :link => nil, - :id => subfolder.id, - :name => 'subfolders[]', - :title => subfolder.title }) %> - - <% end %> - <% @dir_links.each do |link| %> - <% unless link.target_project %> - <% Rails.logger.error "Error: dmsf_link id #{link.id} has no target!" %> - <% next %> + <% if @tree_view %> + <%= render(:partial => 'tree_view') %> + <% else %> + <%= render(:partial => 'list_view') %> <% end %> - - <%= render(:partial => 'dir', - :locals => { - :project => link.target_project, - :subfolder => link.target_folder, - :link => link, - :id => link.id, - :name => 'dir_links[]', - :title => link.name }) %> - - <% end %> - <% @files.each do |file| %> - <% unless file.last_revision %> - <% Rails.logger.error "Error: dmsf_file id #{file.id} has no revision!" %> - <% next %> - <% end %> - - <%= render(:partial => 'file', :locals => { - :project => @project, - :file => file, - :link => nil, - :id => file.id, - :name => 'files[]', - :title => file.title }) %> - - <% end %> - <% @file_links.each do |link| %> - <% unless link.target_file.last_revision %> - <% Rails.logger.error "Error: dmsf_file id #{link.target_id} has no revision!" %> - <% next %> - <% end %> - - <%= render(:partial => 'file', :locals => { - :project => link.target_project, - :file => link.target_file, - :link => link, - :id => link.id, - :name => 'file_links[]', - :title => link.name }) %> - - <% end %> - <% @url_links.each do |link| %> - - <%= render(:partial => 'url', :locals => { - :project => link.target_project, - :file => link.target_file, - :link => link, - :id => link.id, - :name => 'file_links[]', - :title => link.name }) %> - - <% end %> - -
- - <%= l(:link_title) %><%= l(:link_size) %><%= l(:link_modified) %><%= l(:link_ver) %><%= l(:link_workflow) %><%= l(:link_author) %>
<% end %> @@ -228,15 +142,15 @@ $('#browser').dataTable({ 'bJQueryUI': true, 'oLanguage': { - 'sUrl': "<%= plugin_asset_path(:redmine_dmsf, 'javascripts', sUrl) %>" + 'sUrl': "<%= plugin_asset_path(:redmine_dmsf, 'javascripts', sUrl) %>" }, - 'bAutoWidth': false, + 'bAutoWidth': false, 'bPaginate': false, - 'aaSorting': [[1,'asc']], - 'aaSortingFixed': [[8,'asc']], + 'aaSorting': [[1, 'asc']], + 'aaSortingFixed': [[ 8, 'asc']], 'aoColumnDefs': [ - { 'bSearchable': false, 'aTargets': [0, 7, 8, 9] }, - { 'bSortable': false, 'aTargets': [0, 7, 8] }, + { 'bSearchable': false, 'aTargets': [0, 7, 8, 9, 10, 11] }, + { 'bSortable': false, 'aTargets': [0, 7] }, { 'iDataSort': 9, 'aTargets': [ 2 ] }, { 'iDataSort': 10, 'aTargets': [ 3 ] }, { 'iDataSort': 11, 'aTargets': [ 4 ] } @@ -245,7 +159,15 @@ jQuery('div.dmsf_controls').prependTo(jQuery('#browser_wrapper div.fg-toolbar')[0]); }, 'fnInfoCallback': function( oSettings, iStart, iEnd, iMax, iTotal, sPre ) { - return "<%= l(:label_number_of_folders)%>: <%= @subfolders.count + @dir_links.count %>, <%= l(:label_number_of_documents)%>: <%= @files.count + @file_links.count + @url_links.count %>"; + <% if @tree_view %> + <% if @folder %> + return "<%= "#{l(:label_number_of_folders)}: #{@folder.deep_folder_count} #{l(:label_number_of_documents)}: #{@folder.deep_file_count}" %>"; + <% 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(:project_id => @project.id).count + DmsfLink.visible.where(:project_id => @project.id, :target_type => 'DmsfFile').count + DmsfLink.visible.where(:project_id => @project.id, :target_type => 'DmsfUrl').count}" %>"; + <% end %> + <% 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}" %>"; + <% end %> } }); diff --git a/app/views/dmsf_files/show.html.erb b/app/views/dmsf_files/show.html.erb index 27241caa..973a773b 100644 --- a/app/views/dmsf_files/show.html.erb +++ b/app/views/dmsf_files/show.html.erb @@ -27,27 +27,27 @@
<% if User.current.allowed_to?(:file_manipulation, @project) %> <% unless @file.locked_for_user? %> - <% unless @file.locked? %> + <% unless @file.locked? %> <%= link_to(l(:button_lock), lock_dmsf_files_path(:id => @file), :title => l(:title_lock_file), :class => 'icon dmsf_icon-lock') %> <% else %> <%= link_to_if(@file.unlockable?, l(:button_unlock), unlock_dmsf_files_path(:id => @file), - :title => l(:title_unlock_file), :class => 'icon dmsf_icon-unlock') %> + :title => l(:title_unlock_file), :class => 'icon dmsf_icon-unlock') %> <% end %> - <% if @file.notification %> + <% if @file.notification %> <%= link_to(l(:label_notifications_off), notify_deactivate_dmsf_files_path(:id => @file), :title => l(:title_notifications_active_deactivate), :class => 'icon dmsf_icon-notification-on') %> - <% else %> + <% else %> <%= link_to(l(:label_notifications_on), notify_activate_dmsf_files_path(:id => @file), :title => l(:title_notifications_not_active_activate), :class => 'icon dmsf_icon-notification-off') %> <% end %> - <%= link_to(l(:label_link_to), - new_dmsf_link_path(:project_id => @project.id, :dmsf_folder_id => @file.folder ? @file.folder.id : nil, :dmsf_file_id => @file.id, :type => 'link_to'), - :title => l(:title_create_link), + <%= link_to(l(:label_link_to), + new_dmsf_link_path(:project_id => @project.id, :dmsf_folder_id => @file.dmsf_folder ? @file.dmsf_folder.id : nil, :dmsf_file_id => @file.id, :type => 'link_to'), + :title => l(:title_create_link), :class => 'icon dmsf_icon-link') %> <%= link_to("#{l(:button_copy)}/#{l(:button_move)}", copy_file_path(:id => @file), :title => l(:title_copy), :class => 'icon icon-copy') %> @@ -55,13 +55,13 @@ <% else %> <% if User.current.allowed_to?(:force_file_unlock, @project) %> <%= link_to_if(@file.unlockable?, l(:button_unlock), unlock_dmsf_files_path(:id => @file), - :title => l(:title_unlock_file), :class => 'icon dmsf_icon-unlock')%> - <% end %> - <% end %> + :title => l(:title_unlock_file), :class => 'icon dmsf_icon-unlock')%> + <% end %> + <% end %> <% end %>
-<%= render(:partial => '/dmsf/path', +<%= render(:partial => '/dmsf/path', :locals => {:folder => @file.folder, :filename => @file.title, :title => nil}) %> <% if User.current.allowed_to?(:file_manipulation, @file.project) && !@file.locked_for_user? %> @@ -76,13 +76,13 @@

<%= l(:heading_revisions) %>

-<% @file.revisions.visible[@revision_pages.offset, @revision_pages.per_page].each do |revision| %> -
-
+<% @file.dmsf_file_revisions.visible[@revision_pages.offset, @revision_pages.per_page].each do |revision| %> +
+
-
- <%= link_to_function image_tag('rev_downloads.png', :plugin => 'redmine_dmsf'), - "$('#revision_access-#{revision.id}').toggle()", +
+ <%= link_to_function image_tag('rev_downloads.png', :plugin => 'redmine_dmsf'), + "$('#revision_access-#{revision.id}').toggle()", :title => l(:title_download_entries) %> <%= link_to image_tag('rev_download.png', :plugin => 'redmine_dmsf'), dmsf_file_path(@file, :download => revision), @@ -90,8 +90,8 @@ <%= link_to image_tag('rev_delete.png', :plugin => 'redmine_dmsf'), delete_revision_path(revision), :data => {:confirm => l(:text_are_you_sure)}, - :title => l(:title_delete_revision) if @file_delete_allowed && (@file.revisions.visible.count > 1) %> -
+ :title => l(:title_delete_revision) if @file_delete_allowed && (@file.dmsf_file_revisions.visible.count > 1) %> +
<%= l(:info_revision, :rev => revision.id) %> <%= (revision.source_revision.nil? ? l(:label_created) : l(:label_changed)).downcase %> <%= l(:info_changed_by_user, :changed => format_time(revision.updated_at)) %> @@ -103,29 +103,29 @@

<%= label_tag('', l(:label_title)) %> - <%= h(revision.title) %> + <%= h(revision.title) %>

<%= label_tag('', l(:label_file)) %> - <%= ("#{h(revision.file.folder.dmsf_path_str)}/") if revision.file.folder %><%= h(revision.name) %> + <%= ("#{h(revision.dmsf_file.dmsf_folder.dmsf_path_str)}/") if revision.dmsf_file.dmsf_folder %><%= h(revision.name) %>

<% if revision.description.present? %>

- <%= label_tag('', l(:label_description)) %> + <%= label_tag('', l(:label_description)) %>

<%= textilizable(revision.description) %> -
+

<% end %>
-
+

<%= label_tag('', l(:label_version)) %> - <%= revision.major_version %>.<%= revision.minor_version %> + <%= revision.major_version %>.<%= revision.minor_version %>

<%= label_tag('', l(:link_workflow)) %> @@ -133,44 +133,44 @@ <% if wf %> <%= "#{wf.name} - " %> <%= link_to(revision.workflow_str(false), - log_dmsf_workflow_path(:project_id => @project.id, + log_dmsf_workflow_path(:project_id => @project.id, :id => wf.id, :dmsf_file_revision_id => revision.id), :title => DmsfWorkflow.assignments_to_users_str(wf.next_assignments(revision.id)), :remote => true) %> <% else %> <%= revision.workflow_str(true) %> - <% end %> + <% end %>

-
+

<%= label_tag('', l(:label_mime)) %> <%= h(revision.mime_type) %>

<%= label_tag('', l(:label_size)) %> - <%= number_to_human_size(revision.size) %> + <%= number_to_human_size(revision.size) %>

-
-
- <%= render 'dmsf/custom_fields', :object => revision %> +
+
+ <%= render 'dmsf/custom_fields', :object => revision %> <% if revision.comment.present? %>

- <%= label_tag('', l(:label_comment)) %> + <%= label_tag('', l(:label_comment)) %>

<%= textilizable(revision.comment) %> -
+

<% end %> -
" style="display:none"> - <%= render(:partial => 'revision_access', :locals => {:revision => revision}) if User.current.allowed_to?(:file_manipulation, @file.project) %> -
+
" style="display:none"> + <%= render(:partial => 'revision_access', :locals => {:revision => revision}) if User.current.allowed_to?(:file_manipulation, @file.project) %> +
-
-
+ +
<% end %> -<%= pagination_links_full @revision_pages, @file.revisions.visible.count %> +<%= pagination_links_full @revision_pages, @file.dmsf_file_revisions.visible.count %> <% url = 'jquery.dataTables/en.json' @@ -186,16 +186,16 @@ $('a.delete-entry').click(function(event) { if(!window.confirm('<%= l(:text_are_you_sure) %>')) { - event.preventDefault(); + event.preventDefault(); } }); $('#file_upload').change(function() { if($("input[name='version']:checked").val() == '0') { - $('#fileMinorVersionRadio').prop('checked', true); + $('#fileMinorVersionRadio').prop('checked', true); } - $('#fileSameVersionRadio').prop('disabled', true); - }); + $('#fileSameVersionRadio').prop('disabled', true); + }); $('#newRevisionFormContentToggle').click(function() { if($('#newRevisionFormContent').is(':visible')) { @@ -205,24 +205,24 @@ else { $(this).text('[-]'); $('#newRevisionFormContent').show(); - } + } }); $('.access-table').dataTable({ 'bJQueryUI': true, 'oLanguage': { - 'sUrl': '/plugin_assets/<%= :redmine_dmsf %>/javascripts/<%= url %>' + 'sUrl': '/plugin_assets/<%= :redmine_dmsf %>/javascripts/<%= url %>' } }); <% if @revision.valid? && @file.valid? %> <% end %> -<% content_for :header_tags do %> - <%= stylesheet_link_tag 'jquery.dataTables/jquery-ui.dataTables.css', :plugin => 'redmine_dmsf' %> - <%= javascript_include_tag 'jquery.dataTables/jquery.dataTables.min.js', :plugin => 'redmine_dmsf' %> +<% content_for :header_tags do %> + <%= stylesheet_link_tag 'jquery.dataTables/jquery-ui.dataTables.css', :plugin => 'redmine_dmsf' %> + <%= javascript_include_tag 'jquery.dataTables/jquery.dataTables.min.js', :plugin => 'redmine_dmsf' %> <% end %> \ No newline at end of file diff --git a/app/views/dmsf_files_copy/new.html.erb b/app/views/dmsf_files_copy/new.html.erb index dd1b3270..09c80ea0 100644 --- a/app/views/dmsf_files_copy/new.html.erb +++ b/app/views/dmsf_files_copy/new.html.erb @@ -24,17 +24,17 @@ <% html_title(l(:dmsf)) %> -<%= render(:partial => '/dmsf/path', - :locals => {:folder => @file.folder, :filename => @file.title, +<%= render(:partial => '/dmsf/path', + :locals => {:folder => @file.dmsf_folder, :filename => @file.title, :title => "#{l(:button_copy)}/#{l(:button_move)}"}) %> <% if DmsfFile.allowed_target_projects_on_copy.present? %> <%= form_tag({:action => 'create', :id => @file}, :id => 'copyForm') do |f| %>
-

+

<%= label_tag('target_project_id', l(:field_target_project)) %> <%= select_tag('target_project_id', - project_tree_options_for_select(DmsfFile.allowed_target_projects_on_copy, + project_tree_options_for_select(DmsfFile.allowed_target_projects_on_copy, :selected => @target_project)) %>

@@ -46,7 +46,7 @@

<%= submit_tag(l(:button_copy)) %> - <% if User.current.allowed_to?(:file_manipulation, @project) %> + <% if User.current.allowed_to?(:file_manipulation, @project) %> <%= submit_tag(l(:button_move), :id => 'move_button') %> <% end %>

@@ -60,7 +60,7 @@ }); $('#target_project_id').change(function () { - $('#content').load("<%= url_for(:action => 'new') %>", $('#copyForm').serialize()); + $('#content').load("<%= url_for(:action => 'new') %>", $('#copyForm').serialize()); }); $('#target_project_id').select2(); diff --git a/app/views/dmsf_links/_form.html.erb b/app/views/dmsf_links/_form.html.erb index d59727ad..de487e25 100644 --- a/app/views/dmsf_links/_form.html.erb +++ b/app/views/dmsf_links/_form.html.erb @@ -24,11 +24,11 @@ <% if @dmsf_file_id %> <% file = DmsfFile.find_by_id @dmsf_file_id%> - <% title = file.title if file %> + <% title = file.title if file %> <% end %> -<%= render(:partial => '/dmsf/path', - :locals => {:folder => @dmsf_link.folder, :filename => nil, +<%= render(:partial => '/dmsf/path', + :locals => {:folder => @dmsf_link.folder, :filename => nil, :title => (@type == 'link_from') ? l(:label_link_from) : l(:label_link_to) }) %> <%= labelled_form_for @dmsf_link do |f| %> @@ -43,12 +43,12 @@ <%= radio_button_tag(:external_link, 'false', @link_external == false) %> <%= l(:label_internal) %>
<%= radio_button_tag(:external_link, 'true', @link_external) %> <%= l(:label_external) %>

- <% end %> + <% end %> + <% end %> + -

- <%= f.text_field :name, :required => true, :label => l(:label_link_name) %> -

+ +

+ <%= f.text_field :name, :required => true, :label => l(:label_link_name) %> +

<%= f.submit l(:button_create) %>

<% end %> - \ No newline at end of file + \ No newline at end of file diff --git a/app/views/dmsf_mailer/send_documents.html.erb b/app/views/dmsf_mailer/send_documents.html.erb index ef98e05a..ac8f1eeb 100644 --- a/app/views/dmsf_mailer/send_documents.html.erb +++ b/app/views/dmsf_mailer/send_documents.html.erb @@ -1,8 +1,11 @@ -<%# Redmine plugin for Document Management System "Features" +<% +# encoding: utf-8 +# +# Redmine plugin for Document Management System "Features" # # Copyright (C) 2011 Vít Jonáš # Copyright (C) 2012 Daniel Munn -# Copyright (C) 2011-15 Karel Pičman +# Copyright (C) 2011-16 Karel Pičman # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -20,24 +23,30 @@ <%= textilizable(@body) %> -<% if @links_only == '1' %> +<% if @links_only == '1' %> + <% folders = [] %> + <% files = [] %> <% if @folders.present? %> <% JSON.parse(@folders).each do |id| %> <% folder = DmsfFolder.find_by_id id %> - <% if folder %> - <% folder.folder_tree.each do |name, i| %> + <% if folder %> + <% folder.folder_tree.each do |name, i| %> <% dir = DmsfFolder.find_by_id i %> - <% if dir %> + <% if dir && !folders.include?(dir) %>
<%= link_to(h(dir.dmsf_path_str), dmsf_folder_path(:id => dir.project_id, :folder_id => dir.id, :only_path => false)) %>

- <% dir.files.each do |file| %> - <%= link_to(h(file.title), dmsf_file_url(file)) %> -  (<%= link_to(h(file.name), dmsf_file_url(file, :download => '')) %>) -
+ <% dir.dmsf_files.each do |file| %> + <% unless files.include?(file) %> + <%= link_to(h(file.title), dmsf_file_url(file)) %> +  (<%= link_to(h(file.name), dmsf_file_url(file, :download => '')) %>) +
+ <% files << file %> + <% end %> <% end %> + <% folders << dir %> <% end %> - <% end %> + <% end %> <% end %> <% end %> <% end %> @@ -45,11 +54,13 @@
<% JSON.parse(@files).each do |id| %> <% file = DmsfFile.find_by_id id %> - <% if file %> + <% if file && !files.include?(file) %> <%= link_to(h(file.title), dmsf_file_url(file)) %>  (<%= link_to(h(file.name), dmsf_file_url(file, :download => '')) %>)
+ <% files << file %> <% end %> <% end %> <% end %> -<% end %> \ No newline at end of file +<% end %> + \ No newline at end of file diff --git a/app/views/dmsf_mailer/send_documents.text.erb b/app/views/dmsf_mailer/send_documents.text.erb index 62f4baec..b4f4f23d 100644 --- a/app/views/dmsf_mailer/send_documents.text.erb +++ b/app/views/dmsf_mailer/send_documents.text.erb @@ -1,8 +1,11 @@ -<%# Redmine plugin for Document Management System "Features" +<% +# encoding: utf-8 +# +# Redmine plugin for Document Management System "Features" # # Copyright (C) 2011 Vít Jonáš # Copyright (C) 2012 Daniel Munn -# Copyright (C) 2011-15 Karel Pičman +# Copyright (C) 2011-16 Karel Pičman # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -20,29 +23,35 @@ <%= @body %> -<% if @links_only == '1' %> +<% if @links_only == '1' %> + <% folders = [] %> + <% files = [] %> <% if @folders.present? %> <% JSON.parse(@folders).each do |id| %> <% folder = DmsfFolder.find_by_id id %> - <% if folder %> - <% folder.folder_tree.each do |name, i| %> + <% if folder && !folders.include?(folder) %> + <% folder.folder_tree.each do |name, i| %> <% dir = DmsfFolder.find_by_id i %> <% if dir %> <%= dir.dmsf_path_str %> - <% dir.files.each do |file| %> - <%= dmsf_file_url(file, :download => '') %> + <% dir.dmsf_files.each do |file| %> + <% unless files.include?(file) %> + <%= dmsf_file_url(file, :download => '') %> + <% files << file %> + <% end %> <% end %> <% end %> - <% end %> + <% end %> <% end %> <% end %> <% end %> <% if @files.present? %> <% JSON.parse(@files).each do |id| %> <% file = DmsfFile.find_by_id id %> - <% if file %> + <% if file && !files.include?(file) %> <%= dmsf_file_url(file, :download => '') %> + <% files << file %> <% end %> <% end %> <% end %> -<% end %> \ No newline at end of file +<% end %> diff --git a/app/views/dmsf_mailer/workflow_notification.html.erb b/app/views/dmsf_mailer/workflow_notification.html.erb index 911c9ee1..47078947 100644 --- a/app/views/dmsf_mailer/workflow_notification.html.erb +++ b/app/views/dmsf_mailer/workflow_notification.html.erb @@ -17,16 +17,16 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.%>

<%= @user.name %>,

-

+

<%= @text1 %>

- <%= @text2 %> - <% unless @revision.file.folder %> - <%= link_to l(:link_documents), - dmsf_folder_url(:id => @revision.file.project) %> + <%= @text2 %> + <% unless @revision.dmsf_file.dmsf_folder %> + <%= link_to l(:link_documents), + dmsf_folder_url(:id => @revision.dmsf_file.project) %> <% else %> - <%= link_to @revision.file.folder.title, - dmsf_folder_url(:id => @revision.file.project, :folder_id => @revision.file.folder) %> + <%= link_to @revision.dmsf_file.dmsf_folder.title, + dmsf_folder_url(:id => @revision.dmsf_file.project, :folder_id => @revision.dmsf_file.dmsf_folder) %> <% end %>.

\ No newline at end of file diff --git a/app/views/dmsf_mailer/workflow_notification.text.erb b/app/views/dmsf_mailer/workflow_notification.text.erb index f2e104bd..9a36d147 100644 --- a/app/views/dmsf_mailer/workflow_notification.text.erb +++ b/app/views/dmsf_mailer/workflow_notification.text.erb @@ -18,8 +18,8 @@ <%= @user.name %>, <%= @text1 %> -<% unless @revision.file.folder %> - <%= @text2 %> <%= dmsf_folder_url(:id => @revision.file.project) %>. +<% unless @revision.dmsf_file.dmsf_folder %> + <%= @text2 %> <%= dmsf_folder_url(:id => @revision.dmsf_file.project) %>. <% else %> - <%= @text2 %> <%= dmsf_folder_url(:id => @revision.file.project, :folder_id => @revision.file.folder) %>. + <%= @text2 %> <%= dmsf_folder_url(:id => @revision.dmsf_file.project, :folder_id => @revision.dmsf_file.dmsf_folder) %>. <% end %> \ No newline at end of file diff --git a/app/views/hooks/redmine_dmsf/_view_my_account.html.erb b/app/views/hooks/redmine_dmsf/_view_my_account.html.erb index d32164f6..c179abbb 100644 --- a/app/views/hooks/redmine_dmsf/_view_my_account.html.erb +++ b/app/views/hooks/redmine_dmsf/_view_my_account.html.erb @@ -1,3 +1,25 @@ +<%# +# encoding: utf-8 +# +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2011-16 Karel Pičman +# +# 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. +%> + <%= labelled_fields_for :pref, @user.pref do |pref_fields| %>

<%= pref_fields.check_box :dmsf_tree_view %>

<% end %> \ No newline at end of file diff --git a/app/views/hooks/redmine_dmsf/_view_projects_form.html.erb b/app/views/hooks/redmine_dmsf/_view_projects_form.html.erb index f5112d14..a9b28fc9 100644 --- a/app/views/hooks/redmine_dmsf/_view_projects_form.html.erb +++ b/app/views/hooks/redmine_dmsf/_view_projects_form.html.erb @@ -1,8 +1,11 @@ -<%# Redmine plugin for Document Management System "Features" +<%# +# encoding: utf-8 +# +# Redmine plugin for Document Management System "Features" # # Copyright (C) 2011 Vít Jonáš # Copyright (C) 2012 Daniel Munn -# Copyright (C) 2011-14 Karel Pičman +# Copyright (C) 2011-16 Karel Pičman # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -16,11 +19,12 @@ # # 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.%> +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +%> <% if @project.new_record? && @source_project %>

- +

<% end %> diff --git a/app/views/my/blocks/_locked_documents.html.erb b/app/views/my/blocks/_locked_documents.html.erb index 3615e774..eb6086f9 100644 --- a/app/views/my/blocks/_locked_documents.html.erb +++ b/app/views/my/blocks/_locked_documents.html.erb @@ -29,9 +29,9 @@ <%= form_tag({}) do %> - + - + @@ -40,19 +40,19 @@ + + :class => 'icon icon-folder') %> + <% end %> @@ -60,19 +60,19 @@ - + + <% end %> diff --git a/app/views/my/blocks/_open_approvals.html.erb b/app/views/my/blocks/_open_approvals.html.erb index 5727c0f9..a61c499a 100644 --- a/app/views/my/blocks/_open_approvals.html.erb +++ b/app/views/my/blocks/_open_approvals.html.erb @@ -24,11 +24,11 @@ 'LEFT JOIN dmsf_workflow_step_actions ON dmsf_workflow_step_assignments.id = dmsf_workflow_step_actions.dmsf_workflow_step_assignment_id').where( 'dmsf_workflow_step_assignments.user_id = ? AND dmsf_workflow_step_actions.id IS NULL', @user.id).all %> <% assignments = Array.new %> -<% all_assignments.each do |assignment| %> - <% if assignment.dmsf_file_revision.file.last_revision && - !assignment.dmsf_file_revision.file.last_revision.deleted? && - (assignment.dmsf_file_revision.workflow == DmsfWorkflow::STATE_WAITING_FOR_APPROVAL) && - (assignment.dmsf_file_revision == assignment.dmsf_file_revision.file.last_revision) %> +<% all_assignments.each do |assignment| %> + <% if assignment.dmsf_file_revision.dmsf_file.last_revision && + !assignment.dmsf_file_revision.dmsf_file.last_revision.deleted? && + (assignment.dmsf_file_revision.workflow == DmsfWorkflow::STATE_WAITING_FOR_APPROVAL) && + (assignment.dmsf_file_revision == assignment.dmsf_file_revision.dmsf_file.last_revision) %> <% assignments << assignment %> <% end %> <% end %> @@ -37,7 +37,7 @@ <%= form_tag({}) do %>
<%=l(:field_project)%><%=l(:label_document)%>/<%=l(:field_folder)%><%=l(:label_document)%>/<%=l(:field_folder)%> <%=l(:field_folder)%>
<%= link_to_project(folder.project) %> - <%= link_to(h(folder.title), {:controller => 'dmsf', :action => 'show', :id => folder.project, :folder_id => folder}, - :class => 'icon icon-folder') %> - - <% if folder.folder %> - <%= link_to(h(folder.folder.title), - {:controller => 'dmsf', :action => 'show', :id => folder.project, :folder_id => folder.folder}) %> + <% if folder.dmsf_folder %> + <%= link_to(h(folder.dmsf_folder.title), + {:controller => 'dmsf', :action => 'show', :id => folder.project, :folder_id => folder.dmsf_folder}) %> <% else %> - <%= link_to(l(:link_documents), {:controller => 'dmsf', :action => 'show', :id=> folder.project }) %> - <% end %> + <%= link_to(l(:link_documents), {:controller => 'dmsf', :action => 'show', :id=> folder.project }) %> + <% end %>
<%= link_to_project(file.project) %> - - <%= link_to(h(file.title), + + <%= link_to(h(file.title), {:controller => 'dmsf_files', :action => :show, :id => file }, :class => "icon icon-file #{DmsfHelper.filetype_css(file.name)}") %> - - <% if file.folder %> - <%= link_to(h(file.folder.title), + <% if file.dmsf_folder %> + <%= link_to(h(file.dmsf_folder.title), {:controller => 'dmsf', :action => 'show', :id => file.project, :folder_id => file.folder}) %> <% else %> - <%= link_to(l(:link_documents), {:controller => 'dmsf', :action => 'show', :id=> file.project }) %> - <% end %> + <%= link_to(l(:link_documents), {:controller => 'dmsf', :action => 'show', :id=> file.project }) %> + <% end %>
- + @@ -48,29 +48,29 @@ <% assignments.each do |assignment| %> diff --git a/assets/images/bullet_arrow_down.png b/assets/images/bullet_arrow_down.png new file mode 100644 index 00000000..cb819a7d Binary files /dev/null and b/assets/images/bullet_arrow_down.png differ diff --git a/assets/javascripts/redmine_dmsf.js b/assets/javascripts/redmine_dmsf.js new file mode 100644 index 00000000..21cf3308 --- /dev/null +++ b/assets/javascripts/redmine_dmsf.js @@ -0,0 +1,117 @@ +/* encoding: utf-8 +* +* Redmine plugin for Document Management System "Features" +* +* Copyright (C) 2011-16 Karel Pičman +* +* 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. +*/ + +/* Function to allow the projects to show up as a tree */ +function dmsf_toggle(EL, PM) +{ + var els = document.getElementsByTagName('tr'); + var elsLen = els.length; + var pattern = new RegExp("(^|\\s)" + EL + "(\\s|$)"); + var cpattern = new RegExp('span'); + var expand = new RegExp('dmsf_expanded'); + var collapse = new RegExp('dmsf_collapsed'); + var hide = new RegExp('dmsf_hidden'); + var spanid = PM; + var classid = new RegExp('junk'); + var oddeventoggle = 0; + + for(i = 0; i < elsLen; i++) + { + if(cpattern.test(els[i].id)) + { + var tmpspanid = spanid; + var tmpclassid = classid; + + spanid = els[i].id; + classid = spanid; + classid = classid.match(/(\w+)span/)[1]; + classid = new RegExp(classid); + + if(tmpclassid.test(els[i].className) && (tmpspanid.toString() !== PM.toString())) + { + if(collapse.test(document.getElementById(tmpspanid).className)) + { + spanid = tmpspanid; + classid = tmpclassid; + } + } + } + + if(pattern.test(els[i].className)) + { + var cnames = els[i].className; + + cnames = cnames.replace(/dmsf_hidden/g,''); + + if(expand.test(document.getElementById(PM).className)) + { + cnames += ' dmsf_hidden'; + } + else + { + if((spanid.toString() !== PM.toString()) && (classid.test(els[i].className))) + { + if(collapse.test(document.getElementById(spanid).className)) + { + cnames += ' dmsf_hidden'; + } + } + } + + els[i].className = cnames; + } + + if(!(hide.test(els[i].className))) + { + var cnames = els[i].className; + + cnames = cnames.replace(/odd/g,''); + cnames = cnames.replace(/even/g,''); + + if(oddeventoggle === 0) + { + cnames += ' odd'; + } + else + { + cnames += ' even'; + } + + oddeventoggle ^= 1; + els[i].className = cnames; + } + } + + if (collapse.test(document.getElementById(PM).className)) + { + var cnames = document.getElementById(PM).className; + + cnames = cnames.replace(/dmsf_collapsed/,'dmsf_expanded'); + document.getElementById(PM).className = cnames; + } + else + { + var cnames = document.getElementById(PM).className; + + cnames = cnames.replace(/dmsf_expanded/,'dmsf_collapsed'); + document.getElementById(PM).className = cnames; + } +} diff --git a/assets/stylesheets/img/loading.gif b/assets/stylesheets/images/loading.gif similarity index 100% rename from assets/stylesheets/img/loading.gif rename to assets/stylesheets/images/loading.gif diff --git a/assets/stylesheets/img/plupload.png b/assets/stylesheets/images/plupload.png similarity index 100% rename from assets/stylesheets/img/plupload.png rename to assets/stylesheets/images/plupload.png diff --git a/assets/stylesheets/plupload/jquery.ui.plupload.css b/assets/stylesheets/plupload/jquery.ui.plupload.css index e46a3f17..3b9cd1bd 100644 --- a/assets/stylesheets/plupload/jquery.ui.plupload.css +++ b/assets/stylesheets/plupload/jquery.ui.plupload.css @@ -43,7 +43,7 @@ .plupload_logo { width: 40px; height: 40px; - background: url('../img/plupload.png') no-repeat 0 0; + background: url('../images/plupload.png') no-repeat 0 0; position: absolute; top: 8px; left: 8px; @@ -119,7 +119,7 @@ } .plupload_thumb_loading { - background: #eee url(../img/loading.gif) center no-repeat; + background: #eee url(../images/loading.gif) center no-repeat; } .plupload_thumb_loading .plupload_file_dummy, diff --git a/assets/stylesheets/dmsf.css b/assets/stylesheets/redmine_dmsf.css similarity index 88% rename from assets/stylesheets/dmsf.css rename to assets/stylesheets/redmine_dmsf.css index de445d49..ede409dd 100644 --- a/assets/stylesheets/dmsf.css +++ b/assets/stylesheets/redmine_dmsf.css @@ -20,7 +20,6 @@ */ /* DMSF table.list modifications */ - table.dmsf_list th.dmsf_th { border: none; } @@ -222,4 +221,26 @@ tr.dmsf_gray .icon-file.application-x-gzip { background-image: url(../images/fil /* Search results */ dt.dmsf-file { background-image: url(../../../images/document.png); } -dt.dmsf-folder { background-image: url(../../../images/folder.png); } \ No newline at end of file +dt.dmsf-folder { background-image: url(../../../images/folder.png); } + +/* DMSF tree view */ +tr.dmsf_hidden { display:none; } +tr.dmsf_tree span.dmsf_expander { cursor: pointer; } +tr.dmsf_tree.dmsf_expanded td.dmsf_title span { + background: url(../images/bullet_arrow_down.png) no-repeat 0 50%; + padding-left: 16px; +} +tr.dmsf_tree.dmsf_child td.dmsf_title span { padding-left: 16px; } +tr.dmsf_tree.dmsf_collapsed td.dmsf_title span { + background: url(../../../images/bullet_arrow_right.png) no-repeat 0 50%; + padding-left: 16px; +} +tr.dmsf_tree.idnt-1 td.dmsf_title {padding-left: 1.5em;} +tr.dmsf_tree.idnt-2 td.dmsf_title {padding-left: 2em;} +tr.dmsf_tree.idnt-3 td.dmsf_title {padding-left: 2.5em;} +tr.dmsf_tree.idnt-4 td.dmsf_title {padding-left: 3em;} +tr.dmsf_tree.idnt-5 td.dmsf_title {padding-left: 3.5em;} +tr.dmsf_tree.idnt-6 td.dmsf_title {padding-left: 4em;} +tr.dmsf_tree.idnt-7 td.dmsf_title {padding-left: 4.5em;} +tr.dmsf_tree.idnt-8 td.dmsf_title {padding-left: 5em;} +tr.dmsf_tree.idnt-9 td.dmsf_title {padding-left: 5.5em;} diff --git a/config/locales/cs.yml b/config/locales/cs.yml index 5576b09b..3fc3c650 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -26,7 +26,7 @@ cs: label_dmsf_file_revision_plural: Revize dokumentů label_dmsf_file_revision_access_plural: Přístupy k dokumentům warning_no_entries_selected: Není nic vybráno - error_email_to_must_be_entered: Musí být zadán adresát + error_email_to_must_be_entered: Musí být zadán příjemce warning_file_already_locked: Soubor je již zamčen notice_file_locked: Soubor byl zamčen warning_file_not_locked: Soubor není zamčen @@ -34,14 +34,14 @@ cs: error_only_user_that_locked_file_can_unlock_it: Soubor může být odemčen pouze uživatelem, který ho zamkl error_max_files_exceeded: "Limit pro %{number} najednou stažených souborů je překročen" error_entry_project_does_not_match_current_project: Zadaný projekt neodpovídá aktuálnímu projektu - notice_folder_created: Adresář byl vytvořen + notice_folder_created: Složka byla vytvořena error_folder_creation_failed: Vytváření složky selhalo error_folder_title_must_be_entered: Musí být zadán název - notice_folder_deleted: Adresář byl smazán - error_folder_is_not_empty: Adresář není prázdný + notice_folder_deleted: Složka byla smazána + error_folder_is_not_empty: Složka není prázdná error_folder_title_is_already_used: Název již existuje notice_folder_details_were_saved: Detaily složky byly uloženy - error_folder_is_locked: Adresář je zamčen + error_folder_is_locked: Složka je zamčena error_file_is_locked: Soubor je zamčen notice_file_deleted: Soubor byl smazán error_at_least_one_revision_must_be_present: Musí existovat alespoň jedna revize @@ -181,18 +181,18 @@ cs: heading_access_last: Poslední label_dmsf_updated: Změněno label_dmsf_downloaded: Staženo - title_total_size_of_all_files: Celková velikost všech souborů v adresáři + title_total_size_of_all_files: Celková velikost všech souborů ve složce project_module_dmsf: DMSF warning_no_project_to_copy_file_to: Neexistuje projekt, do kterého můžete kopírovat comment_copied_from: "Zkopírováno z %{source}" notice_file_copied: Soubor zkopírován notice_file_moved: Soubor přesunut field_target_project: Cílový projekt - field_target_folder: Cílový adresář + field_target_folder: Cílová složka title_copy_or_move: Kopírovat/Přesunout label_dmsf_folder_plural: Složky comment_moved_from: "Přesunuto z %{source}" - error_target_folder_same: Cílový adresář a projekt jsou stejné jako aktuální + error_target_folder_same: Cílový složka a projekt jsou stejné jako aktuální error_file_cannot_be_moved: Soubor nemůže být přesunut error_file_cannot_be_copied: Soubor nemůže být zkopírován warning_no_project_to_copy_folder_to: Neexistuje projekt, do kterého můžete kopírovat @@ -205,7 +205,7 @@ cs: label_maximum_email_filesize: Maximální velikost souboru emailu header_minimum_filesize: Chyba souboru. error_minimum_filesize: "Soubor %{file} má nulovou velikost a nebude přiložen." - parent_directory: Nadřazený adresář + parent_directory: Nadřazená složka note_webdav: "Webdav je po aktivaci k dispozici na %{protocol}://%{domain}/dmsf/webdav/[identifikátor projektu]" label_webdav: Webdav functionalita label_dmsf_plural: "Kopíruj dokumenty a složky (%{files} souborů v %{folders} složkách)" @@ -292,8 +292,8 @@ cs: label_link_name: Název odkazu label_link_external_url: URL - label_target_folder: Cílový adresář - label_source_folder: Zdrojový adresář + label_target_folder: Cílová složka + label_source_folder: Zdrojová složka label_target_project: Cílový projekt label_source_project: Zdrojový projekt @@ -311,10 +311,10 @@ cs: link_trash_bin: Koš title_restore: Obnovit notice_dmsf_file_restored: Document byl úspěšně obnoven - notice_dmsf_folder_restored: Adresář byl úspěšně obnoven + notice_dmsf_folder_restored: Složka byla úspěšně obnovena notice_dmsf_link_restored: Odkaz byl úspěšně obnoven title_restore_checked: Obnov vybrané - error_parent_folder: Nadřazený adresář neexistuje + error_parent_folder: Nadřazená složka neexistuje error_resource_or_parent_locked: Nelze zamknout - zdrojový nebo nadřazený objekt je zamčený error_parent_locked: Nelze zamknout - nadřazený objekt je zamčený @@ -322,7 +322,7 @@ cs: error_lock_exclusively: Nelze zamknout již zamčený objekt error_unlock_parent_locked: Nelze odemknout - nadřazený objekt je zamčený - field_dmsf_tree_view: Navigate folders in a tree + field_dmsf_tree_view: Zobrazit složky jako stromovou strukturu my: blocks: diff --git a/config/routes.rb b/config/routes.rb index 6f940c06..d1d962a7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -42,8 +42,8 @@ RedmineApp::Application.routes.draw do get '/projects/:id/dmsf/unlock', :controller => 'dmsf', :action => 'unlock', :as => 'unlock_dmsf' get '/projects/:id/dmsf/', :controller => 'dmsf', :action => 'show', :as => 'dmsf_folder' get '/projects/:id/dmsf/new', :controller => 'dmsf', :action => 'new', :as => 'new_dmsf' - get '/projects/:id/dmsf/edit', :controller=> 'dmsf', :action => 'edit', :as => 'edit_dmsf' - get '/projects/:id/dmsf/edit/root', :controller=> 'dmsf', :action => 'edit_root', :as => 'edit_root_dmsf' + get '/projects/:id/dmsf/edit', :controller => 'dmsf', :action => 'edit', :as => 'edit_dmsf' + get '/projects/:id/dmsf/edit/root', :controller => 'dmsf', :action => 'edit_root', :as => 'edit_root_dmsf' get '/projects/:id/dmsf/trash', :controller => 'dmsf', :action => 'trash', :as => 'trash_dmsf' get '/projects/:id/dmsf/restore', :controller => 'dmsf', :action => 'restore', :as => 'restore_dmsf' @@ -63,7 +63,7 @@ RedmineApp::Application.routes.draw do 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' - + # # dmsf_files controller # /dmsf/files/ @@ -78,7 +78,7 @@ RedmineApp::Application.routes.draw do get '/dmsf/files/:id/download', :controller => 'dmsf_files', :action => 'show', :download => '' # Otherwise will not route nil download param get '/dmsf/files/:id/download/:download', :controller => 'dmsf_files', :action => 'show', :as => 'download_revision' get '/dmsf/files/:id/view', :controller => 'dmsf_files', :action => 'view' - get '/dmsf/files/:id', :controller => 'dmsf_files', :action => 'show', :as => 'dmsf_file' + get '/dmsf/files/:id', :controller => 'dmsf_files', :action => 'show', :as => 'dmsf_file' delete '/dmsf/files/:id', :controller => 'dmsf_files', :action => 'delete' get '/dmsf/files/:id/restore', :controller => 'dmsf_files', :action => 'restore', :as => 'restore_dmsf_file' @@ -118,8 +118,8 @@ RedmineApp::Application.routes.draw do :controller_class => RedmineDmsf::Webdav::Controller, :log_to => Rails.logger ), :at => '/dmsf/webdav' - - # Approval workflow + + # Approval workflow resources :dmsf_workflows do member do get 'autocomplete_for_user' @@ -132,16 +132,16 @@ RedmineApp::Application.routes.draw do get 'new_step' end end - + match 'dmsf_workflows/:id/edit', :controller => 'dmsf_workflows', :action => 'add_step', :id => /\d+/, :via => :post match 'dmsf_workflows/:id/edit', :controller => 'dmsf_workflows', :action => 'remove_step', :id => /\d+/, :via => :delete - match 'dmsf_workflows/:id/edit', :controller => 'dmsf_workflows', :action => 'reorder_steps', :id => /\d+/, :via => :put - + match 'dmsf_workflows/:id/edit', :controller => 'dmsf_workflows', :action => 'reorder_steps', :id => /\d+/, :via => :put + # Links resources :dmsf_links do member do get 'restore' - end - end - + end + end + end \ No newline at end of file diff --git a/db/migrate/06_dmsf_1_2_0.rb b/db/migrate/06_dmsf_1_2_0.rb index 522706ca..f2099274 100644 --- a/db/migrate/06_dmsf_1_2_0.rb +++ b/db/migrate/06_dmsf_1_2_0.rb @@ -17,7 +17,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class Dmsf120 < ActiveRecord::Migration - + class DmsfFileRevision < ActiveRecord::Base belongs_to :file, :class_name => 'DmsfFile', :foreign_key => 'dmsf_file_id' belongs_to :source_revision, :class_name => 'DmsfFileRevision', :foreign_key => 'source_dmsf_file_revision_id' @@ -26,22 +26,22 @@ class Dmsf120 < ActiveRecord::Migration belongs_to :deleted_by_user, :class_name => 'User', :foreign_key => 'deleted_by_user_id' belongs_to :project end - + def self.up add_column :dmsf_file_revisions, :project_id, :integer, :null => true - + DmsfFileRevision.find_each do |revision| - if revision.file - revision.project_id = revision.file.project.id + if revision.dmsf_file + revision.project_id = revision.dmsf_file.project.id revision.save end end - + change_column :dmsf_file_revisions, :project_id, :integer, :null => false end def self.down - remove_column :dmsf_file_revisions, :project_id + remove_column :dmsf_file_revisions, :project_id end end diff --git a/db/migrate/20141013102501_remove_project_from_revision.rb b/db/migrate/20141013102501_remove_project_from_revision.rb index 109513ef..2277a3e0 100644 --- a/db/migrate/20141013102501_remove_project_from_revision.rb +++ b/db/migrate/20141013102501_remove_project_from_revision.rb @@ -19,19 +19,19 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class RemoveProjectFromRevision < ActiveRecord::Migration - def up - remove_column :dmsf_file_revisions, :project_id + def up + remove_column :dmsf_file_revisions, :project_id end - + def down add_column :dmsf_file_revisions, :project_id, :integer, :null => true - + DmsfFileRevision.find_each do |revision| - if revision.file - revision.project_id = revision.file.project_id + if revision.dmsf_file + revision.project_id = revision.dmsf_file.project_id revision.save end - end + end end - + end \ No newline at end of file diff --git a/lib/dmsf_zip.rb b/lib/dmsf_zip.rb index 088148f1..5b66858a 100644 --- a/lib/dmsf_zip.rb +++ b/lib/dmsf_zip.rb @@ -30,6 +30,7 @@ class DmsfZip @zip.chmod(0644) @zip_file = Zip::OutputStream.new(@zip.path) @files = [] + @folders = [] end def finish @@ -43,24 +44,29 @@ class DmsfZip end def add_file(file, member, root_path = nil) - string_path = file.folder.nil? ? '' : "#{file.folder.dmsf_path_str}/" - string_path = string_path[(root_path.length + 1) .. string_path.length] if root_path - string_path += file.formatted_name(member ? member.title_format : nil) - @zip_file.put_next_entry(string_path) - File.open(file.last_revision.disk_file, 'rb') do |f| - while (buffer = f.read(8192)) - @zip_file.write(buffer) + unless @files.include?(file) + string_path = file.dmsf_folder.nil? ? '' : "#{file.dmsf_folder.dmsf_path_str}/" + string_path = string_path[(root_path.length + 1) .. string_path.length] if root_path + string_path += file.formatted_name(member ? member.title_format : nil) + @zip_file.put_next_entry(string_path) + File.open(file.last_revision.disk_file, 'rb') do |f| + while (buffer = f.read(8192)) + @zip_file.write(buffer) + end end + @files << file end - @files << file end def add_folder(folder, member, root_path = nil) - string_path = "#{folder.dmsf_path_str}/" - string_path = string_path[(root_path.length + 1) .. string_path.length] if root_path - @zip_file.put_next_entry(string_path) - folder.subfolders.visible.each { |subfolder| self.add_folder(subfolder, root_path) } - folder.files.visible.each { |file| self.add_file(file, member, root_path) } + unless @folders.include?(folder) + string_path = "#{folder.dmsf_path_str}/" + string_path = string_path[(root_path.length + 1) .. string_path.length] if root_path + @zip_file.put_next_entry(string_path) + @folders << folder + folder.dmsf_folders.visible.each { |subfolder| self.add_folder(subfolder, root_path) } + folder.dmsf_files.visible.each { |file| self.add_file(file, member, root_path) } + end end end \ No newline at end of file diff --git a/lib/redmine_dmsf/hooks/views/base_view_hooks.rb b/lib/redmine_dmsf/hooks/views/base_view_hooks.rb index 384375d3..0eff651c 100644 --- a/lib/redmine_dmsf/hooks/views/base_view_hooks.rb +++ b/lib/redmine_dmsf/hooks/views/base_view_hooks.rb @@ -20,16 +20,17 @@ module RedmineDmsf module Hooks - include Redmine::Hook - - class DmsfViewListener < Redmine::Hook::ViewListener - - def view_layouts_base_html_head(context={}) - "\n".html_safe + stylesheet_link_tag('dmsf', :plugin => :redmine_dmsf) + + include Redmine::Hook + + class DmsfViewListener < Redmine::Hook::ViewListener + + def view_layouts_base_html_head(context={}) + "\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) - end - + "\n".html_safe + javascript_include_tag('select2.min.js', :plugin => :redmine_dmsf) + + "\n".html_safe + javascript_include_tag('redmine_dmsf.js', :plugin => :redmine_dmsf) + end + end end end \ No newline at end of file diff --git a/lib/redmine_dmsf/lockable.rb b/lib/redmine_dmsf/lockable.rb index a2433b3f..abedcdd0 100644 --- a/lib/redmine_dmsf/lockable.rb +++ b/lib/redmine_dmsf/lockable.rb @@ -4,7 +4,7 @@ # # Copyright (C) 2011 Vít Jonáš # Copyright (C) 2012 Daniel Munn -# Copyright (C) 2011-15 Karel Pičman +# Copyright (C) 2011-16 Karel Pičman # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -38,17 +38,17 @@ module RedmineDmsf end end if tree - ret = ret | (folder.locks.empty? ? folder.lock : folder.locks) unless folder.nil? + ret = ret | (self.dmsf_folder.locks.empty? ? self.dmsf_folder.lock : self.dmsf_folder.locks) if dmsf_folder end return ret end - def lock! scope = :scope_exclusive, type = :type_write, expire = nil + def lock!(scope = :scope_exclusive, type = :type_write, expire = nil) # Raise a lock error if entity is locked, but its not at resource level existing = locks(false) raise DmsfLockError.new(l(:error_resource_or_parent_locked)) if self.locked? && existing.empty? unless existing.empty? - if existing[0].lock_scope == :scope_shared && scope == :scope_shared + if (existing[0].lock_scope == :scope_shared) && (scope == :scope_shared) # RFC states if an item is exclusively locked and another lock is attempted we reject # if the item is shared locked however, we can always add another lock to it if self.folder.locked? @@ -79,20 +79,20 @@ module RedmineDmsf return false unless self.locked? existing = self.lock(true) # If its empty its a folder that's locked (not root) - (existing.empty? || (!self.folder.nil? && self.folder.locked?)) ? false : true + (existing.empty? || (!self.dmsf_folder.nil? && self.dmsf_folder.locked?)) ? false : true end # # By using the path upwards, surely this would be quicker? def locked_for_user? return false unless locked? - b_shared = nil - self.dmsf_path.each do |entity| + b_shared = nil + self.dmsf_path.each do |entity| locks = entity.locks || entity.lock(false) next if locks.empty? locks.each do |lock| next if lock.expired? # In case we're in between updates - if (lock.lock_scope == :scope_exclusive && b_shared.nil?) + if (lock.lock_scope == :scope_exclusive && b_shared.nil?) return true if (!lock.user) || (lock.user.id != User.current.id) else b_shared = true if b_shared.nil? @@ -103,11 +103,11 @@ module RedmineDmsf end false end - + def unlock!(force_file_unlock_allowed = false) raise DmsfLockError.new(l(:warning_file_not_locked)) unless self.locked? existing = self.lock(true) - if existing.empty? || (!self.folder.nil? && self.folder.locked?) #If its empty its a folder thats locked (not root) + if existing.empty? || (!self.dmsf_folder.nil? && self.dmsf_folder.locked?) #If its empty its a folder thats locked (not root) raise DmsfLockError.new(l(:error_unlock_parent_locked)) else # If entity is locked to you, you aren't the lock originator (or named in a shared lock) so deny action diff --git a/lib/redmine_dmsf/macros.rb b/lib/redmine_dmsf/macros.rb index 9826a29f..51b333c4 100644 --- a/lib/redmine_dmsf/macros.rb +++ b/lib/redmine_dmsf/macros.rb @@ -19,30 +19,30 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Redmine::WikiFormatting::Macros.register do - + # dmsf - link to a document desc "Wiki link to DMSF file:\n\n" + "{{dmsf(file_id [, title [, revision_id]])}}\n\n" + - "_file_id_ / _revision_id_ can be found in the link for file/revision download." + "_file_id_ / _revision_id_ can be found in the link for file/revision download." macro :dmsf do |obj, args| raise ArgumentError if args.length < 1 # Requires file id - file = DmsfFile.visible.find args[0].strip + file = DmsfFile.visible.find args[0].strip if args[2].blank? revision = file.last_revision else revision = DmsfFileRevision.find(args[2]) - if revision.file != file + if revision.dmsf_file != file raise ActiveRecord::RecordNotFound end - end - if User.current && User.current.allowed_to?(:view_dmsf_files, file.project) + end + if User.current && User.current.allowed_to?(:view_dmsf_files, file.project) file_view_url = url_for(:controller => :dmsf_files, :action => 'view', :id => file, :download => args[2]) return link_to(h(args[1] ? args[1] : file.title), file_view_url, :target => '_blank', :title => l(:title_title_version_version_download, :title => h(file.title), :version => file.version), 'data-downloadurl' => "#{file.last_revision.detect_content_type}:#{h(file.name)}:#{file_view_url}") - else + else raise l(:notice_not_authorized) end end @@ -50,48 +50,48 @@ Redmine::WikiFormatting::Macros.register do # dmsff - link to a folder desc "Wiki link to DMSF folder:\n\n" + "{{dmsff(folder_id [, title])}}\n\n" + - "_folder_id_ may be missing. _folder_id_ can be found in the link for folder opening." + "_folder_id_ may be missing. _folder_id_ can be found in the link for folder opening." macro :dmsff do |obj, args| if args.length < 1 return link_to l(:link_documents), dmsf_folder_url(@project) - else + else folder = DmsfFolder.visible.find args[0].strip - if User.current && User.current.allowed_to?(:view_dmsf_folders, folder.project) + if User.current && User.current.allowed_to?(:view_dmsf_folders, folder.project) return link_to h(args[1] ? args[1] : folder.title), dmsf_folder_url(folder.project, :folder_id => folder) - else + else raise l(:notice_not_authorized) end - end - end + end + end # dmsfd - link to a document's description desc "Wiki link to DMSF document description:\n\n" + "{{dmsfd(file_id)}}\n\n" + - "_file_id_ can be found in the document's details." + "_file_id_ can be found in the document's details." macro :dmsfd do |obj, args| raise ArgumentError if args.length < 1 # Requires file id file = DmsfFile.visible.find args[0].strip - if User.current && User.current.allowed_to?(:view_dmsf_files, file.project) + if User.current && User.current.allowed_to?(:view_dmsf_files, file.project) return textilizable(file.description) - else + else raise l(:notice_not_authorized) - end - end + end + end # dmsft - link to a document's content preview desc "Wiki link to DMSF document's content preview:\n\n" + "{{dmsft(file_id)}}\n\n" + - "_file_id_ can be found in the document's details." + "_file_id_ can be found in the document's details." macro :dmsft do |obj, args| raise ArgumentError if args.length < 2 # Requires file id and lines number file = DmsfFile.visible.find args[0].strip - if User.current && User.current.allowed_to?(:view_dmsf_files, file.project) - return file.preview(args[1].strip).gsub("\n", '
').html_safe - else + if User.current && User.current.allowed_to?(:view_dmsf_files, file.project) + return file.preview(args[1].strip).gsub("\n", '
').html_safe + else raise l(:notice_not_authorized) - end - end + end + end # dmsf_image - link to an image desc "Wiki DMSF image:\n\n" + @@ -108,11 +108,11 @@ Redmine::WikiFormatting::Macros.register do width = options[:width] height = options[:height] if file = DmsfFile.find_by_id(file_id) - unless User.current && User.current.allowed_to?(:view_dmsf_files, file.project) + unless User.current && User.current.allowed_to?(:view_dmsf_files, file.project) raise l(:notice_not_authorized) end raise 'Not supported image format' unless file.image? - url = url_for(:controller => :dmsf_files, :action => 'view', :id => file) + url = url_for(:controller => :dmsf_files, :action => 'view', :id => file) if size && size.include?('%') image_tag(url, :alt => file.title, :width => size, :height => size) elsif height @@ -142,11 +142,11 @@ Redmine::WikiFormatting::Macros.register do width = options[:width] height = options[:height] if file = DmsfFile.find_by_id(file_id) - unless User.current && User.current.allowed_to?(:view_dmsf_files, file.project) + unless User.current && User.current.allowed_to?(:view_dmsf_files, file.project) raise l(:notice_not_authorized) end raise 'Not supported image format' unless file.image? - url = url_for(:controller => :dmsf_files, :action => 'view', :id => file) + url = url_for(:controller => :dmsf_files, :action => 'view', :id => file) file_view_url = url_for(:controller => :dmsf_files, :action => 'view', :id => file, :download => args[2]) if size && size.include?("%") img = image_tag(url, :alt => file.title, :width => size, :height => size) @@ -167,20 +167,20 @@ Redmine::WikiFormatting::Macros.register do raise "Document ID #{file_id} not found" end end - + # dmsfw - link to a document's approval workflow status desc "Wiki link to DMSF document's approval workflow status:\n\n" + "{{dmsfw(file_id)}}\n\n" + - "_file_id_ can be found in the document's details." + "_file_id_ can be found in the document's details." macro :dmsfw do |obj, args| raise ArgumentError if args.length < 1 # Requires file id file = DmsfFile.visible.find args[0].strip - if User.current && User.current.allowed_to?(:view_dmsf_files, file.project) + if User.current && User.current.allowed_to?(:view_dmsf_files, file.project) raise ActiveRecord::RecordNotFound unless file.last_revision return file.last_revision.workflow_str(false) - else + else raise l(:notice_not_authorized) - end - end + end + end end \ No newline at end of file diff --git a/lib/redmine_dmsf/patches/project_patch.rb b/lib/redmine_dmsf/patches/project_patch.rb index 578fd1a5..0e387417 100644 --- a/lib/redmine_dmsf/patches/project_patch.rb +++ b/lib/redmine_dmsf/patches/project_patch.rb @@ -31,7 +31,7 @@ module RedmineDmsf base.class_eval do unloadable alias_method_chain :copy, :dmsf - + has_many :dmsf_files, -> { where dmsf_folder_id: nil}, :class_name => 'DmsfFile', :foreign_key => 'project_id', :dependent => :destroy has_many :dmsf_folders, -> {where dmsf_folder_id: nil}, @@ -43,7 +43,9 @@ module RedmineDmsf has_many :file_links, -> { where dmsf_folder_id: nil, target_type: 'DmsfFile' }, :class_name => 'DmsfLink', :foreign_key => 'project_id', :dependent => :destroy has_many :url_links, -> { where dmsf_folder_id: nil, target_type: 'DmsfUrl' }, - :class_name => 'DmsfLink', :foreign_key => 'project_id', :dependent => :destroy + :class_name => 'DmsfLink', :foreign_key => 'project_id', :dependent => :destroy + has_many :dmsf_links, -> { where dmsf_folder_id: nil }, + :class_name => 'DmsfLink', :foreign_key => 'project_id', :dependent => :destroy end end diff --git a/lib/redmine_dmsf/webdav/dmsf_resource.rb b/lib/redmine_dmsf/webdav/dmsf_resource.rb index 833e70d5..6996ddb9 100644 --- a/lib/redmine_dmsf/webdav/dmsf_resource.rb +++ b/lib/redmine_dmsf/webdav/dmsf_resource.rb @@ -29,7 +29,7 @@ module RedmineDmsf def setup @skip_alias |= [ :folder, :file ] end - + # Here we hook into the fact that resources can have a pre-execution routine run for them # Our sole job here is to ensure that any write functionality is restricted to relevent configuration before do |resource, method_name| @@ -49,15 +49,15 @@ module RedmineDmsf unless @childern @children = [] if collection? - folder.subfolders.select(:title).visible.map do |p| + folder.dmsf_folders.select(:title).visible.map do |p| @children.push child(p.title) end - folder.files.select(:name).visible.map do |p| + folder.dmsf_files.select(:name).visible.map do |p| @children.push child(p.name) end end end - @children + @children end # Does the object exist? @@ -65,7 +65,7 @@ module RedmineDmsf # - 2012-06-15: Only if you're allowed to browse the project # - 2012-06-18: Issue #5, ensure item is only listed if project is enabled for dmsf def exist? - return project && project.module_enabled?('dmsf') && (folder || file) && + return project && project.module_enabled?('dmsf') && (folder || file) && (User.current.admin? || User.current.allowed_to?(:view_dmsf_folders, project)) end @@ -74,38 +74,38 @@ module RedmineDmsf folder.present? # No need to check if entity exists, as false is returned if entity does not exist anyways end - # 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 unless @folder - return nil unless project # If the project doesn't exist, this entity can't exist + return nil unless project # If the project doesn't exist, this entity can't exist # Note: Folder is searched for as a generic search to prevent SQL queries being generated: - # if we were to look within parent, we'd have to go all the way up the chain as part of the + # if we were to look within parent, we'd have to go all the way up the chain as part of the # existence check, and although I'm sure we'd love to access the hierarchy, I can't yet - # see a practical need for it - folders = DmsfFolder.visible.where(:project_id => project.id, :title => basename).order('title ASC').to_a + # 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 + else if (('/' + folders[0].dmsf_path_str) == projectless_path) - @folder = folders[0] + @folder = folders[0] end end end @folder - end + end # 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 + # Currently has a dual search approach (depending on if parent can be determined) + def file unless @file return nil unless project # Again if entity project is nil, it cannot exist in context of this object # Hunt for files parent path f = false - if (parent.projectless_path != '/') - f = parent.folder if parent.folder + if (parent.projectless_path != '/') + f = parent.dmsf_folder if parent.dmsf_folder else f = nil end @@ -114,16 +114,16 @@ module RedmineDmsf # 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 + # 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(:project_id => project.id, :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 + files.delete_if { |x| File.dirname('/' + x.dmsf_path_str) != File.dirname(projectless_path) } + @file = files[0] if files.length > 0 end end @file - end + end # Return the content type of file # will return inode/directory for any collections, and appropriate for File entities @@ -187,7 +187,7 @@ module RedmineDmsf end OK end - + # Process incoming MKCOL request # # Create a DmsfFolder at location requested, only if parent is a folder (or root) @@ -199,12 +199,12 @@ module RedmineDmsf return MethodNotAllowed if exist? # If we already exist, why waste the time trying to save? parent_folder = nil if (parent.projectless_path != '/') - return Conflict unless parent.folder - parent_folder = parent.folder.id - end + return Conflict unless parent.dmsf_folder + parent_folder = parent.dmsf_folder.id + end f = DmsfFolder.new f.title = basename - f.dmsf_folder_id = parent_folder + f.dmsf_folder_id = parent_folder f.project = project f.user = User.current f.save ? OK : Conflict @@ -217,7 +217,7 @@ module RedmineDmsf # # should be of entity to be deleted, we simply follow the Dmsf entity method # for deletion and return of appropriate status based on outcome. - def delete + def delete if file raise Forbidden unless User.current.admin? || User.current.allowed_to?(:file_delete, project) file.delete(false) ? NoContent : Conflict @@ -235,13 +235,13 @@ module RedmineDmsf # TODO: Support overwrite between both types of entity, and implement better checking def move(dest, overwrite) # All of this should carry accrross the ResourceProxy frontend, we ensure this to - # prevent unexpected errors - resource = dest.is_a?(ResourceProxy) ? dest.resource : dest - + # prevent unexpected errors + resource = dest.is_a?(ResourceProxy) ? dest.resource : dest + return PreconditionFailed if !resource.is_a?(DmsfResource) || resource.project.nil? || resource.project.id == 0 - + parent = resource.parent - + if collection? # At the moment we don't support cross project destinations return MethodNotImplemented unless project.id == resource.project.id @@ -254,37 +254,37 @@ module RedmineDmsf if(parent.projectless_path == '/') #Project root folder.dmsf_folder_id = nil else - return PreconditionFailed unless parent.exist? && parent.folder - folder.dmsf_folder_id = parent.folder.id + return PreconditionFailed unless parent.exist? && parent.dmsf_folder + folder.dmsf_folder_id = parent.dmsf_folder.id end folder.title = resource.basename folder.save ? Created : PreconditionFailed end else - raise Forbidden unless User.current.admin? || - User.current.allowed_to?(:folder_manipulation, project) || - User.current.allowed_to?(:folder_manipulation, resource.project) + raise Forbidden unless User.current.admin? || + User.current.allowed_to?(:folder_manipulation, project) || + User.current.allowed_to?(:folder_manipulation, resource.project) if dest.exist? - methodNotAllowed + methodNotAllowed # Files cannot be merged at this point, until a decision is made on how to merge them - # ideally, we would merge revision history for both, ensuring the origin file wins with latest revision. + # ideally, we would merge revision history for both, ensuring the origin file wins with latest revision. else if(parent.projectless_path == '/') #Project root f = nil else - return PreconditionFailed unless parent.exist? && parent.folder - f = parent.folder + return PreconditionFailed unless parent.exist? && parent.dmsf_folder + f = parent.dmsf_folder end return PreconditionFailed unless exist? && file return InternalServerError unless file.move_to(resource.project, f) - # Update Revision and names of file [We can link to old physical resource, as it's not changed] + # Update Revision and names of file [We can link to old physical resource, as it's not changed] if file.last_revision - file.last_revision.name = resource.basename + file.last_revision.name = resource.basename file.last_revision.title = DmsfFileRevision.filename_to_title(resource.basename) end - file.name = resource.basename + file.name = resource.basename # Save Changes (file.last_revision.save! && file.save!) ? Created : PreconditionFailed @@ -307,9 +307,9 @@ module RedmineDmsf end return PreconditionFailed if !resource.is_a?(DmsfResource) || resource.project.nil? || resource.project.id == 0 - + parent = resource.parent - + if collection? # Current object is a folder, so now we need to figure out information about Destination return MethodNotAllowed if(dest.exist?) @@ -320,7 +320,7 @@ module RedmineDmsf # View folders on destination project :view_dmsf_folders # View files on the source project :view_dmsf_files # View fodlers on the source project :view_dmsf_folders - raise Forbidden unless User.current.admin? || + raise Forbidden unless User.current.admin? || (User.current.allowed_to?(:folder_manipulation, resource.project) && User.current.allowed_to?(:view_dmsf_folders, resource.project) && User.current.allowed_to?(:view_dmsf_files, project) && @@ -351,12 +351,12 @@ module RedmineDmsf f = nil else return PreconditionFailed unless parent.exist? && parent.folder - f = parent.folder + f = parent.dmsf_folder end return PreconditionFailed unless exist? && file return InternalServerError unless file.copy_to(resource.project, f) - # Update Revision and names of file [We can link to old physical resource, as it's not changed] + # Update Revision and names of file [We can link to old physical resource, as it's not changed] file.last_revision.name = resource.basename if file.last_revision file.name = resource.basename @@ -368,7 +368,7 @@ module RedmineDmsf # Lock Check # Check for the existence of locks - # At present as deletions of folders are not recursive, we do not need to extend + # At present as deletions of folders are not recursive, we do not need to extend # this to cover every file, just queried def lock_check(lock_scope = nil) if file @@ -381,7 +381,7 @@ module RedmineDmsf # Lock def lock(args) return Conflict unless (parent.projectless_path == '/' || parent_exists?) - lock_check(args[:scope]) + lock_check(args[:scope]) unless self.exist? Rails.logger.warn "Path doesn't exist: #{@path}" return super @@ -392,7 +392,7 @@ module RedmineDmsf raise DAV4Rack::LockFailure.new("Failed to lock: #{@path}") else # If scope and type are not defined, the only thing we can - # logically assume is that the lock is being refreshed (office loves + # logically assume is that the lock is being refreshed (office loves # to do this for example, so we do a few checks, try to find the lock # and ultimately extend it, otherwise we return Conflict for any failure if (!args[:scope] && !args[:type]) #Perhaps a lock refresh @@ -459,19 +459,19 @@ module RedmineDmsf raise Forbidden end - # HTTP POST request. - def put(request, response) - raise BadRequest if collection? - raise Forbidden unless User.current.admin? || User.current.allowed_to?(:file_manipulation, project) - - # Ignore Mac OS X resource forks and special Windows files. + # HTTP POST request. + def put(request, response) + raise BadRequest if collection? + raise Forbidden unless User.current.admin? || User.current.allowed_to?(:file_manipulation, project) + + # Ignore Mac OS X resource forks and special Windows files. if basename.match(/^\._/i) || basename.match(/^Thumbs.db$/i) Rails.logger.info "#{basename} ignored" return NoContent end new_revision = DmsfFileRevision.new - + if exist? # We're over-writing something, so ultimately a new revision f = file last_revision = file.last_revision @@ -486,21 +486,21 @@ module RedmineDmsf f = DmsfFile.new f.project = project f.name = basename - f.folder = parent.folder + f.dmsf_folder = parent.folder f.notification = !Setting.plugin_redmine_dmsf['dmsf_default_notifications'].blank? new_revision.minor_version = 0 new_revision.major_version = 0 end - - new_revision.file = f + + new_revision.dmsf_file = f new_revision.user = User.current new_revision.name = basename new_revision.title = DmsfFileRevision.filename_to_title(basename) new_revision.description = nil - new_revision.comment = nil + new_revision.comment = nil new_revision.increase_version(1, true) new_revision.mime_type = Redmine::MimeType.of(new_revision.name) - + # 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 @@ -511,15 +511,15 @@ module RedmineDmsf else new_revision.size = request.content_length # Bad Guess end - - # Ignore Mac OS X resource forks and special Windows files. + + # Ignore Mac OS X resource forks and special Windows files. unless new_revision.size > 0 Rails.logger.info "#{basename} #{new_revision.size}b ignored" - return Created + return Created end - + raise InternalServerError unless new_revision.valid? && f.save - + new_revision.disk_filename = new_revision.new_storage_filename if new_revision.save @@ -543,13 +543,13 @@ module RedmineDmsf case element[:name] when 'supportedlock' supportedlock - when 'lockdiscovery' + when 'lockdiscovery' lockdiscovery - else + else super end end - + # Available properties def properties %w(creationdate displayname getlastmodified getetag resourcetype getcontenttype getcontentlength supportedlock lockdiscovery).collect do |prop| @@ -559,7 +559,7 @@ module RedmineDmsf private # Prepare file for download using Rack functionality: - # Download (see RedmineDmsf::Webdav::Download) extends Rack::File to allow single-file + # Download (see RedmineDmsf::Webdav::Download) extends Rack::File to allow single-file # implementation of service for request, which allows for us to pipe a single file through # also best-utilising DAV4Rack's implementation. def download @@ -567,28 +567,28 @@ module RedmineDmsf # 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 - if @request.env['HTTP_RANGE'].nil? + if @request.env['HTTP_RANGE'].nil? access = DmsfFileRevisionAccess.new access.user = User.current - access.revision = file.last_revision + access.dmsf_file_revision = file.last_revision access.action = DmsfFileRevisionAccess::DownloadAction access.save! end Download.new(file.last_revision.disk_file) end - + # As the name suggests, we're returning lock recovery information for requested resource def lockdiscovery x = Nokogiri::XML::DocumentFragment.parse '' entity = file || folder return nil unless entity.locked? - if entity.folder && entity.folder.locked? - locks = entity.lock.reverse[0].folder.locks(false) # longwinded way of getting base items locks + if entity.dmsf_folder && entity.dmsf_folder.locked? + locks = entity.lock.reverse[0].dmsf_folder.locks(false) # longwinded way of getting base items locks else locks = entity.lock(false) end - + Nokogiri::XML::Builder.with(x) do |doc| doc.lockdiscovery { locks.each do |lock| @@ -601,8 +601,8 @@ module RedmineDmsf else doc.shared end - } - doc.depth lock.folder.nil? ? '0' : 'infinity' + } + doc.depth lock.folder.nil? ? '0' : 'infinity' doc.owner lock.user.to_s if lock.expires_at.nil? doc.timeout 'Infinite' @@ -623,7 +623,7 @@ module RedmineDmsf end x end - + # As the name suggests, we're returning locks supported by our implementation def supportedlock x = Nokogiri::XML::DocumentFragment.parse '' diff --git a/test/functional/dmsf_controller_test.rb b/test/functional/dmsf_controller_test.rb index ad21abb7..e6872de2 100644 --- a/test/functional/dmsf_controller_test.rb +++ b/test/functional/dmsf_controller_test.rb @@ -20,14 +20,14 @@ require File.expand_path('../../test_helper', __FILE__) -class DmsfControllerTest < RedmineDmsf::Test::TestCase - include Redmine::I18n - - fixtures :users, :email_addresses, :dmsf_folders, :custom_fields, - :custom_values, :projects, :roles, :members, :member_roles, :dmsf_links, +class DmsfControllerTest < RedmineDmsf::Test::TestCase + include Redmine::I18n + + fixtures :users, :email_addresses, :dmsf_folders, :custom_fields, + :custom_values, :projects, :roles, :members, :member_roles, :dmsf_links, :dmsf_files, :dmsf_file_revisions - def setup + def setup @project = Project.find_by_id 1 assert_not_nil @project @project.enable_module! :dmsf @@ -39,11 +39,12 @@ class DmsfControllerTest < RedmineDmsf::Test::TestCase @folder_link1 = DmsfLink.find_by_id 1 @role = Role.find_by_id 1 @custom_field = CustomField.find_by_id 21 - @custom_value = CustomValue.find_by_id 21 + @custom_value = CustomValue.find_by_id 21 + @user_member = User.find_by_id 2 User.current = nil - @request.session[:user_id] = 2 + @request.session[:user_id] = @user_member.id end - + def test_truth assert_kind_of Project, @project assert_kind_of DmsfFolder, @folder1 @@ -54,16 +55,17 @@ class DmsfControllerTest < RedmineDmsf::Test::TestCase assert_kind_of DmsfLink, @folder_link1 assert_kind_of Role, @role assert_kind_of CustomField, @custom_field - assert_kind_of CustomValue, @custom_value + assert_kind_of CustomValue, @custom_value + assert_kind_of User, @user_member end - + def test_edit_folder_forbidden - # Missing permissions + # Missing permissions get :edit, :id => @project, :folder_id => @folder1 - assert_response :forbidden + assert_response :forbidden end - - def test_edit_folder_allowed + + def test_edit_folder_allowed # Permissions OK @role.add_permission! :view_dmsf_folders @role.add_permission! :folder_manipulation @@ -72,58 +74,58 @@ class DmsfControllerTest < RedmineDmsf::Test::TestCase assert_select 'label', { :text => @custom_field.name } assert_select 'option', { :value => @custom_value.value } end - + def test_trash_forbidden # Missing permissions get :trash, :id => @project - assert_response :forbidden + assert_response :forbidden end - - def test_trash_allowed + + def test_trash_allowed # Permissions OK @role.add_permission! :file_delete get :trash, :id => @project assert_response :success assert_select 'h2', { :text => l(:link_trash_bin) } end - + def test_delete_forbidden # Missing permissions get :delete, :id => @project, :folder_id => @folder1.id, :commit => false assert_response :forbidden end - + def test_delete_not_empty # Permissions OK but the folder is not empty @role.add_permission! :folder_manipulation get :delete, :id => @project, :folder_id => @folder1.id, :commit => false - assert_response :redirect + assert_response :redirect assert_include l(:error_folder_is_not_empty), flash[:error] end - + def test_delete_locked # Permissions OK but the folder is locked @role.add_permission! :folder_manipulation get :delete, :id => @project, :folder_id => @folder2.id, :commit => false - assert_response :redirect + assert_response :redirect assert_include l(:error_folder_is_locked), flash[:error] end - + def test_delete_ok - # Empty and not locked folder + # Empty and not locked folder @role.add_permission! :folder_manipulation get :delete, :id => @project, :folder_id => @folder4.id, :commit => false - assert_response :redirect + assert_response :redirect end - - def test_restore_forbidden - # Missing permissions + + def test_restore_forbidden + # Missing permissions @folder4.deleted = 1 @folder4.save get :restore, :id => @project, :folder_id => @folder4.id assert_response :forbidden end - + def test_restore_ok # Permissions OK @request.env['HTTP_REFERER'] = trash_dmsf_path(:id => @project.id) @@ -131,49 +133,67 @@ class DmsfControllerTest < RedmineDmsf::Test::TestCase @folder4.deleted = 1 @folder4.save get :restore, :id => @project, :folder_id => @folder4.id - assert_response :redirect + assert_response :redirect end - + def test_delete_restore_entries_forbidden # Missing permissions - get :entries_operation, :id => @project, :delete_entries => 'Delete', - :subfolders => [@folder1.id.to_s], :files => [@file1.id.to_s], + get :entries_operation, :id => @project, :delete_entries => 'Delete', + :subfolders => [@folder1.id.to_s], :files => [@file1.id.to_s], :dir_links => [@folder_link1.id.to_s], :file_links => [@file_link2.id.to_s] - assert_response :forbidden + assert_response :forbidden end - + def test_delete_restore_not_empty - # Permissions OK but the folder is not empty - @request.env['HTTP_REFERER'] = dmsf_folder_path(:id => @project.id) + # Permissions OK but the folder is not empty + @request.env['HTTP_REFERER'] = dmsf_folder_path(:id => @project.id) @role.add_permission! :view_dmsf_files - get :entries_operation, :id => @project, :delete_entries => 'Delete', - :subfolders => [@folder1.id.to_s], :files => [@file1.id.to_s], + get :entries_operation, :id => @project, :delete_entries => 'Delete', + :subfolders => [@folder1.id.to_s], :files => [@file1.id.to_s], :dir_links => [@folder_link1.id.to_s], :file_links => [@file_link2.id.to_s] assert_response :redirect assert_equal flash[:error].to_s, l(:error_folder_is_not_empty) end - + def test_delete_restore_entries_ok # Permissions OK @request.env['HTTP_REFERER'] = dmsf_folder_path(:id => @project.id) @role.add_permission! :view_dmsf_files flash[:error] = nil - get :entries_operation, :id => @project, :delete_entries => 'Delete', - :subfolders => [], :files => [@file1.id.to_s], + get :entries_operation, :id => @project, :delete_entries => 'Delete', + :subfolders => [], :files => [@file1.id.to_s], :dir_links => [], :file_links => [@file_link2.id.to_s] assert_response :redirect assert_nil flash[:error] end - + def test_restore_entries # Restore @role.add_permission! :view_dmsf_files - @request.env['HTTP_REFERER'] = trash_dmsf_path(:id => @project.id) - get :entries_operation, :id => @project, :restore_entries => 'Restore', - :subfolders => [], :files => [@file1.id.to_s], + @request.env['HTTP_REFERER'] = trash_dmsf_path(:id => @project.id) + get :entries_operation, :id => @project, :restore_entries => 'Restore', + :subfolders => [], :files => [@file1.id.to_s], :dir_links => [], :file_links => [@file_link2.id.to_s] assert_response :redirect assert_nil flash[:error] end - + + def test_show + @role.add_permission! :view_dmsf_files + @role.add_permission! :view_dmsf_folders + get :show, :id => @project.id + assert_response :success + assert_select 'tr.dmsf_tree', :count => 0 + end + + def test_show_tree_view + @role.add_permission! :view_dmsf_files + @role.add_permission! :view_dmsf_folders + @user_member.pref[:dmsf_tree_view] = '1' + @user_member.preference.save + get :show, :id => @project.id + assert_response :success + assert_select 'tr.dmsf_tree' + end + end \ No newline at end of file diff --git a/test/functional/dmsf_workflow_controller_test.rb b/test/functional/dmsf_workflow_controller_test.rb index ab220685..07e3360c 100644 --- a/test/functional/dmsf_workflow_controller_test.rb +++ b/test/functional/dmsf_workflow_controller_test.rb @@ -22,15 +22,15 @@ require File.expand_path('../../test_helper', __FILE__) class DmsfWorkflowsControllerTest < RedmineDmsf::Test::TestCase include Redmine::I18n - - fixtures :users, :email_addresses, :dmsf_workflows, :dmsf_workflow_steps, - :projects, :roles, :members, :member_roles, :dmsf_workflow_step_assignments, + + fixtures :users, :email_addresses, :dmsf_workflows, :dmsf_workflow_steps, + :projects, :roles, :members, :member_roles, :dmsf_workflow_step_assignments, :dmsf_file_revisions, :dmsf_files - + def setup - @user_admin = User.find_by_id 1 # Redmine admin - @user_member = User.find_by_id 2 # John Smith - manager - @user_non_member = User.find_by_id 3 # Dave Lopper + @user_admin = User.find_by_id 1 # Redmine admin + @user_member = User.find_by_id 2 # John Smith - manager + @user_non_member = User.find_by_id 3 # Dave Lopper @role_manager = Role.find_by_name('Manager') @role_manager.add_permission! :file_manipulation @role_manager.add_permission! :manage_workflows @@ -39,22 +39,22 @@ class DmsfWorkflowsControllerTest < RedmineDmsf::Test::TestCase @wfs2 = DmsfWorkflowStep.find_by_id 2 # step 2 @wfs3 = DmsfWorkflowStep.find_by_id 3 # step 1 @wfs4 = DmsfWorkflowStep.find_by_id 4 # step 2 - @wfs5 = DmsfWorkflowStep.find_by_id 5 # step 3 - @project1 = Project.find_by_id 1 + @wfs5 = DmsfWorkflowStep.find_by_id 5 # step 3 + @project1 = Project.find_by_id 1 @project1.enable_module! :dmsf @wf1 = DmsfWorkflow.find_by_id 1 @wf3 = DmsfWorkflow.find_by_id 3 @wfsa2 = DmsfWorkflowStepAssignment.find_by_id 2 @revision1 = DmsfFileRevision.find_by_id 1 @revision2 = DmsfFileRevision.find_by_id 2 - @revision3 = DmsfFileRevision.find_by_id 3 + @revision3 = DmsfFileRevision.find_by_id 3 @file1 = DmsfFile.find_by_id 1 @file2 = DmsfFile.find_by_id 2 @request.env['HTTP_REFERER'] = dmsf_folder_path(:id => @project1.id) User.current = nil - @request.session[:user_id] = @user_member.id + @request.session[:user_id] = @user_member.id end - + def test_truth assert_kind_of User, @user_admin assert_kind_of User, @user_member @@ -65,7 +65,7 @@ class DmsfWorkflowsControllerTest < RedmineDmsf::Test::TestCase assert_kind_of DmsfWorkflowStep, @wfs3 assert_kind_of DmsfWorkflowStep, @wfs4 assert_kind_of DmsfWorkflowStep, @wfs5 - assert_kind_of Project, @project1 + assert_kind_of Project, @project1 assert_kind_of DmsfWorkflow, @wf1 assert_kind_of DmsfWorkflow, @wf3 assert_kind_of DmsfWorkflowStepAssignment, @wfsa2 @@ -75,50 +75,50 @@ class DmsfWorkflowsControllerTest < RedmineDmsf::Test::TestCase assert_kind_of DmsfFile, @file1 assert_kind_of DmsfFile, @file2 end - + def test_authorize_admin # Admin @request.session[:user_id] = @user_admin.id get :index assert_response :success - assert_template 'index' + assert_template 'index' end - + def test_authorize_member # Non member - @request.session[:user_id] = @user_non_member.id + @request.session[:user_id] = @user_non_member.id get :index, :project_id => @project1.id - assert_response :forbidden + assert_response :forbidden end - - def test_authorize_administration + + def test_authorize_administration # Administration get :index - assert_response :forbidden + assert_response :forbidden end - - def test_authorize_projects - # Project + + def test_authorize_projects + # Project get :index, :project_id => @project1.id assert_response :success assert_template 'index' end - + def test_authorize_manage_workflows_forbidden # Without permissions @role_manager.remove_permission! :manage_workflows get :index, :project_id => @project1.id assert_response :forbidden end - + def test_authorization_file_approval_ok - @role_manager.add_permission! :file_approval + @role_manager.add_permission! :file_approval @revision2.dmsf_workflow_id = @wf1.id get :start, :id => @revision2.dmsf_workflow_id, :dmsf_file_revision_id => @revision2.id assert_response :redirect end - + def test_authorization_file_approval_forbidden @role_manager.remove_permission! :file_approval @revision2.dmsf_workflow_id = @wf1.id @@ -126,43 +126,43 @@ class DmsfWorkflowsControllerTest < RedmineDmsf::Test::TestCase :dmsf_file_revision_id => @revision2.id assert_response :forbidden end - + def test_authorization_no_module - # Without the module + # Without the module @role_manager.add_permission! :file_manipulation - @project1.disable_module!(:dmsf) + @project1.disable_module!(:dmsf) get :index, :project_id => @project1.id - assert_response :forbidden + assert_response :forbidden end - + def test_index_administration @request.session[:user_id] = @user_admin.id get :index assert_response :success assert_template 'index' end - - def test_index_project + + def test_index_project get :index, :project_id => @project1.id assert_response :success assert_template 'index' end - def test_new + def test_new get :new, :project_id => @project1.id assert_response :success assert_template 'new' - end - + end + def test_lock put :update, :id => @wf1.id, :dmsf_workflow => { :status => DmsfWorkflow::STATUS_LOCKED } @wf1.reload assert @wf1.locked?, "#{@wf1.name} status is #{@wf1.status}" end - + def test_unlock @request.session[:user_id] = @user_admin.id - put :update, :id => @wf3.id, :dmsf_workflow => { :status => DmsfWorkflow::STATUS_ACTIVE } + put :update, :id => @wf3.id, :dmsf_workflow => { :status => DmsfWorkflow::STATUS_ACTIVE } @wf3.reload assert @wf3.active?, "#{@wf3.name} status is #{@wf3.status}" end @@ -170,43 +170,43 @@ class DmsfWorkflowsControllerTest < RedmineDmsf::Test::TestCase def test_show get :show, :id => @wf1.id assert_response :success - assert_template 'show' + assert_template 'show' end - - def test_create - assert_difference 'DmsfWorkflow.count', +1 do - post :create, :dmsf_workflow => {:name => 'wf4'}, :project_id => @project1.id - end - assert_redirected_to settings_project_path(@project1, :tab => 'dmsf_workflow') + + def test_create + assert_difference 'DmsfWorkflow.count', +1 do + post :create, :dmsf_workflow => {:name => 'wf4', :project_id => @project1.id} + end + assert_redirected_to settings_project_path(@project1, :tab => 'dmsf_workflow') end - - def test_update + + def test_update put :update, :id => @wf1.id, :dmsf_workflow => {:name => 'wf1a'} @wf1.reload - assert_equal 'wf1a', @wf1.name + assert_equal 'wf1a', @wf1.name end - - def test_destroy + + def test_destroy assert_difference 'DmsfWorkflow.count', -1 do delete :destroy, :id => @wf1.id end - assert_redirected_to settings_project_path(@project1, :tab => 'dmsf_workflow') - assert_equal 0, DmsfWorkflowStep.where(:dmsf_workflow_id => @wf1.id).all.count + assert_redirected_to settings_project_path(@project1, :tab => 'dmsf_workflow') + assert_equal 0, DmsfWorkflowStep.where(:dmsf_workflow_id => @wf1.id).all.count end - - def test_add_step - assert_difference 'DmsfWorkflowStep.count', +1 do + + def test_add_step + assert_difference 'DmsfWorkflowStep.count', +1 do post :add_step, :commit => l(:dmsf_or), :step => 1, :id => @wf1.id, :user_ids => [@user_non_member.id] end assert_response :success - ws = DmsfWorkflowStep.order('id DESC').first + ws = DmsfWorkflowStep.order('id DESC').first assert_equal @wf1.id, ws.dmsf_workflow_id assert_equal 1, ws.step assert_equal @user_non_member.id, ws.user_id assert_equal DmsfWorkflowStep::OPERATOR_OR, ws.operator end - - def test_remove_step + + def test_remove_step n = DmsfWorkflowStep.where(:dmsf_workflow_id => @wf1.id, :step => 1).count assert_difference 'DmsfWorkflowStep.count', -n do delete :remove_step, :step => @wfs1.id, :id => @wf1.id @@ -215,158 +215,158 @@ class DmsfWorkflowsControllerTest < RedmineDmsf::Test::TestCase ws = DmsfWorkflowStep.where(:dmsf_workflow_id => @wf1.id).order('id ASC').first assert_equal 1, ws.step end - - def test_reorder_steps_to_lower + + def test_reorder_steps_to_lower put :reorder_steps, :step => 1, :id => @wf1.id, :workflow_step => {:move_to => 'lower'} - assert_response :success + assert_response :success @wfs1.reload @wfs2.reload @wfs3.reload @wfs4.reload - @wfs5.reload + @wfs5.reload assert_equal 1, @wfs2.step assert_equal 1, @wfs3.step assert_equal 2, @wfs1.step assert_equal 2, @wfs4.step assert_equal 3, @wfs5.step end - - def test_reorder_steps_to_lowest + + def test_reorder_steps_to_lowest put :reorder_steps, :step => 1, :id => @wf1.id, :workflow_step => {:move_to => 'lowest'} - assert_response :success + assert_response :success @wfs1.reload @wfs2.reload @wfs3.reload @wfs4.reload - @wfs5.reload - assert_equal 1, @wfs2.step + @wfs5.reload + assert_equal 1, @wfs2.step assert_equal 1, @wfs3.step assert_equal 2, @wfs5.step assert_equal 3, @wfs1.step assert_equal 3, @wfs4.step - end - - def test_reorder_steps_to_higher + end + + def test_reorder_steps_to_higher put :reorder_steps, :step => 3, :id => @wf1.id, :workflow_step => {:move_to => 'higher'} - assert_response :success + assert_response :success @wfs1.reload @wfs2.reload @wfs3.reload @wfs4.reload - @wfs5.reload + @wfs5.reload assert_equal 1, @wfs1.step assert_equal 1, @wfs4.step assert_equal 2, @wfs5.step - assert_equal 3, @wfs2.step - assert_equal 3, @wfs3.step + assert_equal 3, @wfs2.step + assert_equal 3, @wfs3.step end - - def test_reorder_steps_to_highest + + def test_reorder_steps_to_highest put :reorder_steps, :step => 3, :id => @wf1.id, :workflow_step => {:move_to => 'highest'} - assert_response :success + assert_response :success @wfs1.reload @wfs2.reload @wfs3.reload @wfs4.reload - @wfs5.reload + @wfs5.reload assert_equal 1, @wfs5.step assert_equal 2, @wfs1.step assert_equal 2, @wfs4.step - assert_equal 3, @wfs2.step - assert_equal 3, @wfs3.step + assert_equal 3, @wfs2.step + assert_equal 3, @wfs3.step end - - def test_action_approve - post( - :new_action, - :commit => l(:button_submit), - :id => @wf1.id, - :dmsf_workflow_step_assignment_id => @wfsa2.id, + + def test_action_approve + post( + :new_action, + :commit => l(:button_submit), + :id => @wf1.id, + :dmsf_workflow_step_assignment_id => @wfsa2.id, :dmsf_file_revision_id => @revision1.id, :step_action => DmsfWorkflowStepAction::ACTION_APPROVE, :user_id => nil, - :note => '') + :note => '') assert_redirected_to dmsf_folder_path(:id => @project1.id) assert DmsfWorkflowStepAction.where( - :dmsf_workflow_step_assignment_id => @wfsa2.id, - :action => DmsfWorkflowStepAction::ACTION_APPROVE).first - end - - def test_action_reject - post( - :new_action, - :commit => l(:button_submit), - :id => @wf1.id, - :dmsf_workflow_step_assignment_id => @wfsa2.id, - :dmsf_file_revision_id => @revision2.id, - :step_action => DmsfWorkflowStepAction::ACTION_REJECT, - :note => 'Rejected because...') - assert_response :redirect - assert DmsfWorkflowStepAction.where( - :dmsf_workflow_step_assignment_id => @wfsa2.id, - :action => DmsfWorkflowStepAction::ACTION_REJECT).first + :dmsf_workflow_step_assignment_id => @wfsa2.id, + :action => DmsfWorkflowStepAction::ACTION_APPROVE).first end - def test_action + def test_action_reject + post( + :new_action, + :commit => l(:button_submit), + :id => @wf1.id, + :dmsf_workflow_step_assignment_id => @wfsa2.id, + :dmsf_file_revision_id => @revision2.id, + :step_action => DmsfWorkflowStepAction::ACTION_REJECT, + :note => 'Rejected because...') + assert_response :redirect + assert DmsfWorkflowStepAction.where( + :dmsf_workflow_step_assignment_id => @wfsa2.id, + :action => DmsfWorkflowStepAction::ACTION_REJECT).first + end + + def test_action xhr( :get, :action, - :project_id => @project1.id, - :id => @wf1.id, + :project_id => @project1.id, + :id => @wf1.id, :dmsf_workflow_step_assignment_id => @wfsa2.id, :dmsf_file_revision_id => @revision2.id, - :title => l(:title_waiting_for_approval)) + :title => l(:title_waiting_for_approval)) assert_response :success assert_match /ajax-modal/, response.body assert_template 'action' end - - def test_new_action_delegate - post( - :new_action, - :commit => l(:button_submit), - :id => @wf1.id, - :dmsf_workflow_step_assignment_id => @wfsa2.id, + + def test_new_action_delegate + post( + :new_action, + :commit => l(:button_submit), + :id => @wf1.id, + :dmsf_workflow_step_assignment_id => @wfsa2.id, :dmsf_file_revision_id => @revision2.id, :step_action => @user_admin.id * 10, - :note => 'Delegated because...') + :note => 'Delegated because...') assert_redirected_to dmsf_folder_path(:id => @project1.id) assert DmsfWorkflowStepAction.where( - :dmsf_workflow_step_assignment_id => @wfsa2.id, - :action => DmsfWorkflowStepAction::ACTION_DELEGATE).first + :dmsf_workflow_step_assignment_id => @wfsa2.id, + :action => DmsfWorkflowStepAction::ACTION_DELEGATE).first @wfsa2.reload - assert_equal @wfsa2.user_id, @user_admin.id + assert_equal @wfsa2.user_id, @user_admin.id end - - def test_assign - xhr( - :get, - :assign, + + def test_assign + xhr( + :get, + :assign, :project_id => @project1.id, - :id => @wf1.id, - :dmsf_file_revision_id => @revision1.id, + :id => @wf1.id, + :dmsf_file_revision_id => @revision1.id, :title => l(:label_dmsf_wokflow_action_assign)) assert_response :success assert_match /ajax-modal/, response.body - assert_template 'assign' + assert_template 'assign' end - + def test_start - @revision2.dmsf_workflow_id = @wf1.id + @revision2.dmsf_workflow_id = @wf1.id get :start, :id => @revision2.dmsf_workflow_id,:dmsf_file_revision_id => @revision2.id assert_redirected_to dmsf_folder_path(:id => @project1.id) end - - def test_assignment - post( - :assignment, - :commit => l(:button_submit), - :id => @wf1.id, - :dmsf_workflow_id => @wf1.id, + + def test_assignment + post( + :assignment, + :commit => l(:button_submit), + :id => @wf1.id, + :dmsf_workflow_id => @wf1.id, :dmsf_file_revision_id => @revision2.id, :action => 'assignment', - :project_id => @project1.id) - assert_response :redirect + :project_id => @project1.id) + assert_response :redirect end end diff --git a/test/integration/dmsf_webdav_get_test.rb b/test/integration/dmsf_webdav_get_test.rb index a3ad1353..20295236 100644 --- a/test/integration/dmsf_webdav_get_test.rb +++ b/test/integration/dmsf_webdav_get_test.rb @@ -23,7 +23,7 @@ require File.expand_path('../../test_helper', __FILE__) class DmsfWebdavGetTest < RedmineDmsf::Test::IntegrationTest - fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles, + fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles, :enabled_modules, :dmsf_folders, :dmsf_files, :dmsf_file_revisions def setup @@ -33,12 +33,12 @@ class DmsfWebdavGetTest < RedmineDmsf::Test::IntegrationTest @project2 = Project.find_by_id 2 @role = Role.find_by_id 1 # Manager Setting.plugin_redmine_dmsf['dmsf_webdav'] = '1' - Setting.plugin_redmine_dmsf['dmsf_webdav_strategy'] = 'WEBDAV_READ_WRITE' + Setting.plugin_redmine_dmsf['dmsf_webdav_strategy'] = 'WEBDAV_READ_WRITE' DmsfFile.storage_path = File.expand_path '../../fixtures/files', __FILE__ User.current = nil end - - def test_truth + + def test_truth assert_kind_of Project, @project1 assert_kind_of Project, @project2 assert_kind_of Role, @role @@ -67,26 +67,26 @@ class DmsfWebdavGetTest < RedmineDmsf::Test::IntegrationTest def test_should_not_list_non_dmsf_enabled_project get '/dmsf/webdav', nil, @jsmith - assert_response :success + assert_response :success assert response.body.match(@project2.name).nil?, "Unexpected find of project #{@project2.name} in return data" end def test_should_return_status_404_when_project_does_not_exist @project1.enable_module! :dmsf # Flag module enabled - get '/dmsf/webdav/project_does_not_exist', nil, @jsmith + get '/dmsf/webdav/project_does_not_exist', nil, @jsmith assert_response :missing end def test_should_return_status_404_when_dmsf_not_enabled get "/dmsf/webdav/#{@project2.identifier}", nil, @jsmith assert_response :missing - end + end def test_download_file_from_dmsf_enabled_project - #@project1.enable_module! :dmsf # Flag module enabled - get "/dmsf/webdav/#{@project1.identifier}/test.txt", nil, @admin + #@project1.enable_module! :dmsf # Flag module enabled + get "/dmsf/webdav/#{@project1.identifier}/test.txt", nil, @admin assert_response :success - assert_equal response.body, '1234', + assert_equal response.body, '1234', "File downloaded with unexpected contents: '#{response.body}'" end @@ -95,19 +95,19 @@ class DmsfWebdavGetTest < RedmineDmsf::Test::IntegrationTest assert_response :success folder = DmsfFolder.find_by_id 1 assert folder - assert response.body.match(folder.title), + assert response.body.match(folder.title), "Expected to find #{folder.title} in return data" file = DmsfFile.find_by_id 1 assert file - assert response.body.match(file.name), + assert response.body.match(file.name), "Expected to find #{file.name} in return data" end - def test_user_assigned_to_project_dmsf_module_not_enabled + def test_user_assigned_to_project_dmsf_module_not_enabled get "/dmsf/webdav/#{@project1.identifier}", nil, @jsmith assert_response :missing end - + def test_user_assigned_to_project_folder_forbidden @project2.enable_module! :dmsf # Flag module enabled get "/dmsf/webdav/#{@project1.identifier}", nil, @jsmith @@ -121,21 +121,21 @@ class DmsfWebdavGetTest < RedmineDmsf::Test::IntegrationTest get "/dmsf/webdav/#{@project1.identifier}", nil, @jsmith assert_response :success end - + def test_user_assigned_to_project_file_forbidden @project1.enable_module! :dmsf # Flag module enabled - @role.add_permission! :view_dmsf_folders + @role.add_permission! :view_dmsf_folders get "/dmsf/webdav/#{@project1.identifier}/test.txt", nil, @jsmith assert_response :forbidden end - + def test_user_assigned_to_project_file_ok @project1.enable_module! :dmsf # Flag module enabled @role.add_permission! :view_dmsf_folders - @role.add_permission! :view_dmsf_files + @role.add_permission! :view_dmsf_files get "/dmsf/webdav/#{@project1.identifier}/test.txt", nil, @jsmith assert_response :success - assert_equal response.body, '1234', + assert_equal response.body, '1234', "File downloaded with unexpected contents: '#{response.body}'" end diff --git a/test/integration/dmsf_webdav_put_test.rb b/test/integration/dmsf_webdav_put_test.rb index 2ddc10df..f0f603bf 100644 --- a/test/integration/dmsf_webdav_put_test.rb +++ b/test/integration/dmsf_webdav_put_test.rb @@ -24,7 +24,7 @@ require 'fileutils' class DmsfWebdavPutTest < RedmineDmsf::Test::IntegrationTest - fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles, + fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles, :enabled_modules, :dmsf_folders, :dmsf_files, :dmsf_file_revisions def setup @@ -36,13 +36,13 @@ class DmsfWebdavPutTest < RedmineDmsf::Test::IntegrationTest @jsmith = credentials 'jsmith' @project1 = Project.find_by_id 1 @project2 = Project.find_by_id 2 - @role = Role.find 1 # + @role = Role.find 1 # Setting.plugin_redmine_dmsf['dmsf_webdav'] = '1' Setting.plugin_redmine_dmsf['dmsf_webdav_strategy'] = 'WEBDAV_READ_WRITE' super end - def teardown + def teardown # Delete our tmp folder begin FileUtils.rm_rf DmsfFile.storage_path @@ -50,8 +50,8 @@ class DmsfWebdavPutTest < RedmineDmsf::Test::IntegrationTest error e.message end end - - def test_truth + + def test_truth assert_kind_of Project, @project1 assert_kind_of Project, @project2 assert_kind_of Role, @role @@ -61,7 +61,7 @@ class DmsfWebdavPutTest < RedmineDmsf::Test::IntegrationTest put '/dmsf/webdav' assert_response 401 end - + def test_put_denied_unless_authenticated put "/dmsf/webdav/#{@project1.identifier}" assert_response 401 @@ -113,43 +113,43 @@ class DmsfWebdavPutTest < RedmineDmsf::Test::IntegrationTest put "/dmsf/webdav/#{@project1.identifier}/test-1234.txt", '1234', @jsmith.merge!({:content_type => :text}) assert_response 409 # We don't hold the permission view_dmsf_folders, and thus project 2 doesn't exist to us. end - + def test_put_failed_when_no_file_manipulation_permission @project1.enable_module! :dmsf # Flag module enabled - @role.add_permission! :view_dmsf_folders + @role.add_permission! :view_dmsf_folders put "/dmsf/webdav/#{@project1.identifier}/test-1234.txt", '1234', @jsmith.merge!({:content_type => :text}) assert_response :forbidden # We don't hold the permission file_manipulation - so we're unable to do anything with files end - + def test_put_failed_when_no_view_dmsf_folders_permission - @project1.enable_module! :dmsf # Flag module enabled + @project1.enable_module! :dmsf # Flag module enabled @role.add_permission! :file_manipulation # Check we don't have write access even if we do have the file_manipulation permission put "/dmsf/webdav/#{@project1.identifier}/test-1234.txt", '1234', @jsmith.merge!({:content_type => :text}) assert_response 409 # We don't hold the permission view_dmsf_folders, and thus project 2 doesn't exist to us. # Lets check for our file file = DmsfFile.find_file_by_name @project1, nil, 'test-1234.txt' - assert_nil file, 'File test-1234 was found in projects dmsf folder.' + assert_nil file, 'File test-1234 was found in projects dmsf folder.' end def test_put_succeeds_for_non_admin_with_correct_permissions - @project1.enable_module! :dmsf # Flag module enabled + @project1.enable_module! :dmsf # Flag module enabled @role.add_permission! :view_dmsf_folders - @role.add_permission! :file_manipulation + @role.add_permission! :file_manipulation put "/dmsf/webdav/#{@project1.identifier}/test-1234.txt", '1234', @jsmith.merge!({:content_type => :text}) assert_response :success # 201 - Now we have permissions # Lets check for our file file = DmsfFile.find_file_by_name @project1, nil, 'test-1234.txt' - assert file, 'File test-1234 was not found in projects dmsf folder.' + assert file, 'File test-1234 was not found in projects dmsf folder.' end def test_put_writes_revision_successfully_for_unlocked_file - @project1.enable_module! :dmsf #Flag module enabled + @project1.enable_module! :dmsf #Flag module enabled @role.add_permission! :view_dmsf_folders @role.add_permission! :file_manipulation file = DmsfFile.find_file_by_name @project1, nil, 'test.txt' assert_not_nil file, 'test.txt file not found' - assert_difference 'file.revisions.count', +1 do + assert_difference 'file.dmsf_file_revisions.count', +1 do put "/dmsf/webdav/#{@project1.identifier}/test.txt", '1234', @jsmith.merge!({:content_type => :text}) assert_response :success # 201 - Created end @@ -163,10 +163,10 @@ class DmsfWebdavPutTest < RedmineDmsf::Test::IntegrationTest assert !User.current.anonymous?, 'Current user is not anonymous' file = DmsfFile.find_file_by_name @project1, nil, 'test.txt' assert file.lock!, "File failed to be locked by #{User.current.name}" - assert_no_difference 'file.revisions.count' do + assert_no_difference 'file.dmsf_file_revisions.count' do put "/dmsf/webdav/#{@project1.identifier}/test.txt", '1234', @jsmith.merge!({:content_type => :text}) assert_response 423 # Locked - end + end end def test_put_fails_revision_when_file_is_locked_and_user_is_administrator @@ -177,10 +177,10 @@ class DmsfWebdavPutTest < RedmineDmsf::Test::IntegrationTest assert !User.current.anonymous?, 'Current user is not anonymous' file = DmsfFile.find_file_by_name @project1, nil, 'test.txt' assert file.lock!, "File failed to be locked by #{User.current.name}" - assert_no_difference 'file.revisions.count' do + assert_no_difference 'file.dmsf_file_revisions.count' do put "/dmsf/webdav/#{@project1.identifier}/test.txt", '1234', @admin.merge!({:content_type => :text}) - assert_response 423 # Locked - end + assert_response 423 # Locked + end end def test_put_accepts_revision_when_file_is_locked_and_user_is_same_as_lock_holder @@ -191,10 +191,10 @@ class DmsfWebdavPutTest < RedmineDmsf::Test::IntegrationTest assert !User.current.anonymous?, 'Current user is not anonymous' file = DmsfFile.find_file_by_name @project1, nil, 'test.txt' assert file.lock!, "File failed to be locked by #{User.current.name}" - assert_difference 'file.revisions.count', +1 do + assert_difference 'file.dmsf_file_revisions.count', +1 do put "/dmsf/webdav/#{@project1.identifier}/test.txt", '1234', @jsmith.merge!({:content_type => :text}) assert_response :success # 201 - Created - end + end end - + end \ No newline at end of file diff --git a/test/unit/dmsf_file_test.rb b/test/unit/dmsf_file_test.rb index b113250c..0e1c9299 100644 --- a/test/unit/dmsf_file_test.rb +++ b/test/unit/dmsf_file_test.rb @@ -22,44 +22,44 @@ require File.expand_path('../../test_helper', __FILE__) class DmsfFileTest < RedmineDmsf::Test::UnitTest - fixtures :projects, :users, :email_addresses, :dmsf_folders, :dmsf_files, - :dmsf_file_revisions, :roles, :members, :member_roles, :dmsf_locks, + fixtures :projects, :users, :email_addresses, :dmsf_folders, :dmsf_files, + :dmsf_file_revisions, :roles, :members, :member_roles, :dmsf_locks, :dmsf_links - + def setup @admin = User.find_by_id 1 - @jsmith = User.find_by_id 2 + @jsmith = User.find_by_id 2 @project1 = Project.find_by_id 1 @file1 = DmsfFile.find_by_id 1 @file2 = DmsfFile.find_by_id 2 @file3 = DmsfFile.find_by_id 3 @file4 = DmsfFile.find_by_id 4 - @file5 = DmsfFile.find_by_id 5 + @file5 = DmsfFile.find_by_id 5 User.current = nil end - + def test_truth assert_kind_of User, @admin - assert_kind_of User, @jsmith + assert_kind_of User, @jsmith assert_kind_of Project, @project1 assert_kind_of DmsfFile, @file1 assert_kind_of DmsfFile, @file2 assert_kind_of DmsfFile, @file3 assert_kind_of DmsfFile, @file4 assert_kind_of DmsfFile, @file5 - end + end def test_project_file_count_differs_from_project_visibility_count assert_not_same(@project1.dmsf_files.count, @project1.dmsf_files.visible.count) end - def test_project_dmsf_file_listing_contains_deleted_items - assert @project1.dmsf_files.index{ |f| f.deleted? }, - 'Expected at least one deleted item in ' + def test_project_dmsf_file_listing_contains_deleted_items + assert @project1.dmsf_files.index{ |f| f.deleted? }, + 'Expected at least one deleted item in ' end - def test_project_dmsf_file_visible_listing_contains_no_deleted_items - assert @project1.dmsf_files.visible.index{ |f| f.deleted? }.nil?, + def test_project_dmsf_file_visible_listing_contains_no_deleted_items + assert @project1.dmsf_files.visible.index{ |f| f.deleted? }.nil?, 'There is a deleted file, this was unexpected' end @@ -71,68 +71,68 @@ class DmsfFileTest < RedmineDmsf::Test::UnitTest assert @file4.locked?, "#{@file4.name} is not locked" end - def test_file_with_folder_up_heirarchy_locked_is_reported_as_locked + def test_file_with_folder_up_heirarchy_locked_is_reported_as_locked assert @file5.locked?, "#{@file5.name} is not locked" end def test_file_locked_is_not_locked_for_user_who_locked User.current = @admin @file1.lock! - assert !@file1.locked_for_user?, + assert !@file1.locked_for_user?, "#{@file1.name} is locked for #{User.current.name}" - @file1.unlock! + @file1.unlock! end - + def test_file_locked_is_locked_for_user_who_didnt_lock User.current = @admin @file1.lock! User.current = @jsmith - assert @file1.locked_for_user?, + assert @file1.locked_for_user?, "#{@file1.name} is locked for #{User.current.name}" User.current = @admin - @file1.unlock! + @file1.unlock! end - + def test_file_with_no_locks_reported_unlocked assert !@file1.locked? end - - def test_delete_restore - assert_equal 1, @file4.revisions.visible.count + + def test_delete_restore + assert_equal 1, @file4.dmsf_file_revisions.visible.count assert_equal 2, @file4.referenced_links.visible.count end - + def test_delete User.current = @admin - @file4.folder.unlock! + @file4.dmsf_folder.unlock! assert @file4.delete(false), @file4.errors.full_messages.to_sentence assert @file4.deleted?, "File #{@file4.name} is not deleted" - assert_equal 0, @file4.revisions.visible.count + assert_equal 0, @file4.dmsf_file_revisions.visible.count # Links should not be deleted assert_equal 2, @file4.referenced_links.visible.count - @file4.folder.lock! + @file4.dmsf_folder.lock! end - + def test_restore User.current = @admin - @file4.folder.unlock! + @file4.dmsf_folder.unlock! assert @file4.delete(false), @file4.errors.full_messages.to_sentence - @file4.restore + @file4.restore assert !@file4.deleted?, "File #{@file4} hasn't been restored" - assert_equal 1, @file4.revisions.visible.count + assert_equal 1, @file4.dmsf_file_revisions.visible.count assert_equal 2, @file4.referenced_links.visible.count - @file4.folder.lock! + @file4.dmsf_folder.lock! end - - def test_destroy + + def test_destroy User.current = @admin - @file4.folder.unlock! - assert_equal 1, @file4.revisions.visible.count + @file4.dmsf_folder.unlock! + assert_equal 1, @file4.dmsf_file_revisions.visible.count assert_equal 2, @file4.referenced_links.visible.count - @file4.delete true - assert_equal 0, @file4.revisions.count + @file4.delete true + assert_equal 0, @file4.dmsf_file_revisions.count assert_equal 0, @file4.referenced_links.count - @file4.folder.lock! + @file4.dmsf_folder.lock! end end \ No newline at end of file
<%=l(:field_project)%> <%=l(:field_label_dmsf_workflow)%> <%=l(:label_document)%>
- <% if assignment.dmsf_file_revision.file.project %> - <%= link_to_project(assignment.dmsf_file_revision.file.project) %> + <% if assignment.dmsf_file_revision.dmsf_file.project %> + <%= link_to_project(assignment.dmsf_file_revision.dmsf_file.project) %> <% end %> - <% if assignment.dmsf_workflow_step && assignment.dmsf_workflow_step.dmsf_workflow %> - <%= link_to(h(assignment.dmsf_workflow_step.dmsf_workflow.name), - edit_dmsf_workflow_path(assignment.dmsf_workflow_step.dmsf_workflow)) %> + <% if assignment.dmsf_workflow_step && assignment.dmsf_workflow_step.dmsf_workflow %> + <%= link_to(h(assignment.dmsf_workflow_step.dmsf_workflow.name), + edit_dmsf_workflow_path(assignment.dmsf_workflow_step.dmsf_workflow)) %> <% end %> - <% if assignment.dmsf_file_revision && assignment.dmsf_file_revision.file %> - <%= link_to(h(assignment.dmsf_file_revision.title), - {:controller => 'dmsf_files', :action => :show, :id => assignment.dmsf_file_revision.file }) %> + <% if assignment.dmsf_file_revision && assignment.dmsf_file_revision.dmsf_file %> + <%= link_to(h(assignment.dmsf_file_revision.title), + {:controller => 'dmsf_files', :action => :show, :id => assignment.dmsf_file_revision.dmsf_file }) %> <% end %> <% if assignment.dmsf_file_revision %> - <% if assignment.dmsf_file_revision.file.folder %> - <%= link_to(h(assignment.dmsf_file_revision.file.folder.title), - {:controller => 'dmsf', :action => 'show', :id => assignment.dmsf_file_revision.file.project, :folder_id => assignment.dmsf_file_revision.file.folder}) %> - <% elsif assignment.dmsf_file_revision.file.project %> - <%= link_to(l(:link_documents), {:controller => 'dmsf', :action => 'show', :id => assignment.dmsf_file_revision.file.project }) %> + <% if assignment.dmsf_file_revision.dmsf_file.dmsf_folder %> + <%= link_to(h(assignment.dmsf_file_revision.dmsf_file.dmsf_folder.title), + {:controller => 'dmsf', :action => 'show', :id => assignment.dmsf_file_revision.dmsf_file.project, :folder_id => assignment.dmsf_file_revision.dmsf_file.dmsf_folder}) %> + <% elsif assignment.dmsf_file_revision.dmsf_file.project %> + <%= link_to(l(:link_documents), {:controller => 'dmsf', :action => 'show', :id => assignment.dmsf_file_revision.dmsf_file.project }) %> <% end %> <% end %>