Merge branch 'devel-1.4.8'

This commit is contained in:
Karel Picman 2014-04-17 09:47:59 +02:00
commit c0eaaa1966
181 changed files with 3869 additions and 4006 deletions

View File

@ -1,6 +1,34 @@
Changelog for Redmine DMSF
==========================
1.4.8: **
-----------------------
Symbolic links
Document tagging
Localization of email notifications
An option to send document links by email
* New: Issue #19 - Documentation?
* Update: Issue #106 - [Feature Request] Save files in folder structure defined via DMSF
* Fix: Issue #107 - Problems upgrading redmine 1.3 to 2.23 regarding DMFS
* Fix: Issue #111 - Cannot sort files in folders by date, size, etc
* Update: Issue #139 - Error 500 on click on "details" icon
* New: Issue #183 - Create document links
* New: Issue #201 - Download link by email
* Fix: Issue #205 - Ampersand shows up in displayed filenames as "&" instead of "&"
* Fix: Issue #212 - Incorrect revision information in email notification
* Fix: Issue #214 - Required DMSF custom field prevents documents to be saved
* Update: Issue #216 - Enhancement : having notification emails translated
* Update: Issue #224 - Setup/Upgrade documentation
* Fix: Issue #226 - undefined method `custom_fields_tabs' for module `CustomFieldsHelper'
* Fix: Issue #233 - Failed Travis builds
* Update: Issue #235 - "You are not member of the project" when changing project notification.
* New: Issue #236 - Documents tagging
* Fix: Issue #240 - Internal server error, redmine 2.5.1-devel.13064, PostgreSQL, dmsf 1.4.8-devel
* Fix: Issue #242 - dsmf 1.4.8 minor ... "link form" tab
* Fix: Issue #246 - "File storage directory" does not default properly when setting is empty
1.4.7: *2014-01-02*
-----------------------

View File

@ -4,6 +4,7 @@ gem 'rubyzip', '>= 1.0.0'
gem 'zip-zip' # Just to avoid 'cannot load such file -- zip/zip' error
gem 'simple_enum'
gem 'uuidtools', '~> 2.1.1'
gem 'dav4rack', '=0.2.11'
group :production do
gem 'nokogiri', '>= 1.5.10'

View File

