#218 Recycle bin
This commit is contained in:
parent
eda5637d45
commit
3e8b141cf6
@ -110,6 +110,16 @@ class DmsfController < ApplicationController
|
||||
@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 trash
|
||||
@folder_manipulation_allowed = User.current.allowed_to? :folder_manipulation, @project
|
||||
@file_manipulation_allowed = User.current.allowed_to? :file_manipulation, @project
|
||||
@file_delete_allowed = User.current.allowed_to? :file_delete, @project
|
||||
@subfolders = @project.dmsf_folders.deleted
|
||||
@files = @project.dmsf_files.deleted
|
||||
@dir_links = @project.folder_links.deleted
|
||||
@file_links = @project.file_links.deleted
|
||||
end
|
||||
|
||||
def download_email_entries
|
||||
send_file(
|
||||
params[:path],
|
||||
@ -319,17 +329,19 @@ class DmsfController < ApplicationController
|
||||
end
|
||||
|
||||
def delete
|
||||
@delete_folder = DmsfFolder.visible.find(params[:delete_folder_id])
|
||||
if @delete_folder
|
||||
if @delete_folder.delete
|
||||
if @folder.delete
|
||||
flash[:notice] = l(:notice_folder_deleted)
|
||||
else
|
||||
flash[:error] = @delete_folder.errors[:base][0]
|
||||
flash[:error] = folder.errors[:base][0]
|
||||
end
|
||||
redirect_to dmsf_folder_path(:id => @project, :folder_id => @folder)
|
||||
end
|
||||
redirect_to dmsf_folder_path(:id => @project, :folder_id => @delete_folder.dmsf_folder_id)
|
||||
rescue DmsfAccessError
|
||||
render_403
|
||||
|
||||
def restore
|
||||
if @folder.restore
|
||||
flash[:notice] = l(:notice_dmsf_folder_restored)
|
||||
end
|
||||
redirect_to :back
|
||||
end
|
||||
|
||||
def edit_root
|
||||
@ -493,13 +505,13 @@ class DmsfController < ApplicationController
|
||||
end
|
||||
|
||||
def find_folder
|
||||
@folder = DmsfFolder.visible.find(params[:folder_id]) if params.keys.include?('folder_id')
|
||||
@folder = DmsfFolder.find params[:folder_id] if params[:folder_id].present?
|
||||
rescue DmsfAccessError
|
||||
render_403
|
||||
end
|
||||
|
||||
def find_parent
|
||||
@parent = DmsfFolder.visible.find(params[:parent_id]) if params.keys.include?('parent_id')
|
||||
@parent = DmsfFolder.visible.find params[:parent_id] if params[:parent_id].present?
|
||||
rescue DmsfAccessError
|
||||
render_403
|
||||
end
|
||||
|
||||
@ -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
|
||||
@ -29,24 +30,16 @@ class DmsfFilesController < ApplicationController
|
||||
helper :dmsf_workflows
|
||||
|
||||
def show
|
||||
@revision = @file.last_revision
|
||||
|
||||
# download is put here to provide more clear and usable links
|
||||
# The download is put here to provide more clear and usable links
|
||||
if params.has_key?(:download)
|
||||
if @file.deleted
|
||||
render_404
|
||||
return
|
||||
end
|
||||
if params[:download].present?
|
||||
@revision = DmsfFileRevision.visible.find(params[:download].to_i)
|
||||
if params[:download].blank?
|
||||
@revision = @file.last_revision
|
||||
else
|
||||
@revision = DmsfFileRevision.find(params[:download].to_i)
|
||||
if @revision.file != @file
|
||||
render_403
|
||||
return
|
||||
end
|
||||
if @revision.deleted
|
||||
render_404
|
||||
return
|
||||
end
|
||||
end
|
||||
check_project(@revision.file)
|
||||
begin
|
||||
@ -58,8 +51,8 @@ class DmsfFilesController < ApplicationController
|
||||
return
|
||||
end
|
||||
|
||||
@revision = @file.last_revision
|
||||
@file_delete_allowed = User.current.allowed_to?(:file_delete, @project)
|
||||
|
||||
@revision_pages = Paginator.new @file.revisions.visible.count, params['per_page'] ? params['per_page'].to_i : 25, params['page']
|
||||
|
||||
render :layout => !request.xhr?
|
||||
@ -139,13 +132,11 @@ class DmsfFilesController < ApplicationController
|
||||
end
|
||||
|
||||
def delete
|
||||
unless User.current.allowed_to?(:file_delete, @project)
|
||||
render _403
|
||||
return
|
||||
end
|
||||
if @file
|
||||
if @file.delete
|
||||
commit = params[:commit] == 'yes'
|
||||
if @file.delete(commit)
|
||||
flash[:notice] = l(:notice_file_deleted)
|
||||
if commit
|
||||
log_activity('deleted')
|
||||
begin
|
||||
DmsfMailer.get_notify_users(User.current, [@file]).each do |u|
|
||||
@ -154,22 +145,23 @@ class DmsfFilesController < ApplicationController
|
||||
rescue Exception => e
|
||||
Rails.logger.error "Could not send email notifications: #{e.message}"
|
||||
end
|
||||
end
|
||||
else
|
||||
@file.errors.each do |e, msg|
|
||||
flash[:error] = msg
|
||||
end
|
||||
end
|
||||
end
|
||||
if commit
|
||||
redirect_to :back
|
||||
else
|
||||
redirect_to dmsf_folder_path(:id => @project, :folder_id => @file.folder)
|
||||
end
|
||||
end
|
||||
|
||||
def delete_revision
|
||||
unless User.current.allowed_to?(:file_delete, @project)
|
||||
render _403
|
||||
return
|
||||
end
|
||||
if @revision && !@revision.deleted
|
||||
if @revision.delete
|
||||
if @revision # && !@revision.deleted
|
||||
if @revision.delete(true)
|
||||
flash[:notice] = l(:notice_revision_deleted)
|
||||
log_activity('deleted')
|
||||
else
|
||||
@ -225,6 +217,14 @@ class DmsfFilesController < ApplicationController
|
||||
redirect_to :back
|
||||
end
|
||||
|
||||
def restore
|
||||
if @file.restore
|
||||
log_activity('restored')
|
||||
flash[:notice] = l(:notice_dmsf_file_restored)
|
||||
end
|
||||
redirect_to :back
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def log_activity(action)
|
||||
@ -243,7 +243,7 @@ class DmsfFilesController < ApplicationController
|
||||
end
|
||||
|
||||
def find_file
|
||||
@file = DmsfFile.visible.find(params[:id])
|
||||
@file = DmsfFile.find params[:id]
|
||||
@project = @file.project
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
|
||||
@ -145,11 +145,16 @@ class DmsfLinksController < ApplicationController
|
||||
end
|
||||
|
||||
def destroy
|
||||
begin
|
||||
@dmsf_link.destroy
|
||||
if @dmsf_link.delete
|
||||
flash[:notice] = l(:notice_successful_delete)
|
||||
rescue
|
||||
flash[:error] = l(:error_unable_delete_dmsf_workflow)
|
||||
end
|
||||
|
||||
redirect_to :back
|
||||
end
|
||||
|
||||
def restore
|
||||
if @dmsf_link.restore
|
||||
flash[:notice] = l(:notice_dmsf_link_restored)
|
||||
end
|
||||
|
||||
redirect_to :back
|
||||
|
||||
@ -33,6 +33,7 @@ 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
|
||||
@ -43,7 +44,8 @@ class DmsfFile < ActiveRecord::Base
|
||||
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)}
|
||||
scope :visible, where('NOT deleted')
|
||||
scope :deleted, where('NOT NOT deleted')
|
||||
|
||||
validates :name, :presence => true
|
||||
validates_format_of :name, :with => DmsfFolder.invalid_characters,
|
||||
@ -51,11 +53,6 @@ class DmsfFile < ActiveRecord::Base
|
||||
|
||||
validate :validates_name_uniqueness
|
||||
|
||||
def self.visible_condition(user, options = {})
|
||||
query = DmsfFile.where(:deleted => false)
|
||||
query.where_values.map {|v| v.respond_to?(:to_sql) ? v.to_sql : v.to_s}.join(' AND ')
|
||||
end
|
||||
|
||||
def validates_name_uniqueness
|
||||
existing_file = DmsfFile.visible.find_file_by_name(self.project, self.folder, self.name)
|
||||
errors.add(:name, l('activerecord.errors.messages.taken')) unless
|
||||
@ -104,19 +101,19 @@ class DmsfFile < ActiveRecord::Base
|
||||
@last_revision = new_revision
|
||||
end
|
||||
|
||||
def delete
|
||||
def delete(commit)
|
||||
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']
|
||||
self.revisions.visible.each {|r| r.delete(true)}
|
||||
# Revisions and links of a deleted file SHOULD be deleted too
|
||||
self.revisions.each { |r| r.delete(commit, true) }
|
||||
self.referenced_links.each { |l| l.delete(commit) }
|
||||
if commit
|
||||
self.destroy
|
||||
else
|
||||
# Revisions of a deleted file SHOULD be deleted too
|
||||
self.revisions.visible.each {|r| r.delete }
|
||||
self.deleted = true
|
||||
self.deleted_by_user = User.current
|
||||
save
|
||||
@ -127,6 +124,14 @@ class DmsfFile < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def restore
|
||||
self.revisions.each { |r| r.restore }
|
||||
self.referenced_links.each { |l| l.restore }
|
||||
self.deleted = false
|
||||
self.deleted_by_user = nil
|
||||
save
|
||||
end
|
||||
|
||||
def title
|
||||
self.last_revision ? self.last_revision.title : self.name
|
||||
end
|
||||
|
||||
@ -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
|
||||
@ -28,16 +29,14 @@ class DmsfFileRevision < ActiveRecord::Base
|
||||
has_many :dmsf_workflow_step_assignment, :dependent => :destroy
|
||||
|
||||
# Returns a list of revisions that are not deleted here, or deleted at parent level either
|
||||
scope :visible, lambda {|*args| joins(:file).where(DmsfFile.visible_condition(args.shift || User.current, *args)).where("#{self.table_name}.deleted = :false", :false => false ).readonly(false) }
|
||||
scope :visible, where('NOT deleted')
|
||||
|
||||
acts_as_customizable
|
||||
|
||||
acts_as_event :title => Proc.new {|o| "#{l(:label_dmsf_updated)}: #{o.file.dmsf_path_str}"},
|
||||
:url => Proc.new {|o| {:controller => 'dmsf_files', :action => 'show', :id => o.file}},
|
||||
: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",
|
||||
@ -61,23 +60,21 @@ class DmsfFileRevision < ActiveRecord::Base
|
||||
remove_extension(filename).gsub(/_+/, ' ');
|
||||
end
|
||||
|
||||
def delete(delete_all = false)
|
||||
def delete(commit = false, force = true)
|
||||
if self.file.locked_for_user?
|
||||
errors[:base] << l(:error_file_is_locked)
|
||||
return false
|
||||
end
|
||||
if !delete_all && self.file.revisions.length <= 1
|
||||
if !commit && (!force && (self.file.revisions.length <= 1))
|
||||
errors[:base] << l(:error_at_least_one_revision_must_be_present)
|
||||
return false
|
||||
end
|
||||
dependent = DmsfFileRevision.where(:source_dmsf_file_revision_id => self.id, :deleted => false).all
|
||||
dependent = DmsfFileRevision.where(:source_dmsf_file_revision_id => self.id).all
|
||||
dependent.each do |d|
|
||||
d.source_revision = self.source_revision
|
||||
d.save!
|
||||
end
|
||||
if Setting.plugin_redmine_dmsf['dmsf_really_delete_files']
|
||||
dependencies = DmsfFileRevision.where(:disk_filename => self.disk_filename).all.count
|
||||
File.delete(self.disk_file) if dependencies <= 1 && File.exist?(self.disk_file)
|
||||
if commit
|
||||
self.destroy
|
||||
else
|
||||
self.deleted = true
|
||||
@ -86,6 +83,12 @@ class DmsfFileRevision < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def restore
|
||||
self.deleted = false
|
||||
self.deleted_by_user = nil
|
||||
save
|
||||
end
|
||||
|
||||
def destroy
|
||||
if Setting.plugin_redmine_dmsf['dmsf_really_delete_files']
|
||||
dependencies = DmsfFileRevision.where(:disk_filename => self.disk_filename).all.count
|
||||
|
||||
@ -27,11 +27,13 @@ class DmsfFolder < 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'
|
||||
belongs_to :user
|
||||
|
||||
has_many :subfolders, :class_name => 'DmsfFolder', :foreign_key => 'dmsf_folder_id',
|
||||
:dependent => :destroy
|
||||
has_many :files, :class_name => 'DmsfFile', :foreign_key => 'dmsf_folder_id',
|
||||
:dependent => :destroy
|
||||
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',
|
||||
@ -43,7 +45,8 @@ class DmsfFolder < ActiveRecord::Base
|
||||
:conditions => {:entity_type => 1},
|
||||
:dependent => :destroy
|
||||
|
||||
scope :visible, lambda {|*args| {:conditions => '' }} #For future use, however best to be referenced now
|
||||
scope :visible, where('NOT deleted')
|
||||
scope :deleted, where('NOT NOT deleted')
|
||||
|
||||
acts_as_customizable
|
||||
|
||||
@ -90,7 +93,15 @@ class DmsfFolder < ActiveRecord::Base
|
||||
errors[:base] << l(:error_folder_is_not_empty)
|
||||
return false
|
||||
end
|
||||
destroy
|
||||
self.deleted = true
|
||||
self.deleted_by_user = User.current
|
||||
self.save
|
||||
end
|
||||
|
||||
def restore
|
||||
self.deleted = false
|
||||
self.deleted_by_user = nil
|
||||
self.save
|
||||
end
|
||||
|
||||
def dmsf_path
|
||||
@ -271,4 +282,3 @@ class DmsfFolder < ActiveRecord::Base
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
@ -21,10 +21,14 @@ class DmsfLink < ActiveRecord::Base
|
||||
|
||||
belongs_to :project
|
||||
belongs_to :dmsf_folder
|
||||
belongs_to :deleted_by_user, :class_name => 'User', :foreign_key => 'deleted_by_user_id'
|
||||
|
||||
validates :name, :presence => true
|
||||
validates :target_id, :presence => true
|
||||
validates_length_of :name, :maximum => 255
|
||||
|
||||
scope :visible, where('NOT deleted')
|
||||
scope :deleted, where('NOT NOT deleted')
|
||||
|
||||
def target_folder_id
|
||||
if self.target_type == DmsfFolder.model_name
|
||||
@ -97,4 +101,20 @@ class DmsfLink < ActiveRecord::Base
|
||||
link
|
||||
end
|
||||
|
||||
def delete(commit = false)
|
||||
if commit
|
||||
self.destroy
|
||||
else
|
||||
self.deleted = true
|
||||
self.deleted_by_user = User.current
|
||||
save
|
||||
end
|
||||
end
|
||||
|
||||
def restore
|
||||
self.deleted = false
|
||||
self.deleted_by_user = nil
|
||||
save
|
||||
end
|
||||
|
||||
end
|
||||
@ -1,7 +1,7 @@
|
||||
<%#=
|
||||
# Redmine plugin for Document Management System "Features"
|
||||
#
|
||||
# Copyright (C) 2014 Karel Pičman <karel.picman@kontron.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
|
||||
@ -85,7 +85,7 @@
|
||||
:class => 'icon icon-del') %>
|
||||
<% else %>
|
||||
<%= link_to('',
|
||||
delete_dmsf_path(:id => project, :folder_id => @folder, :delete_folder_id => subfolder),
|
||||
delete_dmsf_path(:id => project, :folder_id => subfolder),
|
||||
:data => {:confirm => l(:text_are_you_sure)},
|
||||
:title => l(:title_delete),
|
||||
:class => 'icon icon-del') %>
|
||||
|
||||
58
app/views/dmsf/_dir_trash.html.erb
Normal file
58
app/views/dmsf/_dir_trash.html.erb
Normal file
@ -0,0 +1,58 @@
|
||||
<%#=
|
||||
# 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.
|
||||
%>
|
||||
|
||||
<td class="check"><%= check_box_tag(name, id, false,
|
||||
:title => l(:title_check_for_zip_download_or_email)) %></td>
|
||||
<td class="title">
|
||||
<%= content_tag(:span, h(title),
|
||||
:title => h(title),
|
||||
: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) %>
|
||||
</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">
|
||||
<%= link_to('',
|
||||
restore_dmsf_path(:id => project, :folder_id => subfolder),
|
||||
:title => l(:title_restore),
|
||||
:class => 'icon icon-dmsf-restore') %>
|
||||
<%= link_to('',
|
||||
delete_dmsf_path(:id => project, :folder_id => subfolder, :commit => 'yes'),
|
||||
:data => {:confirm => l(:text_are_you_sure)},
|
||||
:title => l(:title_delete),
|
||||
:class => 'icon icon-dmsf-rev-delete') %>
|
||||
</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>
|
||||
60
app/views/dmsf/_file_trash.html.erb
Normal file
60
app/views/dmsf/_file_trash.html.erb
Normal file
@ -0,0 +1,60 @@
|
||||
<%#=
|
||||
# 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.
|
||||
%>
|
||||
|
||||
<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) %>
|
||||
</td>
|
||||
<td class="version"><%= file.last_revision.version %></td>
|
||||
<td class="workflow">
|
||||
<%= file.last_revision.workflow_str(false) %>
|
||||
</td>
|
||||
<td class="author"><%= h(file.last_revision.user) %></td>
|
||||
<td class="actions">
|
||||
<% if @file_manipulation_allowed %>
|
||||
<div class="right_icon_box">
|
||||
<%= link_to('',
|
||||
restore_dmsf_file_path(:id => file),
|
||||
:title => l(:title_restore),
|
||||
:class => 'icon icon-dmsf-restore') %>
|
||||
<%= link_to('',
|
||||
dmsf_file_path(:id => file, :commit => 'yes'),
|
||||
:data => {:confirm => l(:text_are_you_sure)},
|
||||
:method => :delete,
|
||||
:title => l(:title_delete),
|
||||
:class => 'icon icon-dmsf-rev-delete') %>
|
||||
</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>
|
||||
@ -89,6 +89,10 @@
|
||||
:title => l(:link_create_folder),
|
||||
:class => 'icon icon-add') unless @locked_for_user %>
|
||||
<% end %>
|
||||
<%= link_to(l(:link_trash_bin),
|
||||
trash_dmsf_path(@project),
|
||||
:title => l(:link_trash_bin),
|
||||
:class => 'icon icon-del') unless @locked_for_user unless @folder %>
|
||||
</div>
|
||||
|
||||
<%= render(:partial => 'path', :locals => {:folder => @folder, :filename => nil}) %>
|
||||
|
||||
185
app/views/dmsf/trash.html.erb
Normal file
185
app/views/dmsf/trash.html.erb
Normal file
@ -0,0 +1,185 @@
|
||||
<%#=
|
||||
# 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.
|
||||
%>
|
||||
|
||||
<% html_title(l(:dmsf)) %>
|
||||
<div class="contextual">
|
||||
</div>
|
||||
|
||||
<h2><%= l(:link_trash_bin) %></h2>
|
||||
|
||||
<div class="dmsf-header">
|
||||
<div class="wiki">
|
||||
<%= textilizable(@folder ? @folder.description : @project.dmsf_description) %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= error_messages_for('dmsf_workflow') %>
|
||||
|
||||
<%= form_tag({:action => :entries_operation, :id => @project, :folder_id => @folder}, :method => :post,
|
||||
:class => 'dmfs_entries', :id => 'entries_form') do %>
|
||||
<%= hidden_field_tag('action') %>
|
||||
<div class="controls" style="float: left">
|
||||
<%= submit_tag(l(:submit_download), :title => l(:title_download_checked), :name => 'download_entries') %>
|
||||
<% 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 %>
|
||||
</div>
|
||||
<table class="display entries" id="browser">
|
||||
<thead>
|
||||
<tr id="root">
|
||||
<th class="check">
|
||||
<input id="check_all_entries" title="<%= l(:title_check_uncheck_all_for_zip_download_or_email) %>" type="checkbox" />
|
||||
</th>
|
||||
<th><%= l(:link_title) %></th>
|
||||
<th><%= l(:link_size) %></th>
|
||||
<th><%= l(:link_modified) %></th>
|
||||
<th title="<%= l(:label_version) %>"><%= l(:link_ver) %></th>
|
||||
<th><%= l(:link_workflow) %></th>
|
||||
<th><%= l(:link_author) %></th>
|
||||
<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| %>
|
||||
<tr class="dir">
|
||||
<%= render(:partial => 'dir_trash',
|
||||
:locals => {
|
||||
:project => @project,
|
||||
:subfolder => subfolder,
|
||||
:link => nil,
|
||||
:id => subfolder.id,
|
||||
:name => 'subfolders[]',
|
||||
:title => subfolder.title }) %>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% @dir_links.each do |link| %>
|
||||
<tr class="gray">
|
||||
<%= render(:partial => 'dir_trash',
|
||||
: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 %>
|
||||
<tr class="file">
|
||||
<%= render(:partial => 'file_trash', :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_trash', :locals => {
|
||||
:project => link.target_project,
|
||||
:file => link.target_file,
|
||||
:link => link,
|
||||
:id => link.id,
|
||||
:name => 'file_links[]',
|
||||
:title => link.name }) %>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% end %>
|
||||
|
||||
<script type="text/javascript">
|
||||
$('#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();
|
||||
});
|
||||
|
||||
$('#check_all_entries').click(function() {
|
||||
$('input[type=checkbox]', $('#browser > tbody')).prop('checked', this.checked);
|
||||
});
|
||||
</script>
|
||||
|
||||
<%
|
||||
if I18n.locale && !I18n.locale.to_s.match(/^en.*/)
|
||||
sUrl = "jquery.dataTables/#{I18n.locale.to_s.downcase}.json"
|
||||
else
|
||||
sUrl = 'jquery.dataTables/en.json'
|
||||
end
|
||||
%>
|
||||
|
||||
<% content_for :header_tags do %>
|
||||
<%= stylesheet_link_tag 'jquery.dataTables/jquery-ui.dataTables.css', :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">
|
||||
$(document).ready(function() {
|
||||
$('#browser').dataTable({
|
||||
'bJQueryUI': true,
|
||||
'oLanguage': {
|
||||
'sUrl': "<%= plugin_asset_path(:redmine_dmsf, 'javascripts', sUrl) %>"
|
||||
},
|
||||
'bAutoWidth': false,
|
||||
'bPaginate': false,
|
||||
'aaSorting': [[1,'asc']],
|
||||
'aaSortingFixed': [[8,'asc']],
|
||||
'aoColumnDefs': [
|
||||
{ 'bSearchable': false, 'aTargets': [0, 7, 8, 9] },
|
||||
{ 'bSortable': false, 'aTargets': [0, 7, 8] },
|
||||
{ '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]);
|
||||
},
|
||||
'fnInfoCallback': function( oSettings, iStart, iEnd, iMax, iTotal, sPre ) {
|
||||
return "<%= l(:label_number_of_folders)%>: <%= @subfolders.count + @dir_links.count %>, <%= l(:label_number_of_documents)%>: <%= @files.count + @file_links.count %>";
|
||||
}
|
||||
});
|
||||
|
||||
$('#entries_form').submit(function () {
|
||||
$(this).removeAttr('data-submitted');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<% end %>
|
||||
BIN
assets/images/restore.png
Normal file
BIN
assets/images/restore.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 806 B |
@ -292,6 +292,7 @@ table.list td.step {
|
||||
.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-dmsf-restore { background-image: url(../images/restore.png); }
|
||||
|
||||
.icon-edit-gray { background-image: url(../images/edit_gray.png); }
|
||||
.icon-notification-on-gray { background-image: url(../images/notify_gray.png); }
|
||||
|
||||
@ -298,6 +298,12 @@ cs:
|
||||
note_display_notified_recipients: Uživatel bude informován o příjemcích právě odeslané emailové notifikace.
|
||||
warning_email_notifications: "Notifikační email poslán na uživatele %{to}"
|
||||
|
||||
link_trash_bin: Koš
|
||||
title_restore: Obnovit
|
||||
notice_dmsf_file_restored: Document byl úspěšně obnoven
|
||||
notice_dmsf_folder_restored: Adresář byl úspěšně obnoven
|
||||
notice_dmsf_link_restored: Odkaz byl úspěšně obnoven
|
||||
|
||||
my:
|
||||
blocks:
|
||||
locked_documents: Zamčené dokumenty
|
||||
|
||||
@ -298,6 +298,12 @@ de:
|
||||
note_display_notified_recipients: The user will be informed about all recipients of just sent the email notification.
|
||||
warning_email_notifications: "Email notifications sent to %{to}"
|
||||
|
||||
link_trash_bin: Trash bin
|
||||
title_restore: Restore
|
||||
notice_dmsf_file_restored: The document has been successfully restored
|
||||
notice_dmsf_folder_restored: The folder has been successfully restored
|
||||
notice_dmsf_link_restored: The link has been successfully restored
|
||||
|
||||
my:
|
||||
blocks:
|
||||
locked_documents: Locked documents
|
||||
|
||||
@ -298,6 +298,12 @@ en:
|
||||
note_display_notified_recipients: The user will be informed about all recipients of just sent the email notification.
|
||||
warning_email_notifications: "Email notifications sent to %{to}"
|
||||
|
||||
link_trash_bin: Trash bin
|
||||
title_restore: Restore
|
||||
notice_dmsf_file_restored: The document has been successfully restored
|
||||
notice_dmsf_folder_restored: The folder has been successfully restored
|
||||
notice_dmsf_link_restored: The link has been successfully restored
|
||||
|
||||
my:
|
||||
blocks:
|
||||
locked_documents: Locked documents
|
||||
|
||||
@ -298,6 +298,12 @@ es:
|
||||
note_display_notified_recipients: The user will be informed about all recipients of just sent the email notification.
|
||||
warning_email_notifications: "Email notifications sent to %{to}"
|
||||
|
||||
link_trash_bin: Trash bin
|
||||
title_restore: Restore
|
||||
notice_dmsf_file_restored: The document has been successfully restored
|
||||
notice_dmsf_folder_restored: The folder has been successfully restored
|
||||
notice_dmsf_link_restored: The link has been successfully restored
|
||||
|
||||
my:
|
||||
blocks:
|
||||
locked_documents: Locked documents
|
||||
|
||||
@ -298,6 +298,12 @@ fr:
|
||||
note_display_notified_recipients: "L'utilisateur sera informé de tous les destinataires à qui un email de notifcation a été envoyé"
|
||||
warning_email_notifications: "Email de notification envoyé à %{to}"
|
||||
|
||||
link_trash_bin: Trash bin
|
||||
title_restore: Restore
|
||||
notice_dmsf_file_restored: The document has been successfully restored
|
||||
notice_dmsf_folder_restored: The folder has been successfully restored
|
||||
notice_dmsf_link_restored: The link has been successfully restored
|
||||
|
||||
my:
|
||||
blocks:
|
||||
locked_documents: Documents verrouillés
|
||||
|
||||
@ -298,6 +298,12 @@ ja:
|
||||
note_display_notified_recipients: The user will be informed about all recipients of just sent the email notification.
|
||||
warning_email_notifications: "Email notifications sent to %{to}"
|
||||
|
||||
link_trash_bin: Trash bin
|
||||
title_restore: Restore
|
||||
notice_dmsf_file_restored: The document has been successfully restored
|
||||
notice_dmsf_folder_restored: The folder has been successfully restored
|
||||
notice_dmsf_link_restored: The link has been successfully restored
|
||||
|
||||
my:
|
||||
blocks:
|
||||
locked_documents: Locked documents
|
||||
|
||||
@ -298,6 +298,12 @@ ru:
|
||||
note_display_notified_recipients: The user will be informed about all recipients of just sent the email notification.
|
||||
warning_email_notifications: "Email notifications sent to %{to}"
|
||||
|
||||
link_trash_bin: Trash bin
|
||||
title_restore: Restore
|
||||
notice_dmsf_file_restored: The document has been successfully restored
|
||||
notice_dmsf_folder_restored: The folder has been successfully restored
|
||||
notice_dmsf_link_restored: The link has been successfully restored
|
||||
|
||||
my:
|
||||
blocks:
|
||||
locked_documents: Locked documents
|
||||
|
||||
@ -298,6 +298,12 @@ sl:
|
||||
note_display_notified_recipients: The user will be informed about all recipients of just sent the email notification.
|
||||
warning_email_notifications: "Email notifications sent to %{to}"
|
||||
|
||||
link_trash_bin: Trash bin
|
||||
title_restore: Restore
|
||||
notice_dmsf_file_restored: The document has been successfully restored
|
||||
notice_dmsf_folder_restored: The folder has been successfully restored
|
||||
notice_dmsf_link_restored: The link has been successfully restored
|
||||
|
||||
my:
|
||||
blocks:
|
||||
locked_documents: Locked documents
|
||||
|
||||
@ -298,6 +298,12 @@ zh:
|
||||
note_display_notified_recipients: The user will be informed about all recipients of just sent the email notification.
|
||||
warning_email_notifications: "Email notifications sent to %{to}"
|
||||
|
||||
link_trash_bin: Trash bin
|
||||
title_restore: Restore
|
||||
notice_dmsf_file_restored: The document has been successfully restored
|
||||
notice_dmsf_folder_restored: The folder has been successfully restored
|
||||
notice_dmsf_link_restored: The link has been successfully restored
|
||||
|
||||
my:
|
||||
blocks:
|
||||
locked_documents: Locked documents
|
||||
|
||||
@ -42,6 +42,8 @@ RedmineApp::Application.routes.draw do
|
||||
get '/projects/:id/dmsf/new', :controller => 'dmsf', :action => 'new', :as => 'new_dmsf'
|
||||
get '/projects/:id/dmsf/edit', :controller=> 'dmsf', :action => 'edit', :as => 'edit_dmsf'
|
||||
get '/projects/:id/dmsf/edit/root', :controller=> 'dmsf', :action => 'edit_root', :as => 'edit_root_dmsf'
|
||||
get '/projects/:id/dmsf/trash', :controller => 'dmsf', :action => 'trash', :as => 'trash_dmsf'
|
||||
get '/projects/:id/dmsf/restore', :controller => 'dmsf', :action => 'restore', :as => 'restore_dmsf'
|
||||
|
||||
#
|
||||
# dmsf_state controller
|
||||
@ -49,7 +51,6 @@ RedmineApp::Application.routes.draw do
|
||||
##
|
||||
post '/projects/:id/dmsf/state', :controller => 'dmsf_state', :action => 'user_pref_save'
|
||||
|
||||
|
||||
#
|
||||
# dmsf_upload controller
|
||||
# /projects/<project>/dmsf/upload - dmsf_upload controller
|
||||
@ -74,6 +75,7 @@ RedmineApp::Application.routes.draw do
|
||||
get '/dmsf/files/:id/download/:download', :controller => 'dmsf_files', :action => 'show', :as => 'download_revision'
|
||||
get '/dmsf/files/:id', :controller => 'dmsf_files', :action => 'show', :as => 'dmsf_file'
|
||||
delete '/dmsf/files/:id', :controller => 'dmsf_files', :action => 'delete'
|
||||
get '/dmsf/files/:id/restore', :controller => 'dmsf_files', :action => 'restore', :as => 'restore_dmsf_file'
|
||||
|
||||
# Just to keep backward compatibility with old external direct links
|
||||
get '/dmsf_files/:id', :controller => 'dmsf_files', :action => 'show'
|
||||
@ -124,6 +126,7 @@ RedmineApp::Application.routes.draw do
|
||||
# Links
|
||||
resources :dmsf_links do
|
||||
member do
|
||||
get 'restore'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
32
db/migrate/20140519133201_trash_bin.rb
Normal file
32
db/migrate/20140519133201_trash_bin.rb
Normal file
@ -0,0 +1,32 @@
|
||||
# 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.
|
||||
|
||||
class TrashBin < ActiveRecord::Migration
|
||||
def up
|
||||
# DMSF - project's root folder notification
|
||||
add_column :dmsf_folders, :deleted, :boolean, :default => false, :null => false
|
||||
add_column :dmsf_folders, :deleted_by_user_id, :integer
|
||||
|
||||
DmsfFolder.connection.execute('UPDATE dmsf_folders SET deleted = 0')
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column :dmsf_folders, :deleted
|
||||
remove_column :dmsf_folders, :deleted_by_user_id
|
||||
end
|
||||
end
|
||||
6
init.rb
6
init.rb
@ -64,14 +64,14 @@ Redmine::Plugin.register :redmine_dmsf do
|
||||
:dmsf_workflows => [:log]},
|
||||
:read => true
|
||||
permission :folder_manipulation,
|
||||
{:dmsf => [:new, :create, :delete, :edit, :save, :edit_root, :save_root, :lock, :unlock, :notify_activate, :notify_deactivate, :delete_entries]}
|
||||
{:dmsf => [:new, :create, :delete, :edit, :save, :edit_root, :save_root, :lock, :unlock, :notify_activate, :notify_deactivate, :delete_entries, :restore]}
|
||||
permission :file_manipulation,
|
||||
{:dmsf_files => [:create_revision, :lock, :unlock, :delete_revision, :notify_activate, :notify_deactivate],
|
||||
{:dmsf_files => [:create_revision, :lock, :unlock, :delete_revision, :notify_activate, :notify_deactivate, :restore],
|
||||
:dmsf_upload => [:upload_files, :upload_file, :commit_files],
|
||||
:dmsf_workflows => [:action, :new_action, :autocomplete_for_user, :start, :assign, :assignment],
|
||||
:dmsf_links => [:new, :create, :destroy]
|
||||
}
|
||||
permission :file_delete, {:dmsf_files => [:delete]}
|
||||
permission :file_delete, { :dmsf => [:trash], :dmsf_files => [:delete]}
|
||||
permission :manage_workflows,
|
||||
{:dmsf_workflows => [:index, :new, :create, :destroy, :show, :add_step, :remove_step, :reorder_steps, :update]}
|
||||
permission :force_file_unlock, {}
|
||||
|
||||
@ -292,7 +292,7 @@ class DmsfLinksControllerTest < RedmineDmsf::Test::TestCase
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
assert_difference 'DmsfLink.count', -1 do
|
||||
assert_difference 'DmsfLink.visible.count', -1 do
|
||||
delete :destroy, :project_id => @project1.id, :id => @file_link.id
|
||||
end
|
||||
assert_redirected_to dmsf_folder_path(:id => @project1.id, :folder_id => @folder1.id)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user