Global approval workflows Lock/Unlock feature added

This commit is contained in:
Karel Picman 2016-02-17 13:20:06 +01:00
parent 546ef9ed8a
commit 71281cdebd
11 changed files with 138 additions and 43 deletions

View File

@ -28,8 +28,9 @@ class DmsfWorkflowsController < ApplicationController
layout :workflows_layout
def index
@workflow_pages, @workflows = paginate DmsfWorkflow.global.sorted, :per_page => 25
def index
@status = params[:status] || 1
@workflow_pages, @workflows = paginate DmsfWorkflow.status(@status).global.sorted, :per_page => 25
end
def action
@ -238,16 +239,21 @@ class DmsfWorkflowsController < ApplicationController
end
def update
if params[:dmsf_workflow] && @dmsf_workflow.update_attributes(
{:name => params[:dmsf_workflow][:name]})
flash[:notice] = l(:notice_successful_update)
if @project
redirect_to settings_project_path(@project, :tab => 'dmsf_workflow')
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?
if res
flash[:notice] = l(:notice_successful_update)
if @project
redirect_to settings_project_path(@project, :tab => 'dmsf_workflow')
else
redirect_to dmsf_workflows_path
end
else
redirect_to dmsf_workflows_path
end
flash[:error] = @dmsf_workflow.errors.full_messages.to_sentence
redirect_to dmsf_workflow_path(@dmsf_workflow)
end
else
flash[:error] = @dmsf_workflow.errors.full_messages.to_sentence
redirect_to dmsf_workflow_path(@dmsf_workflow)
end
end

View File

@ -1,8 +1,7 @@
# encoding: utf-8
#
# encoding: utf-8#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011-16 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
@ -56,7 +55,7 @@ module DmsfWorkflowsHelper
def dmsf_workflows_for_select(project, dmsf_workflow_id)
options = Array.new
options << ['', -1]
DmsfWorkflow.sorted.where(['project_id = ? OR project_id IS NULL', project.id]).each do |wf|
DmsfWorkflow.active.sorted.where(['project_id = ? OR project_id IS NULL', project.id]).each do |wf|
if wf.project_id
options << [wf.name, wf.id]
else
@ -69,7 +68,7 @@ module DmsfWorkflowsHelper
def dmsf_all_workflows_for_select(dmsf_workflow_id)
options = Array.new
options << ['', 0]
DmsfWorkflow.sorted.all.each do |wf|
DmsfWorkflow.active.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)
@ -95,4 +94,21 @@ module DmsfWorkflowsHelper
end
s.html_safe
end
end
def change_status_link(workflow)
url = { :controller => 'dmsf_workflows', :action => 'update', :id => workflow.id }
if workflow.locked?
link_to l(:button_unlock), url.merge(:dmsf_workflow => {:status => DmsfWorkflow::STATUS_ACTIVE}), :method => :put, :class => 'icon icon-unlock'
else
link_to l(:button_lock), url.merge(:dmsf_workflow => {:status => DmsfWorkflow::STATUS_LOCKED}), :method => :put, :class => 'icon icon-lock'
end
end
def workflows_status_options_for_select(selected)
worflows_count_by_status = DmsfWorkflow.global.group('status').count.to_hash
options_for_select([[l(:label_all), ''],
["#{l(:status_active)} (#{worflows_count_by_status[DmsfWorkflow::STATUS_ACTIVE].to_i})", DmsfWorkflow::STATUS_ACTIVE.to_s],
["#{l(:status_locked)} (#{worflows_count_by_status[DmsfWorkflow::STATUS_LOCKED].to_i})", DmsfWorkflow::STATUS_LOCKED.to_s]], selected.to_s)
end
end

View File

@ -24,6 +24,8 @@ class DmsfWorkflow < ActiveRecord::Base
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
@ -61,6 +63,9 @@ class DmsfWorkflow < ActiveRecord::Base
STATE_APPROVED = 2
STATE_REJECTED = 4
STATUS_LOCKED = 0
STATUS_ACTIVE = 1
def participiants
users = Array.new
self.dmsf_workflow_steps.each do |step|
@ -247,4 +252,13 @@ class DmsfWorkflow < ActiveRecord::Base
end
return new_wf
end
end
def locked?
self.status == STATUS_LOCKED
end
def active?
self.status == STATUS_ACTIVE
end
end

View File

