From b4aaa58faa4a4af56a2c7aa068744d39af3792d1 Mon Sep 17 00:00:00 2001 From: Karel Picman Date: Tue, 12 Apr 2016 14:32:36 +0200 Subject: [PATCH] Approval workflows, operators are switched --- app/controllers/dmsf_workflows_controller.rb | 200 ++++++++++--------- app/models/dmsf_workflow.rb | 149 +++++++------- app/views/dmsf_workflows/_steps.html.erb | 39 ++-- app/views/dmsf_workflows/new.html.erb | 22 +- 4 files changed, 207 insertions(+), 203 deletions(-) diff --git a/app/controllers/dmsf_workflows_controller.rb b/app/controllers/dmsf_workflows_controller.rb index 007bdd79..b22f570a 100644 --- a/app/controllers/dmsf_workflows_controller.rb +++ b/app/controllers/dmsf_workflows_controller.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -# +# # Redmine plugin for Document Management System "Features" # # Copyright (C) 2011-16 Karel Pičman @@ -19,55 +19,55 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class DmsfWorkflowsController < ApplicationController - unloadable + unloadable model_object DmsfWorkflow - - before_filter :find_model_object, :except => [:create, :new, :index, :assign, :assignment] + + before_filter :find_model_object, :except => [:create, :new, :index, :assign, :assignment] before_filter :find_project before_filter :authorize_custom - + layout :workflows_layout - + def index @status = params[:status] || 1 @workflow_pages, @workflows = paginate DmsfWorkflow.status(@status).global.sorted, :per_page => 25 end - - def action + + def action end - + def new_action if params[:commit] == l(:button_submit) action = DmsfWorkflowStepAction.new( :dmsf_workflow_step_assignment_id => params[:dmsf_workflow_step_assignment_id], :action => (params[:step_action].to_i >= 10) ? DmsfWorkflowStepAction::ACTION_DELEGATE : params[:step_action], - :note => params[:note]) + :note => params[:note]) if request.post? if action.save revision = DmsfFileRevision.find_by_id params[:dmsf_file_revision_id] if revision - if @dmsf_workflow.try_finish revision, action, (params[:step_action].to_i / 10) + if @dmsf_workflow.try_finish revision, action, (params[:step_action].to_i / 10) file = DmsfFile.joins(:revisions).where(:dmsf_file_revisions => {:id => revision.id}).first if file begin file.unlock! true rescue DmsfLockError => e - flash[:info] = e.message + flash[:info] = e.message end - end + end if revision.workflow == DmsfWorkflow::STATE_APPROVED - # Just approved + # Just approved recipients = DmsfMailer.get_notify_users(@project) recipients.each do |user| DmsfMailer.workflow_notification( user, - @dmsf_workflow, + @dmsf_workflow, revision, :text_email_subject_approved, :text_email_finished_approved, :text_email_to_see_history).deliver if user end - if Setting.plugin_redmine_dmsf[:dmsf_display_notified_recipients] == '1' + if Setting.plugin_redmine_dmsf[:dmsf_display_notified_recipients] == '1' unless recipients.blank? to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ') to << ((recipients.count > DMSF_MAX_NOTIFICATION_RECEIVERS_INFO) ? ',...' : '.') @@ -75,15 +75,15 @@ class DmsfWorkflowsController < ApplicationController end end else - # Just rejected + # Just rejected recipients = @dmsf_workflow.participiants recipients.push User.find_by_id revision.dmsf_workflow_assigned_by recipients.uniq! recipients = recipients & DmsfMailer.get_notify_users(@project) recipients.each do |user| DmsfMailer.workflow_notification( - user, - @dmsf_workflow, + user, + @dmsf_workflow, revision, :text_email_subject_rejected, :text_email_finished_rejected, @@ -100,19 +100,19 @@ class DmsfWorkflowsController < ApplicationController end else if action.action == DmsfWorkflowStepAction::ACTION_DELEGATE - # Delegation + # Delegation delegate = User.find_by_id params[:step_action].to_i / 10 if DmsfMailer.get_notify_users(@project).include?(delegate) DmsfMailer.workflow_notification( - delegate, - @dmsf_workflow, + delegate, + @dmsf_workflow, revision, :text_email_subject_delegated, :text_email_finished_delegated, :text_email_to_proceed, action.note).deliver if Setting.plugin_redmine_dmsf[:dmsf_display_notified_recipients] == '1' - flash[:warning] = l(:warning_email_notifications, :to => delegate.name) + flash[:warning] = l(:warning_email_notifications, :to => delegate.name) end end else @@ -124,19 +124,19 @@ class DmsfWorkflowsController < ApplicationController assignments.each do |assignment| if assignment.user && DmsfMailer.get_notify_users(@project).include?(assignment.user) DmsfMailer.workflow_notification( - assignment.user, - @dmsf_workflow, + assignment.user, + @dmsf_workflow, revision, :text_email_subject_requires_approval, :text_email_finished_step, :text_email_to_proceed).deliver end end - to = User.find_by_id revision.dmsf_workflow_assigned_by + to = User.find_by_id revision.dmsf_workflow_assigned_by if to && DmsfMailer.get_notify_users(@project).include?(to) DmsfMailer.workflow_notification( - to, - @dmsf_workflow, + to, + @dmsf_workflow, revision, :text_email_subject_updated, :text_email_finished_step_short, @@ -153,31 +153,31 @@ class DmsfWorkflowsController < ApplicationController flash[:warning] = l(:warning_email_notifications, :to => to) end end - end + end end end end end flash[:notice] = l(:notice_successful_update) elsif action.action != DmsfWorkflowStepAction::ACTION_APPROVE && action.note.blank? - flash[:error] = l(:error_empty_note) + flash[:error] = l(:error_empty_note) end - end + end end - redirect_to :back + redirect_to :back end - - def assign + + def assign end - + def assignment - if (params[:commit] == l(:button_submit)) && + if (params[:commit] == l(:button_submit)) && params[:dmsf_workflow_id].present? && (params[:dmsf_workflow_id] != '-1') revision = DmsfFileRevision.find_by_id params[:dmsf_file_revision_id] if revision - revision.set_workflow(params[:dmsf_workflow_id], params[:action]) + revision.set_workflow(params[:dmsf_workflow_id], params[:action]) revision.assign_workflow(params[:dmsf_workflow_id]) - if request.post? + if request.post? if revision.save file = DmsfFile.find_by_id revision.dmsf_file_id if file @@ -186,23 +186,23 @@ class DmsfWorkflowsController < ApplicationController rescue DmsfLockError => e logger.warn e.message end - flash[:notice] = l(:notice_successful_update) + flash[:notice] = l(:notice_successful_update) end else flash[:error] = l(:error_workflow_assign) end - end - end + end + end end - redirect_to :back + redirect_to :back end def log end - - def new + + def new @dmsf_workflow = DmsfWorkflow.new - + # Reload if params[:dmsf_workflow] && params[:dmsf_workflow][:name].present? @dmsf_workflow.name = params[:dmsf_workflow][:name] @@ -210,15 +210,15 @@ class DmsfWorkflowsController < ApplicationController wf = DmsfWorkflow.find_by_id params[:dmsf_workflow][:id] @dmsf_workflow.name = wf.name if wf end - + render :layout => !request.xhr? end - + def create 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 + @dmsf_workflow = wf.copy_to(@project, params[:dmsf_workflow][:name]) if wf else @dmsf_workflow = DmsfWorkflow.new @dmsf_workflow.name = params[:dmsf_workflow][:name] @@ -234,12 +234,12 @@ class DmsfWorkflowsController < ApplicationController else redirect_to dmsf_workflows_path end - else + else render :action => 'new' end end - - def update + + def update if params[:dmsf_workflow] res = @dmsf_workflow.update_attributes({:name => params[:dmsf_workflow][:name]}) if params[:dmsf_workflow][:name].present? res = @dmsf_workflow.update_attributes({:status => params[:dmsf_workflow][:status]}) if params[:dmsf_workflow][:status].present? @@ -249,7 +249,7 @@ class DmsfWorkflowsController < ApplicationController redirect_to settings_project_path(@project, :tab => 'dmsf_workflow') else redirect_to dmsf_workflows_path - end + end else flash[:error] = @dmsf_workflow.errors.full_messages.to_sentence redirect_to dmsf_workflow_path(@dmsf_workflow) @@ -258,10 +258,10 @@ class DmsfWorkflowsController < ApplicationController redirect_to dmsf_workflow_path(@dmsf_workflow) end end - - def destroy + + def destroy begin - @dmsf_workflow.destroy + @dmsf_workflow.destroy flash[:notice] = l(:notice_successful_delete) rescue flash[:error] = l(:error_unable_delete_dmsf_workflow) @@ -270,33 +270,33 @@ class DmsfWorkflowsController < ApplicationController redirect_to settings_project_path(@project, :tab => 'dmsf_workflow') else redirect_to dmsf_workflows_path - end + end end - - def autocomplete_for_user + + def autocomplete_for_user render :layout => false end - + def new_step @steps = @dmsf_workflow.dmsf_workflow_steps.collect{|s| s.step}.uniq respond_to do |format| - format.html + format.html format.js - end + end end - - def add_step - if request.post? + + def add_step + if request.post? if params[:step] == '0' - step = @dmsf_workflow.dmsf_workflow_steps.collect{|s| s.step}.uniq.count + 1 + step = @dmsf_workflow.dmsf_workflow_steps.collect{|s| s.step}.uniq.count + 1 else step = params[:step].to_i end operator = (params[:commit] == l(:dmsf_and)) ? DmsfWorkflowStep::OPERATOR_AND : DmsfWorkflowStep::OPERATOR_OR users = User.where(:id => params[:user_ids]).to_a if users.count > 0 - users.each do |user| + users.each do |user| ws = DmsfWorkflowStep.new ws.dmsf_workflow_id = @dmsf_workflow.id ws.step = step @@ -310,49 +310,49 @@ class DmsfWorkflowsController < ApplicationController end else flash[:error] = l(:error_workflow_assign) - end - end + end + end respond_to do |format| - format.html - end + format.html + end end - - def remove_step - if request.delete? + + def remove_step + if request.delete? DmsfWorkflowStep.where(:dmsf_workflow_id => @dmsf_workflow.id, :step => params[:step]).each do |ws| @dmsf_workflow.dmsf_workflow_steps.delete(ws) - end + end @dmsf_workflow.dmsf_workflow_steps.each do |ws| n = ws.step.to_i - if n > params[:step].to_i + if n > params[:step].to_i ws.step = n - 1 unless ws.save flash[:error] = l(:notice_cannot_renumber_steps) end end - end - end + end + end respond_to do |format| - format.html + format.html end end - - def reorder_steps + + def reorder_steps if request.put? unless @dmsf_workflow.reorder_steps(params[:step].to_i, params[:workflow_step][:move_to]) flash[:error] = l(:notice_cannot_renumber_steps) - end - end + end + end respond_to do |format| - format.html + format.html end end - + def start revision = DmsfFileRevision.find_by_id(params[:dmsf_file_revision_id]) - if revision + if revision revision.set_workflow(@dmsf_workflow.id, params[:action]) - if revision.save + if revision.save assignments = @dmsf_workflow.next_assignments revision.id recipients = assignments.collect{ |a| a.user } recipients.uniq! @@ -360,13 +360,13 @@ class DmsfWorkflowsController < ApplicationController recipients.each do |user| DmsfMailer.workflow_notification( user, - @dmsf_workflow, + @dmsf_workflow, revision, :text_email_subject_started, :text_email_started, :text_email_to_proceed).deliver end - if Setting.plugin_redmine_dmsf[:dmsf_display_notified_recipients] == '1' + if Setting.plugin_redmine_dmsf[:dmsf_display_notified_recipients] == '1' unless recipients.blank? to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ') to << ((recipients.count > DMSF_MAX_NOTIFICATION_RECEIVERS_INFO) ? ',...' : '.') @@ -376,14 +376,14 @@ class DmsfWorkflowsController < ApplicationController flash[:notice] = l(:notice_workflow_started) else flash[:error] = l(:notice_cannot_start_workflow) - end + end end redirect_to :back end - -private - def find_project +private + + def find_project if @dmsf_workflow if @dmsf_workflow.project # Project workflow @project = @dmsf_workflow.project @@ -392,19 +392,21 @@ private @project = revision.file.project if revision && revision.file end else - if params[:project_id].present? + if params[:dmsf_workflow] + @project = Project.find_by_id params[:dmsf_workflow][:project_id] + elsif params[:project_id] @project = Project.find_by_id params[:project_id] else @project = Project.find_by_identifier params[:id] end - end + end end - - def workflows_layout + + def workflows_layout @project ? 'base' : 'admin' - end - - def authorize_custom + end + + def authorize_custom if @project authorize else diff --git a/app/models/dmsf_workflow.rb b/app/models/dmsf_workflow.rb index 6c306edf..10997257 100644 --- a/app/models/dmsf_workflow.rb +++ b/app/models/dmsf_workflow.rb @@ -18,34 +18,34 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -class DmsfWorkflow < ActiveRecord::Base - +class DmsfWorkflow < ActiveRecord::Base + has_many :dmsf_workflow_steps, -> { order 'step ASC, operator DESC' }, :dependent => :destroy belongs_to :author, :class_name => 'User' - + scope :sorted, lambda { order('name ASC') } scope :global, lambda { where('project_id IS NULL') } scope :active, lambda { where(:status => STATUS_ACTIVE) } scope :status, lambda { |arg| where(arg.blank? ? nil : {:status => arg.to_i}) } - + 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 = ?', + 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 = ?', + 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 + else if self.id if DmsfWorkflow.where(['name = ? AND id != ?', self.name, self.id]).count > 0 errors.add(:name, l('activerecord.errors.messages.taken')) @@ -57,16 +57,16 @@ class DmsfWorkflow < ActiveRecord::Base end end end - + STATE_NONE = nil STATE_ASSIGNED = 3 STATE_WAITING_FOR_APPROVAL = 1 STATE_APPROVED = 2 STATE_REJECTED = 4 - + STATUS_LOCKED = 0 STATUS_ACTIVE = 1 - + def participiants users = Array.new self.dmsf_workflow_steps.each do |step| @@ -76,90 +76,90 @@ class DmsfWorkflow < ActiveRecord::Base end def self.workflows(project) - project ? where(:project_id => project) : where('project_id IS NULL') + project ? where(:project_id => project) : where('project_id IS NULL') end - def project + def project Project.find_by_id(project_id) if project_id end def to_s name - end + end def reorder_steps(step, move_to) DmsfWorkflow.transaction do case move_to - when 'highest' - unless step == 1 - dmsf_workflow_steps.each do |ws| + when 'highest' + unless step == 1 + dmsf_workflow_steps.each do |ws| if ws.step < step - return false unless ws.update_attribute('step', ws.step + 1) - elsif ws.step == step + return false unless ws.update_attribute('step', ws.step + 1) + elsif ws.step == step return false unless ws.update_attribute('step', 1) - end - end + end + end end when 'higher' - unless step == 1 + unless step == 1 dmsf_workflow_steps.each do |ws| - if ws.step == step - 1 + if ws.step == step - 1 return false unless ws.update_attribute('step', step) - elsif ws.step == step + elsif ws.step == step return false unless ws.update_attribute('step', step - 1) - end - end + end + end end when 'lower' - unless step == dmsf_workflow_steps.collect{|s| s.step}.uniq.count + unless step == dmsf_workflow_steps.collect{|s| s.step}.uniq.count dmsf_workflow_steps.each do |ws| - if ws.step == step + 1 - return false unless ws.update_attribute('step', step) - elsif ws.step == step - return false unless ws.update_attribute('step', step + 1) - end - end + if ws.step == step + 1 + return false unless ws.update_attribute('step', step) + elsif ws.step == step + return false unless ws.update_attribute('step', step + 1) + end + end end - when 'lowest' + when 'lowest' size = dmsf_workflow_steps.collect{|s| s.step}.uniq.count unless step == size - dmsf_workflow_steps.each do |ws| - if ws.step > step + dmsf_workflow_steps.each do |ws| + if ws.step > step return false unless ws.update_attribute('step', ws.step - 1) - elsif ws.step == step + elsif ws.step == step return false unless ws.update_attribute('step', size) end - end - end - end + end + end + end end - return reload + return reload end - - def delegates(q, dmsf_workflow_step_assignment_id, dmsf_file_revision_id) + + def delegates(q, dmsf_workflow_step_assignment_id, dmsf_file_revision_id) if dmsf_workflow_step_assignment_id && dmsf_file_revision_id sql = [ - 'id NOT IN (SELECT a.user_id FROM dmsf_workflow_step_assignments a WHERE id = ?) AND id IN (SELECT m.user_id FROM members m JOIN dmsf_files f ON f.project_id = m.project_id JOIN dmsf_file_revisions r ON r.dmsf_file_id = f.id WHERE r.id = ?)', - dmsf_workflow_step_assignment_id, + 'id NOT IN (SELECT a.user_id FROM dmsf_workflow_step_assignments a WHERE id = ?) AND id IN (SELECT m.user_id FROM members m JOIN dmsf_files f ON f.project_id = m.project_id JOIN dmsf_file_revisions r ON r.dmsf_file_id = f.id WHERE r.id = ?)', + dmsf_workflow_step_assignment_id, dmsf_file_revision_id] elsif project sql = ['id IN (SELECT user_id FROM members WHERE project_id = ?)', project.id] else sql = '1=1' end - + if q.present? User.active.sorted.where(sql).like(q) else User.active.sorted.where(sql) - end + end end - - def next_assignments(dmsf_file_revision_id) - results = Array.new + + def next_assignments(dmsf_file_revision_id) + results = Array.new nsteps = self.dmsf_workflow_steps.collect{|s| s.step}.uniq nsteps.each do |i| - step_is_finished = false + step_is_finished = false steps = self.dmsf_workflow_steps.collect{|s| s.step == i ? s : nil}.compact steps.each do |step| step.dmsf_workflow_step_assignments.each do |assignment| @@ -168,24 +168,25 @@ class DmsfWorkflow < ActiveRecord::Base case action.action when DmsfWorkflowStepAction::ACTION_APPROVE step_is_finished = true - # Try to find another unfinished AND step + # Try to find another unfinished AND step exists = false stps = self.dmsf_workflow_steps.collect{|s| (s.step == i && s.operator == DmsfWorkflowStep::OPERATOR_AND) ? s : nil}.compact stps.each do |s| s.dmsf_workflow_step_assignments.each do |a| - exists = a.add?(dmsf_file_revision_id) - break if exists + exists = a.add?(dmsf_file_revision_id) + break if exists end - end + break if exists + end step_is_finished = false if exists break when DmsfWorkflowStepAction::ACTION_REJECT - return Array.new + return Array.new end end end break if step_is_finished - end + end break if step_is_finished end unless step_is_finished @@ -199,29 +200,29 @@ class DmsfWorkflow < ActiveRecord::Base end results end - + def self.assignments_to_users_str(assignments) str = '' - if assignments - assignments.each_with_index do |assignment, index| + if assignments + assignments.each_with_index do |assignment, index| if index > 0 str << ', ' end - str << assignment.user.name + str << assignment.user.name end end - str + str end - + def assign(dmsf_file_revision_id) dmsf_workflow_steps.each do |ws| ws.assign(dmsf_file_revision_id) end end - - def try_finish(revision, action, user_id) + + def try_finish(revision, action, user_id) case action.action - when DmsfWorkflowStepAction::ACTION_APPROVE + when DmsfWorkflowStepAction::ACTION_APPROVE assignments = self.next_assignments revision.id return false unless assignments.empty? revision.update_attribute(:workflow, DmsfWorkflow::STATE_APPROVED) @@ -229,7 +230,7 @@ class DmsfWorkflow < ActiveRecord::Base when DmsfWorkflowStepAction::ACTION_REJECT revision.update_attribute(:workflow, DmsfWorkflow::STATE_REJECTED) return true - when DmsfWorkflowStepAction::ACTION_DELEGATE + when DmsfWorkflowStepAction::ACTION_DELEGATE self.dmsf_workflow_steps.each do |step| step.dmsf_workflow_step_assignments.each do |assignment| if assignment.id == action.dmsf_workflow_step_assignment_id @@ -240,27 +241,27 @@ class DmsfWorkflow < ActiveRecord::Base end end return false - end - + end + def copy_to(project, name = nil) - new_wf = self.dup + new_wf = self.dup new_wf.name = name if name new_wf.project_id = project ? project.id : nil new_wf.author = User.current if new_wf.save self.dmsf_workflow_steps.each do |step| step.copy_to(new_wf) - end + end end return new_wf end - + def locked? self.status == STATUS_LOCKED end - + def active? self.status == STATUS_ACTIVE end - + end \ No newline at end of file diff --git a/app/views/dmsf_workflows/_steps.html.erb b/app/views/dmsf_workflows/_steps.html.erb index 4578fcbb..ef3c2699 100644 --- a/app/views/dmsf_workflows/_steps.html.erb +++ b/app/views/dmsf_workflows/_steps.html.erb @@ -28,45 +28,46 @@ <%= labelled_form_for @dmsf_workflow do |f| %> <%= error_messages_for 'workflow' %> -
+