@ -1,14 +1,13 @@
Redmine DMSF Plugin
===================
The current version of Redmine DMSF is **1.4.7**
The current version of Redmine DMSF is **1.4.8** [![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.
Redmine DMSF now comes bundled with Webdav functionality: if switched on within plugin settings this will be accessible from /dmsf/webdav.
Webdav functionality is provided through DAV4Rack, however is provided bundled due to modifications made, DAV4Rack is released under the terms of the
MIT license, more information can be found at <https://github.com/chrisrobers/dav4rack>
Webdav functionality is provided through DAV4Rack gem.
Initial development was for Kontron AG R&D department and it is released as open source thanks to their generosity.
Project home: <http://code.google.com/p/redmine-dmsf/>
@ -28,26 +27,21 @@ Features
* Document locking
* Multi (drag/drop depending on browser) upload/download
* Multi download via zip
* Direct document sending via email
* Direct document or document link sending via email
* Configurable document approval workflow
* Document access auditing
* Integration with Redmine's activity feed
* Wiki macros for quick content linking
* Full read/write webdav functionality
* Optional document content fulltext search
* Compatible with redmine 2.0.x
* Documents and folders symbolic links
* Document tagging
* Compatible with redmine 2.5.x
Dependencies
------------
As of version 1.4.4 of this plugin:
* Bundler 1.1 or greater (Gem)
* Redmine 2.0.x
* Rails 3.2.x (Inline with Redmine installation requirement)
* rubyzip 1.0.0 (Gem)
* UUIDTools 2.1.1 or greater (less than 2.2.0) (Gem)
* simple_enum (Gem)
* Redmine 2.3.x or higher
### Fulltext search (optional)
@ -117,7 +111,9 @@ The DMSF file/revision id can be found in link for file/revision download from w
The DMSF folder id can be found in the link when opening folders within Redmine.
You can also publish Wiki help description: In the file <redmine_root>/public/help/wiki_syntax_detailed.html, after the document link description/definition:
You can also publish Wiki help description:
In the file <redmine_root>/public/help/<language>/wiki_syntax_detailed.html, after the document link description/definition:
<ul>
<li>
@ -134,6 +130,11 @@ You can also publish Wiki help description: In the file <redmine_root>/public/he
</li>
</ul>
In the file <redmine_root>/public/help/<language>/wiki_syntax.html, at the end of the Redmine links section:
<tr><th></th><td>{{dmsf(83)}}</td><td>Document <a href="#">#83</a></td></tr>
Setup / Upgrade
---------------
@ -142,16 +143,21 @@ Before installing ensure that the Redmine instance is stopped.
1. In case of upgrade BACKUP YOUR DATABASE first
2. Put redmine_dmsf plugin directory into plugins
3. Initialize/Update database: `rake redmine:plugins:migrate RAILS_ENV="production"`
4. The access rights must be set for web server, example: `chown -R www-data:www-data /opt/redmine/plugins/redmine_dmsf`
*Ensure that the path used in the above is adjusted for your installation*
4. The access rights must be set for web server, example: `chown -R www-data:www-data plugins/redmine_dmsf`
5. Restart web server
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
rake redmine:dmsf_convert_documents project=test RAILS_ENV="production"
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
rake redmine:dmsf_alert_approvals RAILS_ENV="production"
Example:
rake redmine:dmsf_alert_approvals RAILS_ENV="production"
### Fulltext search (optional)
If you want to use fulltext search features, you must setup file content indexing.
@ -188,4 +194,4 @@ Changes with tests, and full documentation are preferred.
Additional Documentation
------------------------
[CHANGELOG.md](CHANGELOG.md) - Project changelog
[CHANGELOG.md](CHANGELOG.md) - Project changelog

View File

@ -1,8 +1,8 @@
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2013 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011-14 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
@ -26,7 +26,7 @@ class DmsfController < ApplicationController
class FileNotFound < StandardError; end
before_filter :find_project
before_filter :authorize, :except => [:delete_entries]
before_filter :authorize
before_filter :find_folder, :except => [:new, :create, :edit_root, :save_root]
before_filter :find_parent, :only => [:new, :create]
@ -37,36 +37,116 @@ class DmsfController < ApplicationController
@file_manipulation_allowed = User.current.allowed_to?(:file_manipulation, @project)
@force_file_unlock_allowed = User.current.allowed_to?(:force_file_unlock, @project)
@workflows_available = DmsfWorkflow.where(['project_id = ? OR project_id IS NULL', @project.id]).count > 0
unless @folder
@subfolders = @project.dmsf_folders.visible
@files = @project.dmsf_files.visible
if params[:custom_field_id].present? && params[:custom_value].present?
@subfolders = []
DmsfFolder.where(:project_id => @project.id).visible.each do |f|
f.custom_field_values.each do |v|
if v.custom_field_id == params[:custom_field_id].to_i
if v.custom_field.compare_values?(v.value, params[:custom_value])
@subfolders << f
break
end
end
end
end
@files = []
DmsfFile.where(:project_id => @project.id).visible.each do |f|
r = f.last_revision
if r
r.custom_field_values.each do |v|
if v.custom_field_id == params[:custom_field_id].to_i
if v.custom_field.compare_values?(v.value, params[:custom_value])
@files << f
break
end
end
end
end
end
@dir_links = []
DmsfLink.where(:project_id => @project.id, :target_type => DmsfFolder.model_name).visible.each do |l|
l.target_folder.custom_field_values.each do |v|
if v.custom_field_id == params[:custom_field_id].to_i
if v.custom_field.compare_values?(v.value, params[:custom_value])
@dir_links << l
break
end
end
end
end
@file_links = []
DmsfLink.where(:project_id => @project.id, :target_type => DmsfFile.model_name).visible.each do |l|
r = l.target_file.last_revision
if r
r.custom_field_values.each do |v|
if v.custom_field_id == params[:custom_field_id].to_i
if v.custom_field.compare_values?(v.value, params[:custom_value])
@file_links << l
break
end
end
end
end
end
else
@subfolders = @project.dmsf_folders.visible
@files = @project.dmsf_files.visible
@dir_links = @project.folder_links.visible
@file_links = @project.file_links.visible
end
@locked_for_user = false
else
@subfolders = @folder.subfolders.visible
@files = @folder.files.visible
@files = @folder.files.visible
@dir_links = @folder.folder_links.visible
@file_links = @folder.file_links.visible
@locked_for_user = @folder.locked_for_user?
end
@files.sort! do |a,b|
if a.last_revision && b.last_revision
a.last_revision.title <=> b.last_revision.title
else
0
end
end
@ajax_upload_size = Setting.plugin_redmine_dmsf['dmsf_max_ajax_upload_filesize'].present? ? Setting.plugin_redmine_dmsf['dmsf_max_ajax_upload_filesize'] : 100
end
def download_email_entries
send_file(
params[:path],
:filename => 'Documents.zip',
:type => 'application/zip',
:disposition => 'attachment')
rescue Exception => e
flash[:error] = e.message
end
def entries_operation
selected_folders = params[:subfolders]
selected_files = params[:files]
def entries_operation
# Download/Email
selected_folders = params[:subfolders].present? ? params[:subfolders] : []
selected_files = params[:files].present? ? params[:files] : []
selected_dir_links = params[:dir_links]
selected_file_links = params[:file_links]
if selected_folders.nil? && selected_files.nil?
flash[:warning] = l(:warning_no_entries_selected)
redirect_to :action => 'show', :id => @project, :folder_id => @folder
if selected_folders.blank? && selected_files.blank? &&
selected_dir_links.blank? && selected_file_links.blank?
flash[:warning] = l(:warning_no_entries_selected)
redirect_to :back
return
end
if selected_dir_links.present?
selected_dir_links.each do |id|
link = DmsfLink.find_by_id id
selected_folders << link.target_id if link
end
end
if selected_file_links.present?
selected_file_links.each do |id|
link = DmsfLink.find_by_id id
selected_files << link.target_id if link
end
end
if params[:email_entries].present?
email_entries(selected_folders, selected_files)
else
@ -74,74 +154,117 @@ class DmsfController < ApplicationController
end
rescue ZipMaxFilesError
flash[:error] = l(:error_max_files_exceeded, :number => Setting.plugin_redmine_dmsf['dmsf_max_file_download'])
redirect_to({:controller => 'dmsf', :action => 'show', :id => @project, :folder_id => @folder})
redirect_to :back
rescue EmailMaxFileSize
flash[:error] = l(:error_max_email_filesize_exceeded, :number => Setting.plugin_redmine_dmsf['dmsf_max_email_filesize'])
redirect_to({:controller => 'dmsf', :action => 'show', :id => @project, :folder_id => @folder})
redirect_to :back
rescue FileNotFound
render_404
rescue DmsfAccessError
render_403
end
def tag_changed
# Tag filter
if params[:dmsf_folder] && params[:dmsf_folder][:custom_field_values].present?
redirect_to dmsf_folder_path(
:id => @project,
:custom_field_id => params[:dmsf_folder][:custom_field_values].first[0],
:custom_value => params[:dmsf_folder][:custom_field_values].first[1])
else
redirect_to :back
end
end
def entries_email
@email_params = params[:email]
if @email_params['to'].strip.blank?
if @email_params[:to].strip.blank?
flash.now[:error] = l(:error_email_to_must_be_entered)
render :action => 'email_entries'
return
end
DmsfMailer.send_documents(User.current, @email_params['to'], @email_params['cc'],
@email_params['subject'], @email_params['zipped_content'], @email_params['body']).deliver
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'])
redirect_to({:controller => 'dmsf', :action => 'show', :id => @project, :folder_id => @folder})
redirect_to dmsf_folder_path(:id => @project, :folder_id => @folder)
end
def delete_entries
selected_folders = params[:subfolders]
selected_files = params[:files]
if selected_folders.nil? && selected_files.nil?
selected_dir_links = params[:dir_links]
selected_file_links = params[:file_links]
if selected_folders.blank? && selected_files.blank? &&
selected_dir_links.blank? && selected_file_links.blank?
flash[:warning] = l(:warning_no_entries_selected)
else
failed_entries = []
deleted_files = []
deleted_folders = []
if selected_folders
if User.current.allowed_to?(:folder_manipulation, @project)
failed_entries = []
if User.current.allowed_to?(:folder_manipulation, @project)
# Folders
if selected_folders.present?
selected_folders.each do |subfolderid|
subfolder = DmsfFolder.visible.find(subfolderid)
next if subfolder.nil?
subfolder = DmsfFolder.visible.find_by_id subfolderid
next unless subfolder
if subfolder.project != @project || !subfolder.delete
failed_entries.push(subfolder)
else
deleted_folders.push(subfolder)
failed_entries.push(subfolder)
end
end
else
flash[:error] = l(:error_user_has_not_right_delete_folder)
end
end
# Folder links
if selected_dir_links.present?
selected_dir_links.each do |dir_link_id|
link_folder = DmsfLink.visible.find_by_id dir_link_id
next unless link_folder
if link_folder.project != @project || !link_folder.delete
failed_entries.push(link_folder)
end
end
end
else
flash[:error] = l(:error_user_has_not_right_delete_folder)
end
if selected_files
if User.current.allowed_to?(:file_manipulation, @project)
deleted_files = []
if User.current.allowed_to?(:file_manipulation, @project)
# Files
if selected_files.present?
selected_files.each do |fileid|
file = DmsfFile.visible.find(fileid)
file = DmsfFile.visible.find_by_id fileid
next unless file
if file.project != @project || !file.delete
failed_entries.push(file)
else
deleted_files.push(file)
end
end
else
flash[:error] = l(:error_user_has_not_right_delete_file)
end
end
# File links
if selected_file_links.present?
selected_file_links.each do |file_link_id|
file_link = DmsfLink.visible.find_by_id file_link_id
next unless file_link
if file_link.project != @project || !file_link.delete
failed_entries.push(file_link)
end
end
end
else
flash[:error] = l(:error_user_has_not_right_delete_file)
end
unless deleted_files.empty?
deleted_files.each do |f|
log_activity(f, 'deleted')
end
DmsfMailer.files_deleted(User.current, deleted_files).deliver
begin
DmsfMailer.get_notify_users(User.current, deleted_files).each do |u|
DmsfMailer.files_deleted(u, @project, deleted_files).deliver
end
rescue Exception => e
Rails.logger.error "Could not send email notifications: #{e.message}"
end
end
if failed_entries.empty?
flash[:notice] = l(:notice_entries_deleted)
@ -149,8 +272,8 @@ class DmsfController < ApplicationController
flash[:warning] = l(:warning_some_entries_were_not_deleted, :entries => failed_entries.map{|e| e.title}.join(', '))
end
end
redirect_to :controller => 'dmsf', :action => 'show', :id => @project, :folder_id => @folder
redirect_to :back
end
# Folder manipulation
@ -194,16 +317,16 @@ class DmsfController < ApplicationController
end
end
def delete
check_project(@delete_folder = DmsfFolder.visible.find(params[:delete_folder_id]))
def delete
@delete_folder = DmsfFolder.visible.find(params[:delete_folder_id])
if @delete_folder
if @delete_folder.delete
flash[:notice] = l(:notice_folder_deleted)
else
flash[:error] = @delete_folder.errors[:base][0]
end
end
redirect_to :controller => 'dmsf', :action => 'show', :id => @project, :folder_id => @folder
end
redirect_to dmsf_folder_path(:id => @project, :folder_id => @delete_folder.dmsf_folder_id)
rescue DmsfAccessError
render_403
end
@ -229,14 +352,8 @@ class DmsfController < ApplicationController
@project.save
end
flash[:notice] = l(:notice_folder_notifications_activated)
end
if params[:current]
redirect_to params[:current]
elsif @folder
redirect_to({:controller => 'dmsf', :action => 'show', :id => @project, :folder_id => @folder.folder})
else
redirect_to({:controller => 'dmsf', :action => 'show', :id => @project})
end
redirect_to :back
end
def notify_deactivate
@ -250,17 +367,10 @@ class DmsfController < ApplicationController
@project.save
end
flash[:notice] = l(:notice_folder_notifications_deactivated)
end
if params[:current]
redirect_to params[:current]
elsif @folder
redirect_to({:controller => 'dmsf', :action => 'show', :id => @project, :folder_id => @folder.folder})
else
redirect_to({:controller => 'dmsf', :action => 'show', :id => @project})
end
redirect_to :back
end
def lock
if @folder.nil?
flash[:warning] = l(:warning_foler_unlockable)
@ -269,9 +379,8 @@ class DmsfController < ApplicationController
else
@folder.lock!
flash[:notice] = l(:notice_folder_locked)
end
redirect_to params[:current] ? params[:current] :
{:controller => 'dmsf', :action => 'show', :id => @project, :folder_id => @folder.folder}
end
redirect_to :back
end
def unlock
@ -286,9 +395,8 @@ class DmsfController < ApplicationController
else
flash[:error] = l(:error_only_user_that_locked_folder_can_unlock_it)
end
end
redirect_to params[:current] ? params[:current] :
{:controller => 'dmsf', :action => 'show', :id => @project, :folder_id => @folder.folder}
end
redirect_to :back
end
private
@ -302,9 +410,9 @@ class DmsfController < ApplicationController
zip = DmsfZip.new
zip_entries(zip, selected_folders, selected_files)
ziped_content = "#{DmsfHelper.temp_dir}/#{DmsfHelper.temp_filename('dmsf_email_sent_documents.zip')}";
zipped_content = "#{DmsfHelper.temp_dir}/#{DmsfHelper.temp_filename('dmsf_email_sent_documents.zip')}";
File.open(ziped_content, 'wb') do |f|
File.open(zipped_content, 'wb') do |f|
zip_file = File.open(zip.finish, 'rb')
while (buffer = zip_file.read(8192))
f.write(buffer)
@ -312,7 +420,7 @@ class DmsfController < ApplicationController
end
max_filesize = Setting.plugin_redmine_dmsf['dmsf_max_email_filesize'].to_f
if max_filesize > 0 && File.size(ziped_content) > max_filesize * 1048576
if max_filesize > 0 && File.size(zipped_content) > max_filesize * 1048576
raise EmailMaxFileSize
end
@ -323,7 +431,11 @@ class DmsfController < ApplicationController
audit.save!
end
@email_params = {'zipped_content' => ziped_content}
@email_params = {
:zipped_content => zipped_content,
:folders => selected_folders,
:files => selected_files
}
render :action => 'email_entries'
rescue Exception => e
flash[:error] = e.message
@ -357,14 +469,14 @@ class DmsfController < ApplicationController
def zip_entries(zip, selected_folders, selected_files)
if selected_folders && selected_folders.is_a?(Array)
selected_folders.each do |selected_folder_id|
check_project(folder = DmsfFolder.visible.find(selected_folder_id))
selected_folders.each do |selected_folder_id|
folder = DmsfFolder.visible.find(selected_folder_id)
zip.add_folder(folder, (@folder.dmsf_path_str if @folder)) if folder
end
end
if selected_files && selected_files.is_a?(Array)
selected_files.each do |selected_file_id|
check_project(file = DmsfFile.visible.find(selected_file_id))
selected_files.each do |selected_file_id|
file = DmsfFile.visible.find(selected_file_id)
if file && file.last_revision && File.exists?(file.last_revision.disk_file)
zip.add_file(file, (@folder.dmsf_path_str if @folder)) if file
else
@ -379,34 +491,22 @@ class DmsfController < ApplicationController
zip
end
def find_project
@project = Project.find(params[:id])
end
def find_folder
@folder = DmsfFolder.visible.find(params[:folder_id]) if params.keys.include?('folder_id')
check_project(@folder)
@folder = DmsfFolder.visible.find(params[:folder_id]) if params.keys.include?('folder_id')
rescue DmsfAccessError
render_403
end
def find_parent
@parent = DmsfFolder.visible.find(params[:parent_id]) if params.keys.include?('parent_id')
check_project(@parent)
@parent = DmsfFolder.visible.find(params[:parent_id]) if params.keys.include?('parent_id')
rescue DmsfAccessError
render_403
end
def check_project(entry)
if entry && entry.project != @project
raise DmsfAccessError, l(:error_entry_project_does_not_match_current_project)
end
end
def copy_folder(folder)
copy = folder.clone
copy.id = folder.id
copy
end
end
end

View File

@ -59,97 +59,104 @@ class DmsfFilesController < ApplicationController
end
@revision = @file.last_revision
# TODO: line bellow is to handle old installations with errors in data handling
@revision.name = @file.name
@revision_pages = Paginator.new @file.revisions.visible.count, params['per_page'] ? params['per_page'].to_i : 25, params['page']
render :layout => !request.xhr?
end
#TODO: don't create revision if nothing change
def create_revision
unless params[:dmsf_file_revision]
redirect_to :action => 'show', :id => @file
return
end
if @file.locked_for_user?
flash[:error] = l(:error_file_is_locked)
redirect_to :action => 'show', :id => @file
else
#TODO: validate folder_id
@revision = DmsfFileRevision.new(params[:dmsf_file_revision])
@revision.file = @file
@revision.project = @file.project
last_revision = @file.last_revision
@revision.source_revision = last_revision
@revision.user = User.current
@revision.major_version = last_revision.major_version
@revision.minor_version = last_revision.minor_version
version = params[:version].to_i
file_upload = params[:file_upload]
if file_upload.nil?
@revision.disk_filename = last_revision.disk_filename
@revision.increase_version(version, false)
@revision.mime_type = last_revision.mime_type
@revision.size = last_revision.size
else
@revision.increase_version(version, true)
@revision.size = file_upload.size
@revision.disk_filename = @revision.new_storage_filename
@revision.mime_type = Redmine::MimeType.of(file_upload.original_filename)
end
@file.name = @revision.name
@file.folder = @revision.folder
if @revision.valid? && @file.valid?
@revision.save!
@revision.assign_workflow(params[:dmsf_workflow_id])
if file_upload
@revision.copy_file_content(file_upload)
end
if @file.locked? && !@file.locks.empty?
begin
@file.unlock!
flash[:notice] = "#{l(:notice_file_unlocked)}, "
rescue Exception => e
logger.error "Cannot unlock the file: #{e.message}"
if params[:dmsf_file_revision]
if @file.locked_for_user?
flash[:error] = l(:error_file_is_locked)
else
@revision = DmsfFileRevision.new(params[:dmsf_file_revision])
@revision.file = @file
@revision.project = @file.project
last_revision = @file.last_revision
@revision.source_revision = last_revision
@revision.user = User.current
@revision.major_version = last_revision.major_version
@revision.minor_version = last_revision.minor_version
version = params[:version].to_i
file_upload = params[:file_upload]
unless file_upload
@revision.disk_filename = last_revision.disk_filename
@revision.increase_version(version, false)
@revision.mime_type = last_revision.mime_type
@revision.size = last_revision.size
else
@revision.increase_version(version, true)
@revision.size = file_upload.size
@revision.disk_filename = @revision.new_storage_filename
@revision.mime_type = Redmine::MimeType.of(file_upload.original_filename)
end
@file.name = @revision.name
@file.folder = @revision.folder
if @revision.valid? && @file.valid?
@revision.save!
@revision.assign_workflow(params[:dmsf_workflow_id])
if file_upload
@revision.copy_file_content(file_upload)
end
if @file.locked? && !@file.locks.empty?
begin
@file.unlock!
flash[:notice] = "#{l(:notice_file_unlocked)}, "
rescue Exception => e
logger.error "Cannot unlock the file: #{e.message}"
end
end
@file.save!
@file.set_last_revision @revision
flash[:notice] = (flash[:notice].nil? ? '' : flash[:notice]) + l(:notice_file_revision_created)
log_activity('new revision')
begin
recipients = DmsfMailer.get_notify_users(User.current, [@file])
recipients.each do |u|
DmsfMailer.files_updated(u, @project, [@file]).deliver
end
if Setting.plugin_redmine_dmsf[:dmsf_display_notified_recipients] == '1'
unless recipients.empty?
to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ')
to << ((recipients.count > DMSF_MAX_NOTIFICATION_RECEIVERS_INFO) ? ',...' : '.')
flash[:warning] = l(:warning_email_notifications, :to => to)
end
end
rescue Exception => e
logger.error "Could not send email notifications: #{e.message}"
end
end
@file.save!
@file.reload
flash[:notice] = (flash[:notice].nil? ? '' : flash[:notice]) + l(:notice_file_revision_created)
log_activity('new revision')
begin
DmsfMailer.files_updated(User.current, [@file]).deliver
rescue Exception => e
logger.error "Could not send email notifications: #{e.message}"
end
redirect_to :action => 'show', :id => @file
else
render :action => 'show'
end
end
redirect_to :back
end
def delete
if @file
if @file.delete
flash[:notice] = l(:notice_file_deleted)
log_activity('deleted')
DmsfMailer.files_deleted(User.current, [@file]).deliver
log_activity('deleted')
begin
DmsfMailer.get_notify_users(User.current, [@file]).each do |u|
DmsfMailer.files_deleted(u, @project, [@file]).deliver
end
rescue Exception => e
Rails.logger.error "Could not send email notifications: #{e.message}"
end
else
@file.errors.each do |e, msg|
flash[:error] = msg
end
end
end
redirect_to :controller => 'dmsf', :action => 'show', :id => @project, :folder_id => @file.folder
redirect_to dmsf_folder_path(:id => @project, :folder_id => @file.folder)
end
def delete_revision
@ -172,9 +179,8 @@ class DmsfFilesController < ApplicationController
else
@file.lock!
flash[:notice] = l(:notice_file_locked)
end
redirect_to params[:current] ? params[:current] :
{:controller => 'dmsf', :action => 'show', :id => @project, :folder_id => @file.folder}
end
redirect_to :back
end
def unlock
@ -187,9 +193,8 @@ class DmsfFilesController < ApplicationController
else
flash[:error] = l(:error_only_user_that_locked_file_can_unlock_it)
end
end
redirect_to params[:current] ? params[:current] :
{:controller => 'dmsf', :action => 'show', :id => @project, :folder_id => @file.folder}
end
redirect_to :back
end
def notify_activate
@ -198,9 +203,8 @@ class DmsfFilesController < ApplicationController
else
@file.notify_activate
flash[:notice] = l(:notice_file_notifications_activated)
end
redirect_to params[:current] ? params[:current] :
{:controller => 'dmsf', :action => 'show', :id => @project, :folder_id => @file.folder}
end
redirect_to :back
end
def notify_deactivate
@ -209,9 +213,8 @@ class DmsfFilesController < ApplicationController
else
@file.notify_deactivate
flash[:notice] = l(:notice_file_notifications_deactivated)
end
redirect_to params[:current] ? params[:current] :
{:controller => 'dmsf', :action => 'show', :id => @project, :folder_id => @file.folder}
end
redirect_to :back
end
private
@ -234,13 +237,16 @@ class DmsfFilesController < ApplicationController
def find_file
@file = DmsfFile.visible.find(params[:id])
@project = @file.project
rescue
rescue ActiveRecord::RecordNotFound
render_404
end
def find_revision
@revision = DmsfFileRevision.visible.find(params[:id])
@file = @revision.file
@project = @file.project
rescue ActiveRecord::RecordNotFound
render_404
end
def check_project(entry)

View File

@ -68,14 +68,9 @@ class DmsfFilesCopyController < ApplicationController
end
flash[:notice] = l(:notice_file_copied)
log_activity(new_file, 'was copied (is copy)')
begin
DmsfMailer.files_updated(User.current, [new_file]).deliver
rescue ActionView::MissingTemplate => e
Rails.logger.error "Could not send email notifications: #{e.message}"
end
log_activity(new_file, 'was copied (is copy)')
redirect_to :controller => 'dmsf_files', :action => 'show', :id => new_file
redirect_to dmsf_file_path(new_file)
end
def move
@ -105,15 +100,9 @@ class DmsfFilesCopyController < ApplicationController
@file.reload
flash[:notice] = l(:notice_file_moved)
log_activity(@file, 'was moved (is copy)')
begin
# TODO: implement proper mail notification
DmsfMailer.files_updated(User.current, [@file]).deliver
rescue ActionView::MissingTemplate => e
Rails.logger.error "Could not send email notifications: #{e.message}"
end
log_activity(@file, 'was moved (is copy)')
redirect_to :controller => 'dmsf_files', :action => 'show', :id => @file
redirect_to dmsf_file_path(@file)
end
private

View File

@ -69,15 +69,8 @@ class DmsfFoldersCopyController < ApplicationController
flash[:notice] = l(:notice_folder_copied)
log_activity(new_folder, 'was copied (is copy)')
#TODO: implement proper notification for all new files
#begin
# DmsfMailer.files_updated(User.current, [new_file]).deliver
#rescue ActionView::MissingTemplate => e
# Rails.logger.error "Could not send email notifications: " + e
#end
redirect_to :controller => 'dmsf', :action => 'show', :id => @target_project, :folder_id => new_folder
redirect_to dmsf_folder_path(:id => @target_project, :folder_id => new_folder)
end
private

View File

@ -0,0 +1,170 @@
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-14 Karel Pičman <karel.picman@lbcfree.net>
#
# 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 DmsfLinksController < ApplicationController
unloadable
model_object DmsfLink
before_filter :find_model_object, :only => [:destroy]
before_filter :find_link_project
before_filter :authorize
def new
@dmsf_link = DmsfLink.new(:project_id => params[:project_id])
if params[:dmsf_link].present?
# Reload
@dmsf_link.dmsf_folder_id = params[:dmsf_link][:dmsf_folder_id]
@dmsf_file_id = params[:dmsf_link][:dmsf_file_id]
@type = params[:dmsf_link][:type]
@dmsf_link.target_project_id = params[:dmsf_link][:target_project_id]
@target_folder_id = params[:dmsf_link][:target_folder_id].to_i if params[:reload].blank? && DmsfLinksHelper.is_a_number?(params[:dmsf_link][:target_folder_id])
if @type == 'link_to'
if params[:dmsf_link][:dmsf_file_id].present?
file = DmsfFile.find_by_id params[:dmsf_link][:dmsf_file_id]
@dmsf_link.name = file.title if file
else
folder = DmsfFolder.find_by_id params[:dmsf_link][:dmsf_folder_id]
@dmsf_link.name = folder.title if folder
end
else
if params[:dmsf_link][:target_file_id].present?
@target_file_id = params[:dmsf_link][:target_file_id]
file = DmsfFile.find_by_id @target_file_id
if file
folder = DmsfFolder.find_by_id params[:dmsf_link][:target_folder_id]
if (folder && (folder.project_id == @dmsf_link.target_project_id) && folder.files.include?(file)) || folder.nil?
@dmsf_link.name = file.title
end
end
else
folder = DmsfFolder.find_by_id params[:dmsf_link][:target_folder_id]
if folder
if folder.project_id == @dmsf_link.target_project_id
@dmsf_link.name = folder.title if folder
end
end
end
end
else
# Link from/to
@dmsf_link.dmsf_folder_id = params[:dmsf_folder_id]
@dmsf_file_id = params[:dmsf_file_id]
@type = params[:type]
@dmsf_link.target_project_id = params[:project_id]
@target_folder_id = params[:dmsf_folder_id].to_i if params[:dmsf_folder_id].present?
if @type == 'link_to'
if @dmsf_file_id
file = DmsfFile.find_by_id @dmsf_file_id
@dmsf_link.name = file.title if file
else
folder = DmsfFolder.find_by_id @target_folder_id
@dmsf_link.name = folder.title if folder
end
end
end
render :layout => !request.xhr?
end
def create
@dmsf_link = DmsfLink.new
if params[:dmsf_link][:type] == 'link_from'
# Link from
@dmsf_link.project_id = params[:dmsf_link][:project_id]
@dmsf_link.dmsf_folder_id = params[:dmsf_link][:dmsf_folder_id]
@dmsf_link.target_project_id = params[:dmsf_link][:target_project_id]
if params[:dmsf_link][:target_file_id].present?
@dmsf_link.target_id = params[:dmsf_link][:target_file_id]
@dmsf_link.target_type = DmsfFile.model_name
else
@dmsf_link.target_id = DmsfLinksHelper.is_a_number?(params[:dmsf_link][:target_folder_id]) ? params[:dmsf_link][:target_folder_id].to_i : nil
@dmsf_link.target_type = DmsfFolder.model_name
end
@dmsf_link.name = params[:dmsf_link][:name]
if @dmsf_link.save
flash[:notice] = l(:notice_successful_create)
redirect_to dmsf_folder_path(:id => @project.id, :folder_id => @dmsf_link.dmsf_folder_id)
else
@dmsf_file_id = params[:dmsf_link][:dmsf_file_id]
@type = params[:dmsf_link][:type]
@target_folder_id = params[:dmsf_link][:target_folder_id].to_i if DmsfLinksHelper.is_a_number?(params[:dmsf_link][:target_folder_id])
@target_file_id = @dmsf_link.target_id if @dmsf_link.target_type == DmsfFile.model_name
render :action => 'new'
end
else
# Link to
@dmsf_link.project_id = params[:dmsf_link][:target_project_id]
@dmsf_link.dmsf_folder_id = DmsfLinksHelper.is_a_number?(params[:dmsf_link][:target_folder_id]) ? params[:dmsf_link][:target_folder_id].to_i : nil
@dmsf_link.target_project_id = params[:dmsf_link][:project_id]
if params[:dmsf_link][:dmsf_file_id].present?
@dmsf_link.target_id = params[:dmsf_link][:dmsf_file_id]
@dmsf_link.target_type = DmsfFile.model_name
else
@dmsf_link.target_id = params[:dmsf_link][:dmsf_folder_id]
@dmsf_link.target_type = DmsfFolder.model_name
end
@dmsf_link.name = params[:dmsf_link][:name]
if @dmsf_link.save
flash[:notice] = l(:notice_successful_create)
if params[:dmsf_link][:dmsf_file_id].present?
redirect_to dmsf_file_path(@dmsf_link.target_file)
else
redirect_to edit_dmsf_path(:id => params[:dmsf_link][:project_id], :folder_id => params[:dmsf_link][:dmsf_folder_id])
end
else
@dmsf_file_id = params[:dmsf_link][:dmsf_file_id]
@type = params[:dmsf_link][:type]
@target_folder_id = @dmsf_link.dmsf_folder_id
@dmsf_link.target_project_id = @dmsf_link.project.id
@dmsf_link.project_id = params[:dmsf_link][:project_id]
@dmsf_link.dmsf_folder_id = params[:dmsf_link][:dmsf_folder_id]
render :action => 'new'
end
end
end
def destroy
begin
@dmsf_link.destroy
flash[:notice] = l(:notice_successful_delete)
rescue
flash[:error] = l(:error_unable_delete_dmsf_workflow)
end
redirect_to :back
end
private
def find_link_project
if @dmsf_link
@project = @dmsf_link.project
else
@project = Project.find(params[:dmsf_link].present? ? params[:dmsf_link][:project_id] : params[:project_id])
end
rescue ActiveRecord::RecordNotFound
render_404
end
end

View File

@ -1,6 +1,7 @@
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2011-14 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
@ -22,32 +23,18 @@ class DmsfStateController < ApplicationController
menu_item :dmsf
before_filter :find_project
before_filter :authorize
helper :all
before_filter :authorize
def user_pref_save
member = @project.members.find(:first, :conditions => {:user_id => User.current.id})
member = @project.members.where(:user_id => User.current.id).first
if member
member.dmsf_mail_notification = params[:email_notify];
member.dmsf_mail_notification = params[:email_notify]
member.save!
flash[:notice] = l(:notice_your_preferences_were_saved)
else
flash[:warning] = l(:user_is_not_project_member)
end
redirect_to :controller => 'projects', :action => 'settings', :tab => 'dmsf', :id => @project
end
redirect_to settings_project_path(@project, :tab => 'dmsf')
end
private
def find_project
@project = Project.find(params[:id])
end
def check_project(entry)
if entry && entry.project != @project
raise DmsfAccessError, l(:error_entry_project_does_not_match_current_project)
end
end
end
end

View File

@ -1,6 +1,7 @@
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2014 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
@ -77,25 +78,28 @@ class DmsfUploadController < ApplicationController
render :layout => false
end
end
#TODO: flash notice when files saved and unlocked
#TODO: separate control for approval
def commit_files
commited_files = params[:commited_files]
if commited_files && commited_files.is_a?(Hash)
files = []
failed_uploads = []
commited_files.each_value do |commited_file|
name = commited_file['name'];
name = commited_file[:name]
new_revision = DmsfFileRevision.new
file = DmsfFile.visible.find_file_by_name(@project, @folder, name)
if file.nil?
unless file
link = DmsfLink.find_link_by_file_name(@project, @folder, name)
file = link.target_file if link
end
unless file
file = DmsfFile.new
file.project = @project
file.name = name
file.folder = @folder
file.notification = Setting.plugin_redmine_dmsf['dmsf_default_notifications'].present?
file.notification = Setting.plugin_redmine_dmsf[:dmsf_default_notifications].present?
new_revision.minor_version = 0
new_revision.major_version = 0
@ -110,17 +114,17 @@ class DmsfUploadController < ApplicationController
new_revision.minor_version = last_revision.minor_version
end
commited_disk_filepath = "#{DmsfHelper.temp_dir}/#{commited_file['disk_filename'].gsub(/[\/\\]/,'')}"
commited_disk_filepath = "#{DmsfHelper.temp_dir}/#{commited_file[:disk_filename].gsub(/[\/\\]/,'')}"
new_revision.project = @project
new_revision.folder = @folder
new_revision.project = link ? link.target_project : @project
new_revision.folder = link ? link.target_folder : @folder
new_revision.file = file
new_revision.user = User.current
new_revision.name = name
new_revision.title = commited_file['title']
new_revision.description = commited_file['description']
new_revision.comment = commited_file['comment']
new_revision.increase_version(commited_file['version'].to_i, true)
new_revision.title = commited_file[:title]
new_revision.description = commited_file[:description]
new_revision.comment = commited_file[:comment]
new_revision.increase_version(commited_file[:version].to_i, true)
new_revision.mime_type = Redmine::MimeType.of(new_revision.name)
new_revision.size = File.size(commited_disk_filepath)
@ -142,7 +146,13 @@ class DmsfUploadController < ApplicationController
end
# Need to save file first to generate id for it in case of creation.
# File id is needed to properly generate revision disk filename
# File id is needed to properly generate revision disk filename
if commited_file[:dmsf_file_revision].present?
commited_file[:dmsf_file_revision][:custom_field_values].each_with_index do |v, i|
new_revision.custom_field_values[i].value = v[1]
end
end
if new_revision.valid? && file.save
new_revision.disk_filename = new_revision.new_storage_filename
else
@ -151,33 +161,31 @@ class DmsfUploadController < ApplicationController
end
if new_revision.save
new_revision.assign_workflow(commited_file[:dmsf_workflow_id])
file.reload
new_revision.assign_workflow(commited_file[:dmsf_workflow_id])
new_revision.copy_file_content(file_upload)
file_upload.close
File.delete(commited_disk_filepath)
File.delete(commited_disk_filepath)
file.set_last_revision new_revision
files.push(file)
if commited_file['dmsf_file_revision'].present?
commited_file['dmsf_file_revision']['custom_field_values'].each do |v|
cv = CustomValue.where(:customized_id => new_revision.id, :custom_field_id => v[0]).first
if cv
cv.value = v[1]
cv.save
end
end
end
else
failed_uploads.push(commited_file)
end
end
unless files.empty?
files.each { |file| log_activity(file, 'uploaded') if file }
begin
DmsfMailer.files_updated(User.current, files).deliver
rescue ActionView::MissingTemplate => e
unless files.empty?
files.each { |file| log_activity(file, 'uploaded') if file }
begin
recipients = DmsfMailer.get_notify_users(User.current, files)
recipients.each do |u|
DmsfMailer.files_updated(u, @project, files).deliver
end
if Setting.plugin_redmine_dmsf[:dmsf_display_notified_recipients] == '1'
unless recipients.empty?
to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ')
to << ((recipients.count > DMSF_MAX_NOTIFICATION_RECEIVERS_INFO) ? ',...' : '.')
flash[:warning] = l(:warning_email_notifications, :to => to)
end
end
rescue Exception => e
Rails.logger.error "Could not send email notifications: #{e.message}"
end
end
@ -185,7 +193,7 @@ class DmsfUploadController < ApplicationController
flash[:warning] = l(:warning_some_files_were_not_commited, :files => failed_uploads.map{|u| u['name']}.join(', '))
end
end
redirect_to :controller => 'dmsf', :action => 'show', :id => @project, :folder_id => @folder
redirect_to dmsf_folder_path(:id => @project, :folder_id => @folder)
end
private
@ -193,22 +201,11 @@ class DmsfUploadController < ApplicationController
def log_activity(file, action)
Rails.logger.info "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} #{User.current.login}@#{request.remote_ip}/#{request.env['HTTP_X_FORWARDED_FOR']}: #{action} dmsf://#{file.project.identifier}/#{file.id}/#{file.last_revision.id}"
end
def find_project
@project = Project.find(params[:id])
end
def find_folder
@folder = DmsfFolder.visible.find(params[:folder_id]) if params.keys.include?('folder_id')
check_project(@folder)
@folder = DmsfFolder.visible.find(params[:folder_id]) if params.keys.include?('folder_id')
rescue DmsfAccessError
render_403
end
def check_project(entry)
if entry && entry.project != @project
raise DmsfAccessError, l(:error_entry_project_does_not_match_current_project)
end
end
end
end

View File

@ -1,6 +1,6 @@
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2013 Karel Picman <karel.picman@kontron.com>
# Copyright (C) 2011-14 Karel Picman <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,13 +17,14 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class DmsfWorkflowsController < ApplicationController
unloadable
layout :workflows_layout
unloadable
model_object DmsfWorkflow
before_filter :find_model_object, :except => [:create, :new, :index, :assign, :assignment]
before_filter :find_project
before_filter :authorize_custom
before_filter :find_workflow, :except => [:create, :new, :index, :assign, :assignment]
before_filter :find_project, :except => [:start]
before_filter :authorize_global
before_filter :authorize_custom, :except => [:assignment, :start, :new_action]
layout :workflows_layout
def index
if @project
@ -46,7 +47,7 @@ class DmsfWorkflowsController < ApplicationController
if action.save
revision = DmsfFileRevision.find_by_id params[:dmsf_file_revision_id]
if revision
if @workflow.try_finish revision, action, (params[:step_action].to_i / 10)
if @dmsf_workflow.try_finish revision, action, (params[:step_action].to_i / 10)
file = DmsfFile.joins(:revisions).where(:dmsf_file_revisions => {:id => revision.id}).first
if file
begin
@ -57,64 +58,106 @@ class DmsfWorkflowsController < ApplicationController
end
if revision.workflow == DmsfWorkflow::STATE_APPROVED
# Just approved
revision.file.project.members.each do |member|
recipients = revision.file.project.members.collect{ |m| m.user }
if User.current && User.current.logged? && User.current.pref.no_self_notified
recipients.delete User.current
end
recipients.each do |user|
DmsfMailer.workflow_notification(
member.user,
@workflow,
user,
@dmsf_workflow,
revision,
l(:text_email_subject_approved, :name => @workflow.name),
l(:text_email_finished_approved, :name => @workflow.name, :filename => revision.file.name),
l(:text_email_to_see_history)).deliver if member.user
:text_email_subject_approved,
:text_email_finished_approved,
:text_email_to_see_history).deliver if user
end
if Setting.plugin_redmine_dmsf[:dmsf_display_notified_recipients] == '1'
recipients = revision.file.project.members.collect{ |m| m.user }
if User.current && User.current.logged? && User.current.pref.no_self_notified
recipients.delete User.current
end
unless recipients.empty?
to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ')
to << ((recipients.count > DMSF_MAX_NOTIFICATION_RECEIVERS_INFO) ? ',...' : '.')
flash[:warning] = l(:warning_email_notifications, :to => to)
end
end
else
# Just rejected
recipients = @workflow.participiants
recipients = @dmsf_workflow.participiants
recipients.push User.find_by_id revision.dmsf_workflow_assigned_by
recipients.uniq!
if User.current && User.current.logged? && User.current.pref.no_self_notified
recipients.delete User.current
end
recipients.each do |user|
DmsfMailer.workflow_notification(
user,
@workflow,
@dmsf_workflow,
revision,
l(:text_email_subject_rejected, :name => @workflow.name),
l(:text_email_finished_rejected, :name => @workflow.name, :filename => revision.file.name, :notice => action.note),
l(:text_email_to_see_history)).deliver if user
:text_email_subject_rejected,
:text_email_finished_rejected,
:text_email_to_see_history,
action.note).deliver if user
end
if Setting.plugin_redmine_dmsf[:dmsf_display_notified_recipients] == '1'
unless recipients.empty?
to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ')
to << ((recipients.count > DMSF_MAX_NOTIFICATION_RECEIVERS_INFO) ? ',...' : '.')
flash[:warning] = l(:warning_email_notifications, :to => to)
end
end
end
else
if action.action == DmsfWorkflowStepAction::ACTION_DELEGATE
# Delegation
delegate = User.find_by_id params[:step_action].to_i / 10
DmsfMailer.workflow_notification(
delegate,
@workflow,
revision,
l(:text_email_subject_delegated, :name => @workflow.name),
l(:text_email_finished_delegated, :name => @workflow.name, :filename => revision.file.name, :notice => action.note),
l(:text_email_to_proceed)).deliver if delegate
delegate = User.find_by_id params[:step_action].to_i / 10
if delegate
DmsfMailer.workflow_notification(
delegate,
@dmsf_workflow,
revision,
:text_email_subject_delegated,
:text_email_finished_delegated,
:text_email_to_proceed,
action.note).deliver
if Setting.plugin_redmine_dmsf[:dmsf_display_notified_recipients] == '1'
flash[:warning] = l(:warning_email_notifications, :to => delegate.name)
end
end
else
# Next step
assignments = @workflow.next_assignments revision.id
assignments = @dmsf_workflow.next_assignments revision.id
unless assignments.empty?
if assignments.first.dmsf_workflow_step.step != action.dmsf_workflow_step_assignment.dmsf_workflow_step.step
# Next step
assignments.each do |assignment|
DmsfMailer.workflow_notification(
assignment.user,
@workflow,
@dmsf_workflow,
revision,
l(:text_email_subject_requires_approval, :name => @workflow.name),
l(:text_email_finished_step, :name => @workflow.name, :filename => revision.file.name),
l(:text_email_to_proceed)).deliver if assignment.user
:text_email_subject_requires_approval,
:text_email_finished_step,
:text_email_to_proceed).deliver if assignment.user
end
to = User.find_by_id revision.dmsf_workflow_assigned_by
DmsfMailer.workflow_notification(
to,
@workflow,
@dmsf_workflow,
revision,
l(:text_email_subject_updated, :name => @workflow.name),
l(:text_email_finished_step_short, :name => @workflow.name, :filename => revision.file.name),
l(:text_email_to_see_status)).deliver if to
end
:text_email_subject_updated,
:text_email_finished_step_short,
:text_email_to_see_status).deliver if to
if Setting.plugin_redmine_dmsf[:dmsf_display_notified_recipients] == '1'
recipients = assignments.collect{ |a| a.user }
recipients << to if to && !recipients.include?(to)
unless recipients.empty?
to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ')
to << ((recipients.count > DMSF_MAX_NOTIFICATION_RECEIVERS_INFO) ? ',...' : '.')
flash[:warning] = l(:warning_email_notifications, :to => to)
end
end
end
end
end
end
@ -163,12 +206,12 @@ class DmsfWorkflowsController < ApplicationController
end
def new
@workflow = DmsfWorkflow.new
@dmsf_workflow = DmsfWorkflow.new
end
def create
@workflow = DmsfWorkflow.new(:name => params[:name], :project_id => params[:project_id])
if request.post? && @workflow.save
@dmsf_workflow = DmsfWorkflow.new(:name => params[:name], :project_id => params[:project_id])
if request.post? && @dmsf_workflow.save
flash[:notice] = l(:notice_successful_create)
if @project
redirect_to settings_project_path(@project, :tab => 'dmsf_workflow')
@ -180,11 +223,8 @@ class DmsfWorkflowsController < ApplicationController
end
end
def edit
end
def update
if request.put? && @workflow.update_attributes({:name => params[:name]})
if request.put? && @dmsf_workflow.update_attributes({:name => params[:name]})
flash[:notice] = l(:notice_successful_update)
if @project
redirect_to settings_project_path(@project, :tab => 'dmsf_workflow')
@ -198,7 +238,7 @@ class DmsfWorkflowsController < ApplicationController
def destroy
begin
@workflow.destroy
@dmsf_workflow.destroy
flash[:notice] = l(:notice_successful_delete)
rescue
flash[:error] = l(:error_unable_delete_dmsf_workflow)
@ -218,14 +258,14 @@ class DmsfWorkflowsController < ApplicationController
if request.post?
users = User.find_all_by_id(params[:user_ids])
if params[:step] == '0'
step = @workflow.dmsf_workflow_steps.collect{|s| s.step}.uniq.count + 1
step = @dmsf_workflow.dmsf_workflow_steps.collect{|s| s.step}.uniq.count + 1
else
step = params[:step].to_i
end
operator = (params[:commit] == l(:dmsf_and)) ? DmsfWorkflowStep::OPERATOR_AND : DmsfWorkflowStep::OPERATOR_OR
users.each do |user|
@workflow.dmsf_workflow_steps << DmsfWorkflowStep.new(
:dmsf_workflow_id => @workflow.id,
@dmsf_workflow.dmsf_workflow_steps << DmsfWorkflowStep.new(
:dmsf_workflow_id => @dmsf_workflow.id,
:step => step,
:user_id => user.id,
:operator => operator)
@ -238,10 +278,10 @@ class DmsfWorkflowsController < ApplicationController
def remove_step
if request.delete?
DmsfWorkflowStep.where(:dmsf_workflow_id => @workflow.id, :step => params[:step]).each do |ws|
@workflow.dmsf_workflow_steps.delete(ws)
DmsfWorkflowStep.where(:dmsf_workflow_id => @dmsf_workflow.id, :step => params[:step]).each do |ws|
@dmsf_workflow.dmsf_workflow_steps.delete(ws)
end
@workflow.dmsf_workflow_steps.each do |ws|
@dmsf_workflow.dmsf_workflow_steps.each do |ws|
n = ws.step.to_i
if n > params[:step].to_i
ws.step = n - 1
@ -258,7 +298,7 @@ class DmsfWorkflowsController < ApplicationController
def reorder_steps
if request.put?
unless @workflow.reorder_steps(params[:step].to_i, params[:workflow_step][:move_to])
unless @dmsf_workflow.reorder_steps(params[:step].to_i, params[:workflow_step][:move_to])
flash[:error] = l(:notice_cannot_renumber_steps)
end
end
@ -269,49 +309,67 @@ class DmsfWorkflowsController < ApplicationController
def start
revision = DmsfFileRevision.find_by_id(params[:dmsf_file_revision_id])
if revision
if request.post?
revision.set_workflow(@workflow.id, params[:action])
if revision.save
assignments = @workflow.next_assignments revision.id
assignments.each do |assignment|
DmsfMailer.workflow_notification(
assignment.user,
@workflow,
revision,
l(:text_email_subject_started, :name => @workflow.name),
l(:text_email_started, :name => @workflow.name, :filename => revision.file.name),
l(:text_email_to_proceed)).deliver if assignment.user
end
flash[:notice] = l(:notice_workflow_started)
else
flash[:error] = l(:notice_cannot_start_workflow)
if revision
revision.set_workflow(@dmsf_workflow.id, params[:action])
if revision.save
assignments = @dmsf_workflow.next_assignments revision.id
assignments.each do |assignment|
DmsfMailer.workflow_notification(
assignment.user,
@dmsf_workflow,
revision,
:text_email_subject_started,
:text_email_started,
:text_email_to_proceed).deliver if assignment.user
end
end
if Setting.plugin_redmine_dmsf[:dmsf_display_notified_recipients] == '1'
recipients = assignments.collect { |a| a.user }
recipients.uniq!
if User.current && User.current.logged? && User.current.pref.no_self_notified
recipients.delete User.current
end
unless recipients.empty?
to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ')
to << ((recipients.count > DMSF_MAX_NOTIFICATION_RECEIVERS_INFO) ? ',...' : '.')
flash[:warning] = l(:warning_email_notifications, :to => to)
end
end
flash[:notice] = l(:notice_workflow_started)
else
flash[:error] = l(:notice_cannot_start_workflow)
end
end
redirect_to :back
end
private
def find_workflow
@workflow = DmsfWorkflow.find_by_id(params[:id])
end
def find_project
if @workflow && @workflow.project
@project = @workflow.project
elsif params[:project_id].present?
@project = Project.find_by_id params[:project_id]
if @dmsf_workflow
if @dmsf_workflow.project # Project workflow
@project = @dmsf_workflow.project
else # Global workflow
revision = DmsfFileRevision.find_by_id params[:dmsf_file_revision_id]
@project = revision.project if revision
end
else
if params[:project_id].present?
@project = Project.find_by_id params[:project_id]
else
@project = Project.find_by_identifier params[:id]
end
end
end
def workflows_layout
find_workflow
find_project
def workflows_layout
@project ? 'base' : 'admin'
end
def authorize_custom
require_admin unless @project
def authorize_custom
if @project
authorize
else
require_admin
end
end
end
end

View File

@ -74,6 +74,6 @@ module DmsfHelper
# of methods - however seems functional. Not sure if MySQL
return obj.to_s.to_time(ActiveRecord::Base.default_timezone) if obj.class.name == 'Mysql::Time'
return obj
end
end
end

View File

@ -0,0 +1,40 @@
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2014 Karel Pičman <karel.picman@lbcfree.net>
#
# 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.
module DmsfLinksHelper
def folder_tree_options_for_select(folder_tree, options = {})
s = ''
folder_tree.each do |name, id|
tag_options = {:value => id}
if id == options[:selected]
tag_options[:selected] = 'selected'
else
tag_options[:selected] = nil
end
s << content_tag('option', name, tag_options)
end
s.html_safe
end
# An integer test
def self.is_a_number?(s)
s.to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true
end
end

View File

@ -1,6 +1,7 @@
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2011-14 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
@ -31,14 +32,16 @@ class DmsfFile < ActiveRecord::Base
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'
has_many :revisions, :class_name => 'DmsfFileRevision', :foreign_key => 'dmsf_file_id',
:order => "#{DmsfFileRevision.table_name}.major_version DESC, #{DmsfFileRevision.table_name}.minor_version DESC, #{DmsfFileRevision.table_name}.updated_at DESC",
:dependent => :destroy
has_many :locks, :class_name => 'DmsfLock', :foreign_key => 'entity_id',
:order => "#{DmsfLock.table_name}.updated_at DESC",
:conditions => {:entity_type => 0},
:dependent => :destroy
belongs_to :deleted_by_user, :class_name => 'User', :foreign_key => 'deleted_by_user_id'
:dependent => :destroy
has_many :referenced_links, :class_name => 'DmsfLink', :foreign_key => 'target_id',
:conditions => {:target_type => DmsfFile.model_name}, :dependent => :destroy
scope :visible, lambda {|*args| where(DmsfFile.visible_condition(args.shift || User.current, *args)).readonly(false)}
@ -64,14 +67,15 @@ class DmsfFile < ActiveRecord::Base
: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 }
@@storage_path = Setting.plugin_redmine_dmsf['dmsf_storage_directory'].strip
@@storage_path = nil
def self.storage_path
if !File.exists?(@@storage_path)
Dir.mkdir(@@storage_path)
end
unless @@storage_path.present?
@@storage_path = Setting.plugin_redmine_dmsf['dmsf_storage_directory'].strip
@@storage_path = Rails.root.join('files/dmsf').to_s if @@storage_path.blank?
Dir.mkdir(@@storage_path) unless File.exists?(@@storage_path)
end
@@storage_path
end
@ -81,16 +85,11 @@ class DmsfFile < ActiveRecord::Base
@@storage_path = obj
end
def self.project_root_files(project)
visible.where(:project_id => project.id, :dmsf_folder_id => nil).order('name ASC')
end
def self.find_file_by_name(project, folder, name)
if folder
visible.where(:project_id => project, :dmsf_folder_id => folder.id, :name => name).first
else
visible.where(:project_id => project, :dmsf_folder_id => nil, :name => name).first
end
def self.find_file_by_name(project, folder, name)
where(
:project_id => project,
:dmsf_folder_id => folder ? folder.id : nil,
:name => name).visible.first
end
def last_revision
@ -99,14 +98,19 @@ class DmsfFile < ActiveRecord::Base
end
@last_revision
end
def set_last_revision(new_revision)
@last_revision = new_revision
end
def delete
if locked_for_user?
Rails.logger.info l(:error_file_is_locked)
errors[:base] << l(:error_file_is_locked)
return false
end
begin
if Setting.plugin_redmine_dmsf['dmsf_really_delete_files']
if Setting.plugin_redmine_dmsf['dmsf_really_delete_files']
self.revisions.visible.each {|r| r.delete(true)}
self.destroy
else
@ -167,11 +171,7 @@ class DmsfFile < ActiveRecord::Base
def notify_activate
self.notification = true
self.save!
end
def display_name
return self.name
end
end
# Returns an array of projects that current user can copy file to
def self.allowed_target_projects_on_copy
@ -190,7 +190,7 @@ class DmsfFile < ActiveRecord::Base
return false
end
new_revision = self.last_revision.clone
new_revision = self.last_revision.clone
new_revision.folder = folder
new_revision.project = folder ? folder.project : project
@ -201,10 +201,10 @@ class DmsfFile < ActiveRecord::Base
new_revision.custom_values << CustomValue.new({:custom_field => cv.custom_field, :value => cv.value})
end
# If the target project differs from the source project we must physically move the file
# If the target project differs from the source project we must physically copy the file
if self.project != new_revision.project
if File.exist? self.last_revision.disk_file
FileUtils.mv self.last_revision.disk_file, new_revision.disk_file
FileUtils.cp self.last_revision.disk_file, new_revision.disk_file
end
end
@ -221,9 +221,8 @@ class DmsfFile < ActiveRecord::Base
file.name = self.name
file.notification = Setting.plugin_redmine_dmsf['dmsf_default_notifications'].present?
if file.save
if file.save && self.last_revision
new_revision = self.last_revision.clone
new_revision.file = file
new_revision.folder = folder
new_revision.project = folder ? folder.project : project
@ -376,4 +375,11 @@ class DmsfFile < ActiveRecord::Base
[results, results_count]
end
def display_name
if self.name.length > 50
return "#{self.name[0, 25]}...#{self.name[-25, 25]}"
end
self.name
end
end

