diff --git a/CHANGELOG.md b/CHANGELOG.md index a87043d1..014603ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,36 @@ Changelog for Redmine DMSF ========================== +1.5.2 *2015-07-13* +------------------ + + Redmine >= 3.0 compatibility + + +* Bug: #404 - Deleted folder (still in trash) results in errors while accessing parent folder via webdav +* Bug: #401 - Link between project on Redmine 3.0 +* Bug: #400 - internal server error fulltext search +* Bug: #396 - Error when uploading files +* Bug: #394 - DMSF install to Redmine 3.0.3 problem +* Bug: #393 - File can't be created in storage directory (Redmine 3.0.3) +* Bug: #392 - Redmine 3 Search screen error with Xapian +* New: #391 - Searchable document details +* Bug: #387 - Wrong sorting by Modified column +* Bug: #384 - Error when trying to uninstall DMSF +* New: #383 - Missleading number of entities in documents folder +* Bug: #382 - REST API - list of document produces invalid XML +* Bug: #380 - Internal Error 500 when dmsf page is accessed +* Bug: #378 - Revision view, delete revision bug +* Bug: #377 - Can access WebDAV when redmine is located under sub-URI +* Bug: #376 - Links to deleted documents +* Bug: #374 - Number of downloads +* Bug: #373 - internal 500 error : 1.5.1 stable with redmine 3.0.1 when search in dmsf enabled project +* New: #339 - Maximum Upload Size +* Bug: #319 - webdav problem after upgrading to 1.4.9 from 1.4.6 +* New: #78 - Control DMSF via REST API + 1.5.1: *2015-04-01* ------------------------ +------------------- Approval workflow copying Polish localization diff --git a/README.md b/README.md index 5d145f2e..f9e445f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Redmine DMSF Plugin =================== -The current version of Redmine DMSF is **1.5.1** [![Build Status](https://api.travis-ci.org/danmunn/redmine_dmsf.png)](https://travis-ci.org/danmunn/redmine_dmsf) +The current version of Redmine DMSF is **1.5.2** [![Build Status](https://api.travis-ci.org/danmunn/redmine_dmsf.png)](https://travis-ci.org/danmunn/redmine_dmsf) Redmine DMSF is Document Management System Features plugin for Redmine issue tracking system; It is aimed to replace current Redmine's Documents module. @@ -42,7 +42,7 @@ Features Dependencies ------------ - * Redmine 2.5.0 or higher (Not yet fully compatible with Redmine 3.x but it should work in general) + * Redmine 2.5.0 or higher ### Fulltext search (optional) @@ -123,11 +123,12 @@ In the file /public/help//wiki_syntax_detailed.html, aft
  • DMSF:
      -
    • {{dmsf(17)}} (link to file with id 17)
    • -
    • {{dmsf(17,File)}} (link to file with id 17 with link text "File")
    • -
    • {{dmsf(17,File,10)}} (link to file with id 17 with link text "File" and link pointing to revision 10)
    • -
    • {{dmsff(5)}} (link to folder with id 5)
    • -
    • {{dmsff(5,Folder)}} (link to folder with id 5 with link text "Folder")
    • +
    • {{dmsf(17)}} (a link to the file with id 17)
    • +
    • {{dmsf(17, File)}} (a link to the file with id 17 with the link text "File")
    • +
    • {{dmsf(17, File, 10)}} (a link to the file with id 17 with the link text "File" and the link pointing to the revision 10)
    • +
    • {{dmsfd(17)}} (a link to the description of the file with id 17)
    • +
    • {{dmsff(5)}} (a link to the folder with id 5)
    • +
    • {{dmsff(5, Folder)}} (a link to the folder with id 5 with the link text "Folder")
    The DMSF file/revision id can be found in the link for file/revision download from within Redmine.
    The DMSF folder id can be found in the link when opening folders within Redmine. @@ -152,16 +153,24 @@ Before installing ensure that the Redmine instance is stopped. 6. You should configure plugin via Redmine interface: Administration -> Plugins -> DMSF -> Configure 7. Assign DMSF permissions to appropriate roles 8. There are two rake tasks: + a) To convert documents from the standard Redmine document module + Available options: + * project => id or identifier of project (defaults to all projects) * dry => true or false (default false) to perform just check without any conversion * invalid=replace => to perform document title invalid characters replacement for '-' + Example: + rake redmine:dmsf_convert_documents project=test RAILS_ENV="production" + b) To alert all users who are expected to do an approval in the current approval steps + Example: - rake redmine:dmsf_alert_approvals RAILS_ENV="production" + + rake redmine:dmsf_alert_approvals RAILS_ENV="production" ### Fulltext search (optional) If you want to use fulltext search features, you must setup file content indexing. @@ -174,8 +183,8 @@ It is necessary to index DMSF files with omega before searching attempts to rece This command must be run on regular basis (e.g. from cron) Example of cron job (once per hour at 8th minute): - - `8 * * * * root /usr/bin/ruby redmine_dmsf/extra/xapian_indexer.rb -f` + + 8 * * * * root /usr/bin/ruby redmine_dmsf/extra/xapian_indexer.rb -f See redmine_dmsf/extra/xapian_indexer.rb for help. diff --git a/app/controllers/dmsf_controller.rb b/app/controllers/dmsf_controller.rb index 65e355fe..b91025ff 100644 --- a/app/controllers/dmsf_controller.rb +++ b/app/controllers/dmsf_controller.rb @@ -31,10 +31,12 @@ class DmsfController < ApplicationController before_filter :authorize before_filter :find_folder, :except => [:new, :create, :edit_root, :save_root] 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) @@ -118,6 +120,12 @@ class DmsfController < ApplicationController end @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 @@ -134,7 +142,14 @@ class DmsfController < ApplicationController @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? - end + + respond_to do |format| + format.html { + render :layout => !request.xhr? + } + format.api + end + end def trash @folder_manipulation_allowed = User.current.allowed_to? :folder_manipulation, @project @@ -225,20 +240,15 @@ class DmsfController < ApplicationController end end - def entries_email - if (Rails::VERSION::MAJOR > 3) - @email_params = e_params - else - @email_params = params[:email] - end - if @email_params[:to].strip.blank? + def entries_email + if params[:email][:to].strip.blank? flash.now[:error] = l(:error_email_to_must_be_entered) render :action => 'email_entries' return end - DmsfMailer.send_documents(@project, User.current, @email_params).deliver - File.delete(@email_params['zipped_content']) - flash[:notice] = l(:notice_email_sent, @email_params['to']) + DmsfMailer.send_documents(@project, User.current, params[:email]).deliver + File.delete(params[:email][:zipped_content]) + flash[:notice] = l(:notice_email_sent, params[:email][:to]) redirect_to dmsf_folder_path(:id => @project, :folder_id => @folder) end @@ -249,13 +259,11 @@ class DmsfController < ApplicationController render :action => 'edit' end - def create - if (Rails::VERSION::MAJOR > 3) - @folder = DmsfFolder.new( - params.require(:dmsf_folder).permit(:title, :description, :dmsf_folder_id)) - else - @folder = DmsfFolder.new(params[:dmsf_folder]) - end + def create + @folder = DmsfFolder.new + @folder.title = params[:dmsf_folder][:title] + @folder.description = params[:dmsf_folder][:description] + @folder.dmsf_folder_id = params[:dmsf_folder][:dmsf_folder_id] @folder.project = @project @folder.user = User.current @@ -266,13 +274,26 @@ class DmsfController < ApplicationController end end - if @folder.save - flash[:notice] = l(:notice_folder_created) - redirect_to dmsf_folder_path(:id => @project, :folder_id => @folder) - else - @pathfolder = @parent - render :action => 'edit' - end + saved = @folder.save + + respond_to do |format| + format.js + format.api { + unless saved + render_validation_errors(@folder) + end + } + format.html { + if saved + 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 def edit @@ -587,12 +608,16 @@ class DmsfController < ApplicationController @folder = DmsfFolder.find params[:folder_id] if params[:folder_id].present? rescue DmsfAccessError render_403 + rescue ActiveRecord::RecordNotFound + render_404 end def find_parent @parent = DmsfFolder.visible.find params[:parent_id] if params[:parent_id].present? rescue DmsfAccessError render_403 + rescue ActiveRecord::RecordNotFound + render_404 end def copy_folder(folder) @@ -608,7 +633,5 @@ class DmsfController < ApplicationController :to, :zipped_content, :email, :cc, :subject, :zipped_content => [], :files => []) end - - - -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 613d874c..43a11600 100644 --- a/app/controllers/dmsf_files_controller.rb +++ b/app/controllers/dmsf_files_controller.rb @@ -37,6 +37,7 @@ class DmsfFilesController < ApplicationController @revision = @file.last_revision check_project(@revision.file) begin + raise ActionController::MissingFile if @file.deleted log_activity('downloaded') access = DmsfFileRevisionAccess.new access.user = User.current @@ -47,8 +48,7 @@ class DmsfFilesController < ApplicationController :filename => filename_for_content_disposition(@revision.name), :type => @revision.detect_content_type, :disposition => 'inline') - rescue ActionController::MissingFile => e - logger.error e.message + rescue ActionController::MissingFile render_404 end end @@ -67,17 +67,18 @@ class DmsfFilesController < ApplicationController end check_project(@revision.file) begin + raise ActionController::MissingFile if @revision.file.deleted log_activity('downloaded') access = DmsfFileRevisionAccess.new access.user = User.current access.revision = @revision - access.action = DmsfFileRevisionAccess::DownloadAction + access.action = DmsfFileRevisionAccess::DownloadAction + access.save! send_file(@revision.disk_file, :filename => filename_for_content_disposition(@revision.name), :type => @revision.detect_content_type, :disposition => 'attachment') - rescue ActionController::MissingFile => e - logger.error e.message + rescue ActionController::MissingFile render_404 end return @@ -302,7 +303,7 @@ class DmsfFilesController < ApplicationController end def find_revision - @revision = DmsfFileRevision.visible.find(params[:id]) + @revision = DmsfFileRevision.visible.find params[:id] @file = @revision.file @project = @file.project rescue ActiveRecord::RecordNotFound diff --git a/app/controllers/dmsf_links_controller.rb b/app/controllers/dmsf_links_controller.rb index c960128b..a49e34f2 100644 --- a/app/controllers/dmsf_links_controller.rb +++ b/app/controllers/dmsf_links_controller.rb @@ -1,3 +1,5 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # # Copyright (C) 2011-15 Karel Pičman @@ -24,12 +26,9 @@ class DmsfLinksController < ApplicationController before_filter :find_link_project before_filter :authorize - def new - if (Rails::VERSION::MAJOR > 3) - @dmsf_link = DmsfLink.new(l_params) - else - @dmsf_link = DmsfLink.new(:project_id => params[:project_id]) - end + def new + @dmsf_link = DmsfLink.new + @dmsf_link.project_id = params[:project_id] if params[:dmsf_link].present? # Reload diff --git a/app/controllers/dmsf_upload_controller.rb b/app/controllers/dmsf_upload_controller.rb index 0c531d1e..4063ab55 100644 --- a/app/controllers/dmsf_upload_controller.rb +++ b/app/controllers/dmsf_upload_controller.rb @@ -26,10 +26,12 @@ class DmsfUploadController < ApplicationController before_filter :find_project before_filter :authorize - before_filter :find_folder, :except => [:upload_file] + before_filter :find_folder, :except => [:upload_file, :upload, :commit] helper :all helper :dmsf_workflows + + accept_api_auth :upload, :commit def upload_files uploaded_files = params[:attachments] @@ -51,26 +53,23 @@ class DmsfUploadController < ApplicationController end # async single file upload handling - def upload_file - if (Rails::VERSION::MAJOR > 3) - @tempfile = params.require(:file) - else - @tempfile = params[:file] - end + def upload_file + @tempfile = params[:file] unless @tempfile.original_filename render_404 return end @disk_filename = DmsfHelper.temp_filename(@tempfile.original_filename) - File.open("#{DmsfHelper.temp_dir}/#{@disk_filename}", 'wb') do |f| - while (buffer = @tempfile.read(8192)) - f.write(buffer) - end + begin + FileUtils.cp @tempfile.path, "#{DmsfHelper.temp_dir}/#{@disk_filename}" + rescue Exception => e + Rails.logger.error e.message end if File.size("#{DmsfHelper.temp_dir}/#{@disk_filename}") <= 0 begin - File.delete("#{DmsfHelper.temp_dir}/#{@disk_filename}") - rescue + File.delete "#{DmsfHelper.temp_dir}/#{@disk_filename}" + rescue Exception => e + Rails.logger.error e.message end render :layout => nil, :json => { :jsonrpc => '2.0', :error => { @@ -85,14 +84,54 @@ class DmsfUploadController < ApplicationController end end - def commit_files - if (Rails::VERSION::MAJOR > 3) - commited_files = params.require(:commited_files) - else - commited_files = params[:commited_files] + # REST API document upload + def upload + unless request.content_type == 'application/octet-stream' + render :nothing => true, :status => 406 + return end + + @attachment = Attachment.new(:file => request.raw_post) + @attachment.author = User.current + @attachment.filename = params[:filename].presence || Redmine::Utils.random_hex(16) + saved = @attachment.save + + respond_to do |format| + format.js + format.api { + if saved + render :action => 'upload', :status => :created + else + render_validation_errors(@attachment) + end + } + end + end + + def commit_files + commit_files_internal params[:commited_files] + end + + # REST API file commit + def commit + attachments = params[:attachments] + if attachments && attachments.is_a?(Hash) + @folder = DmsfFolder.visible.find_by_id attachments[:folder_id].to_i if attachments[:folder_id].present? + # standard file input uploads + uploaded_files = attachments.select { |key, value| key == 'uploaded_file'} + uploaded_files.each_value do |uploaded_file| + upload = DmsfUpload.create_from_uploaded_attachment(@project, @folder, uploaded_file) + uploaded_file[:disk_filename] = upload.disk_filename + end + end + commit_files_internal uploaded_files + end + + private + + def commit_files_internal(commited_files) if commited_files && commited_files.is_a?(Hash) - files = [] + @files = [] failed_uploads = [] commited_files.each_value do |commited_file| name = commited_file[:name] @@ -146,13 +185,6 @@ class DmsfUploadController < ApplicationController new_revision.mime_type = Redmine::MimeType.of(new_revision.name) new_revision.size = File.size(commited_disk_filepath) - file_upload = File.new(commited_disk_filepath, 'rb') - unless file_upload - failed_uploads.push(commited_file) - flash[:error] = l(:error_file_commit_require_uploaded_file) - next - end - if file.locked? begin file.unlock! @@ -179,23 +211,21 @@ class DmsfUploadController < ApplicationController end if new_revision.save - new_revision.assign_workflow(commited_file[:dmsf_workflow_id]) - new_revision.copy_file_content(file_upload) - file_upload.close - File.delete(commited_disk_filepath) + new_revision.assign_workflow(commited_file[:dmsf_workflow_id]) + FileUtils.mv(commited_disk_filepath, new_revision.disk_file) file.set_last_revision new_revision - files.push(file) + @files.push(file) else failed_uploads.push(commited_file) end end - unless files.empty? - files.each { |file| log_activity(file, 'uploaded') if file } + unless @files.empty? + @files.each { |file| log_activity(file, 'uploaded') if file } if (@folder && @folder.notification?) || (!@folder && @project.dmsf_notification?) begin - recipients = DmsfMailer.get_notify_users(@project, files) + recipients = DmsfMailer.get_notify_users(@project, @files) recipients.each do |u| - DmsfMailer.files_updated(u, @project, files).deliver + DmsfMailer.files_updated(u, @project, @files).deliver end if Setting.plugin_redmine_dmsf[:dmsf_display_notified_recipients] == '1' unless recipients.empty? @@ -213,10 +243,15 @@ class DmsfUploadController < ApplicationController flash[:warning] = l(:warning_some_files_were_not_commited, :files => failed_uploads.map{|u| u['name']}.join(', ')) end end - redirect_to dmsf_folder_path(:id => @project, :folder_id => @folder) + respond_to do |format| + format.js + format.api { + render_validation_errors(failed_uploads) unless failed_uploads.empty? + } + format.html { redirect_to dmsf_folder_path(:id => @project, :folder_id => @folder) } + 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}" diff --git a/app/controllers/dmsf_workflows_controller.rb b/app/controllers/dmsf_workflows_controller.rb index 706f856e..e360e9d7 100644 --- a/app/controllers/dmsf_workflows_controller.rb +++ b/app/controllers/dmsf_workflows_controller.rb @@ -238,7 +238,7 @@ class DmsfWorkflowsController < ApplicationController end def update - if request.put? && params[:dmsf_workflow] && @dmsf_workflow.update_attributes( + if params[:dmsf_workflow] && @dmsf_workflow.update_attributes( {:name => params[:dmsf_workflow][:name]}) flash[:notice] = l(:notice_successful_update) if @project @@ -246,7 +246,8 @@ class DmsfWorkflowsController < ApplicationController else redirect_to dmsf_workflows_path end - else + else + flash[:error] = @dmsf_workflow.errors.full_messages.to_sentence redirect_to dmsf_workflow_path(@dmsf_workflow) end end @@ -269,27 +270,40 @@ class DmsfWorkflowsController < ApplicationController render :layout => false end + def new_step + @steps = @dmsf_workflow.dmsf_workflow_steps.collect{|s| s.step}.uniq + + respond_to do |format| + format.html + format.js + end + end + def add_step - if request.post? - users = User.where(:id => params[:user_ids]) + if request.post? if params[:step] == '0' step = @dmsf_workflow.dmsf_workflow_steps.collect{|s| s.step}.uniq.count + 1 else step = params[:step].to_i end operator = (params[:commit] == l(:dmsf_and)) ? DmsfWorkflowStep::OPERATOR_AND : DmsfWorkflowStep::OPERATOR_OR - users.each do |user| - ws = DmsfWorkflowStep.new( - :dmsf_workflow_id => @dmsf_workflow.id, - :step => step, - :user_id => user.id, - :operator => operator) - if ws.save - @dmsf_workflow.dmsf_workflow_steps << ws - else - flash[:error] = l(:error_workflow_assign) + users = User.where(:id => params[:user_ids]) + if users.count > 0 + users.each do |user| + ws = DmsfWorkflowStep.new( + :dmsf_workflow_id => @dmsf_workflow.id, + :step => step, + :user_id => user.id, + :operator => operator) + if ws.save + @dmsf_workflow.dmsf_workflow_steps << ws + else + flash[:error] = @dmsf_workflow.errors.full_messages.to_sentence + end end - end + else + flash[:error] = l(:error_workflow_assign) + end end respond_to do |format| format.html diff --git a/app/helpers/dmsf_workflows_helper.rb b/app/helpers/dmsf_workflows_helper.rb index ad631d6a..90ca653a 100644 --- a/app/helpers/dmsf_workflows_helper.rb +++ b/app/helpers/dmsf_workflows_helper.rb @@ -1,6 +1,8 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2011-14 Karel Picman +# Copyright (C) 2011-15 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 @@ -23,11 +25,15 @@ module DmsfWorkflowsHelper principal_count = scope.count principal_pages = Redmine::Pagination::Paginator.new principal_count, 10, params['page'] principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all - - if dmsf_workflow_step_assignment_id - s = content_tag('div', principals_radio_button_tags('step_action', principals), :id => 'users_for_delegate') - else - s = content_tag('div', principals_check_box_tags('user_ids[]', principals), :id => 'users') + + if dmsf_workflow_step_assignment_id + s = content_tag('div', + content_tag('div', principals_radio_button_tags('user_ids[]', principals), :id => 'users_for_delegate'), + :class => 'objects-selection') + else + s = content_tag('div', + content_tag('div', principals_check_box_tags('user_ids[]', principals), :id => 'users'), + :class => 'objects-selection') end links = pagination_links_full(principal_pages, principal_count, :per_page_links => false) {|text, parameters, options| diff --git a/app/models/dmsf_file.rb b/app/models/dmsf_file.rb index f6ac3dd9..cafe32d1 100644 --- a/app/models/dmsf_file.rb +++ b/app/models/dmsf_file.rb @@ -29,11 +29,8 @@ end class DmsfFile < ActiveRecord::Base unloadable - - include RedmineDmsf::Lockable - - attr_accessor :event_description - attr_accessible :project + + include RedmineDmsf::Lockable belongs_to :project belongs_to :folder, :class_name => 'DmsfFolder', :foreign_key => 'dmsf_folder_id' @@ -63,14 +60,13 @@ class DmsfFile < ActiveRecord::Base if (Rails::VERSION::MAJOR > 3) accepts_nested_attributes_for :revisions, :locks, :referenced_links end - - if (Rails::VERSION::MAJOR > 3) - scope :visible, -> { where(deleted: false) } - scope :deleted, -> { where(deleted: true) } - else - scope :visible, where(:deleted => false) - scope :deleted, where(:deleted => true) - end + + scope :visible, lambda { |*args| + where(deleted: false) + } + scope :deleted, lambda { |*args| + where(deleted: true) + } validates :name, :presence => true validates_format_of :name, :with => DmsfFolder.invalid_characters, @@ -84,11 +80,29 @@ class DmsfFile < ActiveRecord::Base existing_file.nil? || existing_file.id == self.id end - acts_as_event :title => Proc.new {|o| "#{o.title} - #{o.name}"}, - :description => Proc.new {|o| o.description }, - :url => Proc.new {|o| {:controller => 'dmsf_files', :action => 'show', :id => o}}, - :datetime => Proc.new {|o| o.updated_at }, - :author => Proc.new {|o| o.last_revision.user } + acts_as_event :title => Proc.new { |o| o.name }, + :description => Proc.new { |o| + if (Rails::VERSION::MAJOR > 3) + desc = Redmine::Search.cache_store.fetch("DmsfFile-#{o.id}") + if desc + Redmine::Search.cache_store.delete("DmsfFile-#{o.id}") + else + desc = o.description + desc += " / #{o.last_revision.comment}" if o.last_revision.comment.present? + end + else + desc = o.description + desc += " / #{o.last_revision.comment}" if o.last_revision.comment.present? + end + desc + }, + :url => Proc.new { |o| {:controller => 'dmsf_files', :action => 'show', :id => o} }, + :datetime => Proc.new { |o| o.updated_at }, + :author => Proc.new { |o| o.last_revision.user } + + acts_as_searchable :columns => ["#{table_name}.name", "#{DmsfFileRevision.table_name}.title", "#{DmsfFileRevision.table_name}.description", "#{DmsfFileRevision.table_name}.comment"], + :project_key => 'project_id', + :date_column => "#{table_name}.updated_at" before_create :default_values def default_values @@ -176,8 +190,8 @@ class DmsfFile < ActiveRecord::Base end def description - self.last_revision ? self.last_revision.description : '' - end + self.last_revision ? self.last_revision.description : '' + end def version self.last_revision ? self.last_revision.version : '0' @@ -292,39 +306,39 @@ class DmsfFile < ActiveRecord::Base end # To fulfill searchable module expectations - def self.search(tokens, projects = nil, options = {}) + def self.search(tokens, projects = nil, options = {}, user = User.current) tokens = [] << tokens unless tokens.is_a?(Array) - projects = [] << projects unless projects.nil? || projects.is_a?(Array) - - find_options = {} - find_options[:order] = 'dmsf_files.updated_at ' + (options[:before] ? 'DESC' : 'ASC') + projects = [] << projects if projects.is_a?(Project) + project_ids = projects.collect(&:id) if projects + find_options = {} limit_options = {} limit_options[:limit] = options[:limit] if options[:limit] if options[:offset] limit_options[:conditions] = '(dmsf_files.updated_at ' + (options[:before] ? '<' : '>') + "'#{connection.quoted_date(options[:offset])}')" end - - columns = %w(dmsf_files.name dmsf_file_revisions.title dmsf_file_revisions.description) - columns = ['dmsf_file_revisions.title'] if options[:titles_only] - + + if options[:titles_only] + columns = [searchable_options[:columns][1]] + else + columns = searchable_options[:columns] + end + token_clauses = columns.collect {|column| "(LOWER(#{column}) LIKE ?)"} sql = (['(' + token_clauses.join(' OR ') + ')'] * tokens.size).join(options[:all_words] ? ' AND ' : ' OR ') find_options[:conditions] = [sql, * (tokens.collect {|w| "%#{w.downcase}%"} * token_clauses.size).sort] project_conditions = [] - project_conditions << Project.allowed_to_condition(User.current, :view_dmsf_files) - project_conditions << "#{DmsfFile.table_name}.project_id IN (#{projects.collect(&:id).join(',')})" unless projects.nil? + project_conditions << Project.allowed_to_condition(user, :view_dmsf_files) + project_conditions << "#{DmsfFile.table_name}.project_id IN (#{project_ids.join(',')})" if project_ids.present? - results = [] - results_count = 0 + results = [] - includes(:project, :revisions). - where(project_conditions.join(' AND ') + " AND #{DmsfFile.table_name}.deleted = :false", {:false => false}).scoping do - where(find_options[:conditions]).order(find_options[:order]).scoping do - results_count = count(:all) - results = find(:all, limit_options) + visible.joins(:project, :revisions). + where(project_conditions.join(' AND ')).scoping do + where(find_options[:conditions]).scoping do + results = where(limit_options).uniq end end @@ -381,7 +395,7 @@ class DmsfFile < ActiveRecord::Base next if dmsf_attrs.length == 0 || id_attribute == 0 next unless results.select{|f| f.id.to_s == id_attribute}.empty? - dmsf_file = DmsfFile.where(limit_options[:conditions]).where(:id => id_attribute, :deleted => false).first + dmsf_file = DmsfFile.visible.where(limit_options[:conditions]).where(:id => id_attribute).first if dmsf_file if options[:offset] @@ -390,29 +404,17 @@ class DmsfFile < ActiveRecord::Base else next if dmsf_file.updated_at > options[:offset] end - end + end - allowed = User.current.allowed_to?(:view_dmsf_files, dmsf_file.project) - project_included = false - project_included = true unless projects - unless project_included - projects.each do |x| - if x.is_a?(ActiveRecord::Relation) - project_included = x.first.id == dmsf_file.project.id - else - if dmsf_file.project - project_included = x[:id] == dmsf_file.project.id - else - project_included = false - end - end + if user.allowed_to?(:view_dmsf_files, dmsf_file.project) && + (project_ids.blank? || (project_ids.include?(dmsf_file.project.id))) + if (Rails::VERSION::MAJOR > 3) + Redmine::Search.cache_store.write("DmsfFile-#{dmsf_file.id}", + dochash['sample'].force_encoding('UTF-8')) if dochash['sample'] + else + dmsf_file.event_description = dochash['sample'].force_encoding('UTF-8') if dochash['sample'] end - end - - if (allowed && project_included) - dmsf_file.event_description = dochash['sample'].force_encoding('UTF-8') if dochash['sample'] - results.push(dmsf_file) - results_count += 1 + results << dmsf_file end end end @@ -420,14 +422,14 @@ class DmsfFile < ActiveRecord::Base end end end - - [results, results_count] + + [results, results.count] end def self.search_result_ranks_and_ids(tokens, user = User.current, projects = nil, options = {}) - r = self.search(tokens, projects, options)[0] - r.each_index { |x| [x, r[1][x]] } - end + r = self.search(tokens, projects, options, user)[0] + r.map{ |f| [f.updated_at.to_i, f.id]} + end def display_name if self.name.length > 50 @@ -436,4 +438,4 @@ class DmsfFile < ActiveRecord::Base self.name end -end +end \ No newline at end of file diff --git a/app/models/dmsf_folder.rb b/app/models/dmsf_folder.rb index d2b032ca..3da4b799 100644 --- a/app/models/dmsf_folder.rb +++ b/app/models/dmsf_folder.rb @@ -25,9 +25,7 @@ class DmsfFolder < ActiveRecord::Base include RedmineDmsf::Lockable cattr_reader :invalid_characters - @@invalid_characters = /\A[^\/\\\?":<>]*\z/ - - attr_accessible :title, :description, :dmsf_folder_id, :project + @@invalid_characters = /\A[^\/\\\?":<>]*\z/ belongs_to :project belongs_to :folder, :class_name => 'DmsfFolder', :foreign_key => 'dmsf_folder_id' @@ -39,56 +37,67 @@ class DmsfFolder < ActiveRecord::Base has_many :files, :class_name => 'DmsfFile', :foreign_key => 'dmsf_folder_id', :dependent => :destroy if (Rails::VERSION::MAJOR > 3) - has_many :folder_links, -> { where target_type: DmsfFolder.model_name }, + 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.model_name }, + 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' }, + has_many :url_links, -> { where :target_type => 'DmsfUrl' }, :class_name => 'DmsfLink', :foreign_key => 'dmsf_folder_id', :dependent => :destroy - has_many :referenced_links, -> { where target_type: DmsfFolder.model_name }, + 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 else has_many :folder_links, :class_name => 'DmsfLink', :foreign_key => 'dmsf_folder_id', - :conditions => {:target_type => DmsfFolder.model_name}, :dependent => :destroy + :conditions => { :target_type => 'DmsfFolder' }, :dependent => :destroy has_many :file_links, :class_name => 'DmsfLink', :foreign_key => 'dmsf_folder_id', - :conditions => {:target_type => DmsfFile.model_name}, :dependent => :destroy + :conditions => { :target_type => 'DmsfFile' }, :dependent => :destroy has_many :url_links, :class_name => 'DmsfLink', :foreign_key => 'dmsf_folder_id', - :conditions => {:target_type => 'DmsfUrl'}, :dependent => :destroy + :conditions => { :target_type => 'DmsfUrl' }, :dependent => :destroy has_many :referenced_links, :class_name => 'DmsfLink', :foreign_key => 'target_id', - :conditions => {:target_type => DmsfFolder.model_name}, :dependent => :destroy + :conditions => { :target_type => 'DmsfFolder' }, :dependent => :destroy has_many :locks, :class_name => 'DmsfLock', :foreign_key => 'entity_id', :order => "#{DmsfLock.table_name}.updated_at DESC", :conditions => {:entity_type => 1}, :dependent => :destroy end - - if (Rails::VERSION::MAJOR > 3) - scope :visible, -> { where(deleted: false) } - scope :deleted, -> { where(deleted: true) } - else - scope :visible, where(:deleted => false) - scope :deleted, where(:deleted => true) - end + + scope :visible, lambda { |*args| + where(deleted: false) + } + scope :deleted, lambda { |*args| + where(deleted: true) + } acts_as_customizable + + if (Rails::VERSION::MAJOR > 3) + 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) + else + acts_as_searchable :columns => ["#{self.table_name}.title", "#{self.table_name}.description"], + :project_key => 'project_id', + :date_column => 'updated_at', + :permission => :view_dmsf_files, + :include => :project + end + + 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}}, + :datetime => Proc.new {|o| o.updated_at }, + :author => Proc.new {|o| o.user } validates :title, :presence => true validates_uniqueness_of :title, :scope => [:dmsf_folder_id, :project_id, :deleted] - validates_format_of :title, :with => @@invalid_characters, :message => l(:error_contains_invalid_character) - validate :check_cycle - 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}}, - :datetime => Proc.new {|o| o.updated_at }, - :author => Proc.new {|o| o.user } - before_create :default_values def default_values @notifications = Setting.plugin_redmine_dmsf['dmsf_default_notifications'] @@ -280,50 +289,7 @@ class DmsfFolder < ActiveRecord::Base def available_custom_fields DmsfFileRevisionCustomField.all end - - # To fullfill searchable module expectations - def self.search(tokens, projects = nil, options = {}) - tokens = [] << tokens unless tokens.is_a?(Array) - projects = [] << projects unless projects.nil? || projects.is_a?(Array) - - find_options = {} - find_options[:order] = 'dmsf_folders.updated_at ' + (options[:before] ? 'DESC' : 'ASC') - - limit_options = {} - limit_options[:limit] = options[:limit] if options[:limit] - if options[:offset] - limit_options[:conditions] = '(dmsf_folders.updated_at ' + (options[:before] ? '<' : '>') + "'#{connection.quoted_date(options[:offset])}')" - end - - columns = options[:titles_only] ? ['dmsf_folders.title'] : ['dmsf_folders.title', 'dmsf_folders.description'] - - token_clauses = columns.collect {|column| "(LOWER(#{column}) LIKE ?)"} - - sql = (['(' + token_clauses.join(' OR ') + ')'] * tokens.size).join(options[:all_words] ? ' AND ' : ' OR ') - find_options[:conditions] = [sql, * (tokens.collect {|w| "%#{w.downcase}%"} * token_clauses.size).sort] - - project_conditions = [] - project_conditions << (Project.allowed_to_condition(User.current, :view_dmsf_files)) - project_conditions << "project_id IN (#{projects.collect(&:id).join(',')})" if projects - - results = [] - results_count = 0 - - includes(:project). - where(project_conditions.join(' AND ')).scoping do - where(find_options[:conditions]).order(find_options[:order]).scoping do - results_count = count(:all) - results = find(:all, limit_options) - end - end - - [results, results_count] - end - def self.search_result_ranks_and_ids(tokens, user = User.current, projects = nil, options = {}) - self.search(tokens, :user => user, :projects => projects, :options => options) - end - def modified last_update = updated_at subfolders.each do |subfolder| @@ -343,6 +309,15 @@ class DmsfFolder < ActiveRecord::Base end last_update end + + # Number of items in the folder + def items + subfolders.visible.count + + files.visible.count + + folder_links.visible.count + + file_links.visible.count + + url_links.visible.count + end private @@ -355,4 +330,4 @@ class DmsfFolder < ActiveRecord::Base end end -end +end \ No newline at end of file diff --git a/app/models/dmsf_link.rb b/app/models/dmsf_link.rb index d34d76fc..f21a5864 100644 --- a/app/models/dmsf_link.rb +++ b/app/models/dmsf_link.rb @@ -95,15 +95,13 @@ class DmsfLink < ActiveRecord::Base end def path - if self.target_type == DmsfFile.model_name - file = self.target_file - path = file.dmsf_path.map { |element| element.is_a?(DmsfFile) ? element.name : element.title }.join('/') if file - else - folder = self.target_folder - path = folder.dmsf_path_str if folder + if self.target_type == DmsfFile.model_name + path = self.target_file.dmsf_path.map { |element| element.is_a?(DmsfFile) ? element.name : element.title }.join('/') if self.target_file + 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 && path - if path.length > 50 + path.insert(0, "#{self.target_project.name}:") if self.project_id != self.target_project_id + if path && path.length > 50 return "#{path[0, 25]}...#{path[-25, 25]}" end path diff --git a/app/models/dmsf_mailer.rb b/app/models/dmsf_mailer.rb index 2acb69ec..55c3029f 100644 --- a/app/models/dmsf_mailer.rb +++ b/app/models/dmsf_mailer.rb @@ -1,7 +1,9 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # # Copyright (C) 2011 Vít Jonáš -# Copyright (C) 2011-14 Karel Pičman +# Copyright (C) 2011-15 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 @@ -114,7 +116,7 @@ class DmsfMailer < Mailer end end - notify_members.collect { |m| m.user } + 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 41fc5145..31ae5566 100644 --- a/app/models/dmsf_upload.rb +++ b/app/models/dmsf_upload.rb @@ -45,13 +45,7 @@ class DmsfUpload :original_filename => a.filename, :comment => uploaded_file[:description] } - File.open(a.diskfile, 'rb') do |fr| - File.open("#{DmsfHelper.temp_dir}/#{uploaded[:disk_filename]}", 'wb') do |fw| - while (buffer = fr.read(8192)) - fw.write(buffer) - end - end - end + FileUtils.mv(a.diskfile, "#{DmsfHelper.temp_dir}/#{uploaded[:disk_filename]}") a.destroy DmsfUpload.new(project, folder, uploaded) end diff --git a/app/views/dmsf/_dir.html.erb b/app/views/dmsf/_dir.html.erb index 574e3b6c..dbce36b0 100644 --- a/app/views/dmsf/_dir.html.erb +++ b/app/views/dmsf/_dir.html.erb @@ -1,7 +1,9 @@ <%#= +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2011-14 Karel Pičman +# Copyright (C) 2011-15 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 @@ -18,8 +20,8 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. %> -<% locked_for_user = subfolder.locked_for_user? %> -<% locked = subfolder.locked? %> +<% locked_for_user = subfolder && subfolder.locked_for_user? %> +<% locked = subfolder && subfolder.locked? %> <%= check_box_tag(name, id, false, :title => l(:title_check_for_zip_download_or_email)) %> @@ -30,11 +32,11 @@ <% if link %>
    <%= link.path %>
    <% else %> -
    [<%= subfolder.files.visible.count + subfolder.file_links.visible.count %>]
    +
    [<%= subfolder.items %>]
    <% end %> -<%= format_time(subfolder.modified) %> +<%= format_time(subfolder.modified) if subfolder %> <% if locked_for_user %> <% if subfolder.lock.reverse[0].user %> <%= link_to('', @@ -52,20 +54,24 @@ -<%= h(subfolder.user) %> +<%= h(subfolder.user) if subfolder %> <% if @folder_manipulation_allowed %>
    <% unless locked %> <%= link_to('', edit_dmsf_path(:id => project, :folder_id => subfolder), - :title => l(:link_edit, :title => h(subfolder.title)), + :title => l(:link_edit, :title => subfolder ? h(subfolder.title) : project.name), :class => 'icon icon-edit') %> - <%= link_to('', - lock_dmsf_path(:id => project, :folder_id => subfolder), - :title => l(:title_lock_file), - :class => 'icon icon-dmsf-lock') %> - <% if subfolder.notification %> + <% if subfolder %> + <%= link_to('', + lock_dmsf_path(:id => project, :folder_id => subfolder), + :title => l(:title_lock_file), + :class => 'icon icon-dmsf-lock') %> + <% else %> + + <% end %> + <% if (subfolder && subfolder.notification) || (!subfolder && project.dmsf_notification) %> <%= link_to('', notify_deactivate_dmsf_path(:id => project, :folder_id => subfolder), :title => l(:title_notifications_active_deactivate), @@ -104,5 +110,5 @@ 0 0 -<%= subfolder.updated_at.to_i %> +<%= subfolder.modified.to_i if subfolder %> 0 \ No newline at end of file diff --git a/app/views/dmsf/_dir_trash.html.erb b/app/views/dmsf/_dir_trash.html.erb index 31f6a452..e708653b 100644 --- a/app/views/dmsf/_dir_trash.html.erb +++ b/app/views/dmsf/_dir_trash.html.erb @@ -1,4 +1,6 @@ <%#= +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # # Copyright (C) 2011-15 Karel Pičman @@ -27,12 +29,12 @@ <% if link %>
    <%= link.path %>
    <% else %> -
    [<%= subfolder.files.visible.count + subfolder.file_links.visible.count %>]
    +
    [<%= subfolder.items %>]
    <% end %> - <%= format_time(subfolder.updated_at) %> + <%= format_time(subfolder.modified) if subfolder %> @@ -54,5 +56,5 @@ 0 0 -<%= subfolder.updated_at.to_i %> +<%= subfolder.modified.to_i if subfolder %> 0 \ No newline at end of file diff --git a/app/views/dmsf/_file.html.erb b/app/views/dmsf/_file.html.erb index 3e201646..2d9e0058 100644 --- a/app/views/dmsf/_file.html.erb +++ b/app/views/dmsf/_file.html.erb @@ -1,4 +1,6 @@ <%#= +# encode: utf-8 +# # Redmine plugin for Document Management System "Features" # # Copyright (C) 2011-15 Karel Pičman diff --git a/app/views/dmsf/_file_trash.html.erb b/app/views/dmsf/_file_trash.html.erb index 7023f0b2..b00d59cc 100644 --- a/app/views/dmsf/_file_trash.html.erb +++ b/app/views/dmsf/_file_trash.html.erb @@ -20,13 +20,10 @@ <%= check_box_tag(name, id, false, :title => l(:title_check_for_restore_or_delete)) %> - - <% file_download_url = url_for({:only_path => false, :controller => :dmsf_files, :action => 'show', :id => file, :download => ''}) %> - <%= link_to(h(title), - file_download_url, - :class => "icon icon-file #{DmsfHelper.filetype_css(file.name)}", - :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_download_url}") %> + + <%= content_tag(:span, h(title), + :title => h(title), + :class => "icon icon-file #{DmsfHelper.filetype_css(file.name)}") %>
    <%= h(link ? link.path : file.display_name) %>
    <%= number_to_human_size(file.last_revision.size) %> diff --git a/app/views/dmsf/_url.html.erb b/app/views/dmsf/_url.html.erb index 0b4712b5..15699e0b 100644 --- a/app/views/dmsf/_url.html.erb +++ b/app/views/dmsf/_url.html.erb @@ -1,7 +1,9 @@ <%#= +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2011-14 Karel Pičman +# Copyright (C) 2011-15 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 @@ -55,5 +57,5 @@ 1 - - +link.updated_at.to_i + \ No newline at end of file diff --git a/app/views/dmsf/_url_trash.html.erb b/app/views/dmsf/_url_trash.html.erb index b8ff5a6b..be7ebe7e 100644 --- a/app/views/dmsf/_url_trash.html.erb +++ b/app/views/dmsf/_url_trash.html.erb @@ -1,4 +1,6 @@ <%#= +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # # Copyright (C) 2011-15 Karel Pičman @@ -50,5 +52,5 @@ 1 - - +link.updated_at.to_i + \ No newline at end of file diff --git a/app/views/dmsf/create.api.rsb b/app/views/dmsf/create.api.rsb new file mode 100644 index 00000000..94caf8cc --- /dev/null +++ b/app/views/dmsf/create.api.rsb @@ -0,0 +1,4 @@ +api.dmsf_folder do + api.id @folder.id + api.title @folder.title +end \ No newline at end of file diff --git a/app/views/dmsf/show.api.rsb b/app/views/dmsf/show.api.rsb new file mode 100644 index 00000000..542a39f4 --- /dev/null +++ b/app/views/dmsf/show.api.rsb @@ -0,0 +1,32 @@ +api.dmsf do + api.array :dmsf_folders, api_meta(:total_count => @subfolders.size) do + @subfolders.each do |folder| + api.folder do + api.id folder.id + api.title folder.title + end + end + end + + api.array :dmsf_files, api_meta(:total_count => @files.size) do + @files.each do |file| + api.file do + api.id file.id + api.name file.name + end + end + end + + api.array :dmsf_links, api_meta(:total_count => @dir_links.size + @file_links.size + @url_links.size) do + (@dir_links + @file_links + @url_links).each do |link| + api.link do + api.id link.id + api.name link.name + api.target_type link.target_type + api.target_id link.target_id + api.target_project_id link.target_project_id + api.external_url link.external_url if link.external_url.present? + end + end + end +end \ No newline at end of file diff --git a/app/views/dmsf/show.html.erb b/app/views/dmsf/show.html.erb index 2adadf82..4e76ba60 100644 --- a/app/views/dmsf/show.html.erb +++ b/app/views/dmsf/show.html.erb @@ -153,7 +153,11 @@ :title => subfolder.title }) %> <% end %> - <% @dir_links.each do |link| %> + <% @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 => { @@ -263,7 +267,7 @@ jQuery('div.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 %>"; + return "<%= l(:label_number_of_folders)%>: <%= @subfolders.count + @dir_links.count %>, <%= l(:label_number_of_documents)%>: <%= @files.count + @file_links.count + @url_links.count %>"; } }); diff --git a/app/views/dmsf/trash.html.erb b/app/views/dmsf/trash.html.erb index 8478b707..e7d8a42c 100644 --- a/app/views/dmsf/trash.html.erb +++ b/app/views/dmsf/trash.html.erb @@ -1,4 +1,6 @@ <%#= +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # # Copyright (C) 2011-15 Karel Pičman @@ -184,7 +186,7 @@ jQuery('div.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 %>"; + return "<%= l(:label_number_of_folders)%>: <%= @subfolders.count + @dir_links.count %>, <%= l(:label_number_of_documents)%>: <%= @files.count + @file_links.count + @url_links.count %>"; } }); diff --git a/app/views/dmsf_files/show.api.rsb b/app/views/dmsf_files/show.api.rsb index 8a66d0f3..e846a86d 100644 --- a/app/views/dmsf_files/show.api.rsb +++ b/app/views/dmsf_files/show.api.rsb @@ -1,8 +1,8 @@ -api.file do +api.dmsf_file do api.id @file.id - api.name @file.name + api.name @file.name api.project_id @file.project_id - api.dmsf_folder_id @file.folder ? @file.dmsf_folder_id : -1 - api.version "#{@file.last_revision.major_version}.#{@file.last_revision.minor_version}" + api.dmsf_folder_id @file.folder if @file.dmsf_folder_id + api.version "#{@file.last_revision.major_version}.#{@file.last_revision.minor_version}" if @file.last_revision api.content_url url_for(:controller => :dmsf_files, :action => 'show', :download => '', :id => @file, :only_path => false) end \ No newline at end of file diff --git a/app/views/dmsf_files/show.html.erb b/app/views/dmsf_files/show.html.erb index e9c0b6f0..aec16f88 100644 --- a/app/views/dmsf_files/show.html.erb +++ b/app/views/dmsf_files/show.html.erb @@ -1,4 +1,6 @@ <%#= +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # # Copyright (C) 2011 Vít Jonáš @@ -83,12 +85,12 @@ delete_revision_path(revision), :data => {:confirm => l(:text_are_you_sure)}, :title => l(:title_delete_revision), - :class => 'icon icon-dmsf-rev-delete' if @file_delete_allowed %> + :class => 'icon icon-dmsf-rev-delete' if @file_delete_allowed && (@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)) %> - <%= link_to(revision.user.name, user_path(revision.user)) %> + <%= link_to(revision.user.name, user_path(revision.user)) if revision.user %>
    diff --git a/app/views/dmsf_upload/commit.api.rsb b/app/views/dmsf_upload/commit.api.rsb new file mode 100644 index 00000000..e5e85426 --- /dev/null +++ b/app/views/dmsf_upload/commit.api.rsb @@ -0,0 +1,8 @@ +api.array :dmsf_files, api_meta(:total_count => @files.size) do + @files.each do |file| + api.file do + api.id file.id + api.name file.name + end + end +end \ No newline at end of file diff --git a/app/views/dmsf_upload/upload.api.rsb b/app/views/dmsf_upload/upload.api.rsb new file mode 100644 index 00000000..0a399ec1 --- /dev/null +++ b/app/views/dmsf_upload/upload.api.rsb @@ -0,0 +1,3 @@ +api.upload do + api.token @attachment.token +end diff --git a/app/views/dmsf_workflows/_new_step_form.html.erb b/app/views/dmsf_workflows/_new_step_form.html.erb new file mode 100644 index 00000000..5157e57f --- /dev/null +++ b/app/views/dmsf_workflows/_new_step_form.html.erb @@ -0,0 +1,36 @@ +<% +# encoding: utf-8 +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2011-15 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. +%> + +
    + <%=l(:label_dmsf_workflow_add_approver)%> +

    <%= label_tag 'user_search', l(:label_user_search) %><%= text_field_tag 'user_search', nil %>

    + <%= javascript_tag "observeSearchfield('user_search', 'users', '#{ escape_javascript autocomplete_for_user_dmsf_workflow_path(@dmsf_workflow, :dmsf_workflow_step_assignment_id => nil, :dmsf_file_revision_id => nil, :project_id => @project ? @project.id : nil) }')" %> + +
    + <%= render_principals_for_new_dmsf_workflow_users(@dmsf_workflow, nil, nil) %> +
    +
    + +
    + <%= l(:label_dmsf_workflow_step) %> + <%= select_tag 'step', dmsf_workflow_steps_options_for_select(@steps), + :id => 'selected_step', :style => "width:100px" %> +
    \ No newline at end of file diff --git a/app/views/dmsf_workflows/_new_step_modal.html.erb b/app/views/dmsf_workflows/_new_step_modal.html.erb new file mode 100644 index 00000000..61ed2c36 --- /dev/null +++ b/app/views/dmsf_workflows/_new_step_modal.html.erb @@ -0,0 +1,31 @@ +<% +# encoding: utf-8 +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2011-15 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. +%> + +

    <%= l(:dmsf_new_step) %>

    + +<%= form_for(:dmsf_workflow, {:url => edit_dmsf_workflow_path(@dmsf_workflow), :method => :post}) do |f| %> + <%= render :partial => 'new_step_form' %> +

    + <%= submit_tag l(:dmsf_and), :id => 'add-step-and' %> + <%= submit_tag l(:dmsf_or), :id => 'add-step-or' %> + <%= submit_tag l(:button_cancel), :name => nil, :onclick => 'hideModal(this);', :type => 'button' %> +

    +<% end %> \ No newline at end of file diff --git a/app/views/dmsf_workflows/_steps.html.erb b/app/views/dmsf_workflows/_steps.html.erb index db08246f..6d282c99 100644 --- a/app/views/dmsf_workflows/_steps.html.erb +++ b/app/views/dmsf_workflows/_steps.html.erb @@ -1,6 +1,8 @@ -<%# Redmine plugin for Document Management System "Features" +<% +# encoding: utf-8 +# Redmine plugin for Document Management System "Features" # -# Copyright (C) 2013 Karel Pičman +# Copyright (C) 2011-15 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 @@ -14,7 +16,8 @@ # # 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 @dmsf_workflow.project %>

    <%= link_to l(:label_dmsf_workflow_plural), settings_project_path(@project, :tab => 'dmsf_workflow') %> » <%=h @dmsf_workflow %>

    @@ -29,67 +32,42 @@
    <% end %> -
    - -
    -<% steps = @dmsf_workflow.dmsf_workflow_steps.collect{|s| s.step}.uniq %> -<% if steps.any? %> - - - - - - - - <% steps.each do |i|%> - - - - - - - <% end; reset_cycle %> - -
    <%= l(:label_dmsf_workflow_step) %><%= l(:label_dmsf_workflow_approval_plural) %><%= l(:button_sort)%> -
    <%= i %> - <% @dmsf_workflow.dmsf_workflow_steps.collect{|s| (s.step == i) ? s : nil}.compact.each_with_index do |step, j| %> - <% if j != 0 %> - <%= step.soperator %>  - <% end %> - <%= link_to_user step.user %> - <% end %> - - <%= reorder_links('workflow_step', {:action => 'edit', :id => @dmsf_workflow, :step => i}, :put) %> - - <%= delete_link edit_dmsf_workflow_path(@dmsf_workflow, :step => i) %> -
    -<% else %> -

    <%= l(:label_no_data) %>

    -<% end %> -
    - -
    - <%= form_for(@dmsf_workflow, :url => edit_dmsf_workflow_path(@dmsf_workflow), - :html => {:method => :post}) do |f| %> -
    <%=l(:label_user_new)%> - -

    <%= label_tag 'user_search', l(:label_user_search) %><%= text_field_tag 'user_search', nil %>

    - <%= javascript_tag "observeSearchfield('user_search', 'users', '#{ escape_javascript autocomplete_for_user_dmsf_workflow_path(@dmsf_workflow, :dmsf_workflow_step_assignment_id => nil, :dmsf_file_revision_id => nil, :project_id => @project ? @project.id : nil) }')" %> - -
    - <%= render_principals_for_new_dmsf_workflow_users(@dmsf_workflow, nil, nil) %> -
    - -

    - <%= l(:label_dmsf_workflow_step) %> - <%= select_tag 'step', - dmsf_workflow_steps_options_for_select(steps), - :id => 'selected_step', :style => "width:100px" %> -

    -

    <%= l(:label_dmsf_workflow_add_approver) %>

    -

    <%= submit_tag l(:dmsf_and) %> <%= l(:label_or) %> <%= submit_tag l(:dmsf_or) %>

    -
    +
    +

    + <%= link_to l(:dmsf_new_step), new_step_dmsf_workflow_path(@dmsf_workflow), :remote => true, :class => 'icon icon-add' %> +

    + <% steps = @dmsf_workflow.dmsf_workflow_steps.collect{|s| s.step}.uniq %> + <% if steps.any? %> + + + + + + + + <% steps.each do |i|%> + + + + + + + <% end; reset_cycle %> + +
    <%= l(:label_dmsf_workflow_step) %><%= l(:label_dmsf_workflow_approval_plural) %><%= l(:button_sort)%> +
    <%= i %> + <% @dmsf_workflow.dmsf_workflow_steps.collect{|s| (s.step == i) ? s : nil}.compact.each_with_index do |step, j| %> + <% if j != 0 %> + <%= step.soperator %>  + <% end %> + <%= link_to_user step.user %> + <% end %> + + <%= reorder_links('workflow_step', {:action => 'edit', :id => @dmsf_workflow, :step => i}, :put) %> + + <%= delete_link edit_dmsf_workflow_path(@dmsf_workflow, :step => i) %> +
    + <% else %> +

    <%= l(:label_no_data) %>

    <% end %> -
    -
    \ No newline at end of file diff --git a/app/views/dmsf_workflows/action.js.erb b/app/views/dmsf_workflows/action.js.erb index 1338d7ac..fe39820b 100644 --- a/app/views/dmsf_workflows/action.js.erb +++ b/app/views/dmsf_workflows/action.js.erb @@ -1,6 +1,6 @@ <%# Redmine plugin for Document Management System "Features" # -# Copyright (C) 2013 Karel Pičman +# Copyright (C) 2011-15 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,5 +17,5 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.%> $('#ajax-modal').html('<%= escape_javascript(render :partial => 'action', :locals => {:workflow => @dmsf_workflow}) %>'); -showModal('ajax-modal', '400px'); +showModal('ajax-modal', '35%'); $('#ajax-modal').addClass('new-action'); \ No newline at end of file diff --git a/app/views/dmsf_workflows/assign.js.erb b/app/views/dmsf_workflows/assign.js.erb index 89693237..eae3c44a 100644 --- a/app/views/dmsf_workflows/assign.js.erb +++ b/app/views/dmsf_workflows/assign.js.erb @@ -1,6 +1,6 @@ <%# Redmine plugin for Document Management System "Features" # -# Copyright (C) 2013 Karel Pičman +# Copyright (C) 2011-15 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,5 +17,5 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.%> $('#ajax-modal').html('<%= escape_javascript(render :partial => 'assign', :locals => {:workflow => @dmsf_workflow}) %>'); -showModal('ajax-modal', '400px'); +showModal('ajax-modal', '30%'); $('#ajax-modal').addClass('assignment'); \ No newline at end of file diff --git a/app/views/dmsf_workflows/log.js.erb b/app/views/dmsf_workflows/log.js.erb index 9131f960..7dc28e91 100644 --- a/app/views/dmsf_workflows/log.js.erb +++ b/app/views/dmsf_workflows/log.js.erb @@ -1,6 +1,6 @@ <%# Redmine plugin for Document Management System "Features" # -# Copyright (C) 2013 Karel Pičman +# Copyright (C) 2011-15 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,5 +17,5 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.%> $('#ajax-modal').html('<%= escape_javascript(render :partial => 'log', :locals => {:workflow => @dmsf_workflow}) %>'); -showModal('ajax-modal', '800px'); +showModal('ajax-modal', '90%'); $('#ajax-modal').addClass('workflow-log'); \ No newline at end of file diff --git a/app/views/dmsf_workflows/new_step.html.erb b/app/views/dmsf_workflows/new_step.html.erb new file mode 100644 index 00000000..8baa7cf3 --- /dev/null +++ b/app/views/dmsf_workflows/new_step.html.erb @@ -0,0 +1,19 @@ +<% +# encoding: utf-8 +# +# Redmine plugin for Kontron customisation +# Copyright (c) 2011-15 Kontron +# Karel Pičman +# +# Repository folders +%> + +

    <%= l(:label_repository_folders) %>

    + +<%= form_for(:repository_folder, {:url => edit_dmsf_workflow_path(@dmsf_workflow), :method => :post}) do |f| %> + <%= render :partial => 'new_step_form' %> +

    + <%= submit_tag l(:dmsf_and), :id => 'add-step-and' %> + <%= submit_tag l(:dmsf_or), :id => 'add-step-or' %> +

    +<% end %> \ No newline at end of file diff --git a/app/views/dmsf_workflows/new_step.js.erb b/app/views/dmsf_workflows/new_step.js.erb new file mode 100644 index 00000000..56600c73 --- /dev/null +++ b/app/views/dmsf_workflows/new_step.js.erb @@ -0,0 +1,20 @@ +<%# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2011-15 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.%> + +$('#ajax-modal').html('<%= escape_javascript(render :partial => 'new_step_modal') %>'); +showModal('ajax-modal', '40%'); \ No newline at end of file diff --git a/assets/images/filetypes/odg.png b/assets/images/filetypes/odg.png index 9c2df410..7a0531ec 100644 Binary files a/assets/images/filetypes/odg.png and b/assets/images/filetypes/odg.png differ diff --git a/assets/images/filetypes/odg_gray.png b/assets/images/filetypes/odg_gray.png index 59f96c73..19448d23 100644 Binary files a/assets/images/filetypes/odg_gray.png and b/assets/images/filetypes/odg_gray.png differ diff --git a/assets/images/filetypes/odp.png b/assets/images/filetypes/odp.png index 234ab9f7..35525120 100644 Binary files a/assets/images/filetypes/odp.png and b/assets/images/filetypes/odp.png differ diff --git a/assets/images/filetypes/odp_gray.png b/assets/images/filetypes/odp_gray.png index da112664..a43b9fa4 100644 Binary files a/assets/images/filetypes/odp_gray.png and b/assets/images/filetypes/odp_gray.png differ diff --git a/assets/images/filetypes/ods.png b/assets/images/filetypes/ods.png index c385a9db..7fac192d 100644 Binary files a/assets/images/filetypes/ods.png and b/assets/images/filetypes/ods.png differ diff --git a/assets/images/filetypes/ods_gray.png b/assets/images/filetypes/ods_gray.png index 3fb218bc..deafde94 100644 Binary files a/assets/images/filetypes/ods_gray.png and b/assets/images/filetypes/ods_gray.png differ diff --git a/assets/images/filetypes/odt.png b/assets/images/filetypes/odt.png index db375748..cf6986d8 100644 Binary files a/assets/images/filetypes/odt.png and b/assets/images/filetypes/odt.png differ diff --git a/assets/images/filetypes/odt_gray.png b/assets/images/filetypes/odt_gray.png index b305e6fe..6bad180e 100644 Binary files a/assets/images/filetypes/odt_gray.png and b/assets/images/filetypes/odt_gray.png differ diff --git a/config/locales/cs.yml b/config/locales/cs.yml index cc12a50e..0ecd5e08 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -22,9 +22,9 @@ cs: dmsf: DMSF - label_dmsf_file_plural: Dmsf soubory - label_dmsf_file_revision_plural: Dmsf document revisions - label_dmsf_file_revision_access_plural: Dmsf document accesses + label_dmsf_file_plural: Dokumenty + 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 warning_file_already_locked: Soubor už je zamčen @@ -166,8 +166,8 @@ cs: notice_entries_deleted: Položky smazány warning_some_entries_were_not_deleted: "Některé položky nebyly smazány: %{entries}" title_delete_checked: Smaž vybrané - title_number_of_files_in_directory: Počet souborů ve složce - title_filename_for_download: Název Zip archívu ke stažení + title_items: položek + title_filename_for_download: Název Zip archivu ke stažení label_number_of_folders: Složky label_number_of_documents: Dokumenty error_file_storage_directory_does_not_exist: Cílová složka neexistuje a nemůže být vytvořena @@ -180,8 +180,8 @@ cs: heading_access_downloads_emails: Stažené/Emaily heading_access_first: První heading_access_last: Poslední - label_dmsf_updated: DMSF změněno - label_dmsf_downloaded: DMSF document downloaded + 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 project_module_dmsf: DMSF warning_no_project_to_copy_file_to: Neexistuje projekt, do kterého můžete kopírovat @@ -191,7 +191,7 @@ cs: field_target_project: Cílový projekt field_target_folder: Cílový adresář title_copy_or_move: Kopírovat/Přesunout - label_dmsf_folder_plural: Dmsf složky + 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_file_cannot_be_moved: Soubor nemůže být přesunut @@ -209,7 +209,7 @@ cs: parent_directory: Nadřazený adresář note_webdav: "Webdav je po založení k dispozici na http://.../dmsf/webdav/" label_webdav: Webdav functionalita - label_dmsf_plural: "Kopíruj DMSF soubory a složky (%{files} souborů v %{folders} složkách)" + label_dmsf_plural: "Kopíruj dokumenty a složky (%{files} souborů v %{folders} složkách)" warning_folder_already_locked: Tato složka je již zamčená notice_folder_locked: Složka byla úspěšně zamčena @@ -290,13 +290,14 @@ cs: label_notifications_off: Vypnout notifikace field_target_file: Zdrojový soubor title_download_entries: Historie stahování + label_external: Externí + label_link_name: Název odkazu label_link_external_url: URL label_target_folder: Cílový adresář label_source_folder: Zdrojový adresář label_target_project: Cílový projekt - label_source_project: Zdrojový projekt - label_external: Externí + label_source_project: Zdrojový projekt text_email_doc_updated_subject: "Dokumenty projektu %{project} aktualizovány" text_email_doc_updated: právě aktualizoval dokumenty projektu diff --git a/config/locales/de.yml b/config/locales/de.yml index 422750cb..340b5e3f 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -23,6 +23,8 @@ de: dmsf: DMS label_dmsf_file_plural: DMS + label_dmsf_file_revision_plural: Dokumenteversion + label_dmsf_file_revision_access_plural: Dokumentezugriffe warning_no_entries_selected: Keine Einträge ausgewählt error_email_to_must_be_entered: Es muss ein Email-Empfänger angegeben werden. warning_file_already_locked: Datei schon gesperrt @@ -81,7 +83,7 @@ de: title_lock_file: Sperre um Änderungen anderer Nutzer zu verhindern title_download_checked: Download der ausgewählten Dateien in einem ZIP-Archiv title_send_checked_by_email: Sende gewählte Dateien per Email - link_user_preferences: Deine Einstellungen + link_user_preferences: Deine DMS Projekt Einstellungen heading_send_documents_by_email: Sende Dateien per Email label_email_from: Von label_email_to: An @@ -143,16 +145,16 @@ de: heading_uploaded_files: Hochgeladene Dateien submit_commit: OK link_documents: Dateien - permission_view_dmsf_file_revision_accesses: View downloads in Activity stream - permission_view_dmsf_file_revisions: View revisions in Activity stream + permission_view_dmsf_file_revision_accesses: Betrachte Dokumentezugriffe in Aktivitäten + permission_view_dmsf_file_revisions: Betrachte Dokumenteversion in Aktivitäten permission_view_dmsf_folders: Durchforste Dateien permission_user_preferences: Benutzereinstellungen permission_view_dmsf_files: Betrachte Dateien permission_folder_manipulation: Ordner bearbeiten permission_file_manipulation: Dateien bearbeiten - permission_force_file_unlock: Erzwinge Aufhebung der Dateisperre - permission_file_delete: Datei löschen + permission_force_file_unlock: Erzwinge Aufhebung der Dateisperre permission_manage_workflows: Workflows verwalten + permission_file_delete: Datei löschen label_file: Datei field_folder: Ordner error_create_cycle_in_folder_dependency: Zirkelabhängigkeit in der Ordnerstruktur erstellt @@ -164,7 +166,7 @@ de: notice_entries_deleted: Einträge löschen warning_some_entries_were_not_deleted: "Enige Einträge wurden nicht gelöscht: %{entries}" title_delete_checked: Löschen ausgewählt - title_number_of_files_in_directory: Dateianzahl in dem Ordner + title_items: items title_filename_for_download: Dateiname beim Herunterladen oder in ZIP-Archiv verwenden label_number_of_folders: Order label_number_of_documents: Dokumente @@ -178,7 +180,8 @@ de: heading_access_downloads_emails: Downloads oder Emailversand heading_access_first: Erste heading_access_last: Letzte - label_dmsf_updated: DMS aktualisiert + label_dmsf_updated: aktualisiert + label_dmsf_downloaded: gespeichert title_total_size_of_all_files: Gesamtgröße aller Dateien in diesem Ordner project_module_dmsf: DMS warning_no_project_to_copy_file_to: Kein Projekt, in das die Datei kopiert werden kann. @@ -287,13 +290,14 @@ de: label_notifications_off: Benachrichtigungen aus field_target_file: Quelldatei title_download_entries: Download entries + label_external: Außen + label_link_name: Name der Verknüpfung label_link_external_url: URL label_target_folder: Zielordner label_source_folder: Quellordner label_target_project: Zielprojekt - label_source_project: Quellprojekt - label_external: Außen + label_source_project: Quellprojekt text_email_doc_updated_subject: "Dokumente im Projekt %{project} wurden aktualisiert" text_email_doc_updated: hat folgende Dokumente bearbeitet diff --git a/config/locales/en.yml b/config/locales/en.yml index 4ec072d1..36aa7b7f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -22,9 +22,9 @@ en: dmsf: DMSF - label_dmsf_file_plural: Dmsf files - label_dmsf_file_revision_plural: Dmsf document revisions - label_dmsf_file_revision_access_plural: Dmsf document accesses + label_dmsf_file_plural: Documents + label_dmsf_file_revision_plural: Document revisions + label_dmsf_file_revision_access_plural: Document accesses warning_no_entries_selected: No entries selected error_email_to_must_be_entered: Email To must be entered warning_file_already_locked: File already locked @@ -145,6 +145,8 @@ en: heading_uploaded_files: Uploaded Files submit_commit: Commit link_documents: Documents + permission_view_dmsf_file_revision_accesses: View downloads in Activity stream + permission_view_dmsf_file_revisions: View revisions in Activity stream permission_view_dmsf_folders: Browse documents permission_user_preferences: User preferences permission_view_dmsf_files: View documents @@ -164,7 +166,7 @@ en: notice_entries_deleted: Entries deleted warning_some_entries_were_not_deleted: "Some entries weren't deleted: %{entries}" title_delete_checked: Delete checked - title_number_of_files_in_directory: Number of files in directory + title_items: items title_filename_for_download: Filename used for download or in Zip archive label_number_of_folders: Folders label_number_of_documents: Documents @@ -178,8 +180,8 @@ en: heading_access_downloads_emails: Downloads/Emails heading_access_first: First heading_access_last: Last - label_dmsf_updated: DMSF document updated - label_dmsf_downloaded: DMSF document downloaded + label_dmsf_updated: Updated + label_dmsf_downloaded: Downloaded title_total_size_of_all_files: Total size of all files under this folder project_module_dmsf: DMSF warning_no_project_to_copy_file_to: No project to copy file to @@ -189,7 +191,7 @@ en: field_target_project: Target project field_target_folder: Target folder title_copy_or_move: Copy/Move - label_dmsf_folder_plural: Dmsf folders + label_dmsf_folder_plural: Folders comment_moved_from: "Moved from %{source}" error_target_folder_same: Target folder and project are the same as current error_file_cannot_be_moved: "File can't be moved" @@ -207,7 +209,7 @@ en: parent_directory: Parent Directory note_webdav: Webdav once enabled can be found at http://.../dmsf/webdav/ label_webdav: Webdav functionality - label_dmsf_plural: "Copy DMSF files and folders (%{files} files in %{folders} folders)" + label_dmsf_plural: "Copy Documents and folders (%{files} files in %{folders} folders)" warning_folder_already_locked: This folder is already locked notice_folder_locked: The folder was successfully locked diff --git a/config/locales/es.yml b/config/locales/es.yml index b5e2f353..2586673d 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -22,9 +22,9 @@ es: dmsf: DMSF - label_dmsf_file_plural: DMSF Archivos - label_dmsf_file_revision_plural: Dmsf document revisions - label_dmsf_file_revision_access_plural: Dmsf document accesses + label_dmsf_file_plural: Archivos + label_dmsf_file_revision_plural: Document revisions + label_dmsf_file_revision_access_plural: Document accesses warning_no_entries_selected: No ha seleccionado ningún ítem error_email_to_must_be_entered: Ingrese un email warning_file_already_locked: El archivo ya está bloqueado @@ -166,7 +166,7 @@ es: notice_entries_deleted: Entradas eliminadas warning_some_entries_were_not_deleted: "Algunas entradas no fueron eliminadas: %{entries}" title_delete_checked: Eliminación chequeada - title_number_of_files_in_directory: Número de archivos en directorio + title_items: items title_filename_for_download: Nombre de archivo utilizado para descargar o crear zip label_number_of_folders: Directorios label_number_of_documents: Documentos @@ -191,7 +191,7 @@ es: field_target_project: Proyecto destino field_target_folder: Directorio destino title_copy_or_move: Copiar/Mover - label_dmsf_folder_plural: directorio Dmsf + label_dmsf_folder_plural: directorio comment_moved_from: "Mover desde %{source}" error_target_folder_same: El directorio y proyecto destino son el actual error_file_cannot_be_moved: "Los archivos no puesen ser movidos" @@ -209,7 +209,7 @@ es: parent_directory: Directorio padre note_webdav: Si Webdav está habilitado, se puede encontrar en http://.../dmsf/webdav/ label_webdav: Funcionalidad Webdav - label_dmsf_plural: "Copiar archivos y directorios DMSF (%{files} archivos en %{folders} directorios)" + label_dmsf_plural: "Copiar archivos y directorios (%{files} archivos en %{folders} directorios)" warning_folder_already_locked: El directorio ya se encuentra bloqueado notice_folder_locked: "El directorio se bloqueó exitosamente" @@ -290,13 +290,14 @@ es: label_notifications_off: Notificaciones OFF field_target_file: Archivo fuente title_download_entries: Entradas de descarga + label_external: External + label_link_name: Nombre de enlace label_link_external_url: URL label_target_folder: Directorio destino label_source_folder: Directorio fuente label_target_project: Proyecto destino - label_source_project: Proyecto fuente - label_external: External + label_source_project: Proyecto fuente text_email_doc_updated_subject: "Documentos de %{project} actualizados" text_email_doc_updated: acaba de actualizar los ducumentos de diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 1e551f06..65819018 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -1,3 +1,5 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # # Copyright (C) 2011 Vít Jonáš @@ -20,9 +22,9 @@ fr: dmsf: DMSF - label_dmsf_file_plural: Fichiers DMSF - label_dmsf_file_revision_plural: Dmsf document revisions - label_dmsf_file_revision_access_plural: Dmsf document accesses + label_dmsf_file_plural: Fichiers + label_dmsf_file_revision_plural: Révisions du document + label_dmsf_file_revision_access_plural: Accès au document warning_no_entries_selected: Aucun fichier sélectionné error_email_to_must_be_entered: "La saisie d'une adresse mail est obligatoire" warning_file_already_locked: Fichier déjà verrouillé @@ -61,14 +63,14 @@ fr: submit_create: Ajouter link_create_folder: Créer un sous-dossier title_check_uncheck_all_for_zip_download_or_email: Sélectionner/Ignorer tous les documents pour le téléchargement ou pour la transmission par mail - title_check_uncheck_all_for_restore_or_delete: Check/Uncheck all for restore or delete + title_check_uncheck_all_for_restore_or_delete: Sélectionner/Ignorer pour restaurer ou supprimer link_title: Titre link_size: Taille link_modified: Modifié link_ver: Version link_author: Auteur title_check_for_zip_download_or_email: Sélectionner pour le téléchargement ou la transmission par mail - title_check_for_restore_or_delete: Check for restore or delete + title_check_for_restore_or_delete: Sélectionner pour restaurer ou supprimer title_delete: Supprimer title_notifications_active_deactivate: "Notifications activées : cliquer pour désactiver" title_notifications_not_active_activate: "Notifications désactivées : cliquer pour activer" @@ -119,6 +121,7 @@ fr: option_version_same: (identique) option_version_minor: (modification mineure) option_version_major: (modification majeure) + option_version_custom: Custom label_new_content: Nouvelle version du fichier label_maximum_files_upload: Nombre maximal de documents pouvant être transmis note_maximum_number_of_files_uploaded: Nombre maximal de documents pouvant être transmis en une fois. La valeur 0 signifie illimité. @@ -142,8 +145,8 @@ fr: heading_uploaded_files: Document(s) transmis submit_commit: Appliquer link_documents: Documents - permission_view_dmsf_file_revision_accesses: View downloads in Activity stream - permission_view_dmsf_file_revisions: View revisions in Activity stream + permission_view_dmsf_file_revision_accesses: Voir les téléchargements dans le flux d'activité + permission_view_dmsf_file_revisions: Voir les révisions dans le flux d'activité permission_view_dmsf_folders: Parcourir les documents permission_user_preferences: Préférences utilisateur permission_view_dmsf_files: Afficher documents @@ -163,7 +166,7 @@ fr: notice_entries_deleted: Elément(s) supprimé(s) warning_some_entries_were_not_deleted: "Certains éléments n'ont pas été supprimés : %{entries}" title_delete_checked: Supprimer les éléments sélectionnés - title_number_of_files_in_directory: Nombre de fichiers dans le dossier + title_items: items title_filename_for_download: "Nom du fichier à utiliser lors du téléchargement ou de l'archive ZIP" label_number_of_folders: Dossiers label_number_of_documents: Fichiers @@ -178,7 +181,7 @@ fr: heading_access_first: Premier heading_access_last: Dernier label_dmsf_updated: Dépôt ou mise à jour du document - label_dmsf_downloaded: DMSF document downloaded + label_dmsf_downloaded: Document DMSF téléchargé title_total_size_of_all_files: Taille totale des fichiers de ce dossier project_module_dmsf: DMSF warning_no_project_to_copy_file_to: "Le projet de destination n'est pas défini" @@ -188,7 +191,7 @@ fr: field_target_project: Projet cible field_target_folder: Dossier cible title_copy_or_move: Copie/Déplacement - label_dmsf_folder_plural: Les dossiers de DMSF + label_dmsf_folder_plural: Les dossiers comment_moved_from: "Déplacé depuis %{source}" error_target_folder_same: Le projet et le dossier cible sont identiques au projet et dossier source error_file_cannot_be_moved: Le fichier ne peut pas être déplacé @@ -206,7 +209,7 @@ fr: parent_directory: Dossier parent note_webdav: "Après l'activation du module Webdav, celui-ci sera accessible par http://.../dmsf/webdav/" label_webdav: Module Webdav - label_dmsf_plural: "Copier les fichiers et les dossiers DMSF (%{files} fichiers dans %{folders} dossiers)" + label_dmsf_plural: "Copier les fichiers et les dossiers (%{files} fichiers dans %{folders} dossiers)" warning_folder_already_locked: Ce dossier est déjà verrouillé notice_folder_locked: Dossier verrouillé @@ -287,13 +290,14 @@ fr: label_notifications_off: Désactiver les notifications field_target_file: Fichier source title_download_entries: Historique des téléchargements + label_external: Externe + label_link_name: Nom du lien label_link_external_url: Adresse Internet label_target_folder: Dossier cible label_source_folder: Dossier source label_target_project: Projet cible - label_source_project: Projet source - label_external: External + label_source_project: Projet source text_email_doc_updated_subject: "Documents de %{project} mis à jour" text_email_doc_updated: a mis à jour des documents de @@ -311,8 +315,8 @@ fr: notice_dmsf_file_restored: Le document a été récupéré avec succès notice_dmsf_folder_restored: Le dossier a été récupéré avec succès notice_dmsf_link_restored: Le lien a été récupéré avec succès - title_restore_checked: Restore checked - error_parent_folder: "The parent folder doesn't exist" + title_restore_checked: Restauration vérifiée + error_parent_folder: "Le dossier parent n'existe pas" my: blocks: diff --git a/config/locales/ja.yml b/config/locales/ja.yml index cb625215..85154051 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -167,7 +167,7 @@ ja: notice_entries_deleted: エントリーを削除しました warning_some_entries_were_not_deleted: "いくつかのエントリーは削除されませんでした: %{entries}" title_delete_checked: チェックしたものを削除します - title_number_of_files_in_directory: フォルダ内のファイル数 + title_items: items title_filename_for_download: ファイル名はダウンロードまたは Zip アーカイブに使われます label_number_of_folders: フォルダ label_number_of_documents: 文書 diff --git a/config/locales/pl.yml b/config/locales/pl.yml index b3b81f4e..10d043f8 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -23,9 +23,9 @@ pl: dmsf: DMSF - label_dmsf_file_plural: Pliki Dmsf - label_dmsf_file_revision_plural: Dmsf document revisions - label_dmsf_file_revision_access_plural: Dmsf document accesses + label_dmsf_file_plural: Pliki + label_dmsf_file_revision_plural: Document revisions + label_dmsf_file_revision_access_plural: Document accesses warning_no_entries_selected: Nie zaznaczono żadnych wierszy error_email_to_must_be_entered: Musisz podać adres email warning_file_already_locked: Plik jest już zablokowany @@ -167,7 +167,7 @@ pl: notice_entries_deleted: Wpisy usunięte warning_some_entries_were_not_deleted: "Niektóre wpisy nie zostały usunięte: %{entries}" title_delete_checked: Usuń zaznaczone - title_number_of_files_in_directory: Liczba plików w folderze + title_items: items title_filename_for_download: Nazwa pliku używana do pobierania lub tworzenai archiwum Zip label_number_of_folders: Foldery label_number_of_documents: Dokumenty @@ -192,7 +192,7 @@ pl: field_target_project: Projekt docelowy field_target_folder: Folder docelowy title_copy_or_move: Kopiuj/Przenieś - label_dmsf_folder_plural: Foldery Dmsf + label_dmsf_folder_plural: Foldery comment_moved_from: "Przeniesiono z %{source}" error_target_folder_same: Docelowy projekt i folder są identyczne z obecnym error_file_cannot_be_moved: "Plik nie może zostać przeniesiony" @@ -210,7 +210,7 @@ pl: parent_directory: Folder nadrzędny note_webdav: Webdav once enabled can be found at http://.../dmsf/webdav/ label_webdav: Webdav functionality - label_dmsf_plural: "Skopiuj pliki i foldery DMSF (%{files} plików w %{folders} folderach)" + label_dmsf_plural: "Skopiuj pliki i foldery (%{files} plików w %{folders} folderach)" warning_folder_already_locked: Folder jest już zablokowany notice_folder_locked: Folder został zablokowany @@ -290,13 +290,14 @@ pl: label_notifications_off: Powiadomienia wyłączone field_target_file: Plik źródłowy title_download_entries: Pobrane + label_external: External + label_link_name: Nazwa odnośnika label_link_external_url: URL label_target_folder: Folder docelowy label_source_folder: Folder źródłowy label_target_project: Projekt docelowy - label_source_project: Projekt źródłowy - label_external: External + label_source_project: Projekt źródłowy text_email_doc_updated_subject: "Dokumenty projektu %{project} zostały zaktualizowane" text_email_doc_updated: dokumenty zostały zaktualizowane diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 7cc0a83b..ab3ecf4f 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -22,9 +22,9 @@ ru: dmsf: DMSF - label_dmsf_file_plural: Файлы DMSF - label_dmsf_file_revision_plural: Dmsf document revisions - label_dmsf_file_revision_access_plural: Dmsf document accesses + label_dmsf_file_plural: Файлы + label_dmsf_file_revision_plural: Document revisions + label_dmsf_file_revision_access_plural: Document accesses warning_no_entries_selected: Файлы не выбраны error_email_to_must_be_entered: Нужно указать, на какую почту отправить письмо warning_file_already_locked: Файл уже заблокирован @@ -166,7 +166,7 @@ ru: notice_entries_deleted: Файлы удалены warning_some_entries_were_not_deleted: "Некоторые файлы не были удалены: %{entries}" title_delete_checked: Удалить выбранные документы - title_number_of_files_in_directory: Количество файлов в директории + title_items: items title_filename_for_download: Имя файла для скачиваемого архива label_number_of_folders: Папок label_number_of_documents: Документов @@ -181,7 +181,7 @@ ru: heading_access_first: Первый heading_access_last: Последний label_dmsf_updated: Документ обновлен - label_dmsf_downloaded: DMSF document downloaded + label_dmsf_downloaded: Документ downloaded title_total_size_of_all_files: Общий размер всех файлов в этой папке project_module_dmsf: DMSF warning_no_project_to_copy_file_to: Не выбран проект, в который нужно скопировать файл @@ -191,7 +191,7 @@ ru: field_target_project: Целевой проект field_target_folder: Целевая папка title_copy_or_move: Копировать/Переместить - label_dmsf_folder_plural: DMSF папки + label_dmsf_folder_plural: Папки comment_moved_from: "Перемещен из %{source}" error_target_folder_same: Целевая папка и проект совпадают с текущими error_file_cannot_be_moved: Файл не может быть перемещен @@ -209,7 +209,7 @@ ru: parent_directory: "Родительская директория" note_webdav: "После включения, WebDAV можно найти по адресу http://redmine-host/dmsf/webdav/" label_webdav: "Функциональность WebDAV" - label_dmsf_plural: "Скопировать DMSF файлы и папки (%{files} файлов в %{folders} папках)" + label_dmsf_plural: "Скопировать файлы и папки (%{files} файлов в %{folders} папках)" warning_folder_already_locked: "Эта папка уже заблокирована" notice_folder_locked: "Папка была успешно заблокирована" @@ -290,13 +290,14 @@ ru: label_notifications_off: Notifications off field_target_file: Source file title_download_entries: Download entries + label_external: External + label_link_name: Link name label_link_external_url: URL label_target_folder: Target folder label_source_folder: Source folder label_target_project: Target project - label_source_project: Source project - label_external: External + label_source_project: Source project text_email_doc_updated_subject: "Documents of %{project} updated" text_email_doc_updated: has just actualized documents of diff --git a/config/locales/sl.yml b/config/locales/sl.yml index 31f40f3a..2d26d65f 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -23,8 +23,8 @@ sl: dmsf: Arhiv label_dmsf_file_plural: Arhivske datoteke - label_dmsf_file_revision_plural: Dmsf document revisions - label_dmsf_file_revision_access_plural: Dmsf document accesses + label_dmsf_file_revision_plural: Document revisions + label_dmsf_file_revision_access_plural: Document accesses warning_no_entries_selected: Ničesar niste izbrali error_email_to_must_be_entered: Email Naslovnik mora bit izbran warning_file_already_locked: Datoteka že zaklenjena @@ -166,7 +166,7 @@ sl: notice_entries_deleted: Izbrane enote izbrisane warning_some_entries_were_not_deleted: "Nekatere enote niso izbrisane: %{entries}" title_delete_checked: Izbriši izbrano - title_number_of_files_in_directory: Število datotek v mapi + title_items: items title_filename_for_download: Naziv datoteke za prenos dol ali Zip arhiva label_number_of_folders: Mapa label_number_of_documents: Dokumentacija @@ -181,7 +181,7 @@ sl: heading_access_first: Prvi heading_access_last: Zadnji label_dmsf_updated: Arhiv posodobljen - label_dmsf_downloaded: DMSF document downloaded + label_dmsf_downloaded: Arhiv downloaded title_total_size_of_all_files: Skupna velikost vseh datotek v tej mapi project_module_dmsf: Arhiv warning_no_project_to_copy_file_to: Ni projekta kamor bi kopiral datoteko @@ -290,13 +290,14 @@ sl: label_notifications_off: Notifications off field_target_file: Source file title_download_entries: Download entries + label_external: External + label_link_name: Link name label_link_external_url: URL label_target_folder: Target folder label_source_folder: Source folder label_target_project: Target project - label_source_project: Source project - label_external: External + label_source_project: Source project text_email_doc_updated_subject: "Documents of %{project} updated" text_email_doc_updated: has just actualized documents of diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 06922d62..9fdfa073 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -23,8 +23,8 @@ zh-TW: dmsf: 文件總管 label_dmsf_file_plural: 文件檔案 - label_dmsf_file_revision_plural: Dmsf document revisions - label_dmsf_file_revision_access_plural: Dmsf document accesses + label_dmsf_file_revision_plural: Document revisions + label_dmsf_file_revision_access_plural: Document accesses warning_no_entries_selected: 尚未選取任何項目 error_email_to_must_be_entered: 請輸入收件者的電子郵件 warning_file_already_locked: 檔案己經鎖定 @@ -80,10 +80,8 @@ zh-TW: title_waiting_for_approval: 等待批准 title_approved: 已經被批准 title_unlock_file: 解除鎖定。允許其它使用者修改。 - title_lock_file: 鎖定檔案。禁止其它使用者修改。 - submit_download: 下載 - title_download_checked: 以ZIP下載所選取的檔案 - submit_email: 電子郵件 + title_lock_file: 鎖定檔案。禁止其它使用者修改。 + title_download_checked: 以ZIP下載所選取的檔案 title_send_checked_by_email: 以電子郵件發送所選取的檔案 link_user_preferences: 你的DMSF的系統偏好設定 heading_send_documents_by_email: 電子郵件寄送檔案 @@ -156,6 +154,7 @@ zh-TW: permission_file_manipulation: 文件操作 permission_force_file_unlock: 強制解除檔案鎖定 permission_manage_workflows: Manage workflows + permission_file_delete: Delete documents label_file: 檔案 field_folder: 資料夾 error_create_cycle_in_folder_dependency: 資料夾之間的關係,不得為一個cycle循環。 @@ -167,7 +166,7 @@ zh-TW: notice_entries_deleted: 項目己刪除 warning_some_entries_were_not_deleted: "部份項目無法刪除: %{entries}" title_delete_checked: 刪除選取項目 - title_number_of_files_in_directory: 資料夾的檔案數量 + title_items: items title_filename_for_download: 下載時的檔名,或是ZIP的檔案名稱。 label_number_of_folders: 資料夾 label_number_of_documents: 文件檔案 @@ -181,8 +180,8 @@ zh-TW: heading_access_downloads_emails: 下載/電子郵件 heading_access_first: First heading_access_last: Last - label_dmsf_updated: DMSF updated - label_dmsf_downloaded: DMSF document downloaded + label_dmsf_updated: Updated + label_dmsf_downloaded: Downloaded title_total_size_of_all_files: 資料夾所有檔案的檔案大小 project_module_dmsf: 文件總管 warning_no_project_to_copy_file_to: No project to copy file to @@ -192,7 +191,7 @@ zh-TW: field_target_project: Target project field_target_folder: Target folder title_copy_or_move: Copy/Move - label_dmsf_folder_plural: Dmsf folders + label_dmsf_folder_plural: Folders comment_moved_from: "Moved from %{source}" error_target_folder_same: Target folder and project are the same as current error_file_cannot_be_moved: "File can't be moved" @@ -291,13 +290,14 @@ zh-TW: label_notifications_off: Notifications off field_target_file: Source file title_download_entries: Download entries + label_external: External + label_link_name: Link name label_link_external_url: URL label_target_folder: Target folder label_source_folder: Source folder label_target_project: Target project - label_source_project: Source project - label_external: External + label_source_project: Source project text_email_doc_updated_subject: "Documents of %{project} updated" text_email_doc_updated: has just actualized documents of @@ -309,6 +309,14 @@ zh-TW: label_display_notified_recipients: Display notified recipients note_display_notified_recipients: The user will be informed about all recipients of just sent the email notification. warning_email_notifications: "Email notifications sent to %{to}" + + link_trash_bin: Trash bin + title_restore: Restore + notice_dmsf_file_restored: The document has been successfully restored + notice_dmsf_folder_restored: The folder has been successfully restored + notice_dmsf_link_restored: The link has been successfully restored + title_restore_checked: Restore checked + error_parent_folder: "The parent folder doesn't exist" my: blocks: @@ -316,4 +324,4 @@ zh-TW: open_approvals: Open approvals label_maximum_ajax_upload_filesize: Maximum file size uploadable via AJAX - note_maximum_ajax_upload_filesize: Limits maximum file size that can uploaded via standard AJAX interface otherwise Redmine standard upload form must be used. Number is in MB. + note_maximum_ajax_upload_filesize: Limits maximum file size that can uploaded via standard AJAX interface otherwise Redmine standard upload form must be used. Number is in MB. \ No newline at end of file diff --git a/config/locales/zh.yml b/config/locales/zh.yml index 38e4cd59..9ffbaee9 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -22,9 +22,9 @@ zh: dmsf: 文档管家 - label_dmsf_file_plural: Dmsf files - label_dmsf_file_revision_plural: Dmsf document revisions - label_dmsf_file_revision_access_plural: Dmsf document accesses + label_dmsf_file_plural: Documents + label_dmsf_file_revision_plural: Document revisions + label_dmsf_file_revision_access_plural: Document accesses warning_no_entries_selected: 未选择任何条目 error_email_to_must_be_entered: 请输入电子邮件 warning_file_already_locked: 文件已经锁定 @@ -166,7 +166,7 @@ zh: notice_entries_deleted: 条目已删除 warning_some_entries_were_not_deleted: "某些条目未被删除: %{entries}" title_delete_checked: 删除选中 - title_number_of_files_in_directory: 目录总文件个数 + title_items: items title_filename_for_download: 用于下载或zip归档的文件名 label_number_of_folders: Folders label_number_of_documents: Documents @@ -191,7 +191,7 @@ zh: field_target_project: Target project field_target_folder: Target folder title_copy_or_move: Copy/Move - label_dmsf_folder_plural: Dmsf folders + label_dmsf_folder_plural: Folders comment_moved_from: "Moved from %{source}" error_target_folder_same: Target folder and project are the same as current error_file_cannot_be_moved: "File can't be moved" @@ -209,7 +209,7 @@ zh: parent_directory: Parent Directory note_webdav: Webdav once enabled can be found at http://.../dmsf/webdav/ label_webdav: Webdav functionality - label_dmsf_plural: "Copy DMSF files and folders (%{files} files in %{folders} folders)" + label_dmsf_plural: "Copy documents and folders (%{files} files in %{folders} folders)" warning_folder_already_locked: This folder is already locked notice_folder_locked: The folder was successfully locked @@ -290,13 +290,14 @@ zh: label_notifications_off: Notifications off field_target_file: Source file title_download_entries: Download entries + label_external: External + label_link_name: Link name label_link_external_url: URL label_target_folder: Target folder label_source_folder: Source folder label_target_project: Target project - label_source_project: Source project - label_external: External + label_source_project: Source project text_email_doc_updated_subject: "Documents of %{project} updated" text_email_doc_updated: has just actualized documents of diff --git a/config/routes.rb b/config/routes.rb index 0852c9ab..ab597dfe 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -58,7 +58,9 @@ RedmineApp::Application.routes.draw do post '/projects/:id/dmsf/upload/files', :controller => 'dmsf_upload', :action => 'upload_files' post '/projects/:id/dmsf/upload/file', :controller => 'dmsf_upload', :action => 'upload_file' + post '/projects/:id/dmsf/upload', :controller => 'dmsf_upload', :action => 'upload' post '/projects/:id/dmsf/upload/commit', :controller => 'dmsf_upload', :action => 'commit_files' + post '/projects/:id/dmsf/commit', :controller => 'dmsf_upload', :action => 'commit' # # dmsf_files controller @@ -109,7 +111,7 @@ RedmineApp::Application.routes.draw do # DAV4Rack implementation of Webdav [note: if changing path you'll need to update lib/redmine_dmsf/webdav/no_parse.rb also] # /dmsf/webdav mount DAV4Rack::Handler.new( - :root_uri_path => "/dmsf/webdav", + :root_uri_path => "#{Redmine::Utils::relative_url_root}/dmsf/webdav", :resource_class => RedmineDmsf::Webdav::ResourceProxy, :controller_class => RedmineDmsf::Webdav::Controller ), :at => "/dmsf/webdav" @@ -124,9 +126,10 @@ RedmineApp::Application.routes.draw do post 'new_action' get 'start' post 'assignment' + 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 diff --git a/db/migrate/20120822100401_create_dmsf_workflows.rb b/db/migrate/20120822100401_create_dmsf_workflows.rb index 8bc9de19..bd35ae63 100644 --- a/db/migrate/20120822100401_create_dmsf_workflows.rb +++ b/db/migrate/20120822100401_create_dmsf_workflows.rb @@ -1,6 +1,8 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2013 Karel Picman +# Copyright (C) 2011-15 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 diff --git a/db/migrate/20120822100402_create_dmsf_workflow_steps.rb b/db/migrate/20120822100402_create_dmsf_workflow_steps.rb index d02c29dc..b44c92a6 100644 --- a/db/migrate/20120822100402_create_dmsf_workflow_steps.rb +++ b/db/migrate/20120822100402_create_dmsf_workflow_steps.rb @@ -1,6 +1,8 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2013 Karel Picman +# Copyright (C) 2011-15 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 diff --git a/db/migrate/20120822100403_create_dmsf_workflow_step_assignments.rb b/db/migrate/20120822100403_create_dmsf_workflow_step_assignments.rb index c0f4bd06..f51b37c1 100644 --- a/db/migrate/20120822100403_create_dmsf_workflow_step_assignments.rb +++ b/db/migrate/20120822100403_create_dmsf_workflow_step_assignments.rb @@ -1,6 +1,8 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2013 Karel Picman +# Copyright (C) 2011-15 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 diff --git a/db/migrate/20120822100404_create_dmsf_workflow_step_actions.rb b/db/migrate/20120822100404_create_dmsf_workflow_step_actions.rb index 7a076a5e..a4243d4d 100644 --- a/db/migrate/20120822100404_create_dmsf_workflow_step_actions.rb +++ b/db/migrate/20120822100404_create_dmsf_workflow_step_actions.rb @@ -1,6 +1,8 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2013 Karel Picman +# Copyright (C) 2011-15 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 diff --git a/db/migrate/20130819013955_update_projects.rb b/db/migrate/20130819013955_update_projects.rb index 58901ac2..f4f5be61 100644 --- a/db/migrate/20130819013955_update_projects.rb +++ b/db/migrate/20130819013955_update_projects.rb @@ -1,6 +1,8 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2013 Karel Picman +# Copyright (C) 2011-15 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 diff --git a/db/migrate/20131108141401_add_index_to_dmsf_files.rb b/db/migrate/20131108141401_add_index_to_dmsf_files.rb index 512715e1..d9958433 100644 --- a/db/migrate/20131108141401_add_index_to_dmsf_files.rb +++ b/db/migrate/20131108141401_add_index_to_dmsf_files.rb @@ -1,6 +1,8 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2013 Karel Picman +# Copyright (C) 2011-15 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 diff --git a/db/migrate/20131108141402_add_index_to_dmsf_folders.rb b/db/migrate/20131108141402_add_index_to_dmsf_folders.rb index 991c1aa5..8ed8b912 100644 --- a/db/migrate/20131108141402_add_index_to_dmsf_folders.rb +++ b/db/migrate/20131108141402_add_index_to_dmsf_folders.rb @@ -1,6 +1,8 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2013 Karel Picman +# Copyright (C) 2011-15 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 diff --git a/db/migrate/20131113141401_add_index_to_dmsf_file_revision.rb b/db/migrate/20131113141401_add_index_to_dmsf_file_revision.rb index f0746052..e8e0b029 100644 --- a/db/migrate/20131113141401_add_index_to_dmsf_file_revision.rb +++ b/db/migrate/20131113141401_add_index_to_dmsf_file_revision.rb @@ -1,6 +1,8 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2013 Karel Picman +# Copyright (C) 2011-15 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 diff --git a/db/migrate/20131113141402_add_index_to_dmsf_lock.rb b/db/migrate/20131113141402_add_index_to_dmsf_lock.rb index 9e70a488..fd598a8f 100644 --- a/db/migrate/20131113141402_add_index_to_dmsf_lock.rb +++ b/db/migrate/20131113141402_add_index_to_dmsf_lock.rb @@ -1,6 +1,8 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2013 Karel Picman +# Copyright (C) 2011-15 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 diff --git a/db/migrate/20131113141403_create_dmsf_links.rb b/db/migrate/20131113141403_create_dmsf_links.rb index 901a2834..2fcc9e8e 100644 --- a/db/migrate/20131113141403_create_dmsf_links.rb +++ b/db/migrate/20131113141403_create_dmsf_links.rb @@ -1,6 +1,8 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2014 Karel Pičman +# Copyright (C) 2011-15 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 diff --git a/db/migrate/20140314132501_notifications_on.rb b/db/migrate/20140314132501_notifications_on.rb index 2ba3338b..5e0a2d28 100644 --- a/db/migrate/20140314132501_notifications_on.rb +++ b/db/migrate/20140314132501_notifications_on.rb @@ -1,6 +1,8 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2014 Karel Pičman +# Copyright (C) 2011-15 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,6 +27,6 @@ class NotificationsOn < ActiveRecord::Migration def down change_column :projects, :dmsf_notification, :boolean, :default => false, :null => true - change_column :dmsf_folders, :notification, :boolean, :default => false, :null => false + change_column :dmsf_folders, :notification, :boolean, :default => false end end \ No newline at end of file diff --git a/db/migrate/20140519133201_trash_bin.rb b/db/migrate/20140519133201_trash_bin.rb index 109e9706..32ba217f 100644 --- a/db/migrate/20140519133201_trash_bin.rb +++ b/db/migrate/20140519133201_trash_bin.rb @@ -1,6 +1,8 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2011-14 Karel Pičman +# Copyright (C) 2011-15 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 diff --git a/db/migrate/20141015132701_remove_folder_from_revision.rb b/db/migrate/20141015132701_remove_folder_from_revision.rb index 3f3bc787..007fdd43 100644 --- a/db/migrate/20141015132701_remove_folder_from_revision.rb +++ b/db/migrate/20141015132701_remove_folder_from_revision.rb @@ -1,6 +1,8 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2011-14 Karel Pičman +# Copyright (C) 2011-15 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 diff --git a/db/migrate/20141205143001_remove_uniqueness_from_wf.rb b/db/migrate/20141205143001_remove_uniqueness_from_wf.rb index 2431efa9..886c7a4a 100644 --- a/db/migrate/20141205143001_remove_uniqueness_from_wf.rb +++ b/db/migrate/20141205143001_remove_uniqueness_from_wf.rb @@ -1,6 +1,8 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2011-14 Karel Pičman +# Copyright (C) 2011-15 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,9 +21,5 @@ class RemoveUniquenessFromWf < ActiveRecord::Migration def up remove_index :dmsf_workflows, :name - end - - def down - add_index :dmsf_workflows, [:name], :unique => true - end + end end \ No newline at end of file diff --git a/db/migrate/20150120152101_notifications_nullable.rb b/db/migrate/20150120152101_notifications_nullable.rb index 5155b23c..ff835e78 100644 --- a/db/migrate/20150120152101_notifications_nullable.rb +++ b/db/migrate/20150120152101_notifications_nullable.rb @@ -2,7 +2,7 @@ # # Redmine plugin for Document Management System "Features" # -# Copyright (C) 2011-15 Karel Pičman +# Copyright (C) 2011-15 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 diff --git a/db/migrate/20150130052716_add_external.rb b/db/migrate/20150130052716_add_external.rb index 8c083df7..27f826f4 100644 --- a/db/migrate/20150130052716_add_external.rb +++ b/db/migrate/20150130052716_add_external.rb @@ -1,13 +1,30 @@ +# encoding: utf-8 +# +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2011-15 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. + class AddExternal < ActiveRecord::Migration def up change_column :dmsf_links, :target_id, :integer, :null => true - add_column :dmsf_links, :external_url, :string, :null => true end - def down - change_column :dmsf_links, :target_id, :integer, :null => false - + def down remove_column :dmsf_links, :external_url end end diff --git a/db/migrate/20150202010301_add_user_to_links.rb b/db/migrate/20150202010301_add_user_to_links.rb index 55ed3672..43d8e383 100644 --- a/db/migrate/20150202010301_add_user_to_links.rb +++ b/db/migrate/20150202010301_add_user_to_links.rb @@ -1,3 +1,23 @@ +# encoding: utf-8 +# +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2011-15 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. + class AddUserToLinks < ActiveRecord::Migration def up add_column :dmsf_links, :user_id, :integer diff --git a/dmsf_user_guide.odt b/dmsf_user_guide.odt index 534074c3..7cea4bf8 100644 Binary files a/dmsf_user_guide.odt and b/dmsf_user_guide.odt differ diff --git a/extra/api_client.rb b/extra/api/api_client.rb similarity index 75% rename from extra/api_client.rb rename to extra/api/api_client.rb index 98de7da1..cde89f69 100644 --- a/extra/api_client.rb +++ b/extra/api/api_client.rb @@ -1,3 +1,5 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # # Copyright (C) 2011-15 Karel Pičman @@ -19,22 +21,25 @@ require 'rubygems' require 'active_resource' +# Simple REST API client in Ruby +# usage: ruby api_client.rb [login] [password] + # Dmsf file class DmsfFile < ActiveResource::Base - self.site = 'http://localhost:3000/' - self.user = 'kpicman' - self.password = 'Kontron2014+' + self.site = 'https://localhost:3000/' + self.user = ARGV[0] + self.password = ARGV[1] end -# Retrieving a file -file = DmsfFile.find 17200 +# 2. Get a document +FILE_ID = 41532 +file = DmsfFile.find FILE_ID if file puts file.id puts file.name puts file.version - puts file.project_id - puts file.dmsf_folder_id + puts file.project_id puts file.content_url else - puts 'No file with id = 1 found' -end \ No newline at end of file + puts "No file with id = #{FILE_ID} found" +end diff --git a/extra/api/api_client.sh b/extra/api/api_client.sh new file mode 100644 index 00000000..bb7a112b --- /dev/null +++ b/extra/api/api_client.sh @@ -0,0 +1,43 @@ +# encoding: utf-8 +# +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2011-15 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. + +#!/bin/bash + +# Authentication as input parameters either as login + password or the API key +# -u ${1}:${2} +# -H "X-Redmine-API-Key: ${1}" + +# BOTH XML and JSON formats are supported. +# Just replace .xml with .json + +# 1. List of documents in a given folder or the root folder +curl -v -H "Content-Type: application/xml" -X GET -u ${1}:${2} http://localhost:3000/projects/12/dmsf.xml +#curl -v -H "Content-Type: application/xml" -X GET -u ${1}:${2} http://localhost:3000/projects/12/dmsf.xml?folder_id=5155 + +# 2. Get a document +#curl -v -H "Content-Type: application/xml" -X GET -u ${1}:${2} http://localhost:3000/dmsf/files/17216.xml +#curl -v -H "Content-Type: application/octet-stream" -X GET -u ${1}:${2} http://localhost:3000/dmsf/files/41532/download > file.txt + +# 3. Create a folder +#curl -v -H "Content-Type: application/xml" -X POST --data "@folder.xml" -u ${1}:${2} http://localhost:3000/projects/12/dmsf/create.xml + +# 4. Upload a document into a given folder or the root folder +#curl --data-binary "@cat.gif" -H "Content-Type: application/octet-stream" -X POST -u ${1}:${2} http://localhost:3000/projects/12/dmsf/upload.xml?filename=cat.gif +#curl -v -H "Content-Type: application/xml" -X POST --data "@file.xml" -u ${1}:${2} http://localhost:3000/projects/12/dmsf/commit.xml \ No newline at end of file diff --git a/extra/api/cat.gif b/extra/api/cat.gif new file mode 100644 index 00000000..0329e659 Binary files /dev/null and b/extra/api/cat.gif differ diff --git a/extra/api/file.xml b/extra/api/file.xml new file mode 100644 index 00000000..f1c19385 --- /dev/null +++ b/extra/api/file.xml @@ -0,0 +1,13 @@ + + + 6118 + + cat.gif + cat.gif + cat.gif + REST API + From API + + 15838.c49f68ff81b552d315927df2e27df506 + + diff --git a/extra/api/folder.xml b/extra/api/folder.xml new file mode 100644 index 00000000..fd0bef9c --- /dev/null +++ b/extra/api/folder.xml @@ -0,0 +1,6 @@ + + + rest_api + A folder created via REST API + + diff --git a/extra/xapian_indexer.rb b/extra/xapian_indexer.rb index 1d2093d2..3a818790 100644 --- a/extra/xapian_indexer.rb +++ b/extra/xapian_indexer.rb @@ -542,13 +542,13 @@ if not $onlyrepos then end # Indexing repositories -if not $onlyfiles then - if not File.exist?($scriptindex) then +unless $onlyfiles + unless File.exist?($scriptindex) log("- ERROR! #{$scriptindex} does not exist, exiting...") exit 1 end - $databasepath = File.join( $dbrootpath.rstrip, "repodb" ) - if not File.directory?($databasepath) + $databasepath = File.join($dbrootpath.rstrip, 'repodb') + unless File.directory?($databasepath) log("Db directory #{$databasepath} does not exist, creating...") begin Dir.mkdir($databasepath) @@ -557,32 +557,32 @@ if not $onlyfiles then log("ERROR! #{$databasepath} can not be created!, exiting ...") exit 1 end - end - $project=nil - $projects.each do |proj| - begin - scope = Project.active.has_module(:repository) - $project = scope.find_by_identifier(proj) - raise ActiveRecord::RecordNotFound unless $project - log("- Indexing repositories for #{$project.name} ...", :level=>1) - $repositories = $project.repositories.select { |repository| repository.supports_cat? } - $repositories.each do |repository| - if repository.identifier.nil? then - log("\t>Ignoring repo id #{repository.id}, repo has undefined identifier", :level=>1) - else - if !$userch.nil? then - changeset=Changeset.where("revision='#{$userch}' and repository_id='#{repository.id}'").first - update_log(repository,changeset,nil,nil) unless changeset.nil? - end - delete_log(repository) if ($resetlog) + end + + projects.each do |identifier| + begin + project = Project.active.find_by_identifier(identifier) + raise ActiveRecord::RecordNotFound unless project + raise ActiveRecord::RecordNotFound unless project.has_module(:repository) + log("- Indexing repositories for #{project.name} ...", :level => 1) + repositories = project.repositories.select { |repository| repository.supports_cat? } + repositories.each do |repository| + if repository.identifier.nil? then + log("\t>Ignoring repo id #{repository.id}, repo has undefined identifier", :level => 1) + else + if $userch + changeset = Changeset.where(:revision => $userch, :repository_id => repository.id).first + update_log(repository, changeset, nil, nil) if changeset + end + delete_log(repository) if ($resetlog) indexing(repository) - end + end end rescue ActiveRecord::RecordNotFound - log("- ERROR project identifier #{proj} not found, ignoring...", :level => 1) - Rails.logger.error "Project identifier #{proj} not found " + log("- ERROR project identifier #{identifier} not found or repository module not enabled, ignoring...", :level => 1) + Rails.logger.error "Project identifier #{identifier} not found " end end end -exit 0 +exit 0 \ No newline at end of file diff --git a/init.rb b/init.rb index eb332460..b95901d6 100644 --- a/init.rb +++ b/init.rb @@ -28,7 +28,7 @@ Redmine::Plugin.register :redmine_dmsf do name 'DMSF' author 'Vit Jonas / Daniel Munn / Karel Picman' description 'Document Management System Features' - version '1.5.1 stable' + version '1.5.2' url 'http://www.redmine.org/plugins/dmsf' author_url 'https://github.com/danmunn/redmine_dmsf/graphs/contributors' @@ -74,7 +74,7 @@ Redmine::Plugin.register :redmine_dmsf do {:dmsf => [:new, :create, :delete, :edit, :save, :edit_root, :save_root, :lock, :unlock, :notify_activate, :notify_deactivate, :restore]} permission :file_manipulation, {:dmsf_files => [:create_revision, :lock, :unlock, :delete_revision, :notify_activate, :notify_deactivate, :restore], - :dmsf_upload => [:upload_files, :upload_file, :commit_files], + :dmsf_upload => [:upload_files, :upload_file, :upload, :commit_files, :commit], :dmsf_links => [:new, :create, :destroy, :restore] } permission :file_delete, @@ -84,27 +84,25 @@ Redmine::Plugin.register :redmine_dmsf do permission :file_approval, {:dmsf_workflows => [:action, :new_action, :autocomplete_for_user, :start, :assign, :assignment]} permission :manage_workflows, - {:dmsf_workflows => [:index, :new, :create, :destroy, :show, :add_step, :remove_step, :reorder_steps, :update]} + {:dmsf_workflows => [:index, :new, :create, :destroy, :show, :new_step, :add_step, :remove_step, :reorder_steps, :update]} end # Administration menu extension Redmine::MenuManager.map :admin_menu do |menu| - menu.push :approvalworkflows, {:controller => 'dmsf_workflows', :action => 'index'}, :caption => :label_dmsf_workflow_plural + menu.push :approvalworkflows, {:controller => 'dmsf_workflows', :action => 'index'}, :caption => :label_dmsf_workflow_plural end Redmine::WikiFormatting::Macros.register do desc "Wiki link to DMSF file:\n\n" + - "!{{dmsf(file_id [, title [, revision_id]])}}\n\n" + - "_file_id_ / _revision_id_ can be found in link for file/revision download." + "{{dmsf(file_id [, title [, revision_id]])}}\n\n" + + "_file_id_ / _revision_id_ can be found in the link for file/revision download." macro :dmsf do |obj, args| - return nil if args.length < 1 # require file id - entry_id = args[0].strip - entry = DmsfFile.find(entry_id) - if entry && !entry.deleted && User.current && User.current.allowed_to?(:view_dmsf_files, entry.project) - title = args[1] ? args[1] : entry.title - revision = args[2] ? args[2] : '' - return link_to h(title), download_revision_path(entry, revision, :only_path => false) + return nil if args.length < 1 # require file id + entry = DmsfFile.visible.find_by_id args[0].strip + if entry && User.current && User.current.allowed_to?(:view_dmsf_files, entry.project) + title = args[1] ? args[1] : entry.title + return link_to h(title), dmsf_file_url(entry, :download => args[2]) end nil end @@ -112,18 +110,17 @@ Redmine::Plugin.register :redmine_dmsf do Redmine::WikiFormatting::Macros.register do 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 link for folder opening." + "{{dmsff(folder_id [, title])}}\n\n" + + "_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), :controller => 'dmsf', :action => 'show', :id => @project, :only_path => false - else - entry_id = args[0].strip - entry = DmsfFolder.find(entry_id) + return link_to l(:link_documents), dmsf_folder_url(@project) + else + entry = DmsfFolder.visible.find_by_id args[0].strip if entry && User.current && User.current.allowed_to?(:view_dmsf_folders, entry.project) title = args[1] ? args[1] : entry.title - return link_to h(title), dmsf_folder_path(entry.project, :folder_id => entry, :only_path => false) + return link_to h(title), dmsf_folder_url(entry.project, :folder_id => entry) end end nil @@ -132,19 +129,18 @@ Redmine::Plugin.register :redmine_dmsf do Redmine::WikiFormatting::Macros.register do desc "Wiki link to DMSF document description:\n\n" + - "{{dmsfd(file_id [, title])}}\n\n" + - "_file_id_ / _revision_id_ can be found in link for file/revision download." + "{{dmsfd(file_id)}}\n\n" + + "_file_id_ can be found in the link for file/revision download." macro :dmsfd do |obj, args| - return nil if args.length < 1 # require file id - entry_id = args[0].strip - entry = DmsfFile.find(entry_id) - if entry && !entry.deleted && User.current && User.current.allowed_to?(:view_dmsf_files, entry.project) - title = args[1] ? args[1] : entry.title - return link_to h(title), dmsf_file_path(entry, :only_path => false) + return nil if args.length < 1 # require file id + entry = DmsfFile.visible.find_by_id args[0].strip + if entry && User.current && User.current.allowed_to?(:view_dmsf_files, entry.project) + return entry.description end nil end + end # Rubyzip configuration @@ -154,4 +150,4 @@ end Redmine::Search.map do |search| search.register :dmsf_files search.register :dmsf_folders -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 086b76e4..08d405e2 100644 --- a/lib/redmine_dmsf/patches/project_patch.rb +++ b/lib/redmine_dmsf/patches/project_patch.rb @@ -67,8 +67,8 @@ module RedmineDmsf module InstanceMethods def dmsf_count - file_count = self.dmsf_files.visible.count + self.file_links.count - folder_count = self.dmsf_folders.visible.count + self.folder_links.count + file_count = self.dmsf_files.visible.count + self.file_links.visible.count + folder_count = self.dmsf_folders.visible.count + self.folder_links.visible.count self.dmsf_folders.visible.each do |f| file_count += f.deep_file_count folder_count += f.deep_folder_count diff --git a/lib/redmine_dmsf/webdav/base_resource.rb b/lib/redmine_dmsf/webdav/base_resource.rb index aa51df71..f50bd9f2 100644 --- a/lib/redmine_dmsf/webdav/base_resource.rb +++ b/lib/redmine_dmsf/webdav/base_resource.rb @@ -78,7 +78,7 @@ module RedmineDmsf '-', '', '', - ] + entities unless parent.nil? + ] + entities if parent @response.body << index_page % [ path.empty? ? '/' : path, path.empty? ? '/' : path , entities ] end diff --git a/lib/redmine_dmsf/webdav/controller.rb b/lib/redmine_dmsf/webdav/controller.rb index a1140166..c8be5f39 100644 --- a/lib/redmine_dmsf/webdav/controller.rb +++ b/lib/redmine_dmsf/webdav/controller.rb @@ -1,7 +1,9 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # # Copyright (C) 2012 Daniel Munn -# Copyright (C) 2011-14 Karel Picman +# Copyright (C) 2011-15 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 diff --git a/lib/redmine_dmsf/webdav/dmsf_resource.rb b/lib/redmine_dmsf/webdav/dmsf_resource.rb index 0d3488b1..a399a7f2 100644 --- a/lib/redmine_dmsf/webdav/dmsf_resource.rb +++ b/lib/redmine_dmsf/webdav/dmsf_resource.rb @@ -54,7 +54,7 @@ module RedmineDmsf return @children if @children @children = [] return [] unless collection? - folder.subfolders.map do |p| + folder.subfolders.visible.map do |p| @children.push child(p.title) end folder.files.visible.map do |p| @@ -81,13 +81,13 @@ module RedmineDmsf # Todo: Move folder data retrieval into folder function, and use folder method to determine existence def folder return @folder unless @folder == false - return nil if project.nil? || project.id.nil? #if the project doesnt exist, this entity can't exist + return nil if project.nil? || project.id.nil? #if the project doesn't exist, this entity can't exist @folder = nil # 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 - # existence check, and although I'm sure we'd love to access the heirarchy, I can't yet + # 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').all + 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) then folders.delete_if { |x| '/' + x.dmsf_path_str != projectless_path } @@ -132,7 +132,7 @@ module RedmineDmsf # 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').all + 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)} if files.length > 0 @file = files[0] @@ -252,55 +252,42 @@ module RedmineDmsf # Behavioural differences between collection and single entity # 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 - if dest.is_a?(ResourceProxy) - resource = dest.resource - else - resource = dest - end - + # 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 raise Forbidden unless User.current.admin? || User.current.allowed_to?(:folder_manipulation, project) #Current object is a folder, so now we need to figure out information about Destination - if(dest.exist?) then - + if dest.exist? MethodNotAllowed - else - 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 + folder.dmsf_folder_id = parent.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) + User.current.allowed_to?(:folder_manipulation, resource.project) - if(dest.exist?) then - - methodNotAllowed - + if dest.exist? + 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 @@ -311,8 +298,11 @@ module RedmineDmsf 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] - file.last_revision.name = resource.basename if file.last_revision - file.name = resource.basename + if file.last_revision + file.last_revision.name = resource.basename + file.last_revision.title = DmsfFileRevision.filename_to_title(resource.basename) + end + file.name = resource.basename # Save Changes (file.last_revision.save! && file.save!) ? Created : PreconditionFailed diff --git a/lib/redmine_dmsf/webdav/no_parse.rb b/lib/redmine_dmsf/webdav/no_parse.rb index ee8625bc..bef4080c 100644 --- a/lib/redmine_dmsf/webdav/no_parse.rb +++ b/lib/redmine_dmsf/webdav/no_parse.rb @@ -46,5 +46,6 @@ end # This should probably be configurable somehow or better have the module hunt for the correct pathing # automatically without the need to add a "/dmsf/webdav" configuration to it, as if the route is changed # the functonality of this patch will effectively break. -Rails.configuration.middleware.insert_before(ActionDispatch::ParamsParser, - RedmineDmsf::NoParse, :urls => ['/dmsf/webdav']) \ No newline at end of file +Rails.configuration.middleware.insert_before( + ActionDispatch::ParamsParser, + RedmineDmsf::NoParse, :urls => ["#{Redmine::Utils::relative_url_root}/dmsf/webdav"]) \ No newline at end of file diff --git a/lib/redmine_dmsf/webdav/resource_proxy.rb b/lib/redmine_dmsf/webdav/resource_proxy.rb index 96df6af7..1742c8a3 100644 --- a/lib/redmine_dmsf/webdav/resource_proxy.rb +++ b/lib/redmine_dmsf/webdav/resource_proxy.rb @@ -1,7 +1,9 @@ +# encoding: utf-8 +# # Redmine plugin for Document Management System "Features" # # Copyright (C) 2012 Daniel Munn -# Copyright (C) 2011-14 Karel Picman +# Copyright (C) 2011-15 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 diff --git a/lib/tasks/dmsf_convert_documents.rake b/lib/tasks/dmsf_convert_documents.rake index 82e0321f..7df67efd 100644 --- a/lib/tasks/dmsf_convert_documents.rake +++ b/lib/tasks/dmsf_convert_documents.rake @@ -141,19 +141,12 @@ class DmsfConvertDocuments revision.comment = 'Converted from documents' revision.mime_type = attachment.content_type - revision.disk_filename = revision.new_storage_filename - attachment_file = File.open(attachment.diskfile, 'rb') + revision.disk_filename = revision.new_storage_filename unless dry - File.open(revision.disk_file, 'wb') do |f| - while (buffer = attachment_file.read(8192)) - f.write(buffer) - end - end + FileUtils.cp(attachment.diskfile, revision.disk_file) revision.size = File.size(revision.disk_file) - end - - attachment_file.close + end if dry puts "Dry check revision: #{revision.title}"