devel-1.5.2 merged to the master

This commit is contained in:
Karel Pičman 2015-07-14 10:43:04 +02:00
commit 9b5d7b8942
87 changed files with 984 additions and 609 deletions

View File

@ -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

View File

@ -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 <redmine_root>/public/help/<language>/wiki_syntax_detailed.html, aft
<li>
DMSF:
<ul>
<li><strong>{{dmsf(17)}}</strong> (link to file with id 17)</li>
<li><strong>{{dmsf(17,File)}}</strong> (link to file with id 17 with link text "File")</li>
<li><strong>{{dmsf(17,File,10)}}</strong> (link to file with id 17 with link text "File" and link pointing to revision 10)</li>
<li><strong>{{dmsff(5)}}</strong> (link to folder with id 5)</li>
<li><strong>{{dmsff(5,Folder)}}</strong> (link to folder with id 5 with link text "Folder")</li>
<li><strong>{{dmsf(17)}}</strong> (a link to the file with id 17)</li>
<li><strong>{{dmsf(17, File)}}</strong> (a link to the file with id 17 with the link text "File")</li>
<li><strong>{{dmsf(17, File, 10)}}</strong> (a link to the file with id 17 with the link text "File" and the link pointing to the revision 10)</li>
<li><strong>{{dmsfd(17)}}</strong> (a link to the description of the file with id 17)</li>
<li><strong>{{dmsff(5)}}</strong> (a link to the folder with id 5)</li>
<li><strong>{{dmsff(5, Folder)}}</strong> (a link to the folder with id 5 with the link text "Folder")</li>
</ul>
The DMSF file/revision id can be found in the link for file/revision download from within Redmine.<br />
The DMSF folder id can be found in the link when opening folders within Redmine.
@ -152,15 +153,23 @@ 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"
### Fulltext search (optional)
@ -175,7 +184,7 @@ 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.

View File

@ -32,6 +32,8 @@ class DmsfController < ApplicationController
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
@ -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,6 +142,13 @@ 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?
respond_to do |format|
format.html {
render :layout => !request.xhr?
}
format.api
end
end
def trash
@ -226,19 +241,14 @@ class DmsfController < ApplicationController
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?
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
@ -250,12 +260,10 @@ class DmsfController < ApplicationController
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
@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
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)
@ -609,6 +634,4 @@ class DmsfController < ApplicationController
:cc, :subject, :zipped_content => [], :files => [])
end
end

View File

@ -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.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

View File

@ -1,3 +1,5 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
@ -25,11 +27,8 @@ class DmsfLinksController < ApplicationController
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
@dmsf_link = DmsfLink.new
@dmsf_link.project_id = params[:project_id]
if params[:dmsf_link].present?
# Reload

View File

@ -26,11 +26,13 @@ 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]
@uploads = []
@ -52,25 +54,22 @@ class DmsfUploadController < ApplicationController
# async single file upload handling
def upload_file
if (Rails::VERSION::MAJOR > 3)
@tempfile = params.require(:file)
else
@tempfile = params[:file]
end
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!
@ -180,22 +212,20 @@ class DmsfUploadController < ApplicationController
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)
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
private
end
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}"

View File

@ -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
@ -247,6 +247,7 @@ class DmsfWorkflowsController < ApplicationController
redirect_to dmsf_workflows_path
end
else
flash[:error] = @dmsf_workflow.errors.full_messages.to_sentence
redirect_to dmsf_workflow_path(@dmsf_workflow)
end
end
@ -269,15 +270,25 @@ 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 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 = User.where(:id => params[:user_ids])
if users.count > 0
users.each do |user|
ws = DmsfWorkflowStep.new(
:dmsf_workflow_id => @dmsf_workflow.id,
@ -287,9 +298,12 @@ class DmsfWorkflowsController < ApplicationController
if ws.save
@dmsf_workflow.dmsf_workflow_steps << ws
else
flash[:error] = l(:error_workflow_assign)
flash[:error] = @dmsf_workflow.errors.full_messages.to_sentence
end
end
else
flash[:error] = l(:error_workflow_assign)
end
end
respond_to do |format|
format.html

View File

@ -1,6 +1,8 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-14 Karel Picman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -25,9 +27,13 @@ module DmsfWorkflowsHelper
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')
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', principals_check_box_tags('user_ids[]', principals), :id => 'users')
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|

View File

@ -32,9 +32,6 @@ class DmsfFile < ActiveRecord::Base
include RedmineDmsf::Lockable
attr_accessor :event_description
attr_accessible :project
belongs_to :project
belongs_to :folder, :class_name => 'DmsfFolder', :foreign_key => 'dmsf_folder_id'
belongs_to :deleted_by_user, :class_name => 'User', :foreign_key => 'deleted_by_user_id'
@ -64,13 +61,12 @@ class DmsfFile < ActiveRecord::Base
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,12 +80,30 @@ 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 },
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
@notifications = Setting.plugin_redmine_dmsf['dmsf_default_notifications']
@ -292,21 +306,23 @@ 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)
projects = [] << projects if projects.is_a?(Project)
project_ids = projects.collect(&:id) if projects
find_options = {}
find_options[:order] = 'dmsf_files.updated_at ' + (options[:before] ? 'DESC' : 'ASC')
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 ?)"}
@ -314,17 +330,15 @@ class DmsfFile < ActiveRecord::Base
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
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]
@ -392,27 +406,15 @@ class DmsfFile < ActiveRecord::Base
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
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
if dmsf_file.project
project_included = x[:id] == dmsf_file.project.id
else
project_included = false
end
end
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
end
results << dmsf_file
end
end
end
@ -421,12 +423,12 @@ class DmsfFile < ActiveRecord::Base
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]] }
r = self.search(tokens, projects, options, user)[0]
r.map{ |f| [f.updated_at.to_i, f.id]}
end
def display_name