View File

@ -33,21 +33,21 @@ class DmsfFileRevision < ActiveRecord::Base
acts_as_customizable
acts_as_event :title => Proc.new {|o| "#{l(:label_dmsf_updated)}: #{o.file.dmsf_path_str}"},
:url => Proc.new {|o| {:controller => 'dmsf_files', :action => 'show', :id => o.file}},
:datetime => Proc.new {|o| o.updated_at },
:description => Proc.new {|o| o.comment },
:author => Proc.new {|o| o.user }
:url => Proc.new {|o| {:controller => 'dmsf_files', :action => 'show', :id => o.file}},
:datetime => Proc.new {|o| o.updated_at },
:description => Proc.new {|o| o.comment },
:author => Proc.new {|o| o.user }
acts_as_activity_provider :type => 'dmsf_files',
:timestamp => "#{DmsfFileRevision.table_name}.updated_at",
:author_key => "#{DmsfFileRevision.table_name}.user_id",
:permission => :view_dmsf_files,
:find_options => {:select => "#{DmsfFileRevision.table_name}.*",
:joins =>
"INNER JOIN #{DmsfFile.table_name} ON #{DmsfFileRevision.table_name}.dmsf_file_id = #{DmsfFile.table_name}.id " +
"INNER JOIN #{Project.table_name} ON #{DmsfFile.table_name}.project_id = #{Project.table_name}.id",
:conditions => ["#{DmsfFile.table_name}.deleted = :false", {:false => false}]
}
:timestamp => "#{DmsfFileRevision.table_name}.updated_at",
:author_key => "#{DmsfFileRevision.table_name}.user_id",
:permission => :view_dmsf_files,
:find_options => {:select => "#{DmsfFileRevision.table_name}.*",
:joins =>
"INNER JOIN #{DmsfFile.table_name} ON #{DmsfFileRevision.table_name}.dmsf_file_id = #{DmsfFile.table_name}.id " +
"INNER JOIN #{Project.table_name} ON #{DmsfFile.table_name}.project_id = #{Project.table_name}.id",
:conditions => ["#{DmsfFile.table_name}.deleted = :false", {:false => false}]
}
validates :title, :name, :presence => true
validates_format_of :name, :with => DmsfFolder.invalid_characters,
@ -56,8 +56,7 @@ class DmsfFileRevision < ActiveRecord::Base
def self.remove_extension(filename)
filename[0, (filename.length - File.extname(filename).length)]
end
# TODO: check if better to move to dmsf_upload class
def self.filename_to_title(filename)
remove_extension(filename).gsub(/_+/, ' ');
end
@ -130,8 +129,7 @@ class DmsfFileRevision < ActiveRecord::Base
content_type = 'application/octet-stream' if content_type.blank?
content_type.to_s
end
# TODO: use standard clone method
def clone
new_revision = DmsfFileRevision.new
new_revision.file = self.file
@ -205,11 +203,7 @@ class DmsfFileRevision < ActiveRecord::Base
when 2 then self.major_version + 1
else self.major_version
end
end
def display_title
return self.title
end
end
def new_storage_filename
raise DmsfAccessError, 'File id is not set' unless self.file.id
@ -233,5 +227,10 @@ class DmsfFileRevision < ActiveRecord::Base
def available_custom_fields
DmsfFileRevisionCustomField.all
end
def iversion
parts = self.version.split '.'
parts.size == 2 ? parts[0].to_i * 1000 + parts[1].to_i : 0
end
end

View File