@ -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.sorted.where(:project_id => @project.id) if @project && @workflows.nil? %>
<% @workflows = DmsfWorkflow.active.sorted.where(:project_id => @project.id) if @project && @workflows.nil? %>
<% unless @project %>
<div class="contextual">
@ -24,9 +24,18 @@
</div>
<h2><%=l(:label_dmsf_workflow_plural)%></h2>
<% end %>
<%= form_tag(dmsf_workflows_path, :method => :get) do %>
<fieldset>
<legend><%= l(:label_filter_plural) %></legend>
<label for='status'><%= l(:field_status) %>:</label>
<%= select_tag 'status', workflows_status_options_for_select(@status), :class => 'small', :onchange => "this.form.submit(); return false;" %>
</fieldset>
<% end %>
&nbsp;
<% end %>
<% if @workflows.any? %>
<% if @workflows.any? %>
<table class="list">
<thead><tr>
<th><%=l(:field_name)%></th>
@ -34,9 +43,12 @@
</tr></thead>
<tbody>
<% for workflow in @workflows %>
<tr id="workflow-<%= workflow.id %>" class="<%= cycle('odd', 'even') %>">
<td class="name"><%= link_to(h(workflow.name), dmsf_workflow_path(workflow)) %></td>
<td class="buttons"><%= delete_link dmsf_workflow_path(workflow) %></td>
<tr id="workflow-<%= workflow.id %>" class="workflow <%= workflow.active? ? 'active' : 'locked' %> <%= cycle('odd', 'even') %>">
<td class="name"><%= link_to(h(workflow.name), dmsf_workflow_path(workflow)) %></td>
<td class="buttons">
<%= change_status_link(workflow) unless @project %>
<%= delete_link dmsf_workflow_path(workflow) %>
</td>
</tr>
<% end %>
</tbody>

View File

