mirror of
https://github.com/anteo/redmine_custom_workflows.git
synced 2026-01-26 00:04:20 +00:00
#7: Add ability to activate/deactivate workflows
This commit is contained in:
parent
75fa968ee8
commit
2ee3cb453d
@ -101,7 +101,8 @@ This plug-in is compatible with Redmine 1.2.x, 1.3.x, 1.4.x, 2.x.x, 3.x.x (start
|
|||||||
|
|
||||||
Redmine 3.x.x branch:
|
Redmine 3.x.x branch:
|
||||||
|
|
||||||
[0.1.1] Import/export ability
|
[0.1.1] * Import/export ability
|
||||||
|
* Administrator can activate/deactivate workflows globally
|
||||||
[0.1.0] Compatibility with Redmine 3.x, support of Redmine 2.x.x has dropped (for Redmine 2.x.x please use version 0.0.6)
|
[0.1.0] Compatibility with Redmine 3.x, support of Redmine 2.x.x has dropped (for Redmine 2.x.x please use version 0.0.6)
|
||||||
|
|
||||||
Redmine 2.x.x branch:
|
Redmine 2.x.x branch:
|
||||||
|
|||||||
@ -2,7 +2,7 @@ class CustomWorkflowsController < ApplicationController
|
|||||||
|
|
||||||
layout 'admin'
|
layout 'admin'
|
||||||
before_filter :require_admin
|
before_filter :require_admin
|
||||||
before_filter :find_workflow, :only => [:show, :edit, :update, :destroy, :export]
|
before_filter :find_workflow, :only => [:show, :edit, :update, :destroy, :export, :change_status]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@workflows = CustomWorkflow.includes(:projects).all
|
@workflows = CustomWorkflow.includes(:projects).all
|
||||||
@ -36,6 +36,7 @@ class CustomWorkflowsController < ApplicationController
|
|||||||
xml = params[:file].read
|
xml = params[:file].read
|
||||||
begin
|
begin
|
||||||
@workflow = CustomWorkflow.import_from_xml(xml)
|
@workflow = CustomWorkflow.import_from_xml(xml)
|
||||||
|
@workflow.active = false
|
||||||
if @workflow.save
|
if @workflow.save
|
||||||
flash[:notice] = l(:notice_successful_import)
|
flash[:notice] = l(:notice_successful_import)
|
||||||
else
|
else
|
||||||
@ -63,6 +64,14 @@ class CustomWorkflowsController < ApplicationController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def change_status
|
||||||
|
respond_to do |format|
|
||||||
|
@workflow.update_attributes(:active => params[:active])
|
||||||
|
flash[:notice] = l(:notice_successful_status_change)
|
||||||
|
format.html { redirect_to(custom_workflows_path) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @workflow.update_attributes(params[:custom_workflow])
|
if @workflow.update_attributes(params[:custom_workflow])
|
||||||
|
|||||||
@ -20,6 +20,7 @@ class CustomWorkflow < ActiveRecord::Base
|
|||||||
|
|
||||||
default_scope { order(:position => :asc) }
|
default_scope { order(:position => :asc) }
|
||||||
scope :for_all, lambda { where(:is_for_all => true) }
|
scope :for_all, lambda { where(:is_for_all => true) }
|
||||||
|
scope :active, lambda { where(:active => true) }
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def import_from_xml(xml)
|
def import_from_xml(xml)
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<p><%= f.text_area :description, :cols => 40, :rows => 5 %></p>
|
<p><%= f.text_area :description, :cols => 40, :rows => 5 %></p>
|
||||||
<p><%= f.check_box :is_for_all, :onclick => "checkAndDisable('custom_workflow_enabled_projects', this.checked);", :label => :field_enabled_for_all_projects %></p>
|
<p><%= f.check_box :is_for_all, :onclick => "checkAndDisable('custom_workflow_enabled_projects', this.checked);", :label => :field_enabled_for_all_projects %></p>
|
||||||
|
<p><%= f.check_box :active, :label => :field_custom_workflow_active %></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<% @workflows.each do |workflow| %>
|
<% @workflows.each do |workflow| %>
|
||||||
<tr class="<%= cycle("odd", "even") %>">
|
<tr class="<%= cycle("odd", "even") %> <%= 'disabled' unless workflow.active? %>">
|
||||||
<td class="name"><%= link_to(workflow.name, edit_custom_workflow_path(workflow)) %></td>
|
<td class="name"><%= link_to(workflow.name, edit_custom_workflow_path(workflow)) %></td>
|
||||||
<td class="description"><%= textilizable(workflow.description) %></td>
|
<td class="description"><%= textilizable(workflow.description) %></td>
|
||||||
<td class="author"><%= mail_to workflow.author if workflow.author.present? %></td>
|
<td class="author"><%= mail_to workflow.author if workflow.author.present? %></td>
|
||||||
@ -36,6 +36,11 @@
|
|||||||
</td>
|
</td>
|
||||||
<td align="center"><%= reorder_links("custom_workflow", {:action => 'update', :id => workflow}) %></td>
|
<td align="center"><%= reorder_links("custom_workflow", {:action => 'update', :id => workflow}) %></td>
|
||||||
<td class="buttons">
|
<td class="buttons">
|
||||||
|
<% if workflow.active? %>
|
||||||
|
<%= link_to(l(:button_custom_workflow_deactivate), custom_workflow_status_path(workflow, :active => false), :class => 'icon icon-inactive', :method => :post) %>
|
||||||
|
<% else %>
|
||||||
|
<%= link_to(l(:button_custom_workflow_activate), custom_workflow_status_path(workflow, :active => true), :class => 'icon icon-active', :method => :post) %>
|
||||||
|
<% end %>
|
||||||
<%= link_to(l(:label_custom_workflow_export), export_custom_workflow_path(workflow), :class => 'icon icon-export', :method => :get) %>
|
<%= link_to(l(:label_custom_workflow_export), export_custom_workflow_path(workflow), :class => 'icon icon-export', :method => :get) %>
|
||||||
<%= link_to(l(:button_delete), workflow, :class => 'icon icon-del', :data => {:confirm => l(:text_are_you_sure)}, :confirm => l(:text_are_you_sure), :method => :delete) %>
|
<%= link_to(l(:button_delete), workflow, :class => 'icon icon-del', :data => {:confirm => l(:text_are_you_sure)}, :confirm => l(:text_are_you_sure), :method => :delete) %>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@ -6,8 +6,17 @@
|
|||||||
<% if CustomWorkflow.exists? %>
|
<% if CustomWorkflow.exists? %>
|
||||||
<dl>
|
<dl>
|
||||||
<% CustomWorkflow.all.each do |w| %>
|
<% CustomWorkflow.all.each do |w| %>
|
||||||
<dt><label><%= check_box_tag 'project[custom_workflow_ids][]', w.id, @project.custom_workflow_ids.include?(w.id) || w.is_for_all?, :disabled => w.is_for_all? %> <%= w.name %></label></dt>
|
<dt class="<%= 'disabled' unless w.active? %>">
|
||||||
<dd><em><%= textilizable(w.description) %></em></dd>
|
<label>
|
||||||
|
<%= check_box_tag 'project[custom_workflow_ids][]', w.id, @project.custom_workflow_ids.include?(w.id) || w.is_for_all?, :disabled => w.is_for_all? %> <%= w.name %>
|
||||||
|
<% if !w.active? %>
|
||||||
|
(<%= l(:text_custom_workflow_disabled) %>)
|
||||||
|
<% elsif w.is_for_all? %>
|
||||||
|
(<%= l(:text_custom_workflow_is_for_all) %>)
|
||||||
|
<% end %>
|
||||||
|
</label>
|
||||||
|
</dt>
|
||||||
|
<dd class="<%= 'disabled' unless w.active? %>"><em><%= textilizable(w.description) %></em></dd>
|
||||||
<% end %>
|
<% end %>
|
||||||
</dl>
|
</dl>
|
||||||
<% else %>
|
<% else %>
|
||||||
|
|||||||
BIN
assets/images/active.png
Normal file
BIN
assets/images/active.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 316 B |
BIN
assets/images/inactive.png
Normal file
BIN
assets/images/inactive.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 330 B |
@ -2,6 +2,10 @@
|
|||||||
background-image: url(../../../images/ticket_go.png);
|
background-image: url(../../../images/ticket_go.png);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#tab-content-custom_workflows .disabled {
|
||||||
|
color: silver;
|
||||||
|
}
|
||||||
|
|
||||||
table.list.custom-workflows td {
|
table.list.custom-workflows td {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
@ -10,6 +14,10 @@ table.list.custom-workflows td.description {
|
|||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table.list.custom-workflows tr.disabled {
|
||||||
|
color: silver;
|
||||||
|
}
|
||||||
|
|
||||||
#custom_workflow_description, #custom_workflow_name {
|
#custom_workflow_description, #custom_workflow_name {
|
||||||
width: 98%;
|
width: 98%;
|
||||||
}
|
}
|
||||||
@ -26,3 +34,5 @@ table.list.custom-workflows td.description {
|
|||||||
|
|
||||||
.icon-export { background-image: url(../images/export.png); }
|
.icon-export { background-image: url(../images/export.png); }
|
||||||
.icon-import { background-image: url(../images/import.png); }
|
.icon-import { background-image: url(../images/import.png); }
|
||||||
|
.icon-active { background-image: url(../images/active.png); }
|
||||||
|
.icon-inactive { background-image: url(../images/inactive.png); }
|
||||||
|
|||||||
@ -11,6 +11,8 @@ en:
|
|||||||
label_custom_workflow_import: "Import workflow"
|
label_custom_workflow_import: "Import workflow"
|
||||||
|
|
||||||
button_import: "Import"
|
button_import: "Import"
|
||||||
|
button_custom_workflow_activate: "Activate"
|
||||||
|
button_custom_workflow_deactivate: "Deactivate"
|
||||||
|
|
||||||
field_after_save: "Workflow script executable after saving the issue"
|
field_after_save: "Workflow script executable after saving the issue"
|
||||||
field_before_save: "Workflow script executable before saving the issue"
|
field_before_save: "Workflow script executable before saving the issue"
|
||||||
@ -18,10 +20,12 @@ en:
|
|||||||
field_enabled_for_all_projects: "Enabled for all projects"
|
field_enabled_for_all_projects: "Enabled for all projects"
|
||||||
field_custom_workflow_author: "Author's e-mail"
|
field_custom_workflow_author: "Author's e-mail"
|
||||||
field_custom_workflow_file: "Select the XML file previously exported process"
|
field_custom_workflow_file: "Select the XML file previously exported process"
|
||||||
|
field_custom_workflow_active: "Active"
|
||||||
field_custom_workflow:
|
field_custom_workflow:
|
||||||
script: "Workflow script"
|
script: "Workflow script"
|
||||||
|
|
||||||
notice_successful_import: "Custom workflow has successfully imported"
|
notice_successful_import: "Custom workflow has successfully imported"
|
||||||
|
notice_successful_status_change: "Status has successfully changed"
|
||||||
error_failed_import: "Error importing custom workflow (unknown format? please see log)"
|
error_failed_import: "Error importing custom workflow (unknown format? please see log)"
|
||||||
|
|
||||||
activerecord:
|
activerecord:
|
||||||
@ -37,3 +41,5 @@ en:
|
|||||||
text_custom_workflow_general_note: Both scripts are executed in the context of the issue like ordinary before_save and after_save callbacks. So use methods and properties of the issue directly (or through "self"). Instance variables (@variable) are also allowed and may be used if needed.
|
text_custom_workflow_general_note: Both scripts are executed in the context of the issue like ordinary before_save and after_save callbacks. So use methods and properties of the issue directly (or through "self"). Instance variables (@variable) are also allowed and may be used if needed.
|
||||||
text_no_enabled_projects: No projects
|
text_no_enabled_projects: No projects
|
||||||
text_custom_workflow_author: Will be included in exported XML
|
text_custom_workflow_author: Will be included in exported XML
|
||||||
|
text_custom_workflow_disabled: disabled by admin
|
||||||
|
text_custom_workflow_is_for_all: enabled for all projects
|
||||||
@ -11,6 +11,8 @@ ru:
|
|||||||
label_custom_workflow_import: "Импорт процесса"
|
label_custom_workflow_import: "Импорт процесса"
|
||||||
|
|
||||||
button_import: "Импортировать"
|
button_import: "Импортировать"
|
||||||
|
button_custom_workflow_activate: "Активировать"
|
||||||
|
button_custom_workflow_deactivate: "Деактивировать"
|
||||||
|
|
||||||
field_after_save: "Сценарий выполняемый после сохранения задачи"
|
field_after_save: "Сценарий выполняемый после сохранения задачи"
|
||||||
field_before_save: "Сценарий выполняемый перед сохранением задачи"
|
field_before_save: "Сценарий выполняемый перед сохранением задачи"
|
||||||
@ -18,10 +20,12 @@ ru:
|
|||||||
field_enabled_for_all_projects: "Разрешен для всех проектов"
|
field_enabled_for_all_projects: "Разрешен для всех проектов"
|
||||||
field_custom_workflow_author: "E-Mail адрес автора"
|
field_custom_workflow_author: "E-Mail адрес автора"
|
||||||
field_custom_workflow_file: "Выберите XML файл ранее экспортированного процесса"
|
field_custom_workflow_file: "Выберите XML файл ранее экспортированного процесса"
|
||||||
|
field_custom_workflow_active: "Активен"
|
||||||
field_custom_workflow:
|
field_custom_workflow:
|
||||||
script: "Сценарий"
|
script: "Сценарий"
|
||||||
|
|
||||||
notice_successful_import: "Рабочий процесс успешно импортирован"
|
notice_successful_import: "Рабочий процесс успешно импортирован"
|
||||||
|
notice_successful_status_change: "Статус успешно изменен"
|
||||||
error_failed_import: "Ошибка импорта рабочего процесса (неверный формат? смотри журнал)"
|
error_failed_import: "Ошибка импорта рабочего процесса (неверный формат? смотри журнал)"
|
||||||
|
|
||||||
activerecord:
|
activerecord:
|
||||||
@ -37,3 +41,5 @@ ru:
|
|||||||
text_custom_workflow_general_note: Оба сценария исполняются в контексте задачи, как и обычные обратные вызовы before_save и after_save. Поэтому используйте методы и свойства задачи напрямую или через ключевое слово self.
|
text_custom_workflow_general_note: Оба сценария исполняются в контексте задачи, как и обычные обратные вызовы before_save и after_save. Поэтому используйте методы и свойства задачи напрямую или через ключевое слово self.
|
||||||
text_no_enabled_projects: Нет проектов
|
text_no_enabled_projects: Нет проектов
|
||||||
text_custom_workflow_author: Будет использован в XML файле при экспорте
|
text_custom_workflow_author: Будет использован в XML файле при экспорте
|
||||||
|
text_custom_workflow_disabled: отключен администратором
|
||||||
|
text_custom_workflow_is_for_all: разрешен для всех проектов
|
||||||
@ -3,4 +3,5 @@ RedmineApp::Application.routes.draw do
|
|||||||
resources :custom_workflows
|
resources :custom_workflows
|
||||||
post '/custom_workflows/:id', :to => 'custom_workflows#update'
|
post '/custom_workflows/:id', :to => 'custom_workflows#update'
|
||||||
get '/custom_workflows/:id/export', :to => 'custom_workflows#export', :as => 'export_custom_workflow'
|
get '/custom_workflows/:id/export', :to => 'custom_workflows#export', :as => 'export_custom_workflow'
|
||||||
|
post '/custom_workflows/:id/change_status', :to => 'custom_workflows#change_status', :as => 'custom_workflow_status'
|
||||||
end
|
end
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
class AddActiveFieldToCustomWorkflows < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :custom_workflows, :active, :boolean, :null => false, :default => true
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -13,7 +13,7 @@ module RedmineCustomWorkflows
|
|||||||
|
|
||||||
module InstanceMethods
|
module InstanceMethods
|
||||||
def enabled_custom_workflows
|
def enabled_custom_workflows
|
||||||
(CustomWorkflow.for_all + custom_workflows).uniq.sort
|
(CustomWorkflow.for_all + custom_workflows).select { |w| w.active? }.uniq.sort
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user