<%= f.text_field :name, :required => true %> <%= f.submit l(:button_save) %> -

-
-<% end %> +

+
+<% end %> -
-

+

+

<%= link_to l(:dmsf_new_step), new_step_dmsf_workflow_path(@dmsf_workflow), :remote => true, :class => 'icon icon-add' %> -

+

<% steps = @dmsf_workflow.dmsf_workflow_steps.collect{|s| s.step}.uniq %> <% if steps.any? %> - + - - <% steps.each do |i|%> - + + <% steps.each do |i|%> + - - + - + <% end; reset_cycle %> diff --git a/app/views/dmsf_workflows/new.html.erb b/app/views/dmsf_workflows/new.html.erb index 2c7b1cf8..3fccb993 100644 --- a/app/views/dmsf_workflows/new.html.erb +++ b/app/views/dmsf_workflows/new.html.erb @@ -27,26 +27,26 @@

<%= link_to l(:label_dmsf_workflow_plural), dmsf_workflows_path %> » <%= l(:label_dmsf_workflow_new) %>

<% end %> -<%= labelled_form_for @dmsf_workflow do |f| %> - <%= f.hidden_field(:project_id) if project %> +<%= labelled_form_for @dmsf_workflow do |f| %> + <%= f.hidden_field(:project_id, :value => project.id) if project %> <%= error_messages_for 'dmsf_workflow' %>
-

