#48 Attaching DMS links to issues
This commit is contained in:
parent
5940486c77
commit
10d786c6e4
38
README.md
38
README.md
@ -37,6 +37,7 @@ Features
|
||||
* Documents and folders symbolic links
|
||||
* Document tagging
|
||||
* Trash bin
|
||||
* Documents attachable to issues
|
||||
* Compatible with Redmine 3.3.x
|
||||
|
||||
Dependencies
|
||||
@ -235,9 +236,9 @@ Before installing ensure that the Redmine instance is stopped.
|
||||
6. Restart the web server.
|
||||
7. You should configure the plugin via Redmine interface: Administration -> Plugins -> DMSF -> Configure.
|
||||
8. Assign DMSF permissions to appropriate roles.
|
||||
9. There are two rake tasks:
|
||||
9. There are a few rake tasks:
|
||||
|
||||
a) To convert documents from the standard Redmine document module
|
||||
I) To convert documents from the standard Redmine document module
|
||||
|
||||
Available options:
|
||||
|
||||
@ -253,12 +254,43 @@ Before installing ensure that the Redmine instance is stopped.
|
||||
chown -R www-data:www-data /redmine/files/dmsf
|
||||
afterwards)
|
||||
|
||||
b) To alert all users who are expected to do an approval in the current approval steps
|
||||
II) To alert all users who are expected to do an approval in the current approval steps
|
||||
|
||||
Example:
|
||||
|
||||
rake redmine:dmsf_alert_approvals RAILS_ENV="production"
|
||||
|
||||
III) To clears the Webdav Cache
|
||||
|
||||
Example:
|
||||
|
||||
rake redmine:dmsf_clear_webdav_cache RAILS_ENV="production"
|
||||
|
||||
IV) To create missing MD5 digest for all file revisions
|
||||
|
||||
Available options:
|
||||
|
||||
*dry_run - test, no changes to the database
|
||||
|
||||
Example:
|
||||
|
||||
bundle exec rake redmine:dmsf_create_digests RAILS_ENV="production"
|
||||
bundle exec rake redmine:dmsf_create_digests dry_run=1 RAILS_ENV="production"
|
||||
|
||||
V) To maintain DMSF
|
||||
|
||||
* Remove all files with no database record from the document directory
|
||||
* Remove all links project_id = -1 (added links to an issue which hasn't been created)
|
||||
|
||||
Available options:
|
||||
|
||||
*dry_run - No physical deletion but to list of all unused files only
|
||||
|
||||
Example:
|
||||
|
||||
rake redmine:dmsf_maintenance RAILS_ENV="production"
|
||||
rake redmine:dmsf_maintenance dry_run=1 RAILS_ENV="production"
|
||||
|
||||
### Fulltext search (optional)
|
||||
If you want to use full-text search features, you must setup file content indexing.
|
||||
|
||||
|
||||
@ -728,19 +728,7 @@ class DmsfController < ApplicationController
|
||||
end
|
||||
end
|
||||
# Remove system folders you are not allowed to see because you are not allowed to see the issue
|
||||
@subfolders.delete_if{ |folder|
|
||||
if folder.system
|
||||
issue_id = folder.title.to_i
|
||||
if issue_id > 0
|
||||
issue = Issue.find_by_id issue_id
|
||||
issue && !issue.visible?(User.current)
|
||||
else
|
||||
false
|
||||
end
|
||||
else
|
||||
false
|
||||
end
|
||||
}
|
||||
@subfolders = DmsfHelper.visible_folders(@subfolders)
|
||||
end
|
||||
|
||||
@ajax_upload_size = Setting.plugin_redmine_dmsf['dmsf_max_ajax_upload_filesize'].present? ? Setting.plugin_redmine_dmsf['dmsf_max_ajax_upload_filesize'] : 100
|
||||
|
||||
@ -26,6 +26,7 @@ class DmsfLinksController < ApplicationController
|
||||
before_filter :find_link_project
|
||||
before_filter :authorize
|
||||
before_filter :permissions
|
||||
protect_from_forgery except: :new
|
||||
|
||||
def permissions
|
||||
if @dmsf_link
|
||||
@ -43,50 +44,9 @@ class DmsfLinksController < ApplicationController
|
||||
def new
|
||||
@dmsf_link = DmsfLink.new
|
||||
@dmsf_link.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]
|
||||
@link_external = (@type == 'link_from') && (params[:external_link] == 'true')
|
||||
@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.dmsf_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]
|
||||
@link_external = false
|
||||
@dmsf_link.target_project_id = params[:project_id]
|
||||
@dmsf_link.project_id = params[:project_id]
|
||||
@target_folder_id = params[:dmsf_folder_id].to_i if params[:dmsf_folder_id].present?
|
||||
@ -99,53 +59,65 @@ class DmsfLinksController < ApplicationController
|
||||
@dmsf_link.name = folder.title if folder
|
||||
end
|
||||
end
|
||||
@container = params[:container]
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.js
|
||||
end
|
||||
end
|
||||
|
||||
render :layout => !request.xhr?
|
||||
def autocomplete_for_project
|
||||
respond_to do |format|
|
||||
format.js
|
||||
end
|
||||
end
|
||||
|
||||
def autocomplete_for_folder
|
||||
respond_to do |format|
|
||||
format.js
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
@dmsf_link = DmsfLink.new
|
||||
@dmsf_link.user = User.current
|
||||
|
||||
if params[:dmsf_link][:type] == 'link_from'
|
||||
# Link from
|
||||
if params[:dmsf_link][:container].blank?
|
||||
@dmsf_link.project_id = params[:dmsf_link][:project_id]
|
||||
@dmsf_link.dmsf_folder_id = params[:dmsf_link][:dmsf_folder_id]
|
||||
else
|
||||
# An issue link
|
||||
@dmsf_link.project_id = -1
|
||||
@dmsf_link.dmsf_folder_id = nil
|
||||
end
|
||||
@dmsf_link.target_project_id = params[:dmsf_link][:target_project_id]
|
||||
@link_external = (params[:external_link] == 'true')
|
||||
if (params[:external_link] == 'true')
|
||||
@dmsf_link.external_url = params[:dmsf_link][:external_url]
|
||||
if (@link_external)
|
||||
@dmsf_link.target_type = 'DmsfUrl'
|
||||
elsif params[:dmsf_link][:target_file_id].present?
|
||||
@dmsf_link.target_id = params[:dmsf_link][:target_file_id]
|
||||
@dmsf_link.target_type = DmsfFile.model_name.to_s
|
||||
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_id = DmsfLinksHelper.is_a_number?(
|
||||
params[:dmsf_link][:target_folder_id]) ? params[:dmsf_link][:target_folder_id].to_i : nil
|
||||
@dmsf_link.target_id = nil if(@dmsf_link.target_id == 0)
|
||||
@dmsf_link.target_type = DmsfFolder.model_name.to_s
|
||||
end
|
||||
@dmsf_link.name = params[:dmsf_link][:name]
|
||||
|
||||
if @dmsf_link.save
|
||||
flash[:notice] = l(:notice_successful_create)
|
||||
redirect_to dmsf_folder_path(:id => @project.id, :folder_id => @dmsf_link.dmsf_folder_id)
|
||||
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.to_s
|
||||
render :action => 'new'
|
||||
flash[:error] = @dmsf_link.errors.full_messages.to_sentence
|
||||
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.dmsf_folder_id = DmsfLinksHelper.is_a_number?(
|
||||
params[:dmsf_link][:target_folder_id]) ? params[:dmsf_link][:target_folder_id].to_i : nil
|
||||
@dmsf_link.dmsf_folder_id = nil if(@dmsf_link.dmsf_folder_id == 0)
|
||||
@dmsf_link.target_project_id = params[:dmsf_link][:project_id]
|
||||
@link_external = (params[:external_link] == 'true')
|
||||
@dmsf_link.external_url = params[:dmsf_link][:external_url]
|
||||
if (@link_external)
|
||||
@dmsf_link.target_type = 'DmsfUrl'
|
||||
elsif params[:dmsf_link][:dmsf_file_id].present?
|
||||
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.to_s
|
||||
else
|
||||
@ -153,23 +125,25 @@ class DmsfLinksController < ApplicationController
|
||||
@dmsf_link.target_type = DmsfFolder.model_name.to_s
|
||||
end
|
||||
@dmsf_link.name = params[:dmsf_link][:name]
|
||||
|
||||
if @dmsf_link.save
|
||||
flash[:notice] = l(:notice_successful_create)
|
||||
else
|
||||
flash[:error] = @dmsf_link.errors.full_messages.to_sentence
|
||||
end
|
||||
end
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
if params[:dmsf_link][:type] == 'link_from'
|
||||
redirect_to dmsf_folder_path(:id => @project.id, :folder_id => @dmsf_link.dmsf_folder_id)
|
||||
else
|
||||
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
|
||||
}
|
||||
format.js
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -89,9 +89,30 @@ module DmsfHelper
|
||||
'plupload/js/i18n/en.js'
|
||||
end
|
||||
|
||||
def self.visible_folders(folders)
|
||||
allowed = Setting.plugin_redmine_dmsf['dmsf_act_as_attachable']
|
||||
folders.reject{ |folder|
|
||||
if folder.system
|
||||
unless allowed
|
||||
true
|
||||
else
|
||||
issue_id = folder.title.to_i
|
||||
if issue_id > 0
|
||||
issue = Issue.find_by_id issue_id
|
||||
issue && !issue.visible?(User.current)
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
else
|
||||
false
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def self.all_children_sorted(parent, pos, ident)
|
||||
# Folders && files && links
|
||||
nodes = parent.dmsf_folders.visible + parent.dmsf_links.visible + parent.dmsf_files.visible
|
||||
nodes = visible_folders(parent.dmsf_folders.visible.to_a) + parent.dmsf_links.visible + parent.dmsf_files.visible
|
||||
# Alphabetical and type sort
|
||||
nodes.sort! do |x, y|
|
||||
if ((x.is_a?(DmsfFolder) || (x.is_a?(DmsfLink) && x.is_folder?)) &&
|
||||
|
||||
@ -39,4 +39,16 @@ module DmsfLinksHelper
|
||||
s.to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true
|
||||
end
|
||||
|
||||
def files_for_select(project_id, folder_id)
|
||||
files = []
|
||||
if folder_id && (folder_id != '0')
|
||||
folder = DmsfFolder.find_by_id folder_id
|
||||
files = folder.dmsf_files.visible.to_a if folder
|
||||
elsif project_id
|
||||
project = Project.find_by_id project_id
|
||||
files = project.dmsf_files.visible.to_a if project
|
||||
end
|
||||
files
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -210,7 +210,10 @@ class DmsfFolder < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def self.directory_tree(project, current_folder = nil)
|
||||
tree = [[l(:link_documents), nil]]
|
||||
unless project.is_a? Project
|
||||
project = Project.find_by_id project
|
||||
end
|
||||
tree = [[l(:link_documents), 0]]
|
||||
project.dmsf_folders.visible(false).each do |folder|
|
||||
unless folder == current_folder
|
||||
tree.push(["...#{folder.title}", folder.id])
|
||||
|
||||
@ -122,8 +122,17 @@ class DmsfLink < ActiveRecord::Base
|
||||
link
|
||||
end
|
||||
|
||||
def container
|
||||
if self.folder && self.folder.system
|
||||
Issue.where(:id => self.folder.title.to_i).first
|
||||
end
|
||||
end
|
||||
|
||||
def delete(commit = false)
|
||||
if commit
|
||||
if self.container.is_a?(Issue)
|
||||
self.container.dmsf_file_removed(self.target_file)
|
||||
end
|
||||
self.destroy
|
||||
else
|
||||
self.deleted = STATUS_DELETED
|
||||
|
||||
@ -59,8 +59,9 @@
|
||||
<% end %>
|
||||
<% if @file_manipulation_allowed && !@locked_for_user %>
|
||||
<%= 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') %>
|
||||
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') %>
|
||||
<% end %>
|
||||
<%= link_to(l(:link_create_folder),
|
||||
new_dmsf_path(:id => @project, :parent_id => @folder),
|
||||
@ -100,7 +101,6 @@
|
||||
<% custom_value.custom_field.is_required = false %>
|
||||
<% custom_value.value = params[:custom_value].present? ? params[:custom_value] : '' %>
|
||||
<%= h(custom_value.custom_field.name) %>:
|
||||
<%#= custom_field_tag(:dmsf_folder, custom_value, :style => 'width: auto') %>
|
||||
<%= custom_value.custom_field.format.edit_tag(self,
|
||||
custom_field_tag_id(:dmsf_folder, custom_value.custom_field),
|
||||
custom_field_tag_name(:dmsf_folder, custom_value.custom_field),
|
||||
|
||||
@ -78,7 +78,7 @@
|
||||
<div class="box">
|
||||
<p>
|
||||
<%= label_tag('file_upload', l(:label_new_content)) %>
|
||||
<%= render :partial => 'dmsf_upload/form', :locals => { :multiple => false } %>
|
||||
<%= render :partial => 'dmsf_upload/form', :locals => { :multiple => false, :container => nil } %>
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
%>
|
||||
|
||||
<% if dmsf_files.present? %>
|
||||
<% if dmsf_files.present? || dmsf_links.present? %>
|
||||
<hr/>
|
||||
<div class="attachments dmsf_parent_container">
|
||||
<% for dmsf_file in dmsf_files %>
|
||||
@ -76,4 +76,58 @@
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% for dmsf_link in dmsf_links %>
|
||||
<% dmsf_file = dmsf_link.target_file %>
|
||||
<% if dmsf_file.last_revision %>
|
||||
<p class = "dmsf_gray">
|
||||
<% file_view_url = url_for({:controller => :dmsf_files, :action => 'view', :id => dmsf_file}) %>
|
||||
<%= link_to(h(dmsf_link.title),
|
||||
file_view_url,
|
||||
:target => '_blank',
|
||||
:class => "icon icon-file #{DmsfHelper.filetype_css(dmsf_file.name)}",
|
||||
:title => h(dmsf_file.last_revision.try(:tooltip)),
|
||||
'data-downloadurl' => "#{dmsf_file.last_revision.detect_content_type}:#{h(dmsf_file.name)}:#{file_view_url}") %>
|
||||
<% if dmsf_file.text? || dmsf_file.image? %>
|
||||
<%= link_to l(:button_view),
|
||||
file_view_url,
|
||||
:class => 'icon-only icon-magnifier',
|
||||
:title => l(:button_view) %>
|
||||
<% end %>
|
||||
<%= " - #{dmsf_file.description}" unless dmsf_file.description.blank? %>
|
||||
<span class="size">(<%= number_to_human_size dmsf_file.last_revision.size %>)</span>
|
||||
<% if @issue.attributes_editable? && User.current.allowed_to?(:file_delete, dmsf_file.project) %>
|
||||
<%= link_to('',
|
||||
dmsf_link_path(dmsf_link, :commit => 'yes'),
|
||||
:data => {:confirm => l(:text_are_you_sure)},
|
||||
:method => :delete,
|
||||
:title => l(:title_delete),
|
||||
:class => 'icon icon-del') %>
|
||||
<% end %>
|
||||
<span class="author"><%= dmsf_file.last_revision.user %>, <%= format_time(dmsf_file.last_revision.updated_at) %></span>
|
||||
<span class="dmsf_upload_select">
|
||||
<% wf = DmsfWorkflow.find_by_id(dmsf_file.last_revision.dmsf_workflow_id) if dmsf_file.last_revision.dmsf_workflow_id %>
|
||||
<%= render(:partial => 'dmsf_files/approval_workflow_button',
|
||||
:locals => {:file => dmsf_file,
|
||||
:file_approval_allowed => User.current.allowed_to?(:file_approval, dmsf_file.project),
|
||||
:workflows_available => DmsfWorkflow.where(['project_id = ? OR project_id IS NULL', dmsf_file.project.id]).exists?,
|
||||
:project => dmsf_file.project, :wf => wf }) %>
|
||||
</span>
|
||||
</p>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if defined?(thumbnails) && thumbnails %>
|
||||
<% images = dmsf_links.map{ |link| link.target_file }.select(&:image?) %>
|
||||
<% if images.any? %>
|
||||
<div class="thumbnails">
|
||||
<% images.each do |file| %>
|
||||
<div>
|
||||
<%= link_to image_tag(dmsf_thumbnail_path(file)),
|
||||
url_for({:controller => :dmsf_files, :action => 'view', :id => file}),
|
||||
:alt => dmsf_file.title %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@ -20,40 +20,41 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
%>
|
||||
|
||||
<% html_title l(:dmsf) %>
|
||||
<h3 class="title"><%= l(:title_create_link) %></h3>
|
||||
|
||||
<% 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 => nil,
|
||||
:title => (@type == 'link_from') ? l(:label_link_from) : l(:label_link_to) }) %>
|
||||
|
||||
<%= labelled_form_for @dmsf_link do |f| %>
|
||||
<%= labelled_form_for @dmsf_link, :remote => modal 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 %>
|
||||
<%= f.hidden_field(:container, :value => @container) if @container %>
|
||||
<div class="box tabular">
|
||||
<% if @type == 'link_from' %>
|
||||
<% if (@type == 'link_from') && !@container %>
|
||||
<p>
|
||||
<%= radio_button_tag(:external_link, 'false', @link_external == false) %> <%= l(:label_internal) %><br/>
|
||||
<%= radio_button_tag(:external_link, 'true', @link_external) %> <%= l(:label_external) %>
|
||||
<%= radio_button_tag(:external_link, 'false', true) %> <%= l(:label_internal) %><br/>
|
||||
<%= radio_button_tag(:external_link, 'true', false) %> <%= l(:label_external) %>
|
||||
</p>
|
||||
<% end %>
|
||||
<div id="link_internal" style="<%= @link_external ? 'display:none' : '' %>">
|
||||
<div id="link_internal">
|
||||
<p>
|
||||
<% if @type == 'link_from' %>
|
||||
<label for="dmsf_link[target_project_id]"><%= l(:label_source_project) %><span class="required">*</span></label>
|
||||
<label for="dmsf_link[target_project_id]"><%= l(:label_source_project) %></label>
|
||||
<% else %>
|
||||
<label for="dmsf_link[target_project_id]"><%= l(:label_target_project) %><span class="required">*</span></label>
|
||||
<label for="dmsf_link[target_project_id]"><%= l(:label_target_project) %></label>
|
||||
<% end %>
|
||||
<%= select_tag('dmsf_link[target_project_id]',
|
||||
project_tree_options_for_select(DmsfFile.allowed_target_projects_on_copy,
|
||||
:selected => @dmsf_link.target_project)) %>
|
||||
:selected => @dmsf_link.target_project), :style => "width=100%") %>
|
||||
<%= javascript_tag do %>
|
||||
$('#dmsf_link_target_project_id').change(function(){
|
||||
$.ajax({
|
||||
url: '<%= autocomplete_for_project_dmsf_link_path(@project, :format => 'js') %>',
|
||||
type: 'get',
|
||||
data: $('#new_dmsf_link').serialize()
|
||||
});
|
||||
});
|
||||
<% end %>
|
||||
</p>
|
||||
<p>
|
||||
<% if @type == 'link_from' %>
|
||||
@ -64,51 +65,50 @@
|
||||
<%= select_tag('dmsf_link[target_folder_id]',
|
||||
folder_tree_options_for_select(DmsfFolder.directory_tree(@dmsf_link.target_project),
|
||||
:selected => @target_folder_id)) %>
|
||||
<%= javascript_tag do %>
|
||||
$('#dmsf_link_target_folder_id').change(function(){
|
||||
$.ajax({
|
||||
url: '<%= autocomplete_for_folder_dmsf_link_path(@project, :format => 'js') %>',
|
||||
type: 'get',
|
||||
data: $('#new_dmsf_link').serialize()
|
||||
});
|
||||
});
|
||||
<% end %>
|
||||
</p>
|
||||
<% if @type == 'link_from' %>
|
||||
<p>
|
||||
<% if @target_folder_id %>
|
||||
<% folder = DmsfFolder.find_by_id @target_folder_id %>
|
||||
<% files = folder.dmsf_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)) %>
|
||||
<%= label_tag('dmsf_link[target_file_id]', l(:field_target_file)) %>
|
||||
<% files = files_for_select(@dmsf_link.target_project.id, @target_folder_id) %>
|
||||
<%= select_tag('dmsf_link[target_file_id]',
|
||||
options_for_select(DmsfFolder.file_list(files))) %>
|
||||
</p>
|
||||
<% end %>
|
||||
</div>
|
||||
<div id="link_external" style="<%= @link_external ? '' : 'display:none' %>">
|
||||
<div id="link_external" style="display: none">
|
||||
<p>
|
||||
<%= f.text_field :external_url, :label => l(:label_link_external_url) %>
|
||||
<%= f.text_field :external_url, :required => true %>
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
<%= f.text_field :name, :label => l(:label_link_name) %>
|
||||
<%= f.text_field :name, :required => true %>
|
||||
</p>
|
||||
</div>
|
||||
<p><%= f.submit l(:button_create) %></p>
|
||||
<p><%= f.submit l(:button_create), :onclick => 'hideModal(this);' %></p>
|
||||
<% 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());
|
||||
});
|
||||
|
||||
// Suggest a link name when a file is selected
|
||||
$('#dmsf_link_target_file_id').change(function () {
|
||||
$('#content').load("<%= url_for(:action => 'new', :project_id => @project.id) %>", $('#new_dmsf_link').serialize());
|
||||
});
|
||||
var linkName = $('#dmsf_link_name');
|
||||
var name = linkName.val();
|
||||
|
||||
if(name == '') {
|
||||
linkName.val($('#dmsf_link_target_file_id option:selected').text().replace(/\./g, ''));
|
||||
}
|
||||
});
|
||||
// Internal/External link switch
|
||||
$("input[name=external_link]:radio").change(function(){
|
||||
$("#link_internal").toggle();
|
||||
$("#link_external").toggle();
|
||||
});
|
||||
|
||||
$('#dmsf_link_target_project_id').select2();
|
||||
$('#dmsf_link_target_folder_id').select2();
|
||||
$('#dmsf_link_target_file_id').select2();
|
||||
</script>
|
||||
4
app/views/dmsf_links/autocomplete_for_folder.js.erb
Normal file
4
app/views/dmsf_links/autocomplete_for_folder.js.erb
Normal file
@ -0,0 +1,4 @@
|
||||
$('#dmsf_link_target_file_id').html('<%= escape_javascript(
|
||||
select_tag('dmsf_link[target_file_id]',
|
||||
options_for_select(DmsfFolder.file_list(files_for_select(params[:dmsf_link][:target_project_id],
|
||||
params[:dmsf_link][:target_folder_id]))))) %>');
|
||||
4
app/views/dmsf_links/autocomplete_for_project.js.erb
Normal file
4
app/views/dmsf_links/autocomplete_for_project.js.erb
Normal file
@ -0,0 +1,4 @@
|
||||
$('#dmsf_link_target_folder_id').html('<%= escape_javascript(
|
||||
select_tag('dmsf_link[target_folder_id]',
|
||||
folder_tree_options_for_select(DmsfFolder.directory_tree(params[:dmsf_link][:target_project_id])))) %>');
|
||||
$('#dmsf_link_target_folder_id').change();
|
||||
27
app/views/dmsf_links/create.js.erb
Normal file
27
app/views/dmsf_links/create.js.erb
Normal file
@ -0,0 +1,27 @@
|
||||
<%
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Redmine plugin for Document Management System "Features"
|
||||
#
|
||||
# Copyright (C) 2011-17 Karel Pičman <karel.picman@kontron.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
%>
|
||||
|
||||
var linksSpan = $("#dmsf_links_fields");
|
||||
var linkId = "<%= @dmsf_link.id %>";
|
||||
var linkName = "<%= @dmsf_link.name %>";
|
||||
|
||||
dmsfAddLink(linksSpan, linkId, linkName);
|
||||
@ -20,4 +20,4 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
%>
|
||||
|
||||
<%= render 'form' %>
|
||||
<%= render :partial => 'form', :locals => { :modal => false } %>
|
||||
24
app/views/dmsf_links/new.js.erb
Normal file
24
app/views/dmsf_links/new.js.erb
Normal file
@ -0,0 +1,24 @@
|
||||
<%
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Redmine plugin for Document Management System "Features"
|
||||
#
|
||||
# Copyright (C) 2011-17 Karel Pičman <karel.picman@kontron.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
%>
|
||||
|
||||
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'form', :locals => { :modal => true }) %>');
|
||||
showModal('ajax-modal', '40%');
|
||||
@ -21,7 +21,7 @@
|
||||
%>
|
||||
|
||||
<span id="dmsf_attachments_fields">
|
||||
<% if defined?(container) && container && container.saved_dmsf_attachments %>
|
||||
<% if defined?(container) && container && container.saved_dmsf_attachments.present? %>
|
||||
<% container.saved_dmsf_attachments.each_with_index do |attachment, i| %>
|
||||
<span id="dmsf_attachments_p<%= i %>">
|
||||
<%= text_field_tag("dmsf_attachments[p#{i}][filename]", attachment.filename, :class => 'filename') +
|
||||
@ -47,3 +47,24 @@
|
||||
} %>
|
||||
(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)
|
||||
</span>
|
||||
<% if container %>
|
||||
<br/>
|
||||
<span id="dmsf_links_fields">
|
||||
<% if container.saved_dmsf_links.present? %>
|
||||
<% container.saved_dmsf_links.each_with_index do |dmsf_link, index| %>
|
||||
<span id="dmsf_links_<%= index %>">
|
||||
<input name="dmsf_links[<%= index %>]" value="<%= dmsf_link.id %>" type="hidden">
|
||||
<input type="text" class='filename readonly' value="<%= dmsf_link.name %>">
|
||||
<a href="#" class="remove-upload icon icon-del" onclick="$(this).parent('span').remove();return false;"> </a>
|
||||
<br/>
|
||||
</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</span>
|
||||
<span class="dmsf_add_link">
|
||||
<%= link_to l(:label_link_from),
|
||||
new_dmsf_link_path(:project_id => container.project.id, :type => 'link_from', :container => 'issue'),
|
||||
:title => l(:title_create_link), :class => 'icon icon-add', :remote => true %>
|
||||
</span>
|
||||
<% end %>
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@
|
||||
<div class="dmsf_uploader">
|
||||
<p>
|
||||
<label><%= l(:label_document_plural) %></label>
|
||||
<%= render :partial => 'dmsf_upload/form', :locals => { :multiple => true } %>
|
||||
<%= render :partial => 'dmsf_upload/form', :locals => { :multiple => true, :container => nil } %>
|
||||
</p>
|
||||
</div>
|
||||
<%= submit_tag l(:label_upload) %>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<%# Redmine plugin for Document Management System "Features"
|
||||
<%
|
||||
# Redmine plugin for Document Management System "Features"
|
||||
#
|
||||
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
|
||||
#
|
||||
@ -14,7 +15,8 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.%>
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
%>
|
||||
|
||||
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'assign', :locals => {:workflow => @dmsf_workflow}) %>');
|
||||
showModal('ajax-modal', '30%');
|
||||
|
||||
@ -19,6 +19,24 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
function dmsfAddLink(linksSpan, linkId, linkName) {
|
||||
|
||||
if (linksSpan.children().length < 10) {
|
||||
|
||||
var nextLinkId = dmsfAddLink.nextLinkId++;
|
||||
var linkSpan = $('<span>', { id: 'dmsf_links_' + nextLinkId });
|
||||
|
||||
linkSpan.append(
|
||||
"<input name='dmsf_links[" + nextLinkId + "]' value='" + linkId + "' type='hidden'>",
|
||||
"<input type='text' class='filename readonly' value='" + linkName + "'>",
|
||||
$('<a> </a>').attr({href: "#", 'class': 'remove-upload icon icon-del'}).click(dmsfRemoveFile),
|
||||
"<br/>"
|
||||
).appendTo(linksSpan);
|
||||
}
|
||||
}
|
||||
|
||||
dmsfAddLink.nextLinkId = 1000;
|
||||
|
||||
function dmsfAddFile(inputEl, file, eagerUpload) {
|
||||
|
||||
if ($('#dmsf_attachments_fields').children().length < 10) {
|
||||
|
||||
@ -319,3 +319,5 @@ div.dmsf_revision_inner_box .attribute .label {
|
||||
#dmsf_attachments_fields .ajax-loading input.filename {background:url(../../../images/loading.gif) no-repeat 0px 50%;}
|
||||
#dmsf_attachments_fields div.ui-progressbar { width: 100px; height:14px; margin: 2px 0 -5px 8px; display: inline-block; }
|
||||
|
||||
#dmsf_links_fields span {display:block; white-space:nowrap;}
|
||||
#dmsf_links_fields input.filename {border:0; height:1.8em; width:250px; color:#555; background-color:inherit; background:url(../../../images/link.png) no-repeat 1px 50%; padding-left:18px;}
|
||||
|
||||
@ -151,6 +151,8 @@ if Redmine::Plugin.installed? :redmine_dmsf
|
||||
resources :dmsf_links do
|
||||
member do
|
||||
get 'restore'
|
||||
get 'autocomplete_for_project'
|
||||
get 'autocomplete_for_folder'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
2
init.rb
2
init.rb
@ -89,7 +89,7 @@ Redmine::Plugin.register :redmine_dmsf do
|
||||
permission :file_manipulation,
|
||||
{ :dmsf_files => [:create_revision, :lock, :unlock, :delete_revision, :notify_activate, :notify_deactivate, :restore],
|
||||
:dmsf_upload => [:upload_files, :upload_file, :upload, :commit_files, :commit, :delete_dmsf_attachment],
|
||||
:dmsf_links => [:new, :create, :destroy, :restore] }
|
||||
:dmsf_links => [:new, :create, :destroy, :restore, :autocomplete_for_project, :autocomplete_for_folder] }
|
||||
permission :file_delete,
|
||||
{ :dmsf => [:trash, :delete_entries],
|
||||
:dmsf_files => [:delete] }
|
||||
|
||||
@ -59,6 +59,7 @@ module RedmineDmsf
|
||||
issue = context[:issue]
|
||||
params = context[:params]
|
||||
issue.save_dmsf_attachments(params[:dmsf_attachments])
|
||||
issue.save_dmsf_links(params[:dmsf_links])
|
||||
end
|
||||
end
|
||||
|
||||
@ -85,6 +86,21 @@ module RedmineDmsf
|
||||
DmsfUploadHelper.commit_files_internal uploaded_files, issue.project, system_folder,
|
||||
context[:controller]
|
||||
end
|
||||
dmsf_links = params[:dmsf_links]
|
||||
if dmsf_links && dmsf_links.is_a?(Hash)
|
||||
system_folder = issue.system_folder(true)
|
||||
ids = dmsf_links.map(&:last)
|
||||
ids.each do |id|
|
||||
l = DmsfLink.find_by_id(id)
|
||||
if l
|
||||
l.project_id = system_folder.project_id
|
||||
l.dmsf_folder_id = system_folder.id
|
||||
if l.save
|
||||
issue.dmsf_file_added l.target_file
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -49,7 +49,8 @@ module RedmineDmsf
|
||||
if User.current.allowed_to?(:view_dmsf_files, issue.project) &&
|
||||
Setting.plugin_redmine_dmsf['dmsf_act_as_attachable']
|
||||
context[:controller].send(:render_to_string, {:partial => 'dmsf_files/links',
|
||||
:locals => { :dmsf_files => issue.dmsf_files.to_a, :thumbnails => Setting.thumbnails_enabled? }})
|
||||
:locals => { :dmsf_files => issue.dmsf_files, :dmsf_links => issue.dmsf_links,
|
||||
:thumbnails => Setting.thumbnails_enabled? }})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -34,17 +34,34 @@ module RedmineDmsf
|
||||
|
||||
def save_dmsf_attachments(dmsf_attachments)
|
||||
@saved_dmsf_attachments = []
|
||||
if dmsf_attachments
|
||||
dmsf_attachments = dmsf_attachments.map(&:last)
|
||||
dmsf_attachments.each do |dmsf_attachment|
|
||||
a = Attachment.find_by_token(dmsf_attachment[:token])
|
||||
@saved_dmsf_attachments << a if a
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def saved_dmsf_attachments
|
||||
@saved_dmsf_attachments || []
|
||||
end
|
||||
|
||||
def save_dmsf_links(dmsf_links)
|
||||
@saved_dmsf_links = []
|
||||
if dmsf_links
|
||||
ids = dmsf_links.map(&:last)
|
||||
ids.each do |id|
|
||||
l = DmsfLink.find_by_id(id)
|
||||
@saved_dmsf_links << l if l
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def saved_dmsf_links
|
||||
@saved_dmsf_links || []
|
||||
end
|
||||
|
||||
def system_folder(create = false)
|
||||
parent = DmsfFolder.system.where(:project_id => self.project_id, :title => '.Issues').first
|
||||
if create && !parent
|
||||
@ -73,8 +90,21 @@ module RedmineDmsf
|
||||
end
|
||||
|
||||
def dmsf_files
|
||||
files = []
|
||||
folder = self.system_folder
|
||||
folder.dmsf_files if folder
|
||||
if folder
|
||||
files = folder.dmsf_files.to_a
|
||||
end
|
||||
files
|
||||
end
|
||||
|
||||
def dmsf_links
|
||||
links = []
|
||||
folder = self.system_folder
|
||||
if folder
|
||||
links = folder.dmsf_links
|
||||
end
|
||||
links
|
||||
end
|
||||
|
||||
def delete_system_folder
|
||||
@ -105,6 +135,7 @@ module RedmineDmsf
|
||||
)
|
||||
current_journal.save
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -18,10 +18,11 @@
|
||||
|
||||
desc <<-END_DESC
|
||||
DMSF maintenance task
|
||||
* Remove all files and folders with no database record from the document directory
|
||||
* Remove all files with no database record from the document directory
|
||||
* Remove all links project_id = -1 (added links to an issue which hasn't been created)
|
||||
|
||||
Available options:
|
||||
*dry_run - No physical deletion but to list of all unused files and folders only
|
||||
*dry_run - No physical deletion but to list of all unused files only
|
||||
|
||||
Example:
|
||||
rake redmine:dmsf_maintenance RAILS_ENV="production"
|
||||
@ -54,54 +55,41 @@ class DmsfMaintenance
|
||||
|
||||
def initialize
|
||||
@dry_run = ENV['dry_run']
|
||||
@folders_to_delete = Array.new
|
||||
@files_to_delete = Array.new
|
||||
end
|
||||
|
||||
def files
|
||||
Dir.glob("**/*").each do |f|
|
||||
if Dir.exist?(f)
|
||||
check_dir f
|
||||
else
|
||||
unless Dir.exist?(f)
|
||||
check_file f
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def result
|
||||
if (@files_to_delete.count == 0) && (@folders_to_delete.count == 0)
|
||||
puts "\nNo orphens!\n\n"
|
||||
return
|
||||
end
|
||||
# Files
|
||||
size = 0
|
||||
@files_to_delete.each{ |f| size += File.size(f) }
|
||||
puts "\n#{@files_to_delete.count} files havn't got a coresponding revision and can be deleted"
|
||||
puts "#{number_to_human_size(size)} can be released\n\n"
|
||||
|
||||
# Projects
|
||||
puts "\n#{@folders_to_delete.count} directories havn't got coresponding projects and can be deleted\n\n" if(@folders_to_delete.count > 0)
|
||||
puts "\n#{@files_to_delete.count} files havn't got a coresponding revision and can be deleted."
|
||||
puts "#{number_to_human_size(size)} can be released.\n\n"
|
||||
# Links
|
||||
size = DmsfLink.where(:project_id => -1).count
|
||||
puts "#{size} links can be deleted.\n\n"
|
||||
end
|
||||
|
||||
def clean
|
||||
if (@files_to_delete.count == 0) && (@folders_to_delete.count == 0)
|
||||
puts "\nNo orphens!\n\n"
|
||||
return
|
||||
end
|
||||
# Files
|
||||
size = 0
|
||||
@files_to_delete.each do |f|
|
||||
size += File.size(f)
|
||||
File.delete f
|
||||
end
|
||||
puts "\n#{@files_to_delete.count} files hadn't got a coresponding revision and have been be deleted" if(@files_to_delete.count > 0)
|
||||
puts "#{number_to_human_size(size)} has been released\n\n" if(@files_to_delete.count > 0)
|
||||
|
||||
# Projects
|
||||
@folders_to_delete.each do |d|
|
||||
Dir.delete d
|
||||
end
|
||||
puts "\n#{@folders_to_delete.count} directories hadn't got a coresponding projects and have been deleted\n\n" if(@folders_to_delete.count > 0)
|
||||
puts "\n#{@files_to_delete.count} files hadn't got a coresponding revision and have been be deleted."
|
||||
puts "#{number_to_human_size(size)} has been released\n\n"
|
||||
# Links
|
||||
size = DmsfLink.where(:project_id => -1).count
|
||||
DmsfLink.delete_all(:project_id => -1)
|
||||
puts "#{size} links have been deleted.\n\n"
|
||||
end
|
||||
|
||||
private
|
||||
@ -119,17 +107,4 @@ class DmsfMaintenance
|
||||
end
|
||||
end
|
||||
|
||||
def check_dir(directory)
|
||||
name = Pathname.new(directory).basename.to_s
|
||||
if name =~ /^p_(.*)/
|
||||
p = Project.find_by_identifier $1
|
||||
unless p
|
||||
@folders_to_delete << name
|
||||
puts "\t#{name}"
|
||||
end
|
||||
else
|
||||
STDERR.puts "\t#{directory} doesn't seem to be a DMSF folder!"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
Loading…
x
Reference in New Issue
Block a user