diff --git a/app/controllers/dmsf_controller.rb b/app/controllers/dmsf_controller.rb index 145227bd..a8d09103 100644 --- a/app/controllers/dmsf_controller.rb +++ b/app/controllers/dmsf_controller.rb @@ -37,7 +37,8 @@ class DmsfController < ApplicationController @file_manipulation_allowed = User.current.allowed_to?(:file_manipulation, @project) @file_delete_allowed = User.current.allowed_to?(:file_delete, @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 + @workflows_available = DmsfWorkflow.where(['project_id = ? OR project_id IS NULL', @project.id]).count > 0 + @file_approval_allowed = User.current.allowed_to?(:file_approval, @project) unless @folder if params[:custom_field_id].present? && params[:custom_value].present? diff --git a/app/controllers/dmsf_workflows_controller.rb b/app/controllers/dmsf_workflows_controller.rb index f4d25c6b..0a065521 100644 --- a/app/controllers/dmsf_workflows_controller.rb +++ b/app/controllers/dmsf_workflows_controller.rb @@ -27,11 +27,7 @@ class DmsfWorkflowsController < ApplicationController layout :workflows_layout def index - if @project - @workflow_pages, @workflows = paginate DmsfWorkflow.where(:project_id => @project.id), :per_page => 25 - else - @workflow_pages, @workflows = paginate DmsfWorkflow.where(:project_id => nil), :per_page => 25 - end + @workflow_pages, @workflows = paginate DmsfWorkflow.global.sorted, :per_page => 25 end def action @@ -210,22 +206,24 @@ class DmsfWorkflowsController < ApplicationController @dmsf_workflow.name = params[:dmsf_workflow][:name] elsif params[:dmsf_workflow_id].present? wf = DmsfWorkflow.find_by_id params[:dmsf_workflow_id] - @dmsf_workflow.name = "#{wf.name}-#{@project.identifier}" if wf + @dmsf_workflow.name = wf.name if wf end render :layout => !request.xhr? end def create - if params[:dmsf_workflow_id] && params[:dmsf_workflow] - wf = DmsfWorkflow.find_by_id params[:dmsf_workflow_id] - @dmsf_workflow = wf.copy_to @project, params[:dmsf_workflow][:name] - else - @dmsf_workflow = DmsfWorkflow.new(:name => params[:name], - :project_id => @project.id) - @dmsf_workflow.save + if params[:dmsf_workflow] + if (params[:dmsf_workflow_id].to_i > 0) + wf = DmsfWorkflow.find_by_id params[:dmsf_workflow_id] + @dmsf_workflow = wf.copy_to(@project, params[:dmsf_workflow][:name]) if wf + else + @dmsf_workflow = DmsfWorkflow.new(:name => params[:dmsf_workflow][:name]) + @dmsf_workflow.project_id = @project.id if @project + @dmsf_workflow.save + end end - if request.post? && @dmsf_workflow.valid? + if request.post? && @dmsf_workflow && @dmsf_workflow.valid? flash[:notice] = l(:notice_successful_create) if @project redirect_to settings_project_path(@project, :tab => 'dmsf_workflow') diff --git a/app/helpers/dmsf_workflows_helper.rb b/app/helpers/dmsf_workflows_helper.rb index 616c1b61..ad631d6a 100644 --- a/app/helpers/dmsf_workflows_helper.rb +++ b/app/helpers/dmsf_workflows_helper.rb @@ -49,20 +49,35 @@ module DmsfWorkflowsHelper def dmsf_workflows_for_select(project, dmsf_workflow_id) options = Array.new - DmsfWorkflow.where(['project_id = ? OR project_id IS NULL', project.id]).each do |wf| - options << [wf.name, wf.id] + DmsfWorkflow.sorted.where(['project_id = ? OR project_id IS NULL', project.id]).each do |wf| + if wf.project_id + options << [wf.name, wf.id] + else + options << ["#{wf.name} (global)", wf.id] + end end options_for_select(options, :selected => dmsf_workflow_id) end def dmsf_all_workflows_for_select(dmsf_workflow_id) options = Array.new - options << ['', 0] - DmsfWorkflow.where('project_id IS NOT NULL').each do |wf| - if User.current.allowed_to?(:manage_workflows, wf.project) + options << ['', 0] + DmsfWorkflow.sorted.all.each do |wf| + if wf.project_id + prj = Project.find_by_id wf.project_id + if User.current.allowed_to?(:manage_workflows, prj) + # Local approval workflows + if prj + options << ["#{wf.name} (#{prj.name})", wf.id] + else + options << [wf.name, wf.id] + end + end + else + # Global approval workflows options << [wf.name, wf.id] - end - end + end + end options_for_select(options, :selected => dmsf_workflow_id) end diff --git a/app/models/dmsf_workflow.rb b/app/models/dmsf_workflow.rb index 376eee0a..49868332 100644 --- a/app/models/dmsf_workflow.rb +++ b/app/models/dmsf_workflow.rb @@ -18,11 +18,40 @@ class DmsfWorkflow < ActiveRecord::Base has_many :dmsf_workflow_steps, :dependent => :destroy, :order => 'step ASC, operator DESC' - - validates_uniqueness_of :name, :case_sensitive => false + + scope :sorted, lambda { order('name ASC') } + scope :global, lambda { where('project_id IS NULL') } + + validate :name_validation validates :name, :presence => true validates_length_of :name, :maximum => 255 + def name_validation + if self.project_id + if self.id + if (DmsfWorkflow.where(['(project_id IS NULL OR (project_id = ? AND id != ?)) AND name = ?', + self.project_id, self.name, self.id]).count > 0) + errors.add(:name, l('activerecord.errors.messages.taken')) + end + else + if (DmsfWorkflow.where(['(project_id IS NULL OR project_id = ?) AND name = ?', + self.project_id, self.name]).count > 0) + errors.add(:name, l('activerecord.errors.messages.taken')) + end + end + else + if self.id + if DmsfWorkflow.where(['name = ? AND id != ?', self.name, self.id]).count > 0 + errors.add(:name, l('activerecord.errors.messages.taken')) + end + else + if DmsfWorkflow.where(:name => self.name).count > 0 + errors.add(:name, l('activerecord.errors.messages.taken')) + end + end + end + end + STATE_NONE = nil STATE_ASSIGNED = 3 STATE_WAITING_FOR_APPROVAL = 1 @@ -205,13 +234,9 @@ class DmsfWorkflow < ActiveRecord::Base end def copy_to(project, name = nil) - new_wf = self.dup - if name - new_wf.name = name - else - new_wf.name << "-#{project.identifier}" - end - new_wf.project_id = project.id + new_wf = self.dup + new_wf.name = name if name + new_wf.project_id = project ? project.id : nil if new_wf.save self.dmsf_workflow_steps.each do |step| step.copy_to(new_wf) diff --git a/app/views/dmsf/_file.html.erb b/app/views/dmsf/_file.html.erb index 40f5d8be..b6667643 100644 --- a/app/views/dmsf/_file.html.erb +++ b/app/views/dmsf/_file.html.erb @@ -55,7 +55,7 @@ <%= file.last_revision.version %> - <% if wf && @file_manipulation_allowed %> + <% if wf && @file_approval_allowed %> <%= link_to( file.last_revision.workflow_str(false), log_dmsf_workflow_path( @@ -70,61 +70,64 @@ <%= h(file.last_revision.user) %> - <% if @file_manipulation_allowed %> + <% if @file_manipulation_allowed || @file_approval_allowed %>
- <% 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 %> + <% if @file_manipulation_allowed %> + <% unless locked %> <%= link_to('', - notify_deactivate_dmsf_files_path(:id => file), - :title => l(:title_notifications_active_deactivate), - :class => 'icon icon-notification-on') %> - <% else %> + dmsf_file_path(:id => file), + :title => l(:link_details, :title => h(file.last_revision.title)), + :class => 'icon icon-dmsf-file-details') %> <%= 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 %> - <% if @file_delete_allowed %> + lock_dmsf_files_path(:id => file), + :title => l(:title_lock_file), + :class => 'icon icon-dmsf-lock') %> + <% if file.notification %> <%= link_to('', - dmsf_file_path(:id => file), + 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') unless locked_for_user %> + :class => 'icon icon-del') %> + <% else %> + <% if @file_delete_allowed %> + <%= 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 %> + <% else %> + + <% end %> + <% end %> + <% else %> + + <% 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 %> <% end %> - <% end %> - <% else %> - - <% 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 %> + <% end %> - - <% end %> - <% case file.last_revision.workflow %> + <% if @file_approval_allowed %> + <% case file.last_revision.workflow %> <% when DmsfWorkflow::STATE_WAITING_FOR_APPROVAL %> <% if wf %> <% assignments = wf.next_assignments(file.last_revision.id) %> @@ -178,7 +181,8 @@ :class => 'icon icon-dmsf-none', :remote => true) %> <% end %> - <% end %> + <% end %> + <% end %>
<% end %> diff --git a/app/views/dmsf_workflows/_main.html.erb b/app/views/dmsf_workflows/_main.html.erb index acf4f166..a48b189e 100644 --- a/app/views/dmsf_workflows/_main.html.erb +++ b/app/views/dmsf_workflows/_main.html.erb @@ -1,6 +1,6 @@ <%# Redmine plugin for Document Management System "Features" # -# Copyright (C) 2013 Karel Pičman +# Copyright (C) 2011-14 Karel Pičman # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.%> -<% @workflows = DmsfWorkflow.where(:project_id => @project.id) if @project && @workflows.nil? %> +<% @workflows = DmsfWorkflow.sorted.where(:project_id => @project.id) if @project && @workflows.nil? %>
<% if @project %> diff --git a/app/views/dmsf_workflows/new.html.erb b/app/views/dmsf_workflows/new.html.erb index f30f57b1..87a91fef 100644 --- a/app/views/dmsf_workflows/new.html.erb +++ b/app/views/dmsf_workflows/new.html.erb @@ -42,6 +42,6 @@ \ No newline at end of file diff --git a/db/migrate/20141205143001_remove_uniqueness_from_wf.rb b/db/migrate/20141205143001_remove_uniqueness_from_wf.rb new file mode 100644 index 00000000..2431efa9 --- /dev/null +++ b/db/migrate/20141205143001_remove_uniqueness_from_wf.rb @@ -0,0 +1,27 @@ +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2011-14 Karel Pičman +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +class RemoveUniquenessFromWf < ActiveRecord::Migration + def up + remove_index :dmsf_workflows, :name + end + + def down + add_index :dmsf_workflows, [:name], :unique => true + end +end \ No newline at end of file diff --git a/init.rb b/init.rb index 0c5d87e4..d99226bb 100644 --- a/init.rb +++ b/init.rb @@ -26,7 +26,7 @@ Redmine::Plugin.register :redmine_dmsf do name 'DMSF' author 'Vit Jonas / Daniel Munn / Karel Picman' description 'Document Management System Features' - version '1.4.9 stable' + version '1.5.1 devel' url 'http://www.redmine.org/plugins/dmsf' author_url 'https://github.com/danmunn/redmine_dmsf/graphs/contributors' @@ -67,14 +67,15 @@ Redmine::Plugin.register :redmine_dmsf do {: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, :restore], - :dmsf_upload => [:upload_files, :upload_file, :commit_files], - :dmsf_workflows => [:action, :new_action, :autocomplete_for_user, :start, :assign, :assignment], + :dmsf_upload => [:upload_files, :upload_file, :commit_files], :dmsf_links => [:new, :create, :destroy, :restore] } - permission :file_delete, { :dmsf => [:trash], :dmsf_files => [:delete]} + permission :file_delete, { :dmsf => [:trash], :dmsf_files => [:delete]} + permission :force_file_unlock, {} + permission :file_approval, + {:dmsf_workflows => [:action, :new_action, :autocomplete_for_user, :start, :assign, :assignment]} permission :manage_workflows, {:dmsf_workflows => [:index, :new, :create, :destroy, :show, :add_step, :remove_step, :reorder_steps, :update]} - permission :force_file_unlock, {} end # Administration menu extension