+

<%= f.text_field :name, :required => true %>

-

- <%= f.select(:id, - dmsf_all_workflows_for_select(params[:dmsf_workflow] ? params[:dmsf_workflow][:id] : nil), +

+ <%= f.select(:id, + dmsf_all_workflows_for_select(params[:dmsf_workflow] ? params[:dmsf_workflow][:id] : nil), :label => l(:label_copy_workflow_from)) %> -

+

<%= f.submit l(:button_create) %> <% end %> - - \ No newline at end of file + \ No newline at end of file
<%= l(:label_dmsf_workflow_step) %> <%= l(:label_dmsf_workflow_approval_plural) %><%= l(:button_sort)%><%= l(:button_sort) %>
<%= i %> - <% @dmsf_workflow.dmsf_workflow_steps.collect{|s| (s.step == i) ? s : nil}.compact.each_with_index do |step, j| %> - <% if j != 0 %> - <%= step.soperator %>  + + <% stps = @dmsf_workflow.dmsf_workflow_steps.collect{|s| (s.step == i) ? s : nil}.compact %> + <% stps.each_with_index do |step, j| %> + <% if (j != 0) || (stps.count > 1) %> + <%= step.soperator %> <% end %> <%= link_to_user step.user %> <% end %> - + <%= reorder_links('workflow_step', {:action => 'edit', :id => @dmsf_workflow, :step => i}, :put) %> + <%= delete_link edit_dmsf_workflow_path(@dmsf_workflow, :step => i) %> -