View File

@ -27,8 +27,6 @@ class DmsfFolder < ActiveRecord::Base
cattr_reader :invalid_characters
@@invalid_characters = /\A[^\/\\\?":<>]*\z/
attr_accessible :title, :description, :dmsf_folder_id, :project
belongs_to :project
belongs_to :folder, :class_name => 'DmsfFolder', :foreign_key => 'dmsf_folder_id'
belongs_to :deleted_by_user, :class_name => 'User', :foreign_key => 'deleted_by_user_id'
@ -39,49 +37,54 @@ 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
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
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
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 },
@ -89,6 +92,12 @@ class DmsfFolder < ActiveRecord::Base
: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
before_create :default_values
def default_values
@notifications = Setting.plugin_redmine_dmsf['dmsf_default_notifications']
@ -281,49 +290,6 @@ class DmsfFolder < ActiveRecord::Base
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|
@ -344,6 +310,15 @@ class DmsfFolder < ActiveRecord::Base
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
def self.directory_subtree(tree, folder, level, current_folder)

View File

@ -96,14 +96,12 @@ class DmsfLink < ActiveRecord::Base
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
path = self.target_file.dmsf_path.map { |element| element.is_a?(DmsfFile) ? element.name : element.title }.join('/') if self.target_file
else
folder = self.target_folder
path = folder.dmsf_path_str if folder
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

View File

@ -1,7 +1,9 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2011-14 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -114,7 +116,7 @@ class DmsfMailer < Mailer
end
end
notify_members.collect { |m| m.user }
notify_members.collect { |m| m.user }.uniq
end
end

View File

@ -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

View File