@ -18,7 +18,17 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class DmsfFileRevisionCustomField < CustomField
def type_name
:menu_dmsf
end
def compare_values?(x, y)
if x.is_a?(Array) && y.is_a?(Array) && !y.empty?
x.include? y[0]
else
x == y
end
end
end

View File

@ -1,6 +1,7 @@
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2011-14 Karel Pičman <karel.picman@konton.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -26,18 +27,23 @@ class DmsfFolder < ActiveRecord::Base
belongs_to :project
belongs_to :folder, :class_name => 'DmsfFolder', :foreign_key => 'dmsf_folder_id'
has_many :subfolders, :class_name => 'DmsfFolder', :foreign_key => 'dmsf_folder_id', :order => "#{DmsfFolder.table_name}.title ASC",
:dependent => :destroy
has_many :files, :class_name => 'DmsfFile', :foreign_key => 'dmsf_folder_id',
:dependent => :destroy
has_many :subfolders, :class_name => 'DmsfFolder', :foreign_key => 'dmsf_folder_id',
:dependent => :destroy
has_many :files, :class_name => 'DmsfFile', :foreign_key => 'dmsf_folder_id',
:dependent => :destroy
belongs_to :user
has_many :folder_links, :class_name => 'DmsfLink', :foreign_key => 'dmsf_folder_id',
:conditions => {:target_type => DmsfFolder.model_name}, :dependent => :destroy
has_many :file_links, :class_name => 'DmsfLink', :foreign_key => 'dmsf_folder_id',
:conditions => {:target_type => DmsfFile.model_name}, :dependent => :destroy
has_many :referenced_links, :class_name => 'DmsfLink', :foreign_key => 'target_id',
:conditions => {:target_type => DmsfFolder.model_name}, :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
scope :visible, lambda {|*args| {:conditions => '' }} #For future use, however best to be referenced now
scope :visible, lambda {|*args| {:conditions => '' }} #For future use, however best to be referenced now
acts_as_customizable
@ -68,10 +74,6 @@ class DmsfFolder < ActiveRecord::Base
return true
end
def self.project_root_folders(project)
visible.where(:project_id => project.id, :dmsf_folder_id => nil, ).order('title ASC').all
end
def self.find_by_title(project, folder, title)
if folder
visible.where(:project_id => project.id, :dmsf_folder_id => nil, :title => title).first
@ -126,27 +128,42 @@ class DmsfFolder < ActiveRecord::Base
def self.directory_tree(project, current_folder = nil)
tree = [[l(:link_documents), nil]]
DmsfFolder.visible.project_root_folders(project).each do |folder|
project.dmsf_folders.visible.each do |folder|
unless folder == current_folder
tree.push(["...#{folder.title}", folder.id])
directory_subtree(tree, folder, 2, current_folder)
end
end
return tree
end
end
def folder_tree
tree = [[self.title, self.id]]
DmsfFolder.directory_subtree(tree, self, 2, nil)
return tree
end
def self.file_list(files)
options = Array.new
options.push ['', nil]
files.each do |f|
options.push [f.title, f.id]
end
options
end
def deep_file_count
file_count = self.files.visible.count
self.subfolders.visible.each {|subfolder| file_count += subfolder.deep_file_count}
file_count
file_count + self.file_links.visible.count
end
def deep_folder_count
folder_count = self.subfolders.visible.count
self.subfolders.visible.each {|subfolder| folder_count += subfolder.deep_folder_count}
folder_count
end
folder_count + self.folder_links.visible.count
end
def deep_size
size = 0
self.files.visible.each {|file| size += file.size}
@ -181,11 +198,19 @@ class DmsfFolder < ActiveRecord::Base
return new_folder unless new_folder.save
self.files.visible.each do |f|
f.copy_to(project, new_folder)
f.copy_to project, new_folder
end
self.subfolders.each do |s|
s.copy_to(project, new_folder)
self.subfolders.visible.each do |s|
s.copy_to project, new_folder
end
self.folder_links.visible.each do |l|
l.copy_to project, new_folder
end
self.file_links.visible.each do |l|
l.copy_to project, new_folder
end
return new_folder
@ -239,7 +264,7 @@ class DmsfFolder < ActiveRecord::Base
def self.directory_subtree(tree, folder, level, current_folder)
folder.subfolders.visible.each do |subfolder|
unless subfolder == current_folder
tree.push(["#{"..." * level}#{subfolder.title}", subfolder.id])
tree.push(["#{'...' * level}#{subfolder.title}", subfolder.id])
directory_subtree(tree, subfolder, level + 1, current_folder)
end
end

100
app/models/dmsf_link.rb Normal file
View File

@ -0,0 +1,100 @@
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-14 Karel Pičman <karel.picman@lbcfree.net>
#
# 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 DmsfLink < ActiveRecord::Base
unloadable
belongs_to :project
belongs_to :dmsf_folder
validates :name, :presence => true
validates :target_id, :presence => true
validates_length_of :name, :maximum => 255
scope :visible, where('NOT deleted')
def target_folder_id
if self.target_type == DmsfFolder.model_name
self.target_id
else
f = DmsfFile.find_by_id self.target_id
f.dmsf_folder_id if f
end
end
def target_folder
DmsfFolder.find_by_id self.target_folder_id if self.target_folder_id
end
def target_file_id
self.target_id if self.target_type == DmsfFile.model_name
end
def target_file
DmsfFile.find_by_id self.target_file_id if self.target_file_id
end
def target_project
Project.find_by_id self.target_project_id
end
def folder
DmsfFolder.find_by_id self.dmsf_folder_id
end
def title
self.name
end
def self.find_link_by_file_name(project, folder, filename)
links = DmsfLink.where(
:project_id => project.id,
:dmsf_folder_id => folder ? folder.id : nil,
:target_type => DmsfFile.model_name).visible.all
links.each do |link|
return link if link.target_file.name == filename
end
nil
end
def path
if self.target_type == DmsfFile.model_name
file = self.target_file
path = file.dmsf_path.map { |element| element.is_a?(DmsfFile) ? element.name : element.title }.join('/') if file
else
folder = self.target_folder
path = folder.dmsf_path_str if folder
end
path.insert(0, "#{self.target_project.name}:") if self.project_id != self.target_project_id && path
if path.length > 50
return "#{path[0, 25]}...#{path[-25, 25]}"
end
path
end
def copy_to(project, folder)
link = DmsfLink.new(
:target_project_id => self.target_project_id,
:target_id => self.target_id,
:target_type => self.target_type,
:name => self.name,
:project_id => project.id,
:dmsf_folder_id => folder ? folder.id : nil)
link.save
link
end
end

View File

@ -1,6 +1,7 @@
# 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>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -19,72 +20,83 @@
require 'mailer'
class DmsfMailer < Mailer
layout 'mailer'
def files_updated(user, files)
project = files[0].project
files = files.select { |file| file.notify? }
def files_updated(user, project, files)
if user && project && files.count > 0
files = files.select { |file| file.notify? }
redmine_headers 'Project' => project.identifier if project
@files = files
@project = project
set_language_if_valid user.language
mail :to => user.mail,
:subject => l(:text_email_doc_updated_subject, :project => project.name)
end
end
def files_deleted(user, project, files)
if user && files.count > 0
files = files.select { |file| file.notify? }
redmine_headers 'Project' => project.identifier if project
@files = files
@project = project
set_language_if_valid user.language
mail :to => user.mail,
:subject => l(:text_email_doc_deleted_subject, :project => project.name)
end
end
redmine_headers "Project" => project.identifier
@user = user
@files = files
@project = project
mail :to => get_notify_user_emails(user, files),
:subject => "#{project.name}: Dmsf files updated"
end
def files_deleted(user, files)
project = files[0].project
files = files.select { |file| file.notify? }
def send_documents(project, user, email_params)
zipped_content_data = open(email_params[:zipped_content], 'rb') { |io| io.read }
redmine_headers 'Project' => project.identifier
redmine_headers 'Project' => project.identifier if project
@user = user
@files = files
@project = project
mail :to => get_notify_user_emails(user, files),
:subject => "#{project.name}: Dmsf files deleted"
@body = email_params[:body]
@links_only = email_params[:links_only]
@folders = email_params[:folders]
@files = email_params[:files]
unless @links_only == '1'
attachments['Documents.zip'] = { :content_type => 'application/zip', :content => zipped_content_data }
end
mail :to => email_params[:to], :cc => email_params[:cc], :subject => email_params[:subject], :from => user.mail
end
def send_documents(user, email_to, email_cc, email_subject, zipped_content, email_plain_body)
zipped_content_data = open(zipped_content, 'rb') {|io| io.read }
@body = email_plain_body
attachments['Documents.zip'] = {:content_type => 'application/zip', :content => zipped_content_data}
mail(:to => email_to, :cc => email_cc, :subject => email_subject, :from => user.mail)
end
def workflow_notification(user, workflow, revision, subject, text1, text2)
def workflow_notification(user, workflow, revision, subject_id, text1_id, text2_id, notice = nil)
if user && workflow && revision
set_language_if_valid user.language
if revision.file && revision.file.project
@project = revision.file.project
redmine_headers 'Project' => @project.identifier
end
set_language_if_valid user.language
@user = user
@workflow = workflow
@revision = revision
@text1 = text1
@text2 = text2
mail :to => user.mail, :subject => subject
@revision = revision
@text1 = l(text1_id, :name => workflow.name, :filename => revision.file.name, :notice => notice)
@text2 = l(text2_id)
@notice = notice
mail :to => user.mail, :subject => l(subject_id, :name => workflow.name)
end
end
private
end
def get_notify_user_emails(user, files)
if files.empty?
return []
end
project = files[0].project
def self.get_notify_users(user, files)
notify_files = files.select { |file| file.notify? }
return [] if notify_files.empty?
project = notify_files[0].project
notify_members = project.members
notify_members = notify_members.select do |notify_member|
notify_user = notify_member.user
if notify_user.pref[:no_self_notified] && notify_user == user
notify_user = notify_member.user
if notify_user == user && user.pref.no_self_notified
false
else
if notify_member.dmsf_mail_notification.nil?
unless notify_member.dmsf_mail_notification
case notify_user.mail_notification
when 'all'
true
@ -101,7 +113,7 @@ class DmsfMailer < Mailer
end
end
notify_members.collect {|m| m.user.mail }
notify_members.collect { |m| m.user }
end
end
end

View File

@ -1,8 +1,8 @@
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2013 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011-14 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
@ -38,12 +38,12 @@ class DmsfUpload
def self.create_from_uploaded_file(project, folder, uploaded_file)
uploaded = {
'disk_filename' => DmsfHelper.temp_filename(uploaded_file.original_filename),
'content_type' => uploaded_file.content_type.to_s,
'original_filename' => uploaded_file.original_filename,
:disk_filename => DmsfHelper.temp_filename(uploaded_file.original_filename),
:content_type => uploaded_file.content_type.to_s,
:original_filename => uploaded_file.original_filename,
}
File.open("#{DmsfHelper.temp_dir}/#{uploaded["disk_filename"]}", "wb") do |f|
File.open("#{DmsfHelper.temp_dir}/#{uploaded[:disk_filename]}", 'wb') do |f|
while (buffer = uploaded_file.read(8192))
f.write(buffer)
end
@ -52,15 +52,19 @@ class DmsfUpload
end
def initialize(project, folder, uploaded)
@name = uploaded['original_filename']
@name = uploaded[:original_filename]
dmsf_file = DmsfFile.visible.find_file_by_name(project, folder, @name)
file = DmsfFile.find_file_by_name(project, folder, @name)
unless file
link = DmsfLink.find_link_by_file_name(project, folder, @name)
file = link.target_file if link
end
@disk_filename = uploaded['disk_filename']
@mime_type = uploaded['content_type']
@disk_filename = uploaded[:disk_filename]
@mime_type = uploaded[:content_type]
@size = File.size(disk_file)
if dmsf_file.nil? || dmsf_file.last_revision.nil?
if file.nil? || file.last_revision.nil?
@title = DmsfFileRevision.filename_to_title(@name)
@description = nil
@major_version = 0
@ -68,24 +72,24 @@ class DmsfUpload
@workflow = nil
@custom_values = DmsfFileRevision.new(:file => DmsfFile.new(:project => @project)).custom_field_values
else
last_revision = dmsf_file.last_revision
last_revision = file.last_revision
@title = last_revision.title
@description = last_revision.description
@major_version = last_revision.major_version
@minor_version = last_revision.minor_version
@workflow = last_revision.workflow
@custom_values = Array.new(dmsf_file.last_revision.custom_values)
@custom_values = Array.new(file.last_revision.custom_values)
# Add default value for CFs not existing
present_custom_fields = dmsf_file.last_revision.custom_values.collect(&:custom_field).uniq
dmsf_file.last_revision.available_custom_fields.each do |cf|
present_custom_fields = file.last_revision.custom_values.collect(&:custom_field).uniq
file.last_revision.available_custom_fields.each do |cf|
unless present_custom_fields.include?(cf)
@custom_values << CustomValue.new({:custom_field => cf, :value => cf.default_value}) if cf.default_value
end
end
end
@locked = dmsf_file && dmsf_file.locked_for_user?
@locked = file && file.locked_for_user?
end
end
end

View File

@ -32,7 +32,7 @@ class DmsfWorkflow < ActiveRecord::Base
def participiants
users = Array.new
self.dmsf_workflow_steps.each do |step|
users << step.user
users << step.user unless users.include? step.user
end
users
end
@ -110,7 +110,7 @@ class DmsfWorkflow < ActiveRecord::Base
sql = '1=1'
end
unless q.nil? || q.empty?
if q.present?
User.active.sorted.where(sql).like(q)
else
User.active.sorted.where(sql)

View File

@ -0,0 +1,108 @@
<%#=
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2014 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.
%>
<% locked_for_user = subfolder.locked_for_user? %>
<% locked = subfolder.locked? %>
<td class="check"><%= check_box_tag(name, id, false,
:title => l(:title_check_for_zip_download_or_email)) %></td>
<td class="title">
<%= link_to(h(title),
dmsf_folder_path(:id => project, :folder_id => subfolder),
:class => 'icon icon-folder') %>
<% 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>
<% end %>
</td>
<td class="size"></td>
<td class="modified"><%= format_time(subfolder.updated_at) %>
<% if locked_for_user %>
<% if subfolder.lock.reverse[0].user %>
<%= link_to('',
user_path(subfolder.lock.reverse[0].user),
:title => l(:title_locked_by_user, :user => subfolder.lock.reverse[0].user),
:class => 'icon icon-dmsf-locked') %>
<% else %>
<%= content_tag(:span, '', :title => l(:notice_account_unknown_email),
:class => 'icon icon-dmsf-locked') %>
<% end %>
<% elsif locked %>
<%= content_tag(:span, '', :title => l(:title_locked_by_you),
:class => 'icon icon-dmsf-lockedbycurrent') %>
<% end %>
</td>
<td class="version"></td>
<td class="workflow"></td>
<td class="author"><%= h(subfolder.user) %></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)),
:class => 'icon icon-edit') %>
<%= link_to('',
lock_dmsf_path(:id => project, :folder_id => subfolder),
:title => l(:title_lock_file),
:class => 'icon icon-dmsf-lock') %>
<% if subfolder.notification %>
<%= link_to('',
notify_deactivate_dmsf_path(:id => project, :folder_id => subfolder),
:title => l(:title_notifications_active_deactivate),
:class => 'icon icon-notification-on') %>
<% else %>
<%= link_to('',
notify_activate_dmsf_path(:id => project, :folder_id => subfolder),
:title => l(:title_notifications_not_active_activate),
:class => 'icon icon-notification-off') %>
<% end %>
<% if link %>
<%= link_to('',
dmsf_link_path(link),
:data => {:confirm => l(:text_are_you_sure)},
:method => :delete,
:title => l(:title_delete),
:class => 'icon icon-del') %>
<% else %>
<%= link_to('',
delete_dmsf_path(:id => project, :folder_id => @folder, :delete_folder_id => subfolder),
:data => {:confirm => l(:text_are_you_sure)},
:title => l(:title_delete),
:class => 'icon icon-del') %>
<% end %>
<% else %>
<span class="icon"></span>
<% if (!locked_for_user || @force_file_unlock_allowed) && subfolder.unlockable? %>
<%= link_to('',
unlock_dmsf_path(:id => project, :folder_id => subfolder),
:title => l(:title_unlock_file),
:class => 'icon icon-dmsf-unlock')%>
<% end %>
<% end %>
</div>
<% end %>
</td>
<td class="hidden">0</td>
<td class="hidden">0</td>
<td class="hidden"><%= subfolder.updated_at.to_i %></td>
<td class="hidden">0</td>

View File

@ -0,0 +1,183 @@
<%#=
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-14 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.
%>
<% locked_for_user = file.locked_for_user? %>
<% locked = file.locked? %>
<% wf = DmsfWorkflow.find_by_id(file.last_revision.dmsf_workflow_id) %>
<td class="check"><%= check_box_tag(name, id, false,
:title => l(:title_check_for_zip_download_or_email)) %></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}") %>
<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>
<td class="modified">
<%= format_time(file.last_revision.updated_at) %>
<% if locked_for_user %>
<% if file.lock.reverse[0].user %>
<%= link_to('',
user_path(file.lock.reverse[0].user),
:title => l(:title_locked_by_user, :user => file.lock.reverse[0].user),
:class => 'icon icon-dmsf-locked') %>
<% else %>
<%= content_tag(:span, '',
:title => l(:notice_account_unknown_email),
:class => 'icon icon-dmsf-locked') %>
<% end %>
<% elsif locked %>
<%= content_tag(:span, '', :title => l(:title_locked_by_you),
:class => 'icon icon-dmsf-lockedbycurrent') %>
<% end %>
</td>
<td class="version"><%= file.last_revision.version %></td>
<td class="workflow">
<% if wf && @file_manipulation_allowed %>
<%= link_to(
file.last_revision.workflow_str(false),
log_dmsf_workflow_path(
:project_id => project.id,
:id => wf.id,
:dmsf_file_revision_id => file.last_revision.id),
:title => DmsfWorkflow.assignments_to_users_str(wf.next_assignments(file.last_revision.id)),
:remote => true) %>
<% else %>
<%= file.last_revision.workflow_str(false) %>
<% end %>
</td>
<td class="author"><%= h(file.last_revision.user) %></td>
<td class="actions">
<% if @file_manipulation_allowed %>
<div class="right_icon_box">
<% unless locked %>
<%= link_to('',
dmsf_file_path(:id => file),
:title => l(:link_details, :title => h(file.last_revision.title)),
:class => 'icon icon-dmsf-file-details') %>
<%= link_to('',
lock_dmsf_files_path(:id => file),
:title => l(:title_lock_file),
:class => 'icon icon-dmsf-lock') %>
<% if file.notification %>
<%= link_to('',
notify_deactivate_dmsf_files_path(:id => file),
:title => l(:title_notifications_active_deactivate),
:class => 'icon icon-notification-on') %>
<% else %>
<%= link_to('',
notify_activate_dmsf_files_path(:id => file),
:title => l(:title_notifications_not_active_activate),
:class => 'icon icon-notification-off') %>
<% end %>
<% if link %>
<%= link_to('',
dmsf_link_path(link),
:data => {:confirm => l(:text_are_you_sure)},
:method => :delete,
:title => l(:title_delete),
:class => 'icon icon-del') %>
<% else %>
<%= link_to('',
dmsf_file_path(:id => file),
:data => {:confirm => l(:text_are_you_sure)},
:method => :delete,
:title => l(:title_delete),
:class => 'icon icon-del') unless locked_for_user %>
<% end %>
<% else %>
<span class="icon"></span>
<% if (!locked_for_user || @force_file_unlock_allowed) && file.unlockable? %>
<%= link_to('',
unlock_dmsf_files_path(:id => file),
:title => l(:title_unlock_file),
:class => 'icon icon-dmsf-unlock')%>
<% else %>
<span class="icon"></span>
<% end %>
<span class="icon icon-margin-left"></span>
<span class="icon"></span>
<% end %>
<% case file.last_revision.workflow %>
<% when DmsfWorkflow::STATE_WAITING_FOR_APPROVAL %>
<% if wf %>
<% assignments = wf.next_assignments(file.last_revision.id) %>
<% index = assignments.find_index{|assignment| assignment.user_id == User.current.id} if assignments %>
<% if index %>
<%= link_to('',
action_dmsf_workflow_path(
:project_id => project.id,
:id => wf.id,
:dmsf_workflow_step_assignment_id => assignments[index].id,
:dmsf_file_revision_id => file.last_revision.id),
:title => l(:title_waiting_for_approval),
:class => 'icon icon-dmsf-waiting-for-approval',
:remote => true) %>
<% else %>
<%= content_tag(:span, '',
:title => "#{l(:label_dmsf_wokflow_action_approve)} #{l(:label_dmsf_wokflow_action_reject)} #{l(:label_dmsf_wokflow_action_delegate)}",
:class => 'icon icon-dmsf-waiting-for-approval') %>
<% end %>
<% else %>
<%= content_tag(:span, '',
:title => "#{l(:label_dmsf_wokflow_action_approve)} #{l(:label_dmsf_wokflow_action_reject)} #{l(:label_dmsf_wokflow_action_delegate)}",
:class => 'icon icon-dmsf-waiting-for-approval') %>
<% end %>
<% when DmsfWorkflow::STATE_APPROVED %>
<%= content_tag(:span, '', :title => l(:title_approved),
:class => 'icon icon-dmsf-approved') %>
<% when DmsfWorkflow::STATE_ASSIGNED %>
<% if User.current && (file.last_revision.dmsf_workflow_assigned_by == User.current.id) && wf %>
<%= link_to('',
start_dmsf_workflow_path(
:id => file.last_revision.dmsf_workflow_id,
:dmsf_file_revision_id => file.last_revision.id),
:title => l(:label_dmsf_wokflow_action_start),
:class => 'icon icon-dmsf-assigned') %>
<% else %>
<%= content_tag(:span, '',
title => l(:label_dmsf_wokflow_action_start),
:class => 'icon icon-dmsf-assigned') %>
<% end %>
<% when DmsfWorkflow::STATE_REJECTED %>
<%= content_tag(:span, '', :title => l(:title_rejected),
:class => 'icon icon-dmsf-rejected') %>
<% else %>
<% if @workflows_available %>
<%= link_to('',
assign_dmsf_workflow_path(
:project_id => project.id,
:dmsf_file_revision_id => file.last_revision.id),
:title => l(:label_dmsf_wokflow_action_assign),
:class => 'icon icon-dmsf-none',
:remote => true) %>
<% end %>
<% end %>
</div>
<% end %>
</td>
<td class="hidden">1</td>
<td class="hidden"><%= file.last_revision.size %></td>
<td class="hidden"><%= file.last_revision.updated_at.to_i %></td>
<td class="hidden"><%= file.last_revision.iversion %></td>