@ -211,6 +211,7 @@ table.access-table tbody td, table.access-table tbody tr:hover td {
#admin-menu a.approvalworkflows { background-image: url(../images/ticket_go.png); }
#users_for_delegate {height: 200px; overflow:auto;}
#users_for_delegate label {display: block;}
tr.workflow.locked a { color: #aaa; }
.revision_box{
padding: 0px 0px 0px 0px;

View File

@ -2,7 +2,7 @@
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2015 Karel Pičman <karel.picman@kontorn.com>
# Copyright (C) 2011-16 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

View File

@ -2,7 +2,7 @@
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2015 Karel Pičman <karel.picman@kontorn.com>
# Copyright (C) 2011-16 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -18,12 +18,13 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class TitleFormat < ActiveRecord::Migration
class ApprovalWorkflowStatus < ActiveRecord::Migration
def self.up
add_column :members, :title_format, :text, :null => true, :limit => 100
add_column :dmsf_workflows, :status, :integer, :null => false, :default => DmsfWorkflow::STATUS_ACTIVE
DmsfWorkflow.all.each {|wf| wf.update_attribute(:status, DmsfWorkflow::STATUS_ACTIVE)}
end
def self.down
remove_column :members, :title_format
remove_column :dmsf_workflows, :status
end
end

View File

@ -6,4 +6,9 @@ wf1:
wf2:
id: 2
name: wf2
name: wf2
wf3:
id: 3
name: wf3
status: 0

View File

@ -43,6 +43,7 @@ class DmsfWorkflowsControllerTest < RedmineDmsf::Test::TestCase
@project1 = Project.find_by_id 1
@project1.enable_module! :dmsf
@wf1 = DmsfWorkflow.find_by_id 1
@wf3 = DmsfWorkflow.find_by_id 3
@wfsa2 = DmsfWorkflowStepAssignment.find_by_id 2
@revision1 = DmsfFileRevision.find_by_id 1
@revision2 = DmsfFileRevision.find_by_id 2
@ -66,6 +67,7 @@ class DmsfWorkflowsControllerTest < RedmineDmsf::Test::TestCase
assert_kind_of DmsfWorkflowStep, @wfs5
assert_kind_of Project, @project1
assert_kind_of DmsfWorkflow, @wf1
assert_kind_of DmsfWorkflow, @wf3
assert_kind_of DmsfWorkflowStepAssignment, @wfsa2
assert_kind_of DmsfFileRevision, @revision1
assert_kind_of DmsfFileRevision, @revision2
@ -133,7 +135,14 @@ class DmsfWorkflowsControllerTest < RedmineDmsf::Test::TestCase
assert_response :forbidden
end
def test_index
def test_index_administration
@request.session[:user_id] = @user_admin.id
get :index
assert_response :success
assert_template 'index'
end
def test_index_project
get :index, :project_id => @project1.id
assert_response :success
assert_template 'index'
@ -144,6 +153,19 @@ class DmsfWorkflowsControllerTest < RedmineDmsf::Test::TestCase
assert_response :success
assert_template 'new'
end
def test_lock
put :update, :id => @wf1.id, :dmsf_workflow => { :status => DmsfWorkflow::STATUS_LOCKED }
@wf1.reload
assert @wf1.locked?, "#{@wf1.name} status is #{@wf1.status}"
end
def test_unlock
@request.session[:user_id] = @user_admin.id
put :update, :id => @wf3.id, :dmsf_workflow => { :status => DmsfWorkflow::STATUS_ACTIVE }
@wf3.reload
assert @wf3.active?, "#{@wf3.name} status is #{@wf3.status}"
end
def test_show
get :show, :id => @wf1.id
@ -153,7 +175,7 @@ class DmsfWorkflowsControllerTest < RedmineDmsf::Test::TestCase
def test_create
assert_difference 'DmsfWorkflow.count', +1 do
post :create, :dmsf_workflow => {:name => 'wf3'}, :project_id => @project1.id
post :create, :dmsf_workflow => {:name => 'wf4'}, :project_id => @project1.id
end
assert_redirected_to settings_project_path(@project1, :tab => 'dmsf_workflow')
end

View File

@ -21,8 +21,7 @@
require File.expand_path('../../test_helper.rb', __FILE__)
class DmsfLockTest < RedmineDmsf::Test::UnitTest
#attr_reader :lock
class DmsfLockTest < RedmineDmsf::Test::UnitTest
fixtures :projects, :users, :email_addresses, :dmsf_folders, :dmsf_files,
:dmsf_file_revisions, :roles, :members, :member_roles, :enabled_modules,
:enumerations, :dmsf_locks
@ -77,6 +76,7 @@ class DmsfLockTest < RedmineDmsf::Test::UnitTest
end
def test_locked_folder_cannot_be_unlocked_by_someone_without_rights_or_anon
User.current = nil
assert_no_difference ('@folder2.lock.count') do
assert_raise DmsfLockError do
@folder2.unlock!

View File

@ -2,7 +2,7 @@
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-16 Karel Picman <karel.picman@kontron.com>
# Copyright (C) 2011-16 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
@ -27,15 +27,16 @@ class DmsfWorkflowTest < RedmineDmsf::Test::UnitTest
:dmsf_workflow_step_assignments, :dmsf_workflow_step_actions
def setup
@wf1 = DmsfWorkflow.find_by_id(1)
@wf2 = DmsfWorkflow.find_by_id(2)
@wfs1 = DmsfWorkflowStep.find_by_id(1)
@wfs2 = DmsfWorkflowStep.find_by_id(2)
@wfs3 = DmsfWorkflowStep.find_by_id(3)
@wfs4 = DmsfWorkflowStep.find_by_id(4)
@wfs5 = DmsfWorkflowStep.find_by_id(5)
@wfsa1 = DmsfWorkflowStepAssignment.find_by_id(1)
@wfsac1 = DmsfWorkflowStepAction.find_by_id(1)
@wf1 = DmsfWorkflow.find_by_id 1
@wf2 = DmsfWorkflow.find_by_id 2
@wf3 = DmsfWorkflow.find_by_id 3
@wfs1 = DmsfWorkflowStep.find_by_id 1
@wfs2 = DmsfWorkflowStep.find_by_id 2
@wfs3 = DmsfWorkflowStep.find_by_id 3
@wfs4 = DmsfWorkflowStep.find_by_id 4
@wfs5 = DmsfWorkflowStep.find_by_id 5
@wfsa1 = DmsfWorkflowStepAssignment.find_by_id 1
@wfsac1 = DmsfWorkflowStepAction.find_by_id 1
@revision1 = DmsfFileRevision.find_by_id 1
@revision2 = DmsfFileRevision.find_by_id 2
@project = Project.find_by_id 2
@ -45,6 +46,7 @@ class DmsfWorkflowTest < RedmineDmsf::Test::UnitTest
def test_truth
assert_kind_of DmsfWorkflow, @wf1
assert_kind_of DmsfWorkflow, @wf2
assert_kind_of DmsfWorkflow, @wf3
assert_kind_of DmsfWorkflowStep, @wfs1
assert_kind_of DmsfWorkflowStep, @wfs2
assert_kind_of DmsfWorkflowStep, @wfs3
@ -210,4 +212,20 @@ class DmsfWorkflowTest < RedmineDmsf::Test::UnitTest
assert_equal participiants.count, 2
end
def test_locked
assert @wf3.locked?, "#{@wf2.name} status is #{@wf3.status}"
end
def test_active
assert @wf1.active?, "#{@wf1.name} status is #{@wf1.status}"
end
def test_scope_active
assert_equal DmsfWorkflow.count, (DmsfWorkflow.active.count + 1)
end
def test_scope_status
assert_equal 1, DmsfWorkflow.status(DmsfWorkflow::STATUS_LOCKED).count
end
end