@ -1,7 +1,9 @@
<%#=
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-14 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -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? %>
<td class="check"><%= check_box_tag(name, id, false,
:title => l(:title_check_for_zip_download_or_email)) %></td>
@ -30,11 +32,11 @@
<% if link %>
<div class="filename" title="<%= l(:label_target_folder)%>"><%= link.path %></div>
<% else %>
<div class="filename" title="<%= l(:title_number_of_files_in_directory)%>">[<%= subfolder.files.visible.count + subfolder.file_links.visible.count %>]</div>
<div class="filename" title="<%= l(:title_items)%>">[<%= subfolder.items %>]</div>
<% end %>
</td>
<td class="size"></td>
<td class="modified"><%= format_time(subfolder.modified) %>
<td class="modified"><%= format_time(subfolder.modified) if subfolder %>
<% if locked_for_user %>
<% if subfolder.lock.reverse[0].user %>
<%= link_to('',
@ -52,20 +54,24 @@
</td>
<td class="version"></td>
<td class="workflow"></td>
<td class="author"><%= h(subfolder.user) %></td>
<td class="author"><%= h(subfolder.user) if subfolder %></td>
<td class="actions">
<% if @folder_manipulation_allowed %>
<div class="right_icon_box">
<% 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') %>
<% if subfolder %>
<%= link_to('',
lock_dmsf_path(:id => project, :folder_id => subfolder),
:title => l(:title_lock_file),
:class => 'icon icon-dmsf-lock') %>
<% if subfolder.notification %>
<% else %>
<span class="icon"></span>
<% 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 @@
</td>
<td class="invisible">0</td>
<td class="invisible">0</td>
<td class="invisible"><%= subfolder.updated_at.to_i %></td>
<td class="invisible"><%= subfolder.modified.to_i if subfolder %></td>
<td class="invisible">0</td>

View File

@ -1,4 +1,6 @@
<%#=
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
@ -27,12 +29,12 @@
<% if link %>
<div class="filename" title="<%= l(:label_target_folder)%>"><%= link.path %></div>
<% else %>
<div class="filename" title="<%= l(:title_number_of_files_in_directory)%>">[<%= subfolder.files.visible.count + subfolder.file_links.visible.count %>]</div>
<div class="filename" title="<%= l(:title_items)%>">[<%= subfolder.items %>]</div>
<% end %>
</td>
<td class="size"></td>
<td class="modified">
<%= format_time(subfolder.updated_at) %>
<%= format_time(subfolder.modified) if subfolder %>
</td>
<td class="version"></td>
<td class="workflow"></td>
@ -54,5 +56,5 @@
</td>
<td class="invisible">0</td>
<td class="invisible">0</td>
<td class="invisible"><%= subfolder.updated_at.to_i %></td>
<td class="invisible"><%= subfolder.modified.to_i if subfolder %></td>
<td class="invisible">0</td>

View File

@ -1,4 +1,6 @@
<%#=
# encode: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>

View File

@ -21,12 +21,9 @@
<td class="check"><%= check_box_tag(name, id, false,
:title => l(:title_check_for_restore_or_delete)) %></td>
<td class="title">
<% 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)}") %>
<div class="filename" title="<%= l(:title_filename_for_download)%>"><%= h(link ? link.path : file.display_name) %></div>
</td>
<td class="size"><%= number_to_human_size(file.last_revision.size) %></td>

View File

@ -1,7 +1,9 @@
<%#=
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-14 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -55,5 +57,5 @@
</td>
<td class="invisible">1</td>
<td class="invisible"></td>
<td class="invisible"></td>
<td class="invisible">link.updated_at.to_i</td>
<td class="invisible"></td>

View File

@ -1,4 +1,6 @@
<%#=
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
@ -50,5 +52,5 @@
</td>
<td class="invisible">1</td>
<td class="invisible"></td>
<td class="invisible"></td>
<td class="invisible">link.updated_at.to_i</td>
<td class="invisible"></td>

View File

@ -0,0 +1,4 @@
api.dmsf_folder do
api.id @folder.id
api.title @folder.title
end

View File

@ -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

View File

@ -154,6 +154,10 @@
</tr>
<% end %>
<% @dir_links.each do |link| %>
<% unless link.target_project %>
<% Rails.logger.error "Error: dmsf_link id #{link.id} has no target!" %>
<% next %>
<% end %>
<tr class="gray">
<%= 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 %>";
}
});

View File

@ -1,4 +1,6 @@
<%#=
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
@ -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 %>";
}
});

View File

@ -1,8 +1,8 @@
api.file do
api.dmsf_file do
api.id @file.id
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

View File

@ -1,4 +1,6 @@
<%#=
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
@ -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) %>
</div>
<i><%= l(:info_revision, :rev => revision.id) %></i>
<%= (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 %>
</div>
</div>
<div style="border: 1px solid #e4e4e4;">

View File

@ -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

View File

@ -0,0 +1,3 @@
api.upload do
api.token @attachment.token
end

View File

@ -0,0 +1,36 @@
<%
# encoding: utf-8
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
%>
<fieldset class="box">
<legend><%=l(:label_dmsf_workflow_add_approver)%></legend>
<p><%= label_tag 'user_search', l(:label_user_search) %><%= text_field_tag 'user_search', nil %></p>
<%= 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) }')" %>
<div id="users">
<%= render_principals_for_new_dmsf_workflow_users(@dmsf_workflow, nil, nil) %>
</div>
</fieldset>
<fieldset class="box">
<legend><%= l(:label_dmsf_workflow_step) %></legend>
<%= select_tag 'step', dmsf_workflow_steps_options_for_select(@steps),
:id => 'selected_step', :style => "width:100px" %>
</fieldset>

View File

@ -0,0 +1,31 @@
<%
# encoding: utf-8
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
%>
<h3 class="title"><%= l(:dmsf_new_step) %></h3>
<%= form_for(:dmsf_workflow, {:url => edit_dmsf_workflow_path(@dmsf_workflow), :method => :post}) do |f| %>
<%= render :partial => 'new_step_form' %>
<p class="buttons">
<%= 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' %>
</p>
<% end %>

View File