View File

@ -18,17 +18,17 @@
<h2>
<% if folder %>
<%= link_to l(:link_documents), dmsf_path(:id => @project) %>
<%= link_to l(:link_documents), dmsf_folder_path(:id => @project) %>
<% folder.dmsf_path.each do |path_element| %>
/
<% if !filename && path_element == folder.dmsf_path.last %>
<%= h(path_element.title) %>
<% else %>
<%= link_to h(path_element.title), dmsf_path(:id => @project, :folder_id => path_element) %>
<%= link_to h(path_element.title), dmsf_folder_path(:id => @project, :folder_id => path_element) %>
<% end %>
<% end %>
<% else %>
<%= link_to l(:link_documents), dmsf_path(:id => @project) %>
<%= link_to l(:link_documents), dmsf_folder_path(:id => @project) %>
<% end %>
<% if filename %>
/

View File

@ -20,9 +20,43 @@
<% html_title(l(:dmsf)) %>
<div class="contextual">
<%= link_to(image_tag('copy.png'),
{:controller => :dmsf_folders_copy, :action => 'new', :id => @folder },
:title => l(:title_copy)) if @folder.id %>
<% if User.current.allowed_to?(:folder_manipulation, @project) && params[:action] == 'edit' %>
<% unless @folder.locked? %>
<%= link_to(l(:button_lock),
lock_dmsf_path(:id => @project, :folder_id => @folder),
:title => l(:title_lock_file),
:class => 'icon icon-dmsf-lock') %>
<% if @folder.notification %>
<%= link_to(l(:label_notifications_off),
notify_deactivate_dmsf_path(:id => @project, :folder_id => @folder),
:title => l(:title_notifications_active_deactivate),
:class => 'icon icon-notification-on') %>
<% else %>
<%= link_to(l(:label_notifications_on),
notify_activate_dmsf_path(:id => @project, :folder_id => @folder),
:title => l(:title_notifications_not_active_activate),
:class => 'icon icon-notification-off') %>
<% end %>
<%= link_to(l(:label_link_to),
new_dmsf_link_path(:project_id => @project.id, :dmsf_folder_id => @folder.id, :type => 'link_to'),
:title => l(:title_create_link),
:class => 'icon icon-link') %>
<%= link_to(l(:button_copy), copy_folder_path(:id => @folder),
:title => l(:title_copy), :class => 'icon icon-copy') %>
<%= link_to(l(:button_delete),
delete_dmsf_path(:id => @project, :folder_id => @folder.dmsf_folder_id, :delete_folder_id => @folder),
:data => {:confirm => l(:text_are_you_sure)},
:title => l(:title_delete),
:class => 'icon icon-del') %>
<% else %>
<% if (!@folder.locked_for_user? || User.current.allowed_to?(:force_file_unlock, @project)) && @folder.unlockable? %>
<%= link_to(l(:button_unlock),
unlock_dmsf_path(:id => @project, :folder_id => @folder),
:title => l(:title_unlock_file),
:class => 'icon icon-dmsf-unlock')%>
<% end %>
<% end %>
<% end %>
</div>
<% create = @pathfolder == @parent %>
@ -64,7 +98,3 @@
<% end %>
<%= wikitoolbar_for 'dmsf_folder_description' %>
<% content_for :header_tags do %>
<%= stylesheet_link_tag 'dmsf', :plugin => 'redmine_dmsf' %>
<% end %>

View File

@ -20,11 +20,22 @@
<% html_title(l(:dmsf)) %>
<div class="contextual">
<% if User.current.allowed_to?(:folder_manipulation, @project) %>
<% if @project.dmsf_notification %>
<%= link_to(l(:label_notifications_off),
notify_deactivate_dmsf_path(:id => @project),
:title => l(:title_notifications_active_deactivate),
:class => 'icon icon-notification-on') %>
<% else %>
<%= link_to(l(:label_notifications_on),
notify_activate_dmsf_path(:id => @project),
:title => l(:title_notifications_active_deactivate),
:class => 'icon icon-notification-off') %>
<% end %>
<% end %>
</div>
<h2>
<%= link_to l(:link_documents), {:controller => 'dmsf', :action => 'show', :id => @project } %>
</h2>
<%= render(:partial => 'path', :locals => {:folder => nil, :filename => nil}) %>
<%= form_for(@project, :url => {:action => 'save_root', :id => @project},
:html => {:method=>:post}) do |f| %>
@ -39,8 +50,4 @@
<%= submit_tag(l(:submit_save)) %>
<% end %>
<%= wikitoolbar_for 'dmsf_folder_description' %>
<% content_for :header_tags do %>
<%= stylesheet_link_tag 'dmsf', :plugin => 'redmine_dmsf' %>
<% end %>
<%= wikitoolbar_for 'project_dmsf_description' %>

View File

@ -1,7 +1,8 @@
<%# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011-14 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
@ -28,10 +29,13 @@
<%= form_tag({:action => 'entries_email', :id => @project, :folder_id => @folder},
{ :method=>:post, :class => 'tabular'}) do %>
<%= hidden_field_tag('email[zipped_content]', @email_params[:zipped_content]) %>
<%= hidden_field_tag('email[folders]', @email_params[:folders].to_json) %>
<%= hidden_field_tag('email[files]', @email_params[:files].to_json) %>
<div class="box">
<p>
<%= label_tag('', "#{l(:label_email_from)}:") %>
<%= h(User.current.mail) %>
<i><%= h(Setting.mail_from) %></i>
</p>
<p>
<%= label_tag('email[to]', "#{l(:label_email_to)}:") %>
@ -47,8 +51,8 @@
</p>
<p>
<%= label_tag('', "#{l(:label_email_documents)}:") %>
<strong>Documents.zip</strong>
<%= hidden_field_tag('email[zipped_content]', @email_params['zipped_content']) %>
<%= link_to 'Documents.zip', download_email_entries_path(:id => @project, :folder_id => @folder, :path => @email_params[:zipped_content]) %>
<%= l(:label_or) %> <%= check_box_tag('email[links_only]') %> <%= l(:label_links_only) %>
</p>
<p>
<%= label_tag('email[body]', "#{l(:label_email_body)}:") %>
@ -57,3 +61,5 @@
<p><%= submit_tag(l(:label_email_send)) %></p>
</div>
<% end %>
<%= wikitoolbar_for 'email_body' %>

View File