@ -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 <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -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 %>
<h2><%= link_to l(:label_dmsf_workflow_plural), settings_project_path(@project, :tab => 'dmsf_workflow') %> &#187; <%=h @dmsf_workflow %></h2>
@ -30,8 +33,9 @@
<% end %>
<div class="tab-content" id="tab-content-members">
<div class="splitcontentleft">
<p>
<%= link_to l(:dmsf_new_step), new_step_dmsf_workflow_path(@dmsf_workflow), :remote => true, :class => 'icon icon-add' %>
</p>
<% steps = @dmsf_workflow.dmsf_workflow_steps.collect{|s| s.step}.uniq %>
<% if steps.any? %>
<table class="list">
@ -67,29 +71,3 @@
<p class="nodata"><%= l(:label_no_data) %></p>
<% end %>
</div>
<div class="splitcontentright">
<%= form_for(@dmsf_workflow, :url => edit_dmsf_workflow_path(@dmsf_workflow),
:html => {:method => :post}) do |f| %>
<fieldset><legend><%=l(:label_user_new)%></legend>
<p><%= label_tag 'user_search', l(:label_user_search) %><%= text_field_tag 'user_search', nil %></p>
<%= 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) }')" %>
<div id="users">
<%= render_principals_for_new_dmsf_workflow_users(@dmsf_workflow, nil, nil) %>
</div>
<p>
<%= l(:label_dmsf_workflow_step) %>
<%= select_tag 'step',
dmsf_workflow_steps_options_for_select(steps),
:id => 'selected_step', :style => "width:100px" %>
</p>
<p><%= l(:label_dmsf_workflow_add_approver) %></p>
<p><%= submit_tag l(:dmsf_and) %>&nbsp<%= l(:label_or) %>&nbsp<%= submit_tag l(:dmsf_or) %></p>
</fieldset>
<% end %>
</div>
</div>

View File

@ -1,6 +1,6 @@
<%# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2013 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -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');

View File

@ -1,6 +1,6 @@
<%# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2013 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -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');

View File

@ -1,6 +1,6 @@
<%# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2013 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -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');

View File

@ -0,0 +1,19 @@
<%
# encoding: utf-8
#
# Redmine plugin for Kontron customisation
# Copyright (c) 2011-15 Kontron
# Karel Pičman <karel.picman@kontron.com>
#
# Repository folders
%>
<h2><%= l(:label_repository_folders) %></h2>
<%= form_for(:repository_folder, {:url => edit_dmsf_workflow_path(@dmsf_workflow), :method => :post}) do |f| %>
<%= render :partial => 'new_step_form' %>
<p>
<%= submit_tag l(:dmsf_and), :id => 'add-step-and' %>
<%= submit_tag l(:dmsf_or), :id => 'add-step-or' %>
</p>
<% end %>

View File

@ -0,0 +1,20 @@
<%# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.%>
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'new_step_modal') %>');
showModal('ajax-modal', '40%');

Binary file not shown.

Before

Width:  |  Height:  |  Size: 803 B

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 419 B

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 759 B

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 416 B

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 764 B

After

Width:  |  Height:  |  Size: 427 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 B

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 719 B

After

Width:  |  Height:  |  Size: 421 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 413 B

After

Width:  |  Height:  |  Size: 350 B

View File

@ -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í
text_email_doc_updated_subject: "Dokumenty projektu %{project} aktualizovány"
text_email_doc_updated: právě aktualizoval dokumenty projektu

View File

@ -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_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
text_email_doc_updated_subject: "Dokumente im Projekt %{project} wurden aktualisiert"
text_email_doc_updated: hat folgende Dokumente bearbeitet

View File

@ -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

View File

@ -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
text_email_doc_updated_subject: "Documentos de %{project} actualizados"
text_email_doc_updated: acaba de actualizar los ducumentos de

View File

@ -1,3 +1,5 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
@ -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
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:

View File

@ -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: 文書

View File

@ -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
text_email_doc_updated_subject: "Dokumenty projektu %{project} zostały zaktualizowane"
text_email_doc_updated: dokumenty zostały zaktualizowane

View File

@ -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
text_email_doc_updated_subject: "Documents of %{project} updated"
text_email_doc_updated: has just actualized documents of

View File

@ -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
text_email_doc_updated_subject: "Documents of %{project} updated"
text_email_doc_updated: has just actualized documents of

View File

@ -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: 檔案己經鎖定
@ -81,9 +81,7 @@ zh-TW:
title_approved: 已經被批准
title_unlock_file: 解除鎖定。允許其它使用者修改。
title_lock_file: 鎖定檔案。禁止其它使用者修改。
submit_download: 下載
title_download_checked: 以ZIP下載所選取的檔案
submit_email: 電子郵件
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
text_email_doc_updated_subject: "Documents of %{project} updated"
text_email_doc_updated: has just actualized documents of
@ -310,6 +310,14 @@ zh-TW:
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:
locked_documents: Locked documents

View File

@ -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
text_email_doc_updated_subject: "Documents of %{project} updated"
text_email_doc_updated: has just actualized documents of

View File

@ -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,6 +126,7 @@ RedmineApp::Application.routes.draw do
post 'new_action'
get 'start'
post 'assignment'
get 'new_step'
end
end

View File

@ -1,6 +1,8 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2013 Karel Picman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,8 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2013 Karel Picman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,8 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2013 Karel Picman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,8 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2013 Karel Picman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,8 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2013 Karel Picman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,8 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2013 Karel Picman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,8 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2013 Karel Picman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,8 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2013 Karel Picman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,8 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2013 Karel Picman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,8 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2014 Karel Pičman <karel.picman@lbcfree.net>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,8 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2014 Karel Pičman <karel.picman@lbcfree.net>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -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

View File

@ -1,6 +1,8 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-14 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,8 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-14 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,8 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-14 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -20,8 +22,4 @@ class RemoveUniquenessFromWf < ActiveRecord::Migration
def up
remove_index :dmsf_workflows, :name
end
def down
add_index :dmsf_workflows, [:name], :unique => true
end
end

View File

@ -2,7 +2,7 @@
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-15 Karel Pičman <karel.picman@lbcfree.net>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@ -1,13 +1,30 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class 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
remove_column :dmsf_links, :external_url
end
end

View File

@ -1,3 +1,23 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class AddUserToLinks < ActiveRecord::Migration
def up
add_column :dmsf_links, :user_id, :integer

Binary file not shown.

View File

@ -1,3 +1,5 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
@ -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.content_url
else
puts 'No file with id = 1 found'
puts "No file with id = #{FILE_ID} found"
end

43
extra/api/api_client.sh Normal file
View File

@ -0,0 +1,43 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#!/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

BIN
extra/api/cat.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

13
extra/api/file.xml Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8" ?>
<attachments>
<folder_id>6118</folder_id>
<uploaded_file>
<disk_filename>cat.gif</disk_filename>
<name>cat.gif</name>
<title>cat.gif</title>
<description>REST API</description>
<comment>From API</comment>
<version/>
<token>15838.c49f68ff81b552d315927df2e27df506</token>
</uploaded_file>
</attachments>

6
extra/api/folder.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<dmsf_folder>
<title>rest_api</title>
<description>A folder created via REST API</description>
<dmsf_folder_id/>
</dmsf_folder>

View File

@ -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)
@ -558,29 +558,29 @@ if not $onlyfiles then
exit 1
end
end
$project=nil
$projects.each do |proj|
projects.each do |identifier|
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|
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.nil? then
changeset=Changeset.where("revision='#{$userch}' and repository_id='#{repository.id}'").first
update_log(repository,changeset,nil,nil) unless changeset.nil?
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
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

42
init.rb
View File

@ -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,7 +84,7 @@ 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
@ -94,17 +94,15 @@ Redmine::Plugin.register :redmine_dmsf do
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)
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
revision = args[2] ? args[2] : ''
return link_to h(title), download_revision_path(entry, revision, :only_path => false)
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
return link_to l(:link_documents), dmsf_folder_url(@project)
else
entry_id = args[0].strip
entry = DmsfFolder.find(entry_id)
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)
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

View File

@ -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

View File

@ -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

View File

@ -1,7 +1,9 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011-14 Karel Picman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@ -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,31 +252,23 @@ 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
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?)
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
@ -285,22 +277,17 @@ module RedmineDmsf
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)
if(dest.exist?) then
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.
else
if(parent.projectless_path == '/') #Project root
f = nil
else
@ -311,7 +298,10 @@ 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
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

View File

@ -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'])
Rails.configuration.middleware.insert_before(
ActionDispatch::ParamsParser,
RedmineDmsf::NoParse, :urls => ["#{Redmine::Utils::relative_url_root}/dmsf/webdav"])

View File

@ -1,7 +1,9 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011-14 Karel Picman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@ -142,19 +142,12 @@ class DmsfConvertDocuments
revision.mime_type = attachment.content_type
revision.disk_filename = revision.new_storage_filename
attachment_file = File.open(attachment.diskfile, 'rb')
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
if dry
puts "Dry check revision: #{revision.title}"
if revision.invalid?