@ -1,9 +1,9 @@
<%#=
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2013 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011-14 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
@ -22,47 +22,73 @@
<% html_title(l(:dmsf)) %>
<div class="contextual">
<% if User.current.allowed_to?(:folder_manipulation, @project) %>
<% if @folder.nil? %>
&nbsp;
<%= link_to('', {:action => 'edit_root', :id => @project},
:title => l(:link_edit, :title => l(:link_documents)), :class => 'icon icon-edit') %>
<% elsif @locked_for_user %>
&nbsp;
<%= link_to('', {:action => 'edit', :id => @project, :folder_id => @folder },
:title => l(:link_edit, :title => h(@folder.title)), :class => 'icon icon-edit') %>
<% if @folder_manipulation_allowed %>
<% if @folder.nil? %>
<%= link_to(l(:button_edit),
edit_root_dmsf_path(:id => @project),
:title => l(:link_edit, :title => l(:link_documents)),
:class => 'icon icon-edit') %>
<% elsif !@locked_for_user %>
<%= link_to(l(:button_edit),
edit_dmsf_path(:id => @project, :folder_id => @folder),
:title => l(:link_edit, :title => h(@folder.title)),
:class => 'icon icon-edit') %>
<% end %>
<% if @folder && (!@locked_for_user || User.current.allowed_to?(:force_file_unlock, @project)) %>
<% if @folder.locked? %>
<% unless @folder.unlockable? %>
<%= image_tag('locked.png', :plugin => :redmine_dmsf, :title => l(:title_folder_parent_locked, :name => @folder.folder.lock.reverse[0].folder.title)) unless @folder.nil?%>
<%= link_to(l(:button_unlock),
:title => l(:title_folder_parent_locked, :name => @folder.folder.lock.reverse[0].folder.title),
:class => 'icon icon-dmsf-unlock') if @folder %>
<% else %>
<%= link_to_function(image_tag('unlock.png', :plugin => 'redmine_dmsf'),
"manipulation_link('#{url_for(:action => 'unlock', :id => @project, :folder_id => @folder, :current => request.url)}')",
:title => l(:title_unlock_folder)) if @folder %>
<%= link_to(l(:button_unlock),
unlock_dmsf_path(:id => @project, :folder_id => @folder, :current => request.url),
:title => l(:title_unlock_folder),
:class => 'icon icon-dmsf-unlock') if @folder %>
<% end %>
<% else %>
<%= link_to_function(image_tag('lock.png', :plugin => 'redmine_dmsf'),
"manipulation_link('#{url_for(:action => 'lock', :id => @project, :folder_id => @folder, :current => request.url)}')",
:title => l(:title_lock_folder)) if @folder %>
<%= link_to(l(:button_lock),
lock_dmsf_path(:id => @project, :folder_id => @folder, :current => request.url),
:title => l(:title_lock_folder),
:class => 'icon icon-dmsf-lock') if @folder %>
<% end %>
<% end %>
<% unless @folder %>
&nbsp;
<% if @project.dmsf_notification %>
<%= link_to_function(image_tag('notify.png', :plugin => :redmine_dmsf),
"manipulation_link('#{url_for(:action => 'notify_deactivate', :id => @project)}')",
:title => l(:title_notifications_active_deactivate)) %>
<% else %>
<%= link_to_function(image_tag('notifynot.png', :plugin => :redmine_dmsf),
"manipulation_link('#{url_for(:action => 'notify_activate', :id => @project)}')",
:title => l(:title_notifications_not_active_activate)) %>
<% end %>
<% end %>
&nbsp;
<%= link_to('', {:action => 'new', :id => @project, :parent_id => @folder },
:title => l(:link_create_folder), :class => 'icon icon-add') unless @locked_for_user %>
<% end %>
<% unless @folder %>
<% if @project.dmsf_notification %>
<%= link_to(l(:label_notifications_off),
notify_deactivate_dmsf_path(:id => @project),
:title => l(:title_notifications_active_deactivate),
:class => 'icon icon-notification-on') %>
<% else %>
<%= link_to(l(:label_notifications_on),
notify_activate_dmsf_path(:id => @project),
:title => l(:title_notifications_active_deactivate),
:class => 'icon icon-notification-off') %>
<% end %>
<% else %>
<% if @folder.notification %>
<%= link_to(l(:label_notifications_off),
notify_deactivate_dmsf_path(:id => @project, :folder_id => @folder),
:title => l(:title_notifications_active_deactivate),
:class => 'icon icon-notification-on') %>
<% else %>
<%= link_to(l(:label_notifications_on),
notify_activate_dmsf_path(:id => @project, :folder_id => @folder),
:title => l(:title_notifications_not_active_activate),
:class => 'icon icon-notification-off') %>
<% end %>
<% end %>
<% if @file_manipulation_allowed %>
<%= link_to(l(:label_link_from),
new_dmsf_link_path(:project_id => @project.id, :dmsf_folder_id => @folder ? @folder.id : @folder, :type => 'link_from'),
:title => l(:title_create_link),
:class => 'icon icon-link') unless @locked_for_user %>
<% end %>
<%= link_to(l(:link_create_folder),
new_dmsf_path(:id => @project, :parent_id => @folder),
:title => l(:link_create_folder),
:class => 'icon icon-add') unless @locked_for_user %>
<% end %>
</div>
<%= render(:partial => 'path', :locals => {:folder => @folder, :filename => nil}) %>
@ -81,10 +107,18 @@
<div class="controls" style="float: left">
<%= submit_tag(l(:submit_download), :title => l(:title_download_checked), :name => 'download_entries') %>
<%= submit_tag(l(:submit_email), :title => l(:title_send_checked_by_email), :name => 'email_entries') %>
<% if User.current.allowed_to?(:file_manipulation, @project) && @folder && !@locked_for_user %>
<% if @file_manipulation_allowed && @folder_manipulation_allowed && !@locked_for_user %>
<button type="button" id="entries_delete_button" title="<%= l(:title_delete_checked) %>"><%= l(:button_delete) %></button>
<% end %>
<% end %>
</div>
<% values = @folder ? @folder.custom_field_values : @parent ? @parent.custom_field_values : DmsfFolder.new(:project => @project).custom_field_values %>
<% unless values.empty? %>
<div class="controls" style="float: right">
<%= custom_field_tag_with_label(
:dmsf_folder,
CustomValue.new(:custom_field_id => params[:custom_field_id].present? ? params[:custom_field_id] : values.first.custom_field_id, :value => params[:custom_value])) %>
</div>
<% end %>
<table class="display entries" id="browser">
<thead>
<tr id="root">
@ -100,250 +134,84 @@
<th></th>
<th class="hidden"></th>
<th class="hidden"></th>
<th class="hidden"></th>
<th class="hidden"></th>
</tr>
</thead>
<tbody>
<% @subfolders.each do |subfolder| %>
<% locked_for_user = subfolder.locked_for_user? %>
<% locked = subfolder.locked? %>
<tbody>
<% @subfolders.each do |subfolder| %>
<tr class="dir">
<td class="check"><%= check_box_tag('subfolders[]', subfolder.id, false, :title => l(:title_check_for_zip_download_or_email)) %></td>
<td class="title">
<%= link_to(h(subfolder.title),
{:action => 'show', :id => @project, :folder_id => subfolder}, :class => 'icon icon-folder') %>
<div class="filename" title="<%= l(:title_number_of_files_in_directory)%>">[<%= subfolder.files.visible.count %>]</div>
</td>
<td class="size"></td>
<td class="modified"><%= format_time(subfolder.updated_at) %>
<% if locked_for_user %>
<% if subfolder.lock.reverse[0].user %>
<%= link_to(image_tag('locked.png', :plugin => :redmine_dmsf),
{ :controller => 'users', :action => 'show', :id => subfolder.lock.reverse[0].user },
:title => l(:title_locked_by_user, :user => subfolder.lock.reverse[0].user.to_s)) %>
<% else %>
<%= image_tag('locked.png', :title => l(:notice_account_unknown_email), :plugin => :redmine_dmsf) %>
<% end %>
<% elsif locked %>
<%= image_tag('lockedbycurrent.png', :title => l(:title_locked_by_you), :plugin => :redmine_dmsf) %>
<% end %>
</td>
<td class="version"></td>
<td class="workflow"></td>
<td class="author"><%= h(subfolder.user) %></td>
<td class="actions">
<% if @folder_manipulation_allowed %>
<div class="right_icon_box" style="width:26px;">
<% if subfolder.notification %>
<%= link_to_function(image_tag('notify.png', :plugin => :redmine_dmsf),
"manipulation_link('#{url_for(:action => 'notify_deactivate', :id => @project, :folder_id => subfolder)}')",
:title => l(:title_notifications_active_deactivate)) %>
<% else %>
<%= link_to_function(image_tag('notifynot.png', :plugin => :redmine_dmsf),
"manipulation_link('#{url_for(:action => 'notify_activate', :id => @project, :folder_id => subfolder)}')",
:title => l(:title_notifications_not_active_activate)) %>
<% end %>
</div>
<div class="right_icon_box" style="width: 70px;">
<div style="float: left">
<%= link_to(image_tag('edit.png', :class =>'detail_icon'),
{:action => 'edit', :id => @project, :folder_id => subfolder },
:title => l(:link_edit, :title => h(subfolder.title))) unless locked_for_user %>
</div>
<div style="float: right; width: 44px;">
<% unless locked_for_user && !User.current.allowed_to?(:force_file_unlock, @project)%>
<% if locked %>
<% if subfolder.unlockable? %>
<%= link_to_function(image_tag('unlock.png', :plugin => :redmine_dmsf),
"manipulation_link('#{url_for(:controller => 'dmsf', :action => 'unlock',
:id => @project, :folder_id => subfolder)}')",
:title => l(:title_unlock_file))%>
<% else %>
<%= image_tag('locked.png', :plugin => :redmine_dmsf,
:title => l(:title_folder_parent_locked, :name => subfolder.lock.reverse[0].folder.title)) %>
<% end %>
<% else %>
<%= link_to_function(image_tag('lock.png', :plugin => :redmine_dmsf),
"manipulation_link('#{url_for(:controller => 'dmsf', :action => 'lock',
:id => @project, :folder_id => subfolder)}')",
:title => l(:title_lock_file)) %>
<% end %>
&nbsp;
<% end %>
<%= link_to_function(image_tag('delete.png', :plugin => :redmine_dmsf),
"confirmation_link('#{url_for(:action => 'delete', :id => @project, :folder_id => @folder, :delete_folder_id => subfolder)}', '#{l(:question_do_you_really_want_to_delete_this_entry)}')",
:title => l(:title_delete)) unless locked_for_user %>
</div>
</div>
<br class="clear" />
<% end %>
</td>
<td class="hidden">0</td>
<td class="hidden">0</td>
<%= render(:partial => 'dir',
:locals => {
:project => @project,
:subfolder => subfolder,
:link => nil,
:id => subfolder.id,
:name => 'subfolders[]',
:title => subfolder.title }) %>
</tr>
<% end %>
<% workflows_available = DmsfWorkflow.where(['project_id = ? OR project_id IS NULL', @project.id]).count > 0 %>
<% @dir_links.each do |link| %>
<tr class="gray">
<%= render(:partial => 'dir',
:locals => {
:project => link.target_project,
:subfolder => link.target_folder,
:link => link,
:id => link.id,
:name => 'dir_links[]',
:title => link.name }) %>
</tr>
<% end %>
<% @files.each do |file| %>
<% unless file.last_revision %>
<% Rails.logger.error "Error: dmsf_file id #{file.id} has no revision!" %>
<% next %>
<% end %>
<% locked_for_user = file.locked_for_user? %>
<% locked = file.locked? %>
<% wf = DmsfWorkflow.find_by_id(file.last_revision.dmsf_workflow_id) %>
<% end %>
<tr class="file">
<td class="check"><%= check_box_tag('files[]', file.id, false, :title => l(:title_check_for_zip_download_or_email)) %></td>
<td class="title">
<% file_download_url = url_for({:only_path => false, :controller => :dmsf_files, :action => 'show', :id => file, :download => ''}) %>
<%= link_to(h(file.last_revision.display_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}") %>
<div class="filename" title="<%= l(:title_filename_for_download)%>"><%= h(file.display_name) %></div>
</td>
<td class="size"><%= number_to_human_size(file.last_revision.size) %></td>
<td class="modified">
<%= format_time(file.last_revision.updated_at) %>
<% if locked_for_user %>
<% if file.lock.reverse[0].user %>
<%= link_to(image_tag('locked.png', :plugin => :redmine_dmsf),
{:controller => 'users', :action => 'show', :id => file.lock.reverse[0].user },
:title => l(:title_locked_by_user, :user => file.lock.reverse[0].user.to_s)) %>
<% else %>
<%= image_tag('locked.png', :title => l(:notice_account_unknown_email), :plugin => :redmine_dmsf) %>
<% end %>
<% elsif locked %>
<%= image_tag('lockedbycurrent.png', :title => l(:title_locked_by_you), :plugin => :redmine_dmsf) %>
<% end %>
</td>
<td class="version"><%= file.last_revision.version %></td>
<td class="workflow">
<% if wf && @file_manipulation_allowed %>
<%= link_to(
file.last_revision.workflow_str(false),
log_dmsf_workflow_path(
:project_id => @project.id,
:id => wf.id,
:dmsf_file_revision_id => file.last_revision.id),
:title => DmsfWorkflow.assignments_to_users_str(wf.next_assignments(file.last_revision.id)),
:remote => true) %>
<% else %>
<%= file.last_revision.workflow_str(false) %>
<% end %>
</td>
<td class="author"><%= h(file.last_revision.user) %></td>
<td class="actions">
<% if @file_manipulation_allowed %>
<div class="right_icon_box" style="width:26px;">
<% if file.notification %>
<%= link_to_function(image_tag('notify.png', :plugin => :redmine_dmsf),
"manipulation_link('#{url_for(:controller => 'dmsf_files', :action => 'notify_deactivate', :id => file)}')",
:title => l(:title_notifications_active_deactivate)) %>
<% else %>
<%= link_to_function(image_tag('notifynot.png', :plugin => :redmine_dmsf),
"manipulation_link('#{url_for(:controller => 'dmsf_files', :action => 'notify_activate', :id => file)}')",
:title => l(:title_notifications_not_active_activate)) %>
<% end %>
<% case file.last_revision.workflow %>
<% when DmsfWorkflow::STATE_WAITING_FOR_APPROVAL %>
<% if wf %>
<% assignments = wf.next_assignments(file.last_revision.id) %>
<% index = assignments.find_index{|assignment| assignment.user_id == User.current.id} if assignments %>
<% if index %>
<%= link_to(
image_tag('waiting_for_approval.png', :plugin => :redmine_dmsf),
action_dmsf_workflow_path(
:project_id => @project.id,
:id => wf.id,
:dmsf_workflow_step_assignment_id => assignments[index].id,
:dmsf_file_revision_id => file.last_revision.id),
:title => l(:title_waiting_for_approval),
:remote => true) %>
<% else %>
<%= image_tag('waiting_for_approval.png', :title => "#{l(:label_dmsf_wokflow_action_approve)} #{l(:label_dmsf_wokflow_action_reject)} #{l(:label_dmsf_wokflow_action_delegate)}", :plugin => :redmine_dmsf) %>
<% end %>
<% else %>
<%= image_tag('waiting_for_approval.png', :title => "#{l(:label_dmsf_wokflow_action_approve)} #{l(:label_dmsf_wokflow_action_reject)} #{l(:label_dmsf_wokflow_action_delegate)}", :plugin => :redmine_dmsf) %>
<% end %>
<% when DmsfWorkflow::STATE_APPROVED %>
<%= image_tag('approved.png', :title => l(:title_approved), :plugin => :redmine_dmsf) %>
<% when DmsfWorkflow::STATE_ASSIGNED %>
<% if User.current && (file.last_revision.dmsf_workflow_assigned_by == User.current.id) && wf %>
<%= link_to_function(image_tag('assigned.png', :plugin => :redmine_dmsf),
"manipulation_link('#{start_dmsf_workflow_path(
:id => file.last_revision.dmsf_workflow_id,
:dmsf_file_revision_id => file.last_revision.id)}')",
:title => l(:label_dmsf_wokflow_action_start)) %>
<% else %>
<%= image_tag('assigned.png', :title => l(:label_dmsf_wokflow_action_start), :plugin => :redmine_dmsf) %>
<% end %>
<% when DmsfWorkflow::STATE_REJECTED %>
<%= image_tag('rejected.png', :title => l(:title_rejected), :plugin => :redmine_dmsf) %>
<% else %>
<% if workflows_available %>
<%= link_to(
image_tag('none.png', :plugin => :redmine_dmsf),
assign_dmsf_workflow_path(
:project_id => @project.id,
:dmsf_file_revision_id => file.last_revision.id),
:title => l(:label_dmsf_wokflow_action_assign),
:remote => true) %>
<% end %>
<% end %>
</div>
<div class="right_icon_box" style="width: 70px">
<div style="float: left">
<%= link_to(image_tag('filedetails.png', :plugin => :redmine_dmsf, :class =>'detail_icon'),
{:controller => 'dmsf_files', :action => :show, :id => file },
:title => l(:link_details, :title =>h(file.last_revision.title))) %>
</div>
<div style="float: right; width: 44px;">
<% if !locked_for_user || @force_file_unlock_allowed %>
<% if locked %>
<% if file.unlockable? %>
<%= link_to_function(image_tag('unlock.png', :plugin => :redmine_dmsf),
"manipulation_link('#{url_for(:controller => 'dmsf_files', :action => 'unlock', :id => file)}')",
:title => l(:title_unlock_file))%>
<% else %>
<%= image_tag('locked.png', :plugin => :redmine_dmsf,
:title => l(:title_file_parent_locked, :name => file.folder.lock.reverse[0].folder.title)) %>
<% end%>
<% else %>
<%= link_to_function(image_tag('lock.png', :plugin => :redmine_dmsf),
"manipulation_link('#{url_for(:controller => 'dmsf_files', :action => 'lock', :id => file)}')",
:title => l(:title_lock_file)) %>
<% end %>
&nbsp;
<% end %>
<% unless locked_for_user %>
<%= link_to_function(image_tag('delete.png', :plugin => :redmine_dmsf),
"confirmation_link('#{url_for(:controller => 'dmsf_files', :action => 'delete', :id => file)}', '#{l(:question_do_you_really_want_to_delete_this_entry)}')",
:title => l(:title_delete)) %>
<% end %>
</div>
</div>
<br class="clear" />
<% end %>
</td>
<td class="hidden">1</td>
<td class="hidden"><%= file.last_revision.size %></td>
<%= render(:partial => 'file', :locals => {
:project => @project,
:file => file,
:link => nil,
:id => file.id,
:name => 'files[]',
:title => file.title }) %>
</tr>
<% end %>
<% @file_links.each do |link| %>
<% unless link.target_file.last_revision %>
<% Rails.logger.error "Error: dmsf_file id #{link.target_id} has no revision!" %>
<% next %>
<% end %>
<tr class="gray">
<%= render(:partial => 'file', :locals => {
:project => link.target_project,
:file => link.target_file,
:link => link,
:id => link.id,
:name => 'file_links[]',
:title => link.name }) %>
</tr>
<% end %>
</tbody>
</table>
<br />
</table>
<% end %>
<script type="text/javascript">
jQuery('#entries_delete_button').click(function() {
if(window.confirm("<%= l(:question_do_you_really_want_to_delete_entries) %>")) {
jQuery('#entries_form').attr('action', "<%= url_for(:action => :delete_entries, :id => @project, :folder_id => @folder) %>");
jQuery('#entries_form').submit();
$('#entries_delete_button').click(function() {
if(window.confirm("<%= l(:text_are_you_sure) %>")) {
$('#entries_form').attr('action', "<%= delete_entries_path(:id => @project, :folder_id => @folder) %>");
$('#entries_form').submit();
}
});
$('.list_cf').change(function() {
$('#entries_form').attr('action', "<%= tag_changed_path(:id => @project, :folder_id => @folder) %>");
$('#entries_form').submit();
});
jQuery('#check_all_entries').click(function() {
jQuery('input[type=checkbox]', jQuery('#browser > tbody')).prop('checked', this.checked);
$('#check_all_entries').click(function() {
$('input[type=checkbox]', $('#browser > tbody')).prop('checked', this.checked);
});
</script>
@ -355,19 +223,16 @@
end
%>
<% content_for :header_tags do %>
<%= stylesheet_link_tag 'jquery-ui/jquery-ui-1.9.2.css', :plugin => 'redmine_dmsf' %>
<% content_for :header_tags do %>
<%= stylesheet_link_tag 'plupload/jquery.ui.plupload.css', :plugin => 'redmine_dmsf' %>
<%= stylesheet_link_tag 'jquery.dataTables/jquery-ui.dataTables.css', :plugin => 'redmine_dmsf' %>
<%= stylesheet_link_tag 'dmsf', :plugin => 'redmine_dmsf' %>
<%= javascript_include_tag 'jquery-1.6.1.min.js', :plugin => 'redmine_dmsf' %>
<%= javascript_include_tag 'jquery-ui-1.8.13.min.js', :plugin => 'redmine_dmsf' %>
<%= javascript_include_tag 'jquery.dataTables/jquery.dataTables.min.js', :plugin => 'redmine_dmsf' %>
<script type="text/javascript">
jQuery.noConflict();
jQuery(document).ready(function() {
jQuery('#browser').dataTable({
<script type="text/javascript">
$(document).ready(function() {
$('#browser').dataTable({
'bJQueryUI': true,
'oLanguage': {
'sUrl': "<%= plugin_asset_path(:redmine_dmsf, 'javascripts', sUrl) %>"
@ -379,17 +244,19 @@
'aoColumnDefs': [
{ 'bSearchable': false, 'aTargets': [0, 7, 8, 9] },
{ 'bSortable': false, 'aTargets': [0, 7, 8] },
{ 'iDataSort': 9, 'aTargets': [ 2 ] }
{ 'iDataSort': 9, 'aTargets': [ 2 ] },
{ 'iDataSort': 10, 'aTargets': [ 3 ] },
{ 'iDataSort': 11, 'aTargets': [ 4 ] }
],
'fnInitComplete': function() {
jQuery('div.controls').prependTo(jQuery('#browser_wrapper div.fg-toolbar')[0]);
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.length %>, <%= l(:label_number_of_documents)%>: <%= @files.length %>";
return "<%= l(:label_number_of_folders)%>: <%= @subfolders.count + @dir_links.count %>, <%= l(:label_number_of_documents)%>: <%= @files.count + @file_links.count %>";
}
});
jQuery('[data-downloadurl]').each(function() {
$('[data-downloadurl]').each(function() {
var url = this.getAttribute('data-downloadurl');
if (this.addEventListener) {
this.addEventListener('dragstart', function(e) {
@ -400,12 +267,11 @@
}
});
jQuery('#entries_form').submit(function () {
jQuery(this).removeAttr('data-submitted');
$('#entries_form').submit(function () {
$(this).removeAttr('data-submitted');
});
});
</script>
<% end %>
<%= render(:partial => 'multi_upload') if (@file_manipulation_allowed && !@locked_for_user) %>
<br/>
<%= render(:partial => 'multi_upload') if (@file_manipulation_allowed && !@locked_for_user) %>

View File

@ -26,13 +26,13 @@
<% if @file.locked_for_user? %>
<p class="warning"><%= l(:info_file_locked) %></p>
<% else %>
<%= form_for(@revision, :url => {:action => 'create_revision', :id => @file},
:html => {:method=>:post, :multipart => true, :id => 'new_revision_form'}) do |f| %>
<%= form_for(@revision, :url => { :action => 'create_revision', :id => @file },
:html => { :method => :post, :multipart => true, :id => 'new_revision_form' }) do |f| %>
<div class="clear">
<div class="splitcontentleft">
<p>
<%= label_tag('dmsf_file_revision_title', "#{l(:label_title)}:") %>
<%= f.text_field(:title, :size => '32') %>
<%= f.text_field(:title, :size => 32) %>
</p>
</div>
<div class="splitcontentright">
@ -41,7 +41,7 @@
<%= f.select(:dmsf_folder_id,
options_for_select(DmsfFolder.directory_tree(@project),
:selected => (@revision.folder.id if @revision.folder))) %> /
<%= f.text_field(:name, :size => '22') %>
<%= f.text_field(:name, :size => 22) %>
</p>
</div>
</div>
@ -49,7 +49,7 @@
<%= label_tag('dmsf_file_revision_description', "#{l(:label_description)}:") %>
</p>
<div class="wiki data clear">
<%= f.text_area(:description, :rows=> '6', :class => 'wiki-edit') %>
<%= f.text_area(:description, :rows => 6, :class => 'wiki-edit') %>
</div>
<div class="splitcontentleft">
<p>
@ -69,14 +69,14 @@
<div class="splitcontentright clear">
<p>
<%= label_tag('file_upload', "#{l(:label_new_content)}:") %>
<div class="data">
<%= file_field_tag('file_upload', :size => 30) %>
<br />
<small>
(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)
</small>
</div>
</p>
</p>
<div class="data">
<%= file_field_tag('file_upload') %>
<br/>
<small>
(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)
</small>
</div>
</div>
<br style="clear: both"/>
<div class="custom_fields">
@ -87,12 +87,12 @@
<div class="comment">
<p>
<%= label_tag('dmsf_file_revision_comment', "#{l(:label_comment)}:") %>
<div class="data">
<%= f.text_area(:comment, :rows=> '2', :style => 'width: 99%;') %>
</div>
</p>
<div class="data">
<%= f.text_area(:comment, :rows=> 2, :style => 'width: 99%;') %>
</div>
</div>
<br />
<br/>
<%= submit_tag(l(:submit_create)) %>
<% end %>
<% end %>

View File

@ -19,25 +19,24 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
%>
<p>
<table class="display access-table list">
<thead>
<br/>
<table class="display access-table list">
<thead>
<tr>
<th><%= l(:field_user) %></th>
<th><%= l(:heading_access_downloads_emails) %></th>
<th><%= l(:heading_access_first) %></th>
<th><%= l(:heading_access_last) %></th>
</tr>
</thead>
<tbody>
<% revision.access_grouped.each do |access| %>
<tr>
<th><%= l(:field_user) %></th>
<th><%= l(:heading_access_downloads_emails) %></th>
<th><%= l(:heading_access_first) %></th>
<th><%= l(:heading_access_last) %></th>
<td><%= link_to_user(access.user) %></td>
<td><%= access['count'] %></td>
<td><%= format_time(DmsfHelper::to_time(access.first_at)) %></td>
<td><%= format_time(DmsfHelper::to_time(access.last_at)) %></td>
</tr>
</thead>
<tbody>
<% revision.access_grouped.each do |access| %>
<tr>
<td><%= link_to_user(access.user) %></td>
<td><%= access['count'] %></td>
<td><%= format_time(DmsfHelper::to_time(access.first_at)) %></td>
<td><%= format_time(DmsfHelper::to_time(access.last_at)) %></td>
</tr>
<% end %>
</tbody>
</table>
</p>
<% end %>
</tbody>
</table>

View File

@ -1,9 +1,9 @@
<%#=
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2013 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011-14 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
@ -24,40 +24,38 @@
<div class="contextual">
<% if User.current.allowed_to?(:file_manipulation, @project) %>
<% unless @file.locked_for_user? && !User.current.allowed_to?(:force_file_unlock, @project)%>
<% if @file.locked? %>
<% unless @file.unlockable? %>
<%= image_tag('locked.png', :plugin => :redmine_dmsf, :title => l(:title_file_parent_locked, :name => @file.lock.reverse[0].folder.title)) %>
<% else %>
<%= link_to_function(image_tag('unlock.png', :plugin => 'redmine_dmsf'),
"manipulation_link('#{url_for(:action => 'unlock', :id => @file, :current => request.url)}')",
:title => l(:title_unlock_file)) %>
<% end %>
<% else %>
<%= link_to_function(image_tag('lock.png', :plugin => 'redmine_dmsf'),
"manipulation_link('#{url_for(:action => 'lock', :id => @file, :current => request.url)}')",
:title => l(:title_lock_file)) %>
<% end %>
<% end %>
<% unless @file.locked_for_user? %>
&nbsp;
<%= link_to_function(image_tag('delete.png', :plugin => 'redmine_dmsf'),
"confirmation_link('#{url_for(:action => 'delete', :id => @file)}', '#{l(:question_do_you_really_want_to_delete_this_entry)}')",
:title => l(:title_delete)) %>
<% end %>
&nbsp;
<% if @file.notification %>
<%= link_to_function(image_tag('notify.png', :plugin => 'redmine_dmsf'),
"manipulation_link('#{url_for(:action => 'notify_deactivate', :id => @file, :current => request.url)}')",
:title => l(:title_notifications_active_deactivate)) %>
<% unless @file.locked? %>
<%= link_to(l(:button_lock),
lock_dmsf_files_path(:id => @file),
:title => l(:title_lock_file),
:class => 'icon icon-dmsf-lock') %>
<% if @file.notification %>
<%= link_to(l(:label_notifications_off),
notify_deactivate_dmsf_files_path(:id => @file),
:title => l(:title_notifications_active_deactivate),
:class => 'icon icon-notification-on') %>
<% else %>
<%= link_to(l(:label_notifications_on),
notify_activate_dmsf_files_path(:id => @file),
:title => l(:title_notifications_not_active_activate),
:class => 'icon icon-notification-off') %>
<% end %>
<%= link_to(l(:label_link_to),
new_dmsf_link_path(:project_id => @project.id, :dmsf_folder_id => @file.folder ? @file.folder.id : nil, :dmsf_file_id => @file.id, :type => 'link_to'),
:title => l(:title_create_link),
:class => 'icon icon-link') %>
<%= link_to("#{l(:button_copy)}/#{l(:button_move)}", copy_file_path(:id => @file),
:title => l(:title_copy), :class => 'icon icon-copy') %>
<%= delete_link @file %>
<% else %>
<%= link_to_function(image_tag('notifynot.png', :plugin => 'redmine_dmsf'),
"manipulation_link('#{url_for(:action => 'notify_activate', :id => @file, :current => request.url)}')",
:title => l(:title_notifications_not_active_activate)) %>
<% end %>
&nbsp;
<%= link_to(image_tag('copy.png'), {:controller => :dmsf_files_copy, :action => 'new', :id => @file }, :title => l(:title_copy_or_move)) %>
<% end %>
<% if (!@file.locked_for_user? || User.current.allowed_to?(:force_file_unlock, @project)) && @file.unlockable? %>
<%= link_to(l(:button_unlock),
unlock_dmsf_files_path(:id => @file),
:title => l(:title_unlock_file),
:class => 'icon icon-dmsf-unlock')%>
<% end %>
<% end %>
<% end %>
</div>
<%= render(:partial => '/dmsf/path', :locals => {:folder => @file.folder, :filename => @file.title}) %>
@ -65,22 +63,28 @@
<%= error_messages_for('file') %>
<%= error_messages_for('revision') %>
<%= render(:partial => 'file_new_revision') if User.current.allowed_to?(:file_manipulation, @file.project) %>
<%= form_tag('', :id => 'entries_form') %>
<h3><%= l(:heading_revisions) %></h3>
<% @file.revisions.visible[@revision_pages.offset,@revision_pages.per_page].each do |revision| %>
<div class="revision_box dmsf_detail dataTables_wrapper">
<div class="fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix">
<div class="dataTables_lenght">
<div class="controls" style="float: right">
<%= link_to_function(image_tag('rev_downloads.png', :plugin => 'redmine_dmsf'), "$('#revision_access-#{revision.id}').toggle()", :title => 'Download entries')%>
<%= link_to(image_tag('rev_download.png', :plugin => 'redmine_dmsf'),
{:action => 'show', :id => @file, :download => revision},
:title => l(:title_title_version_version_download, :title => h(revision.title), :version => revision.version)) %>
<div class="controls" style="float: right">
<%= link_to_function(
'',
"$('#revision_access-#{revision.id}').toggle()",
:title => l(:title_download_entries),
:class => 'icon icon-dmsf-rev-downloads') %>
<%= link_to('',
dmsf_file_path(@file, :download => revision),
:title => l(:title_title_version_version_download, :title => h(revision.title), :version => revision.version),
:class => 'icon icon-dmsf-rev-download') %>
<% if User.current.allowed_to?(:file_manipulation, @project) %>
<%= link_to_function(image_tag('rev_delete.png', :plugin => 'redmine_dmsf'),
"confirmation_link('#{url_for(:action => 'delete_revision', :id => revision)}', '#{l(:question_do_you_really_want_to_delete_this_revision)}')",
:title => l(:title_delete_revision)) %>
<%= link_to '',
delete_revision_path(revision),
:data => {:confirm => l(:text_are_you_sure)},
:title => l(:title_delete_revision),
:class => 'icon icon-dmsf-rev-delete' %>
<% end %>
</div>
<i><%= l(:info_revision, :rev => revision.id) %></i>
@ -141,13 +145,12 @@
<%= h(revision.comment) %>
</div>
<br/>
<div id="<%= "revision_access-#{revision.id}" %>" style="display:none">
<%= render(:partial => 'revision_access', :locals => {:revision => revision}) if User.current.allowed_to?(:file_manipulation, @file.project) %>
<div id="<%= "revision_access-#{revision.id}" %>" style="display:none">
<%= render(:partial => 'revision_access', :locals => {:revision => revision}) if User.current.allowed_to?(:file_manipulation, @file.project) %>
</div>
</div>
</div>
<br/>
<br/>
<br/>
<% end %>
<p class="pagination"><%= pagination_links_full @revision_pages, @file.revisions.visible.count %></p>
@ -158,34 +161,34 @@
%>
<script type="text/javascript">
jQuery('a.delete-revision').click(function(event) {
if(!window.confirm('<%= l(:question_do_you_really_want_to_delete_this_revision) %>')) {
$('a.delete-revision').click(function(event) {
if(!window.confirm('<%= l(:text_are_you_sure) %>')) {
event.preventDefault();
}
});
jQuery('a.delete-entry').click(function(event) {
if(!window.confirm('<%= l(:question_do_you_really_want_to_delete_this_entry) %>')) {
$('a.delete-entry').click(function(event) {
if(!window.confirm('<%= l(:text_are_you_sure) %>')) {
event.preventDefault();
}
});
jQuery('#file_upload').change(function() {
if(jQuery("input[name='version']:checked").val() == '0') {
jQuery('#fileMinorVersionRadio').prop('checked', true);
$('#file_upload').change(function() {
if($("input[name='version']:checked").val() == '0') {
$('#fileMinorVersionRadio').prop('checked', true);
}
jQuery('#fileSameVersionRadio').prop('disabled', true);
$('#fileSameVersionRadio').prop('disabled', true);
});
jQuery('#newRevisionFormContentToggle').toggle(function() {
jQuery('#newRevisionFormContentToggle').text('[-]');
jQuery('#newRevisionFormContent').show();
$('#newRevisionFormContentToggle').toggle(function() {
$('#newRevisionFormContentToggle').text('[-]');
$('#newRevisionFormContent').show();
}, function() {
jQuery('#newRevisionFormContentToggle').text('[+]');
jQuery('#newRevisionFormContent').hide();
$('#newRevisionFormContentToggle').text('[+]');
$('#newRevisionFormContent').hide();
});
jQuery('.access-table').dataTable({
$('.access-table').dataTable({
'bJQueryUI': true,
'oLanguage': {
'sUrl': '/plugin_assets/<%= :redmine_dmsf %>/javascripts/<%= url %>'
@ -194,15 +197,13 @@
</script>
<% if @revision.valid? && @file.valid? %>
<script type="text/javascript">
jQuery('#newRevisionFormContentToggle').text('[+]');
jQuery('#newRevisionFormContent').hide();
$('#newRevisionFormContentToggle').text('[+]');
$('#newRevisionFormContent').hide();
</script>
<% end %>
<% content_for :header_tags do %>
<%= stylesheet_link_tag 'jquery-ui/jquery-ui-1.9.2.css', :plugin => 'redmine_dmsf' %>
<% content_for :header_tags do %>
<%= stylesheet_link_tag 'jquery.dataTables/jquery-ui.dataTables.css', :plugin => 'redmine_dmsf' %>
<%= stylesheet_link_tag 'dmsf', :plugin => 'redmine_dmsf' %>
<%= javascript_include_tag 'jquery-1.6.1.min.js', :plugin => 'redmine_dmsf' %>
<%= javascript_include_tag 'jquery-ui-1.8.13.min.js', :plugin => 'redmine_dmsf' %>
<%= javascript_include_tag 'jquery.dataTables/jquery.dataTables.min.js', :plugin => 'redmine_dmsf' %>

View File

@ -28,12 +28,12 @@
<%= form_tag({:action => 'create', :id => @file}, :id => 'copyForm') do |f| %>
<div class="box dmsf_detail">
<p>
<label for="target_project_id"><%=l(:label_target_project)%>:</label>
<label for="target_project_id"><%=l(:field_target_project)%>:</label>
<%= select_tag('target_project_id',
project_tree_options_for_select(DmsfFile.allowed_target_projects_on_copy, :selected => @target_project)) %>
</p>
<p>
<%= label_tag('target_folder_id', "#{l(:label_target_folder)}:") %>
<%= label_tag('target_folder_id', "#{l(:field_target_folder)}:") %>
<%= select_tag('target_folder_id',
options_for_select(DmsfFolder.directory_tree(@target_project),
:selected => (@target_folder.id if @target_folder))) %>
@ -55,12 +55,4 @@
jQuery('#target_project_id').change(function () {
jQuery('#content').load("<%= url_for(:action => 'new') %>", jQuery('#copyForm').serialize());
});
</script>
<% content_for :header_tags do %>
<%= stylesheet_link_tag 'dmsf', :plugin => 'redmine_dmsf' %>
<%= javascript_include_tag 'jquery-1.6.1.min.js', :plugin => 'redmine_dmsf' %>
<script type="text/javascript">
jQuery.noConflict();
</script>
<% end %>
</script>

View File

@ -27,12 +27,12 @@
<%= form_tag({:action => 'copy_to', :id => @folder}, :id => 'copyForm') do |f| %>
<div class="box dmsf_detail">
<p>
<label for="target_project_id"><%= l(:label_target_project) %>:</label>
<label for="target_project_id"><%= l(:field_target_project) %>:</label>
<%= select_tag('target_project_id',
project_tree_options_for_select(DmsfFolder.allowed_target_projects_on_copy, :selected => @target_project)) %>
</p>
<p>
<%= label_tag('target_folder_id', "#{l(:label_target_folder)}:") %>
<%= label_tag('target_folder_id', "#{l(:field_target_folder)}:") %>
<%= select_tag('target_folder_id',
options_for_select(DmsfFolder.directory_tree(@target_project, @folder),
:selected => (@target_folder.id if @target_folder))) %>
@ -46,12 +46,4 @@
jQuery('#target_project_id').change(function () {
jQuery('#content').load("<%= url_for(:action => 'new') %>", jQuery('#copyForm').serialize());
});
</script>
<% content_for :header_tags do %>
<%= stylesheet_link_tag 'dmsf', :plugin => 'redmine_dmsf' %>
<%= javascript_include_tag 'jquery-1.6.1.min.js', :plugin => 'redmine_dmsf' %>
<script type="text/javascript">
jQuery.noConflict();
</script>
<% end %>
</script>

View File

@ -0,0 +1,88 @@
<%# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-14 Karel Pičman <karel.picman@lbcfree.net>
#
# 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.%>
<% html_title(l(:dmsf)) %>
<div class="contextual">
</div>
<% if @dmsf_file_id %>
<% file = DmsfFile.find_by_id @dmsf_file_id%>
<% title = file.title if file %>
<% end %>
<%= render(:partial => '/dmsf/path', :locals => {:folder => @dmsf_link.folder, :filename => title}) %>
<%= labelled_form_for @dmsf_link do |f| %>
<%= error_messages_for @dmsf_link %>
<%= f.hidden_field :project_id, :value => @dmsf_link.project_id %>
<%= f.hidden_field :dmsf_folder_id, :value => @dmsf_link.dmsf_folder_id if @dmsf_link.dmsf_folder_id %>
<%= f.hidden_field :type, :value => @type %>
<%= f.hidden_field :dmsf_file_id, :value => @dmsf_file_id %>
<div class="box dmsf_detail">
<p>
<% if @type == 'link_from' %>
<%= label_tag('dmsf_link[target_project_id]', l(:label_source_project), :class => 'required') %>
<% else %>
<%= label_tag('dmsf_link[target_project_id]', l(:label_target_project), :class => 'required') %>
<% end %>
<%= select_tag('dmsf_link[target_project_id]',
project_tree_options_for_select(DmsfFile.allowed_target_projects_on_copy,
:selected => @dmsf_link.target_project)) %>
</p>
<p>
<% if @type == 'link_from' %>
<%= label_tag('dmsf_link[target_folder_id]', l(:label_source_folder)) %>
<% else %>
<%= label_tag('dmsf_link[target_folder_id]', l(:label_target_folder)) %>
<% end %>
<%= select_tag('dmsf_link[target_folder_id]',
folder_tree_options_for_select(DmsfFolder.directory_tree(@dmsf_link.target_project),
:selected => @target_folder_id)) %>
</p>
<% if @type == 'link_from' %>
<p>
<% if @target_folder_id %>
<% folder = DmsfFolder.find_by_id @target_folder_id %>
<% files = folder.files.visible if folder %>
<% else %>
<% files = @dmsf_link.target_project.dmsf_files.visible if @dmsf_link.target_project %>
<% end %>
<%= f.select(:target_file_id,
options_for_select(DmsfFolder.file_list(files), @target_file_id)) %>
</p>
<% end %>
<p>
<%= label_tag('dmsf_link[name]', l(:label_link_name), :class => 'required') %>
<%= text_field_tag 'dmsf_link[name]', @dmsf_link.name, :size => 40, :maxlength => 255 %>
</p>
</div>
<%= f.submit l(:button_create) %>
<% end %>
<script type="text/javascript">
$('#dmsf_link_target_project_id').change(function () {
$('#content').load("<%= url_for(:action => 'new', :project_id => @project.id, :reload => true) %>", $('#new_dmsf_link').serialize());
});
$('#dmsf_link_target_folder_id').change(function () {
$('#content').load("<%= url_for(:action => 'new', :project_id => @project.id) %>", $('#new_dmsf_link').serialize());
});
$('#dmsf_link_target_file_id').change(function () {
$('#content').load("<%= url_for(:action => 'new', :project_id => @project.id) %>", $('#new_dmsf_link').serialize());
});
</script>

View File

@ -1,6 +1,6 @@
# Redmine plugin for Document Management System "Features"
<%# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2014 Karel Pičman <karel.picman@lbcfree.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -14,8 +14,6 @@
#
# 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.%>
vendor = File.expand_path('../vendor', __FILE__)
$:.unshift(vendor) unless $:.include?(vendor)
require 'dav4rack'
<%= render 'form' %>

View File

@ -1,7 +1,8 @@
<%# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2014 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,13 +18,13 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.%>
User <%= link_to(h(@user), {:only_path => false, :controller => 'users', :action => 'show', :id => @user }) %>
deleted DMSF files in project <%= @project.name %>:
<%= link_to User.current, user_path(User.current, :only_path => false) %> <%= l(:text_email_doc_deleted) %>
<%= link_to @project, project_path(@project, :only_path => false) %> <%= l(:text_email_doc_follows) %>
<% @files.each do |file| %>
<p>
<%= h(file.dmsf_path_str) %> (<%= file.name %>)
<% if file.last_revision %>
, <%= number_to_human_size(file.last_revision.size) %>, version: <%= file.last_revision.major_version %>.<%= file.last_revision.minor_version %>
, <%= number_to_human_size(file.last_revision.size) %>, <%= l(:label_version) %> <%= file.last_revision.major_version %>.<%= file.last_revision.minor_version %>
<% end %>
</p>
<% end %>

View File

@ -1,7 +1,8 @@
<%# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2014 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
@ -16,11 +17,11 @@
# 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.%>
User <%= @user %> deleted DMSF files in project <%= @project.name %>:
<% @files.each do |file| %>
<%= file.dmsf_path_str %> (<%= file.name %>)
<% if file.last_revision %>
, <%= number_to_human_size(file.last_revision.size) %>, version: <%= file.last_revision.major_version %>.<%= file.last_revision.minor_version %>
<% end %>
<%= User.current.name %> <%= l(:text_email_doc_deleted) %> <%= @project.name %> <%= l(:text_email_doc_follows) %>
<% @files.each do |file| %>
<%= h(file.dmsf_path_str) %> (<%= file.name %>)
<% if file.last_revision %>
, <%= number_to_human_size(file.last_revision.size) %>, <%= l(:label_version) %> <%= file.last_revision.major_version %>.<%= file.last_revision.minor_version %>
<% end %>
<% end %>

View File

@ -1,7 +1,8 @@
<%# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2014 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,20 +18,20 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.%>
User <%= link_to(h(@user), {:only_path => false, :controller => 'users', :action => 'show', :id => @user }) %>
actualized DMSF files in project <%= @project.name %>:
<%= link_to User.current, user_path(User.current, :only_path => false) %> <%= l(:text_email_doc_updated) %>
<%= link_to @project, project_path(@project, :only_path => false) %> <%= l(:text_email_doc_follows) %>
<% @files.each do |file| %>
<p>
<%= link_to(h(file.dmsf_path_str),
{:only_path => false, :controller => 'dmsf_files', :action => 'show', :id => file,
:download => ''}) %> (<%= file.name %>),
dmsf_file_path(file, :download => '', :only_path => false)) %>
(<%= file.name %>),
<%= number_to_human_size(file.last_revision.size) %>,
version: <%= file.last_revision.major_version %>.<%= file.last_revision.minor_version %>,
<%= "#{file.last_revision.workflow_str(true)}," if file.last_revision.workflow_str(true).present? %>
<%= link_to('Details',
{:only_path => false, :controller => 'dmsf_files', :action => 'show', :id => file}) %>
<%= l(:label_version) %> <%= file.last_revision.major_version %>.<%= file.last_revision.minor_version %>,
<%= "#{file.last_revision.workflow_str(true)}," if file.last_revision.workflow_str(true) != l(:title_none) %>
<%= link_to(l(:link_details, :title => h(file.title)),
dmsf_file_path(file, :only_path => false)) %>
<% if file.last_revision.comment.present? %>
<br /><span style="font-size: 0.9em">&nbsp;&nbsp;&nbsp;&nbsp;<em><%= h(file.last_revision.comment) %></em></span>
<br/><span style="font-size: 0.9em">&nbsp;&nbsp;&nbsp;&nbsp;<em><%= h(file.last_revision.comment) %></em></span>
<% end %>
</p>
<% end %>

View File

@ -1,7 +1,8 @@
<%# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2014 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
@ -16,10 +17,16 @@
# 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.%>
User <%= @user %> actualized DMSF files in project <%= @project.name %>:
<%= User.current.name %> <%= l(:text_email_doc_updated) %>
<%= @project.name %> <%= l(:text_email_doc_follows) %>
<% @files.each do |file| %>
<%= file.dmsf_path_str %> (<%= file.name %>), <%= number_to_human_size(file.last_revision.size) %>, version: <%= file.last_revision.major_version %>.<%= file.last_revision.minor_version %><%= ", #{file.last_revision.workflow_str(true)}" unless file.last_revision.workflow_str(true).blank? %>
<%= url_for({:only_path => false, :controller => 'dmsf_files', :action => 'show', :id => file}) %>
<% if file.last_revision.comment.present? %> comment: <%= file.last_revision.comment %><% end %>
<%= h(file.dmsf_path_str) %> (<%= file.name %>),
<%= number_to_human_size(file.last_revision.size) %>,
<%= l(:label_version) %> <%= file.last_revision.major_version %>.<%= file.last_revision.minor_version %>,
<%= "#{file.last_revision.workflow_str(true)}," if file.last_revision.workflow_str(true) != l(:title_none) %>
<%= dmsf_file_path(file, :only_path => false) %>
<% if file.last_revision.comment.present? %>
<%= l(:label_comment) %> <%= h(file.last_revision.comment) %>
<% end %>
<% end %>

View File

@ -1,7 +1,8 @@
<%# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011-14 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,4 +18,38 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.%>
<%= simple_format(@body) %>
<%= textilizable(@body) %>
<% if @links_only == '1' %>
<% if @folders.present? %>
<% JSON.parse(@folders).each do |id| %>
<% folder = DmsfFolder.find_by_id id %>
<% if folder %>
<% folder.folder_tree.each do |name, i| %>
<% dir = DmsfFolder.find_by_id i %>
<% if dir %>
<br/>
<%= link_to(h(dir.dmsf_path_str), dmsf_folder_path(:id => dir.project_id, :folder_id => dir.id, :only_path => false)) %>
<br/><br/>
<% dir.files.each do |file| %>
<%= link_to(h(file.title), dmsf_file_path(file, :only_path => false)) %>
&nbsp;(<%= link_to(h(file.name), dmsf_file_path(file, :download => '', :only_path => false)) %>)
<br/>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
<% if @files.present? %>
<br/>
<% JSON.parse(@files).each do |id| %>
<% file = DmsfFile.find_by_id id %>
<% if file %>
<%= link_to(h(file.title), dmsf_file_path(file, :only_path => false)) %>
&nbsp;(<%= link_to(h(file.name), dmsf_file_path(file, :download => '', :only_path => false)) %>)
<br/>
<% end %>
<% end %>
<% end %>
<% end %>

View File

@ -1,7 +1,8 @@
<%# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011-14 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,3 +19,30 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.%>
<%= @body %>
<% if @links_only == '1' %>
<% if @folders.present? %>
<% JSON.parse(@folders).each do |id| %>
<% folder = DmsfFolder.find_by_id id %>
<% if folder %>
<% folder.folder_tree.each do |name, i| %>
<% dir = DmsfFolder.find_by_id i %>
<% if dir %>
<%= dir.dmsf_path_str %>
<% dir.files.each do |file| %>
<%= dmsf_file_path(file, :download => '', :only_path => false) %>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
<% if @files.present? %>
<% JSON.parse(@files).each do |id| %>
<% file = DmsfFile.find_by_id id %>
<% if file %>
<%= dmsf_file_path(file, :download => '', :only_path => false) %>
<% end %>
<% end %>
<% end %>
<% end %>

View File

@ -23,9 +23,11 @@
<p>
<%= @text2 %>
<% unless @revision.folder %>
<%= link_to l(:link_documents), {:controller => 'dmsf', :action => 'show', :id=> @revision.file.project, :only_path => false } %>
<%= link_to l(:link_documents),
dmsf_folder_path(:id => @revision.file.project, :only_path => false) %>
<% else %>
<%= link_to @revision.folder.title, {:controller => 'dmsf', :action => 'show', :id=> @revision.file.project, :folder_id => @revision.folder, :only_path => false } %>
<%= link_to @revision.folder.title,
dmsf_folder_path(:id => @revision.file.project, :folder_id => @revision.folder, :only_path => false) %>
<% end %>.
</p>

View File

@ -16,10 +16,10 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.%>
<%= @user.name %> ,
<%= @user.name %>,
<%= @text1 %>
<% unless @revision.folder %>
<%= @text2 %> <%= url_for(:controller => 'dmsf', :action => 'show', :id => @revision.file.project, :only_path => false) %>.
<%= @text2 %> <%= dmsf_folder_path(:id => @revision.file.project, :only_path => false) %>.
<% else %>
<%= @text2 %> <%= url_for(:controller => 'dmsf', :action => 'show', :id => @revision.file.project, :folder_id => @revision.folder, :only_path => false) %>.
<%= @text2 %> <%= dmsf_folder_path(:id => @revision.file.project, :folder_id => @revision.folder, :only_path => false) %>.
<% end %>

View File

@ -32,8 +32,4 @@
<%= submit_tag(l(:submit_save), :title => l(:title_save_preferences)) %>
</div>
<% end %>
</div>
<% content_for :header_tags do %>
<%= stylesheet_link_tag 'dmsf', :plugin => 'redmine_dmsf' %>
<% end %>
</div>

View File

@ -1,9 +1,9 @@
<%#=
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2013 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011-14 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,7 +25,7 @@
<div class="splitcontentleft">
<p>
<%= label_tag("commited_files[#{i}][title]", "#{l(:label_title)}:") %>
<%= text_field_tag("commited_files[#{i}][title]", upload.title, :size => '32') %>
<%= text_field_tag("commited_files[#{i}][title]", upload.title, :size => 32) %>
</p>
</div>
<div class="splitcontentright">
@ -40,7 +40,7 @@
<%= label_tag("commited_files[#{i}][description]", "#{l(:label_description)}:") %>
</p>
<div class="wiki data clear">
<%= text_area_tag("commited_files[#{i}][description]", upload.description, :rows=> '6', :class => 'wiki-edit') %>
<%= text_area_tag("commited_files[#{i}][description]", upload.description, :rows=> 6, :class => 'wiki-edit') %>
</div>
<div class="splitcontentleft">
<p>
@ -69,10 +69,10 @@
<% end %>
<p>
<%= label_tag("commited_files[#{i}][comment]", "#{l(:label_comment)}:") %>
<div class="data">
<%= text_area_tag("commited_files[#{i}][comment]", upload.comment, :rows=> '2', :style => 'width: 99%;') %>
</div>
</p>
<div class="data">
<%= text_area_tag("commited_files[#{i}][comment]", upload.comment, :rows => 2, :style => 'width: 99%;') %>
</div>
</div>
<%= wikitoolbar_for "commited_files_#{i}_description" %>

View File

@ -2,6 +2,7 @@
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2014 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 +18,6 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.%>
{"original_filename":"<%= h(@tempfile.original_filename) %>", "content_type":"<%= h(@tempfile.content_type) %>",
"disk_filename":"<%= h(@disk_filename) %>"}
{"original_filename":"<%= (@tempfile.original_filename).html_safe %>",
"content_type":"<%= (@tempfile.content_type).html_safe %>",
"disk_filename":"<%= (@disk_filename).html_safe %>"}

View File

@ -41,14 +41,4 @@
<% i += 1 %>
<% end %>
<%= submit_tag(l(:submit_commit)) %>
<% end %>
<% content_for :header_tags do %>
<%= stylesheet_link_tag 'dmsf', :plugin => 'redmine_dmsf' %>
<%= javascript_include_tag 'jquery-1.6.1.min.js', :plugin => 'redmine_dmsf' %>
<script type="text/javascript">
jQuery.noConflict();
jQuery(document).ready(function() {
});
</script>
<% end %>
<% end %>

View File

@ -34,8 +34,8 @@
<p>
<%= label_tag 'delegate', l(:label_dmsf_wokflow_action_delegate) %><br/>
<%= text_field_tag 'user_search', nil %>
<%= javascript_tag "observeSearchfield('user_search', 'users_for_delegate', '#{ escape_javascript autocomplete_for_user_dmsf_workflow_path(@workflow, :dmsf_workflow_step_assignment_id => params[:dmsf_workflow_step_assignment_id], :dmsf_file_revision_id => params[:dmsf_file_revision_id]) }')" %>
<%= content_tag('div', principals_radio_button_tags('step_action', @workflow.delegates(nil, params[:dmsf_workflow_step_assignment_id], params[:dmsf_file_revision_id])), :id => 'users_for_delegate') %>
<%= javascript_tag "observeSearchfield('user_search', 'users_for_delegate', '#{ escape_javascript autocomplete_for_user_dmsf_workflow_path(@dmsf_workflow, :dmsf_workflow_step_assignment_id => params[:dmsf_workflow_step_assignment_id], :dmsf_file_revision_id => params[:dmsf_file_revision_id]) }')" %>
<%= content_tag('div', principals_radio_button_tags('step_action', @dmsf_workflow.delegates(nil, params[:dmsf_workflow_step_assignment_id], params[:dmsf_file_revision_id])), :id => 'users_for_delegate') %>
</p>
<p class="buttons">

View File

@ -24,10 +24,10 @@
<div class="log_header_box">
<div class="log_header_left">
<%= label_tag 'workflow_name', "#{l(:link_workflow)} #{l(:field_name).downcase}: " %>
<% if User.current.allowed_to?(:manage_workflows, @workflow.project) %>
<%= link_to @workflow.name, edit_dmsf_workflow_path(@workflow) %>
<% if User.current.allowed_to?(:manage_workflows, @dmsf_workflow.project) %>
<%= link_to @dmsf_workflow.name, edit_dmsf_workflow_path(@dmsf_workflow) %>
<% else %>
<%= @workflow.name %>
<%= @dmsf_workflow.name %>
<% end %>
</div>
<div>
@ -78,7 +78,7 @@
<td><%= link_to_user User.find_by_id(row['author_id'].present? ? row['author_id'] : row['user_id']) %></td>
<td><%= DmsfWorkflowStepAction.action_str(row['action']) %></td>
<td>
<% if((row['step'].to_i == @workflow.dmsf_workflow_steps.last.step) && (revision.workflow == DmsfWorkflow::STATE_APPROVED) && (row['action'] != DmsfWorkflowStepAction::ACTION_DELEGATE)) %>
<% if((row['step'].to_i == @dmsf_workflow.dmsf_workflow_steps.last.step) && (revision.workflow == DmsfWorkflow::STATE_APPROVED) && (row['action'] != DmsfWorkflowStepAction::ACTION_DELEGATE)) %>
<%= l(:title_approved) %>
<% else %>
<%= DmsfWorkflowStepAction.workflow_str(row['action']) %>

View File

@ -36,7 +36,7 @@
<tbody>
<% for workflow in @workflows %>
<tr id="workflow-<%= workflow.id %>" class="<%= cycle('odd', 'even') %>">
<td class="name"><%= link_to(h(workflow.name), edit_dmsf_workflow_path(workflow)) %></td>
<td class="name"><%= link_to(h(workflow.name), dmsf_workflow_path(workflow)) %></td>
<td class="buttons">
<%= delete_link dmsf_workflow_path(workflow) %>
</td>

View File

@ -16,23 +16,23 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.%>
<% if @workflow.project %>
<h2><%= link_to l(:label_dmsf_workflow_plural), settings_project_path(@project, :tab => 'dmsf_workflow') %> &#187; <%=h @workflow %></h2>
<% if @dmsf_workflow.project %>
<h2><%= link_to l(:label_dmsf_workflow_plural), settings_project_path(@project, :tab => 'dmsf_workflow') %> &#187; <%=h @dmsf_workflow %></h2>
<% else %>
<h2><%= link_to l(:label_dmsf_workflow_plural), dmsf_workflows_path %> &#187; <%=h @workflow %></h2>
<h2><%= link_to l(:label_dmsf_workflow_plural), dmsf_workflows_path %> &#187; <%=h @dmsf_workflow %></h2>
<% end %>
<%= labelled_form_for @workflow do |f| %>
<%= labelled_form_for @dmsf_workflow do |f| %>
<%= error_messages_for 'workflow' %>
<div class="box tabular">
<p><%= f.label :label_dmsf_workflow_name %><%= text_field_tag :name, @workflow.name %><%= submit_tag l(:button_save) %></p>
<p><%= f.label :label_dmsf_workflow_name %><%= text_field_tag :name, @dmsf_workflow.name %><%= submit_tag l(:button_save) %></p>
</div>
<% end %>
<div class="tab-content" id="tab-content-members">
<div class="splitcontentleft">
<% steps = @workflow.dmsf_workflow_steps.collect{|s| s.step}.uniq %>
<% steps = @dmsf_workflow.dmsf_workflow_steps.collect{|s| s.step}.uniq %>
<% if steps.any? %>
<table class="list">
<thead><tr>
@ -46,7 +46,7 @@
<tr id="step-<%= i %>" class="<%= cycle 'odd', 'even' %> step">
<td class="step"><%= i %></td>
<td class="approval">
<% @workflow.dmsf_workflow_steps.collect{|s| (s.step == i) ? s : nil}.compact.each_with_index do |step, j| %>
<% @dmsf_workflow.dmsf_workflow_steps.collect{|s| (s.step == i) ? s : nil}.compact.each_with_index do |step, j| %>
<% if j != 0 %>
<b><%= step.soperator %></b>&nbsp
<% end %>
@ -54,10 +54,10 @@
<% end %>
</td>
<td class="reorder">
<%= reorder_links('workflow_step', {:action => 'edit', :id => @workflow, :step => i}, :put) %>
<%= reorder_links('workflow_step', {:action => 'edit', :id => @dmsf_workflow, :step => i}, :put) %>
</td>
<td class="buttons">
<%= delete_link edit_dmsf_workflow_path(@workflow, :step => i) %>
<%= delete_link edit_dmsf_workflow_path(@dmsf_workflow, :step => i) %>
</td>
</tr>
<% end; reset_cycle %>
@ -69,15 +69,15 @@
</div>
<div class="splitcontentright">
<%= form_for(@workflow, :url => edit_dmsf_workflow_path(@workflow),
<%= 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(@workflow, :dmsf_workflow_step_assignment_id => nil, :dmsf_file_revision_id => nil, :project_id => @project ? @project.id : nil) }')" %>
<%= javascript_tag "observeSearchfield('user_search', 'users', '#{ escape_javascript autocomplete_for_user_dmsf_workflow_path(@dmsf_workflow, :dmsf_workflow_step_assignment_id => nil, :dmsf_file_revision_id => nil, :project_id => @project ? @project.id : nil) }')" %>
<div id="users">
<%= render_principals_for_new_dmsf_workflow_users(@workflow, nil, nil) %>
<%= render_principals_for_new_dmsf_workflow_users(@dmsf_workflow, nil, nil) %>
</div>
<p>

View File

@ -16,6 +16,6 @@
# 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 => 'action', :locals => {:workflow => @workflow}) %>');
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'action', :locals => {:workflow => @dmsf_workflow}) %>');
showModal('ajax-modal', '400px');
$('#ajax-modal').addClass('new-action');

View File

@ -16,6 +16,6 @@
# 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 => 'assign', :locals => {:workflow => @workflow}) %>');
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'assign', :locals => {:workflow => @dmsf_workflow}) %>');
showModal('ajax-modal', '400px');
$('#ajax-modal').addClass('assignment');

View File

@ -16,4 +16,4 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.%>
<%= render_principals_for_new_dmsf_workflow_users(@workflow, params[:dmsf_workflow_step_assignment_id], params[:dmsf_file_revision_id]) %>
<%= render_principals_for_new_dmsf_workflow_users(@dmsf_workflow, params[:dmsf_workflow_step_assignment_id], params[:dmsf_file_revision_id]) %>

View File

@ -16,6 +16,6 @@
# 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 => 'log', :locals => {:workflow => @workflow}) %>');
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'log', :locals => {:workflow => @dmsf_workflow}) %>');
showModal('ajax-modal', '800px');
$('#ajax-modal').addClass('workflow-log');

View File

@ -23,8 +23,8 @@
<h2><%= link_to l(:label_dmsf_workflow_plural), dmsf_workflows_path %> &#187; <%=l(:label_dmsf_workflow_new)%></h2>
<% end %>
<%= labelled_form_for @workflow do |f| %>
<%= error_messages_for 'workflow' %>
<%= labelled_form_for @dmsf_workflow do |f| %>
<%= error_messages_for 'dmsf_workflow' %>
<div class="box tabular">
<p><%= f.label :label_dmsf_workflow_name %><%= text_field_tag :name %></p>
<% if project %>

View File

@ -27,7 +27,7 @@
<h3><%= l(:label_my_locked_documents)%> (<%= folders.count %>/<%= files.count %>)</h3>
<% if folders.any? || files.any?%>
<%= form_tag({}) do %>
<div><table class="list">
<table class="list">
<thead>
<tr>
<th><%=l(:field_project)%></th>
@ -62,7 +62,7 @@
<%= link_to_project(file.project) %>
</td>
<td class="title">
<%= link_to(h(file.last_revision.display_title),
<%= link_to(h(file.title),
{:controller => 'dmsf_files', :action => :show, :id => file },
:class => "icon icon-file #{DmsfHelper.filetype_css(file.name)}") %>
</td>

View File

@ -30,7 +30,7 @@
<h3><%= l(:label_my_open_approvals)%> (<%= assignments.count %>)</h3>
<% if assignments.any? %>
<%= form_tag({}) do %>
<div><table class="list">
<table class="list">
<thead>
<tr>
<th><%=l(:field_project)%></th>
@ -55,7 +55,7 @@
</td>
<td class="title">
<% if assignment.dmsf_file_revision && assignment.dmsf_file_revision.file %>
<%= link_to(h(assignment.dmsf_file_revision.display_title),
<%= link_to(h(assignment.dmsf_file_revision.title),
{:controller => 'dmsf_files', :action => :show, :id => assignment.dmsf_file_revision.file }) %>
<% end %>
</td>

View File

@ -1,7 +1,8 @@
<%# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011-14 Karel Picman <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
@ -93,6 +94,18 @@
(<%= l(:label_default) %>: <%= l(:select_option_deactivated) %>)
</p>
<p>
<%= content_tag(:label, "#{l(:label_display_notified_recipients)}:") %>
<%= select_tag('settings[dmsf_display_notified_recipients]',
options_for_select([
[l(:select_option_deactivated), nil],
[l(:select_option_activated), '1']],
:selected => @settings['dmsf_display_notified_recipients'])) %><br/>
(<%= l(:label_default) %>: <%= l(:select_option_deactivated) %>)
<br/>
<%= l(:note_display_notified_recipients).html_safe %>
</p>
<hr />
<p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 471 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 473 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 B

BIN
assets/images/link.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 662 B

View File

@ -1,32 +0,0 @@
/*
* Redmine plugin for Document Management System "Features"
*
* Copyright (C) 2013 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.
*/
function manipulation_link(action) {
jQuery('#entries_form').attr('action', action);
jQuery('#entries_form').submit();
};
function confirmation_link(action, question) {
if(!window.confirm(question)) {
return;
}
jQuery('#entries_form').attr('action', action);
jQuery('#entries_form').submit();
};

View File

@ -34,13 +34,13 @@ table.entries {
}
table.entries td.modified {
min-width: 104px;
width: 104px;
min-width: 127px;
width: 127px;
}
table.entries td.actions {
min-width: 116px;
width: 116px;
min-width: 96px;
width: 96px;
}
table.entries td.title {
@ -71,42 +71,6 @@ table.display tbody tr.odd {
table.display tbody tr:hover { background-color:#ffffdd; }
.icon-file.filetype-doc, .icon-file.filetype-docx {
background-image: url(../images/filetypes/doc.png);
}
.icon-file.filetype-xls, .icon-file.filetype-xlsx {
background-image: url(../images/filetypes/xls.png);
}
.icon-file.filetype-ppt, .icon-file.filetype-pptx {
background-image: url(../images/filetypes/ppt.png);
}
.icon-file.filetype-vsd, .icon-file.filetype-vsdx {
background-image: url(../images/filetypes/vsd.png);
}
.icon-file.filetype-mpp {
background-image: url(../images/filetypes/mpp.png);
}
.icon-file.filetype-odt {
background-image: url(../images/filetypes/odt.png);
}
.icon-file.filetype-ods {
background-image: url(../images/filetypes/ods.png);
}
.icon-file.filetype-odp {
background-image: url(../images/filetypes/odp.png);
}
.icon-file.filetype-odg {
background-image: url(../images/filetypes/odg.png);
}
form.dmfs_entries {
margin-bottom: 10px;
display: block;
@ -167,10 +131,7 @@ div.right_icon_box {
float: right;
white-space: nowrap;
padding: 0 5px 0 5px;
}
div.right_icon_box img.detail_icon {
padding-top: 2px;
width: 96px;
}
/* DMSF entries upload control */
@ -312,3 +273,92 @@ table.list td.step {
.modal a, .modal a:link, .modal a:visited{ color: #169; text-decoration: none; }
.modal a:hover, .modal a:active{ color: #c61a1a; text-decoration: underline;}
.modal{ font-size: 12px}
/* Command icons */
.icon-margin-left { margin-left: 3px; }
.icon-link { background-image: url(../images/link.png); }
.icon-notification-on { background-image: url(../images/notify.png); margin-left: 3px; }
.icon-notification-off { background-image: url(../images/notifynot.png); margin-left: 3px; }
.icon-dmsf-lock { background-image: url(../images/lock.png); }
.icon-dmsf-unlock { background-image: url(../images/unlock.png); }
.icon-dmsf-locked { background-image: url(../images/locked.png); margin-left: 2px }
.icon-dmsf-lockedbycurrent { background-image: url(../images/lockedbycurrent.png); margin-left: 2px }
.icon-dmsf-waiting-for-approval { background-image: url(../images/waiting_for_approval.png); }
.icon-dmsf-approved { background-image: url(../images/approved.png); }
.icon-dmsf-assigned { background-image: url(../images/assigned.png); }
.icon-dmsf-rejected { background-image: url(../images/rejected.png); }
.icon-dmsf-none { background-image: url(../images/none.png); }
.icon-dmsf-file-details { background-image: url(../images/filedetails.png); }
.icon-dmsf-rev-download { background-image: url(../images/rev_download.png); }
.icon-dmsf-rev-downloads { background-image: url(../images/rev_downloads.png); }
.icon-dmsf-rev-delete { background-image: url(../images/rev_delete.png); }
.icon-edit-gray { background-image: url(../images/edit_gray.png); }
.icon-notification-on-gray { background-image: url(../images/notify_gray.png); }
.icon-notification-off-gray { background-image: url(../images/notifynot_gray.png); }
.icon-dmsf-lock-gray { background-image: url(../images/lock_gray.png); }
.icon-dmsf-unlock-gray { background-image: url(../images/unlock_gray.png); }
.icon-dmsf-waiting-for-approval-gray { background-image: url(../images/waiting_for_approval_gray.png); }
.icon-dmsf-approved-gray { background-image: url(../images/approved_gray.png); }
.icon-dmsf-assigned-gray { background-image: url(../images/assigned_gray.png); }
.icon-dmsf-rejected-gray { background-image: url(../images/rejected_gray.png); }
.icon-dmsf-file-details-gray { background-image: url(../images/filedetails_gray.png); }
tr.gray .icon-dmsf-locked { background-image: url(../images/locked_gray.png); margin-left: 2px }
tr.gray .icon-dmsf-lockedbycurrent { background-image: url(../images/lockedbycurrent_gray.png); margin-left: 2px }
tr.gray .icon-dmsf-locked { background-image: url(../images/locked_gray.png); margin-left: 2px }
tr.gray .icon-dmsf-lockedbycurrent { background-image: url(../images/lockedbycurrent_gray.png); margin-left: 2px }
/* File types */
tr.gray .icon-folder { background-image: url(../images/folder_gray.png); }
.icon-file.filetype-doc, .icon-file.filetype-docx { background-image: url(../images/filetypes/doc.png); }
.icon-file.filetype-xls, .icon-file.filetype-xlsx { background-image: url(../images/filetypes/xls.png); }
.icon-file.filetype-ppt, .icon-file.filetype-pptx { background-image: url(../images/filetypes/ppt.png); }
.icon-file.filetype-vsd, .icon-file.filetype-vsdx { background-image: url(../images/filetypes/vsd.png); }
.icon-file.filetype-mpp { background-image: url(../images/filetypes/mpp.png); }
.icon-file.filetype-odt { background-image: url(../images/filetypes/odt.png); }
.icon-file.filetype-ods { background-image: url(../images/filetypes/ods.png); }
.icon-file.filetype-odp { background-image: url(../images/filetypes/odp.png); }
.icon-file.filetype-odg { background-image: url(../images/filetypes/odg.png); }
tr.gray .icon-file.filetype-doc { background-image: url(../images/filetypes/doc_gray.png); }
tr.gray .icon-file.filetype-docx { background-image: url(../images/filetypes/doc_gray.png); }
tr.gray .icon-file.filetype-xls { background-image: url(../images/filetypes/xls_gray.png); }
tr.gray .icon-file.filetype-xlsx { background-image: url(../images/filetypes/xls_gray.png); }
tr.gray .icon-file.filetype-ppt { background-image: url(../images/filetypes/ppt_gray.png); }
tr.gray .icon-file.filetype-pptx { background-image: url(../images/filetypes/ppt_gray.png); }
tr.gray .icon-file.filetype-vsd { background-image: url(../images/filetypes/vsd_gray.png); }
tr.gray .icon-file.filetype-vsdx { background-image: url(../images/filetypes/vsd_gray.png); }
tr.gray .icon-file.filetype-mpp { background-image: url(../images/filetypes/mpp_gray.png); }
tr.gray .icon-file.filetype-odt { background-image: url(../images/filetypes/odt_gray.png); }
tr.gray .icon-file.filetype-ods { background-image: url(../images/filetypes/ods_gray.png); }
tr.gray .icon-file.filetype-odp { background-image: url(../images/filetypes/odp_gray.png); }
tr.gray .icon-file.filetype-odg { background-image: url(../images/filetypes/odg_gray.png); }
tr.gray .icon-file.text-x-c { background-image: url(../images/filetypes/c_gray.png); }
tr.gray .icon-file.text-x-csharp { background-image: url(../images/filetypes/csharp_gray.png); }
tr.gray .icon-file.text-x-java { background-image: url(../images/files/filetypes_gray.png); }
tr.gray .icon-file.text-x-javascript { background-image: url(../images/filetypes/js_gray.png); }
tr.gray .icon-file.text-x-php { background-image: url(../images/filetypes/php_gray.png); }
tr.gray .icon-file.text-x-ruby { background-image: url(../images/filetypes/ruby_gray.png); }
tr.gray .icon-file.text-xml { background-image: url(../images/filetypes/xml_gray.png); }
tr.gray .icon-file.text-css { background-image: url(../images/filetypes/css_gray.png); }
tr.gray .icon-file.text-html { background-image: url(../images/filetypes/html_gray.png); }
tr.gray .icon-file.image-gif { background-image: url(../images/filetypes/image_gray.png); }
tr.gray .icon-file.image-jpeg { background-image: url(../images/filetypes/image_gray.png); }
tr.gray .icon-file.image-png { background-image: url(../images/filetypes/image_gray.png); }
tr.gray .icon-file.image-tiff { background-image: url(../images/filetypes/image_gray.png); }
tr.gray .icon-file.application-pdf { background-image: url(../images/filetypes/pdf_gray.png); }
tr.gray .icon-file.application-zip { background-image: url(../images/filetypes/zip_gray.png); }
tr.gray .icon-file.application-x-gzip { background-image: url(../images/filetypes/zip_gray.png); }
/* Links */
.gray { color: #AAA }
.gray a, .gray a:link, .gray a:visited{ color: #484848; text-decoration: none; }
label.required:after {
content: " *";
color: #bb0000;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 B

Some files were not shown because too many files have changed in this diff Show More