Unit tests

This commit is contained in:
Karel Pičman 2018-12-20 14:34:00 +01:00
parent 70ac21518d
commit e76c3a7de7
67 changed files with 2014 additions and 664 deletions

80
CHANGELOG.md Normal file
View File

@ -0,0 +1,80 @@
Changelog for Custom Workflows
==========================
1.0.0
-----
Redmine 4.0 compatibility
0.1.6
-----
* New observable objects added (TimeEntry, Version)
* Bug fixes
0.1.5
-----
* New observable objects added (Project, Wiki Content, Attachment, Issue Attachments, Project Attachments, Wiki Page Attachments)
* Ability to hook before_destroy and after_destroy events
0.1.4
-----
* Ability to exit current workflow with `return` or `return true` and cancel workflow's execution chain with `return false`
* Non-active workflows are now not checked for syntax. Now you can import non-valid (for your Redmine instance for example) workflow, make changes to it and then activate.
0.1.3
-----
* Compatibility with Redmine 2.x.x returned, support of Redmine 1.x.x cancelled
0.1.2
-----
* Added new observable objects. Along with Issue objects you can now watch for changes in User and Group objects
* Added support of shared workflows - special workflows that running before all other workflows and can provide functions and classes for it
* Added Mailer helper for sending custom emails from workflows (check Wiki)
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.0.6
-----
* Import/export ability
0.0.5
-----
* Compatibility with latest versions of Redmine 2.x.x
0.0.4
-----
* Added ability to enable workflows globally for all projects. No need to enable 'Custom workflows' project module anymore. Just go to the 'Administration' -> 'Custom workflows' section and enable or disable your workflows in one place.
* Fixed bug with 'Status transition prohibited' when updating the issue status by the repository commit
0.0.3
-----
* Compatibility with 1.2.x, 1.3.x
0.0.2
-----
* Added ability to define after_save script along with before_save, improved logging, changed context of executing script to the issue.
0.0.1
-----
* Initial commit

46
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at karel.picman@kontron.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

14
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,14 @@
## How to contribute to Redmine Custom Workflows plugin
#### **Did you find a bug?**
* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/anteo/redmine_custom_workflows/issues).
* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/anteo/redmine_custom_workflows/issues/new). Be sure to include a **title and clear description**, as much relevant information as possible, **Redmine and the plugin version**, a part of the **production.log** related to the issue and **screen-shots**.
#### **A wrong or missing translation?**
* Feel free to update language files (_config/locales/*.yml_) in your mother language or languages you are familiar with and send them back to us via a **pull request**.
#### **Do you want to patch the existing code?**
* Make a new fork of the current development branch (_devel-x.x.x_). Make your changes and [create a pull request](https://github.com/anteo/redmine_custom_workflows/compare). Only pull requests into the **development branch** except those fixing serious errors will be accepted.

21
Gemfile
View File

@ -1,3 +1,24 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
source 'https://rubygems.org'
require 'rails'

View File

@ -1,4 +1,7 @@
= Custom Workflows plug-in
Custom Workflows plug-in
========================
The current version of Redmine CustomWorkflows is **1.0.0** [![Build Status](https://api.travis-ci.org/anteo/redmine_custom_workflows.png)](https://travis-ci.org/anteo/redmine_custom_workflows)
This plug-in provides a great functionality for those who is familiar with the Ruby language.
It allows to customize workflow by defining own rules for issues processing. It's possible:
@ -12,17 +15,19 @@ Starting with version 0.1.2 you can specify observable object for workflow. Supp
* Group (before_save, after_save)
* User (before_save, after_save)
* Group users (before_add, after_add, before_remove, after_remove)
* <Shared code>
* \<Shared code\>
<Shared code> - special type for workflows that running before all other workflows and can provide libraries of additional functions or classes.
\<Shared code\> - special type for workflows that running before all other workflows and can provide libraries of additional functions or classes.
== Thanks to
Thanks to
---------
Plugin development is supported by DOM Digital Online Media GmbH
http://www.dom.de
== Getting help
Getting help
------------
Create an issue if you want to propose a feature or report a bug:
@ -32,7 +37,8 @@ Check Wiki for examples and programming hints:
https://github.com/anteo/redmine_custom_workflows/wiki
== Installation
Installation
------------
From a ZIP file:
@ -48,7 +54,8 @@ After download:
* Run <b>rake redmine:plugins:migrate</b>
* Restart Redmine
== Configuration
Configuration
-------------
First, you need to define your own custom workflow(s). We already included one, called "Duration/Done Ratio/Status correlation". You'll find it after installing the plug-in. It demonstrates some possibilities of plug-in.
@ -58,7 +65,8 @@ Then click the <b>Create a custom workflow</b> button. Enter a short name and fu
Both scripts are executed in the context of the issue. So access properties and methods of the issue directly (or through keyword "self"). You can also raise exceptions by <b>raise WorkflowError, "Your message"</b>. If you change some properties of the issue before saving it, it will be revalidated then and additional validation errors can appear.
== Enabling workflows for projects
Enabling custom workflows for projects
-------------------------------
After you defined your custom workflow(s), you need to enable it for particular project(s). There are two ways of doing this.
* While editing existing or creating new custom workflow;
@ -66,75 +74,57 @@ After you defined your custom workflow(s), you need to enable it for particular
Now go to the *Issues* and test it.
== Duration/Done Ratio/Status correlation example
Duration/Done Ratio/Status correlation example
----------------------------------------------
Fill the "before save" script with:
if done_ratio_changed?
if done_ratio==100 && status_id==2
self.status_id=3
elsif [1,3,4].include?(status_id) && done_ratio<100
self.status_id=2
if done_ratio_changed?
if done_ratio==100 && status_id==2
self.status_id=3
elsif [1,3,4].include?(status_id) && done_ratio<100
self.status_id=2
end
end
end
if status_id_changed?
if status_id==2
self.start_date ||= Time.now
if status_id_changed?
if status_id==2
self.start_date ||= Time.now
end
if status_id==3
self.done_ratio = 100
self.start_date ||= created_on
self.due_date ||= Time.now
end
end
if status_id==3
self.done_ratio = 100
self.start_date ||= created_on
self.due_date ||= Time.now
end
end
== Example of creating subtask if the issue's status has changed.
Example of creating subtask if the issue's status has changed
-------------------------------------------------------------
Fill the "before save" script with:
@need_create = status_id_changed? && !new_record?
@need_create = status_id_changed? && !new_record?
Fill the "after save" script with:
if @need_create
issue = Issue.new(
:author => User.current,
:project => project,
:tracker => tracker,
:assigned_to => author,
:parent_issue_id => id,
:subject => "Subtask",
:description => "Description")
if @need_create
issue = Issue.new(
:author => User.current,
:project => project,
:tracker => tracker,
:assigned_to => author,
:parent_issue_id => id,
:subject => "Subtask",
:description => "Description")
issue.save!
end
issue.save!
end
Do not forget to check whether issue is just created. Here we create the new issue and newly created issue will also be passed to this script on save. So without check, it will create another sub-issue. And etc. Thus it will fall into infinite recursion.
== Compatibility
Compatibility
-------------
This plug-in is compatible with Redmine 2.x.x, 3.x.x
This plug-in is compatible with Redmine 3.4.x and 4.x.x
== Changelog
[0.1.6] * New observable objects added (TimeEntry, Version)
* Bug fixes
[0.1.5] * New observable objects added (Project, Wiki Content, Attachment, Issue Attachments, Project Attachments, Wiki Page Attachments)
* Ability to hook before_destroy and after_destroy events
[0.1.4] * Ability to exit current workflow with `return` or `return true` and cancel workflow's execution chain with `return false`
* Non-active workflows are now not checked for syntax. Now you can import non-valid (for your Redmine instance for example) workflow, make changes to it and then activate.
[0.1.3] Compatibility with Redmine 2.x.x returned, support of Redmine 1.x.x cancelled
[0.1.2] * Added new observable objects. Along with Issue objects you can now watch for changes in User and Group objects
* Added support of shared workflows - special workflows that running before all other workflows and can provide functions and classes for it
* Added Mailer helper for sending custom emails from workflows (check Wiki)
[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.0.6] Import/export ability
[0.0.5] Compatibility with latest versions of Redmine 2.x.x
[0.0.4] * Added ability to enable workflows globally for all projects. No need to enable 'Custom workflows' project module anymore. Just go to the 'Administration' -> 'Custom workflows' section and enable or disable your workflows in one place.
* Fixed bug with 'Status transition prohibited' when updating the issue status by the repository commit
[0.0.3] Compatibility with 1.2.x, 1.3.x
[0.0.2] Added ability to define after_save script along with before_save, improved logging, changed context of executing script to the issue.
[0.0.1] Initial commit

View File

@ -1,3 +1,24 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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 CustomWorkflowsController < ApplicationController
layout 'admin'
@ -64,11 +85,11 @@ class CustomWorkflowsController < ApplicationController
if @workflow.save
flash[:notice] = l(:notice_successful_import)
else
flash[:error] = @workflow.errors.full_messages.to_sentence
flash[:errors] = @workflow.errors.full_messages.to_sentence
end
rescue Exception => e
Rails.logger.warn "Workflow import error: #{e.message}\n #{e.backtrace.join("\n ")}"
flash[:error] = l(:error_failed_import)
flash[:errors] = l(:error_failed_import)
end
respond_to do |format|
format.html { redirect_to(custom_workflows_path) }
@ -82,7 +103,7 @@ class CustomWorkflowsController < ApplicationController
@workflow.name = params[:custom_workflow][:name]
@workflow.description = params[:custom_workflow][:description]
@workflow.position = CustomWorkflow.count + 1
@workflow.is_for_all = params[:custom_workflow][:is_for_all].present?
@workflow.is_for_all = params[:custom_workflow][:is_for_all] == '1'
@workflow.author = params[:custom_workflow][:author]
@workflow.active = params[:custom_workflow][:active]
@workflow.observable = params[:custom_workflow][:observable]
@ -93,6 +114,7 @@ class CustomWorkflowsController < ApplicationController
@workflow.after_remove = params[:custom_workflow][:after_remove]
@workflow.before_destroy = params[:custom_workflow][:before_destroy]
@workflow.after_destroy = params[:custom_workflow][:after_destroy]
@workflow.project_ids = params[:custom_workflow][:project_ids]
respond_to do |format|
if params.has_key?(:commit) && @workflow.save
flash[:notice] = l(:notice_successful_create)
@ -121,7 +143,7 @@ class CustomWorkflowsController < ApplicationController
@workflow.after_save = params[:custom_workflow][:after_save]
@workflow.name = params[:custom_workflow][:name]
@workflow.description = params[:custom_workflow][:description]
@workflow.is_for_all = params[:custom_workflow][:is_for_all].present?
@workflow.is_for_all = params[:custom_workflow][:is_for_all] == '1'
@workflow.author = params[:custom_workflow][:author]
@workflow.active = params[:custom_workflow][:active]
@workflow.shared_code = params[:custom_workflow][:shared_code]
@ -131,6 +153,7 @@ class CustomWorkflowsController < ApplicationController
@workflow.after_remove = params[:custom_workflow][:after_remove]
@workflow.before_destroy = params[:custom_workflow][:before_destroy]
@workflow.after_destroy = params[:custom_workflow][:after_destroy]
@workflow.project_ids = params[:custom_workflow][:project_ids]
if params.has_key?(:commit) && @workflow.save
flash[:notice] = l(:notice_successful_update)
format.html { redirect_to(custom_workflows_path) }

View File

@ -1,11 +1,23 @@
class WorkflowError < StandardError
attr_accessor :error
def initialize(message)
@error = message.dup
super message
end
end
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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 CustomWorkflow < ActiveRecord::Base
OBSERVABLES = [:issue, :issue_attachments, :user, :attachment, :group, :group_users, :project, :project_attachments,
@ -37,50 +49,48 @@ class CustomWorkflow < ActiveRecord::Base
end)
scope :observing, lambda { |observable| where(:observable => observable) }
class << self
def import_from_xml(xml)
attributes = Hash.from_xml(xml).values.first
attributes.delete('exported_at')
attributes.delete('plugin_version')
attributes.delete('ruby_version')
attributes.delete('rails_version')
CustomWorkflow.new(attributes)
end
def self.import_from_xml(xml)
attributes = Hash.from_xml(xml).values.first
attributes.delete('exported_at')
attributes.delete('plugin_version')
attributes.delete('ruby_version')
attributes.delete('rails_version')
CustomWorkflow.new(attributes)
end
def log_message(str, object)
Rails.logger.info str + " for #{object.class} (\##{object.id}) \"#{object}\""
end
def self.log_message(str, object)
Rails.logger.info str + " for #{object.class} (\##{object.id}) \"#{object}\""
end
def run_shared_code(object)
workflows = CustomWorkflow.observing(:shared).active
log_message '= Running shared code', object
workflows.each do |workflow|
unless workflow.run(object, :shared_code)
log_message '= Abort running shared code', object
return false
end
def self.run_shared_code(object)
workflows = CustomWorkflow.observing(:shared).active
log_message '= Running shared code', object
workflows.each do |workflow|
unless workflow.run(object, :shared_code)
log_message '= Abort running shared code', object
return false
end
log_message '= Finished running shared code', object
true
end
log_message '= Finished running shared code', object
true
end
def run_custom_workflows(observable, object, event)
workflows = CustomWorkflow.active.observing(observable)
if PROJECT_OBSERVABLES.include? observable
return true unless object.project
workflows = workflows.for_project(object.project)
end
return true unless workflows.any?
log_message "= Running #{event} custom workflows", object
workflows.each do |workflow|
unless workflow.run(object, event)
log_message "= Abort running #{event} custom workflows", object
return false
end
end
log_message "= Finished running #{event} custom workflows", object
true
def self.run_custom_workflows(observable, object, event)
workflows = CustomWorkflow.active.observing(observable)
if PROJECT_OBSERVABLES.include? observable
return true unless object.project
workflows = workflows.for_project(object.project)
end
return true unless workflows.any?
log_message "= Running #{event} custom workflows", object
workflows.each do |workflow|
unless workflow.run(object, event)
log_message "= Abort running #{event} custom workflows", object
return false
end
end
log_message "= Finished running #{event} custom workflows", object
true
end
def run(object, event)
@ -106,7 +116,7 @@ class CustomWorkflow < ActiveRecord::Base
object.instance_eval(read_attribute(event)) if respond_to?(event) && read_attribute(event)
rescue WorkflowError => _
rescue Exception => e
errors.add event, :invalid_script, :error => e
errors.add event, :invalid_script, :errors => e
end
def validate_scripts_presence

View File

@ -11,23 +11,31 @@
:disabled => !@workflow.new_record? %></p>
<p><%= f.text_area :description, cols: 40, rows: 5 , class: 'wiki-edit' %></p>
<% if @workflow.has_projects_association? %>
<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>
<% end %>
<p><%= f.check_box :active, :label => :field_custom_workflow_active %></p>
</div>
</div>
<% if @workflow.has_projects_association? %>
<div class="splitcontentright">
<fieldset class="box" id="custom_workflow_enabled_projects">
<legend><%= l(:label_enabled_projects) %></legend>
<%= custom_workflows_render_nested_projects(Project.visible.active) do |p|
content_tag('label', check_box_tag('custom_workflow[project_ids][]', p.id, @workflow.project_ids.include?(p.id) || @workflow.is_for_all?,
:id => nil, :disabled => @workflow.is_for_all?) + ' ' + h(p), :class => 'block')
end %>
<%= hidden_field_tag('custom_workflow[project_ids][]', '', :id => nil) %>
<p><%= check_all_links 'custom_workflow_enabled_projects' %></p>
</fieldset>
<div class="box tabular">
<%= content_tag 'fieldset', id: 'custom_workflow_enabled_projects' do %>
<legend>
<%= toggle_checkboxes_link("#custom_workflow_enabled_projects input[type=checkbox]") %>
<%= l(:label_project_plural) %>
</legend>
<%= render_project_nested_lists(Project.visible.active) do |p| %>
<%= content_tag('label',
check_box_tag('custom_workflow[project_ids][]', p.id,
@workflow.project_ids.include?(p.id) || @workflow.is_for_all?, id: nil,
:disabled => @workflow.is_for_all?) + ' ' + h(p), class: 'block') %>
<% end %>
<%= hidden_field_tag('custom_workflow[project_ids][]', '', id: nil) %>
<% end %>
</div>
</div>
<% end %>
</div>
@ -111,18 +119,11 @@
</fieldset>
<script>
jQuery('.custom_workflow_script').taboverride(2, true);
function checkAndDisable(id, checked) {
if (checked) {
jQuery('#' + id).find('input[type=checkbox]').attr('checked', true).attr('disabled', true);
} else {
jQuery('#' + id).find('input[type=checkbox]').removeAttr('checked').removeAttr('disabled');
}
}
$('.custom_workflow_script').taboverride(2, true);
</script>
<%= wikitoolbar_for :custom_workflow_description %>
<% content_for :header_tags do %>
<%= javascript_include_tag "tab_override", :plugin => 'redmine_custom_workflows' %>
<%= javascript_include_tag 'tab_override', plugin: 'redmine_custom_workflows' %>
<% end %>

View File

@ -1,3 +1,25 @@
/* encoding: utf-8
*
* Redmine plugin for Custom Workflows
*
* Copyright Anton Argirov
* Copyright 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.
*/
(function($) {
$.fn.taboverride = function(tabSize, autoIndent) {
this.each(function() {
@ -321,3 +343,11 @@
};
})(jQuery);
function checkAndDisable(id, checked) {
if (checked) {
$('#' + id).find('input[type=checkbox]').attr('checked', true).attr('disabled', true);
} else {
$('#' + id).find('input[type=checkbox]').removeAttr('checked').removeAttr('disabled');
}
}

View File

@ -1,3 +1,24 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
cs:
project_module_custom_workflows_module: Uživatelské procesy
permission_manage_project_workflow: Spravovat uživatelské procesy

View File

@ -1,3 +1,24 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
en:
project_module_custom_workflows_module: "Custom workflows"
permission_manage_project_workflow: "Manage project custom workflows"

View File

@ -1,3 +1,24 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
pt-br:
project_module_custom_workflows_module: "Fluxo de Trabalho Personalizado"
permission_manage_project_workflow: "Gerenciar fluxos de trabalho personalizados de projeto"

View File

@ -1,3 +1,24 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
ru:
project_module_custom_workflows_module: "Пользовательские рабочие процессы"
permission_manage_project_workflow: "Управление пользовательскими рабочими процессами в проекте"

View File

@ -1,6 +1,33 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
RedmineApp::Application.routes.draw do
resources :custom_workflows do
member do
end
end
post '/custom_workflows/import', :to => 'custom_workflows#import', :as => 'import_custom_workflow'
resources :custom_workflows
post '/custom_workflows/:id', :to => 'custom_workflows#update'
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'

View File

@ -1,4 +1,26 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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 CreateCustomWorkflows < ActiveRecord::Migration[4.2]
def change
create_table :custom_workflows, :force => true do |t|
t.references :project

View File

@ -1,4 +1,26 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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 AlterCustomWorkflows < ActiveRecord::Migration[4.2]
def self.up
remove_column :custom_workflows, :project_id
remove_column :custom_workflows, :is_enabled

View File

@ -1,4 +1,26 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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 CreateCustomWorkflowsProjects < ActiveRecord::Migration[4.2]
def change
create_table :custom_workflows_projects, :force => true, :id => false do |t|
t.references :project

View File

@ -1,3 +1,24 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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 ChangeCustomWorkflowsDescriptionType < ActiveRecord::Migration[4.2]
def self.up
change_column :custom_workflows, :description, :text, :null => true, :default => nil

View File

@ -1,11 +1,35 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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 AddAfterSaveToCustomWorkflows < ActiveRecord::Migration[4.2]
def self.up
def up
rename_column :custom_workflows, :script, :before_save
change_column :custom_workflows, :before_save, :text, :null => true
add_column :custom_workflows, :after_save, :text, :null => true, :after => :before_save
end
def self.down
def down
remove_column :custom_workflows, :after_save
rename_column :custom_workflows, :before_save, :script
end
end

View File

@ -1,5 +1,28 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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 AddIsForAllToCustomWorkflows < ActiveRecord::Migration[4.2]
def change
add_column :custom_workflows, :is_for_all, :boolean, :null => false, :default => false
end
end

View File

@ -1,6 +1,29 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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 MakeAfterSaveAndBeforeSaveNullable < ActiveRecord::Migration[4.2]
def up
change_column :custom_workflows, :before_save, :text, :null => true, :default => nil
change_column :custom_workflows, :after_save, :text, :null => true, :default => nil
end
end

View File

@ -1,5 +1,28 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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 SetPositionFieldNullable < ActiveRecord::Migration[4.2]
def up
change_column :custom_workflows, :position, :integer, :null => true
end
end

View File

@ -1,6 +1,29 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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 AddAuthorAndTimestampsToCustomWorkflows < ActiveRecord::Migration[4.2]
def change
add_column :custom_workflows, :author, :string, :null => true
add_timestamps :custom_workflows
end
end

View File

@ -1,5 +1,27 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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 CreateExampleWorkflow < ActiveRecord::Migration[4.2]
def self.up
def up
CustomWorkflow.reset_column_information
old = CustomWorkflow.where(:name => 'Duration/Done Ratio/Status correlation').first
old.destroy if old
@ -34,4 +56,5 @@ if @issue.status_id_changed?
end
EOS
end
end

View File

@ -1,5 +1,28 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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 AddActiveFieldToCustomWorkflows < ActiveRecord::Migration[4.2]
def change
add_column :custom_workflows, :active, :boolean, :null => false, :default => true
end
end

View File

@ -1,5 +1,28 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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 AddObservableFieldToCustomWorkflows < ActiveRecord::Migration[4.2]
def change
add_column :custom_workflows, :observable, :string, :null => false, :default => 'issue'
end
end

View File

@ -1,4 +1,26 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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 AddAdditionalScriptFieldsToCustomWorkflows < ActiveRecord::Migration[4.2]
def change
add_column :custom_workflows, :shared_code, :text, :null => true
add_column :custom_workflows, :before_add, :text, :null => true
@ -6,4 +28,5 @@ class AddAdditionalScriptFieldsToCustomWorkflows < ActiveRecord::Migration[4.2]
add_column :custom_workflows, :before_remove, :text, :null => true
add_column :custom_workflows, :after_remove, :text, :null => true
end
end

View File

@ -1,6 +1,29 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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 AddBeforeAndAfterDestroyToCustomWorkflows < ActiveRecord::Migration[4.2]
def change
add_column :custom_workflows, :before_destroy, :text, :null => true
add_column :custom_workflows, :after_destroy, :text, :null => true
end
end

67
init.rb
View File

@ -1,3 +1,24 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
require 'redmine'
Redmine::Plugin.register :redmine_custom_workflows do
@ -9,49 +30,13 @@ Redmine::Plugin.register :redmine_custom_workflows do
requires_redmine version_or_higher: '3.0.0'
menu :admin_menu, :custom_workflows, {:controller => 'custom_workflows', :action => 'index'},
:if => Proc.new { User.current.admin? }, :caption => :label_custom_workflow_plural,
:html => {:class => 'icon icon-workflows'}
permission :manage_project_workflow, {}, :require => :member
end
require 'redmine_custom_workflows/hooks'
require_dependency File.dirname(__FILE__) + '/lib/redmine_custom_workflows.rb'
require File.dirname(__FILE__) + '/lib/redmine_custom_workflows/projects_helper_patch'
Rails.application.config.to_prepare do
unless Project.include?(RedmineCustomWorkflows::ProjectPatch)
Project.send(:include, RedmineCustomWorkflows::ProjectPatch)
end
unless Attachment.include?(RedmineCustomWorkflows::AttachmentPatch)
Attachment.send(:include, RedmineCustomWorkflows::AttachmentPatch)
end
unless Issue.include?(RedmineCustomWorkflows::IssuePatch)
Issue.send(:include, RedmineCustomWorkflows::IssuePatch)
end
unless User.include?(RedmineCustomWorkflows::UserPatch)
User.send(:include, RedmineCustomWorkflows::UserPatch)
end
unless Group.include?(RedmineCustomWorkflows::GroupPatch)
Group.send(:include, RedmineCustomWorkflows::GroupPatch)
end
unless TimeEntry.include?(RedmineCustomWorkflows::TimeEntryPatch)
TimeEntry.send(:include, RedmineCustomWorkflows::TimeEntryPatch)
end
unless Version.include?(RedmineCustomWorkflows::VersionPatch)
Version.send(:include, RedmineCustomWorkflows::VersionPatch)
end
unless WikiContent.include?(RedmineCustomWorkflows::WikiContentPatch)
WikiContent.send(:include, RedmineCustomWorkflows::WikiContentPatch)
end
unless WikiPage.include?(RedmineCustomWorkflows::WikiPagePatch)
WikiPage.send(:include, RedmineCustomWorkflows::WikiPagePatch)
end
unless Mailer.include?(RedmineCustomWorkflows::MailerPatch)
Mailer.send(:include, RedmineCustomWorkflows::MailerPatch)
end
unless ActionView::Base.include?(RedmineCustomWorkflows::Helper)
ActionView::Base.send(:include, RedmineCustomWorkflows::Helper)
end
# Administration menu extension
Redmine::MenuManager.map :admin_menu do |menu|
menu.push :custom_workflows, { controller: 'custom_workflows', action: 'index'},
caption: :label_custom_workflow_plural, html: { class: 'icon icon-workflows'}
end

View File

@ -0,0 +1,39 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
# Hooks
require 'redmine_custom_workflows/hooks/hooks'
# Errors
require 'redmine_custom_workflows/errors/workflow_error'
# Patches
require 'redmine_custom_workflows/patches/attachment_patch'
require 'redmine_custom_workflows/patches/group_patch'
require 'redmine_custom_workflows/patches/issue_patch'
require 'redmine_custom_workflows/patches/mailer_patch'
require 'redmine_custom_workflows/patches/project_patch'
require 'redmine_custom_workflows/patches/projects_helper_patch'
require 'redmine_custom_workflows/patches/time_entry_patch'
require 'redmine_custom_workflows/patches/user_patch'
require 'redmine_custom_workflows/patches/version_patch'
require 'redmine_custom_workflows/patches/wiki_content_patch'
require 'redmine_custom_workflows/patches/wiki_page_patch'

View File

@ -1,38 +0,0 @@
module RedmineCustomWorkflows
module AttachmentPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
before_save :before_save_custom_workflows
after_save :after_save_custom_workflows
before_destroy :before_destroy_custom_workflows
after_destroy :after_destroy_custom_workflows
end
end
module InstanceMethods
def before_save_custom_workflows
@attachment = self
@saved_attributes = attributes.dup
CustomWorkflow.run_shared_code(self)
CustomWorkflow.run_custom_workflows(:attachment, self, :before_save)
errors.empty? && (@saved_attributes == attributes || valid?)
ensure
@saved_attributes = nil
end
def after_save_custom_workflows
CustomWorkflow.run_custom_workflows(:attachment, self, :after_save)
end
def before_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:attachment, self, :before_destroy)
end
def after_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:attachment, self, :after_destroy)
end
end
end
end

View File

@ -0,0 +1,29 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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 WorkflowError < StandardError
attr_accessor :error
def initialize(message)
@error = message.dup
super message
end
end

View File

@ -1,52 +0,0 @@
module RedmineCustomWorkflows
module GroupPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
before_save :before_save_custom_workflows
after_save :after_save_custom_workflows
before_destroy :before_destroy_custom_workflows
after_destroy :after_destroy_custom_workflows
def self.users_callback(event, group, user)
group.instance_variable_set(:@group, group)
group.instance_variable_set(:@user, user)
CustomWorkflow.run_shared_code(group) if event.to_s.starts_with? 'before_'
CustomWorkflow.run_custom_workflows(:group_users, group, event)
end
[:before_add, :before_remove, :after_add, :after_remove].each do |observable|
send("#{observable}_for_users") << if Rails::VERSION::MAJOR >= 4
lambda { |event, group, user| Group.users_callback(event, group, user) }
else
lambda { |group, user| Group.users_callback(observable, group, user) }
end
end
end if CustomWorkflow.table_exists?
end
module InstanceMethods
def before_save_custom_workflows
@group = self
@saved_attributes = attributes.dup
CustomWorkflow.run_shared_code(self)
CustomWorkflow.run_custom_workflows(:group, self, :before_save)
errors.empty? && (@saved_attributes == attributes || valid?)
ensure
@saved_attributes = nil
end
def after_save_custom_workflows
CustomWorkflow.run_custom_workflows(:group, self, :after_save)
end
def before_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:group, self, :before_destroy)
end
def after_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:group, self, :after_destroy)
end
end
end
end

View File

@ -1,37 +0,0 @@
module RedmineCustomWorkflows
module Helper
# Renders a tree of projects as a nested set of unordered lists
# The given collection may be a subset of the whole project tree
# (eg. some intermediate nodes are private and can not be seen)
def custom_workflows_render_nested_projects(projects)
s = ''
if projects.any?
ancestors = []
original_project = @project
projects.sort_by(&:lft).each do |project|
# set the project environment to please macros.
@project = project
if ancestors.empty? || project.is_descendant_of?(ancestors.last)
s << "<ul class='projects #{ ancestors.empty? ? 'root' : nil}'>\n"
else
ancestors.pop
s << '</li>'
while ancestors.any? && !project.is_descendant_of?(ancestors.last)
ancestors.pop
s << "</ul></li>\n"
end
end
classes = (ancestors.empty? ? 'root' : 'child')
s << "<li class='#{classes}'><div class='#{classes}'>"
s << h(block_given? ? yield(project) : project.name)
s << "</div>\n"
ancestors << project
end
s << ("</li></ul>\n" * ancestors.size)
@project = original_project
end
s.html_safe
end
end
end

View File

@ -1,7 +0,0 @@
module RedmineCustomWorkflows
class Hooks < Redmine::Hook::ViewListener
def view_layouts_base_html_head(context)
stylesheet_link_tag :style, :plugin => 'redmine_custom_workflows'
end
end
end

View File

@ -0,0 +1,30 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
module RedmineCustomWorkflows
class Hooks < Redmine::Hook::ViewListener
def view_layouts_base_html_head(context)
stylesheet_link_tag :style, :plugin => 'redmine_custom_workflows'
end
end
end

View File

@ -1,66 +0,0 @@
module RedmineCustomWorkflows
module IssuePatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
before_save :before_save_custom_workflows
after_save :after_save_custom_workflows
before_destroy :before_destroy_custom_workflows
after_destroy :after_destroy_custom_workflows
validate :validate_status
def self.attachments_callback(event, issue, attachment)
issue.instance_variable_set(:@issue, issue)
issue.instance_variable_set(:@attachment, attachment)
CustomWorkflow.run_shared_code(issue) if event.to_s.starts_with? 'before_'
CustomWorkflow.run_custom_workflows(:issue_attachments, issue, event)
end
[:before_add, :before_remove, :after_add, :after_remove].each do |observable|
send("#{observable}_for_attachments") << if Rails::VERSION::MAJOR >= 4
lambda { |event, issue, attachment| Issue.attachments_callback(event, issue, attachment) }
else
lambda { |issue, attachment| Issue.attachments_callback(observable, issue, attachment) }
end
end
end
end
module InstanceMethods
def validate_status
return true unless @saved_attributes && @saved_attributes['status_id'] != status_id &&
!new_statuses_allowed_to(User.current, new_record?).collect(&:id).include?(status_id)
status_was = IssueStatus.find_by_id(status_id_was)
status_new = IssueStatus.find_by_id(status_id)
errors.add :status, :new_status_invalid,
:old_status => status_was && status_was.name,
:new_status => status_new && status_new.name
end
def before_save_custom_workflows
@issue = self
@saved_attributes = attributes.dup
CustomWorkflow.run_shared_code(self)
CustomWorkflow.run_custom_workflows(:issue, self, :before_save)
errors.empty? && (@saved_attributes == attributes || valid?)
ensure
@saved_attributes = nil
end
def after_save_custom_workflows
CustomWorkflow.run_custom_workflows(:issue, self, :after_save)
end
def before_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:issue, self, :before_destroy)
end
def after_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:issue, self, :after_destroy)
end
end
end
end

View File

@ -1,35 +0,0 @@
module RedmineCustomWorkflows
module MailerPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
end
end
module InstanceMethods
def self.deliver_custom_email(headers={})
user = headers.delete :user
headers[:to] = user.mail if user
text_body = headers.delete :text_body
html_body = headers.delete :html_body
template_name = headers.delete :template_name
template_params = headers.delete(:template_params) || {}
if text_body || html_body
mail headers do |format|
format.text { render :text => text_body } if text_body
format.html { render :text => html_body } if html_body
end
elsif template_name
template_params.each { |k,v| instance_variable_set("@#{k}", v) }
mail headers do |format|
format.text { render template_name }
format.html { render template_name } unless Setting.plain_text_mail?
end
else
raise 'Not :text_body, :html_body or :template_name specified'
end
end
end
end
end

View File

@ -0,0 +1,68 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
module RedmineCustomWorkflows
module Patches
module AttachmentPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
before_save :before_save_custom_workflows
after_save :after_save_custom_workflows
before_destroy :before_destroy_custom_workflows
after_destroy :after_destroy_custom_workflows
end
end
module InstanceMethods
def before_save_custom_workflows
@attachment = self
@saved_attributes = attributes.dup
CustomWorkflow.run_shared_code(self)
CustomWorkflow.run_custom_workflows(:attachment, self, :before_save)
errors.empty? && (@saved_attributes == attributes || valid?)
ensure
@saved_attributes = nil
end
def after_save_custom_workflows
CustomWorkflow.run_custom_workflows(:attachment, self, :after_save)
end
def before_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:attachment, self, :before_destroy)
end
def after_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:attachment, self, :after_destroy)
end
end
end
end
end
unless Attachment.include?(RedmineCustomWorkflows::Patches::AttachmentPatch)
Attachment.send(:include, RedmineCustomWorkflows::Patches::AttachmentPatch)
end

View File

@ -0,0 +1,82 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
module RedmineCustomWorkflows
module Patches
module GroupPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
before_save :before_save_custom_workflows
after_save :after_save_custom_workflows
before_destroy :before_destroy_custom_workflows
after_destroy :after_destroy_custom_workflows
def self.users_callback(event, group, user)
group.instance_variable_set(:@group, group)
group.instance_variable_set(:@user, user)
CustomWorkflow.run_shared_code(group) if event.to_s.starts_with? 'before_'
CustomWorkflow.run_custom_workflows(:group_users, group, event)
end
[:before_add, :before_remove, :after_add, :after_remove].each do |observable|
send("#{observable}_for_users") << if Rails::VERSION::MAJOR >= 4
lambda { |event, group, user| Group.users_callback(event, group, user) }
else
lambda { |group, user| Group.users_callback(observable, group, user) }
end
end
end if CustomWorkflow.table_exists?
end
module InstanceMethods
def before_save_custom_workflows
@group = self
@saved_attributes = attributes.dup
CustomWorkflow.run_shared_code(self)
CustomWorkflow.run_custom_workflows(:group, self, :before_save)
errors.empty? && (@saved_attributes == attributes || valid?)
ensure
@saved_attributes = nil
end
def after_save_custom_workflows
CustomWorkflow.run_custom_workflows(:group, self, :after_save)
end
def before_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:group, self, :before_destroy)
end
def after_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:group, self, :after_destroy)
end
end
end
end
end
unless Group.include?(RedmineCustomWorkflows::Patches::GroupPatch)
Group.send(:include, RedmineCustomWorkflows::Patches::GroupPatch)
end

View File

@ -0,0 +1,96 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
module RedmineCustomWorkflows
module Patches
module IssuePatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
before_save :before_save_custom_workflows
after_save :after_save_custom_workflows
before_destroy :before_destroy_custom_workflows
after_destroy :after_destroy_custom_workflows
validate :validate_status
def self.attachments_callback(event, issue, attachment)
issue.instance_variable_set(:@issue, issue)
issue.instance_variable_set(:@attachment, attachment)
CustomWorkflow.run_shared_code(issue) if event.to_s.starts_with? 'before_'
CustomWorkflow.run_custom_workflows(:issue_attachments, issue, event)
end
[:before_add, :before_remove, :after_add, :after_remove].each do |observable|
send("#{observable}_for_attachments") << if Rails::VERSION::MAJOR >= 4
lambda { |event, issue, attachment| Issue.attachments_callback(event, issue, attachment) }
else
lambda { |issue, attachment| Issue.attachments_callback(observable, issue, attachment) }
end
end
end
end
module InstanceMethods
def validate_status
return true unless @saved_attributes && @saved_attributes['status_id'] != status_id &&
!new_statuses_allowed_to(User.current, new_record?).collect(&:id).include?(status_id)
status_was = IssueStatus.find_by_id(status_id_was)
status_new = IssueStatus.find_by_id(status_id)
errors.add :status, :new_status_invalid,
:old_status => status_was && status_was.name,
:new_status => status_new && status_new.name
end
def before_save_custom_workflows
@issue = self
@saved_attributes = attributes.dup
CustomWorkflow.run_shared_code(self)
CustomWorkflow.run_custom_workflows(:issue, self, :before_save)
errors.empty? && (@saved_attributes == attributes || valid?)
ensure
@saved_attributes = nil
end
def after_save_custom_workflows
CustomWorkflow.run_custom_workflows(:issue, self, :after_save)
end
def before_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:issue, self, :before_destroy)
end
def after_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:issue, self, :after_destroy)
end
end
end
end
end
unless Issue.include?(RedmineCustomWorkflows::Patches::IssuePatch)
Issue.send(:include, RedmineCustomWorkflows::Patches::IssuePatch)
end

View File

@ -0,0 +1,65 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
module RedmineCustomWorkflows
module Patches
module MailerPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
end
end
module InstanceMethods
def self.deliver_custom_email(headers={})
user = headers.delete :user
headers[:to] = user.mail if user
text_body = headers.delete :text_body
html_body = headers.delete :html_body
template_name = headers.delete :template_name
template_params = headers.delete(:template_params) || {}
if text_body || html_body
mail headers do |format|
format.text { render :text => text_body } if text_body
format.html { render :text => html_body } if html_body
end
elsif template_name
template_params.each { |k,v| instance_variable_set("@#{k}", v) }
mail headers do |format|
format.text { render template_name }
format.html { render template_name } unless Setting.plain_text_mail?
end
else
raise 'Not :text_body, :html_body or :template_name specified'
end
end
end
end
end
end
unless Mailer.include?(RedmineCustomWorkflows::Patches::MailerPatch)
Mailer.send(:include, RedmineCustomWorkflows::Patches::MailerPatch)
end

View File

@ -0,0 +1,87 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
module RedmineCustomWorkflows
module Patches
module ProjectPatch
def self.included(base)
base.send :include, InstanceMethods
base.class_eval do
has_and_belongs_to_many :custom_workflows
safe_attributes :custom_workflow_ids, :if =>
lambda { |project, user| project.new_record? || user.allowed_to?(:manage_project_workflow, project) }
before_save :before_save_custom_workflows
after_save :after_save_custom_workflows
before_destroy :before_destroy_custom_workflows
after_destroy :after_destroy_custom_workflows
def self.attachments_callback(event, project, attachment)
project.instance_variable_set(:@project, project)
project.instance_variable_set(:@attachment, attachment)
CustomWorkflow.run_shared_code(project) if event.to_s.starts_with? 'before_'
CustomWorkflow.run_custom_workflows(:project_attachments, project, event)
end
[:before_add, :before_remove, :after_add, :after_remove].each do |observable|
send("#{observable}_for_attachments") << if Rails::VERSION::MAJOR >= 4
lambda { |event, project, attachment| Project.attachments_callback(event, project, attachment) }
else
lambda { |project, attachment| Project.attachments_callback(observable, project, attachment) }
end
end
end
end
module InstanceMethods
def before_save_custom_workflows
@project = self
@saved_attributes = attributes.dup
CustomWorkflow.run_shared_code(self)
CustomWorkflow.run_custom_workflows(:project, self, :before_save)
errors.empty? && (@saved_attributes == attributes || valid?)
ensure
@saved_attributes = nil
end
def after_save_custom_workflows
CustomWorkflow.run_custom_workflows(:project, self, :after_save)
end
def before_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:project, self, :before_destroy)
end
def after_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:project, self, :after_destroy)
end
end
end
end
end
unless Project.include?(RedmineCustomWorkflows::Patches::ProjectPatch)
Project.send(:include, RedmineCustomWorkflows::Patches::ProjectPatch)
end

View File

@ -0,0 +1,37 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
module RedmineCustomWorkflows
module Patches
module ProjectsHelperPatch
def project_settings_tabs
tabs = super
tabs << { name: 'custom_workflows', action: :manage_project_workflow, partial: 'projects/settings/custom_workflow',
label: :label_custom_workflow_plural } if User.current.allowed_to?(:manage_project_workflow, @project)
tabs
end
end
end
end
ProjectsHelper.send(:prepend, RedmineCustomWorkflows::Patches::ProjectsHelperPatch)

View File

@ -0,0 +1,68 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
module RedmineCustomWorkflows
module Patches
module TimeEntryPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
before_save :before_save_custom_workflows
after_save :after_save_custom_workflows
before_destroy :before_destroy_custom_workflows
after_destroy :after_destroy_custom_workflows
end
end
module InstanceMethods
def before_save_custom_workflows
@time_entry = self
@saved_attributes = attributes.dup
CustomWorkflow.run_shared_code(self)
CustomWorkflow.run_custom_workflows(:time_entry, self, :before_save)
errors.empty? && (@saved_attributes == attributes || valid?)
ensure
@saved_attributes = nil
end
def after_save_custom_workflows
CustomWorkflow.run_custom_workflows(:time_entry, self, :after_save)
end
def before_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:time_entry, self, :before_destroy)
end
def after_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:time_entry, self, :after_destroy)
end
end
end
end
end
unless TimeEntry.include?(RedmineCustomWorkflows::Patches::TimeEntryPatch)
TimeEntry.send(:include, RedmineCustomWorkflows::Patches::TimeEntryPatch)
end

View File

@ -0,0 +1,68 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
module RedmineCustomWorkflows
module Patches
module UserPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
before_save :before_save_custom_workflows
after_save :after_save_custom_workflows
before_destroy :before_destroy_custom_workflows
after_destroy :after_destroy_custom_workflows
end
end
module InstanceMethods
def before_save_custom_workflows
@user = self
@saved_attributes = attributes.dup
CustomWorkflow.run_shared_code(self)
CustomWorkflow.run_custom_workflows(:user, self, :before_save)
errors.empty? && (@saved_attributes == attributes || valid?)
ensure
@saved_attributes = nil
end
def after_save_custom_workflows
CustomWorkflow.run_custom_workflows(:user, self, :after_save)
end
def before_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:user, self, :before_destroy)
end
def after_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:user, self, :after_destroy)
end
end
end
end
end
unless User.include?(RedmineCustomWorkflows::Patches::UserPatch)
User.send(:include, RedmineCustomWorkflows::Patches::UserPatch)
end

View File

@ -0,0 +1,68 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
module RedmineCustomWorkflows
module Patches
module VersionPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
before_save :before_save_custom_workflows
after_save :after_save_custom_workflows
before_destroy :before_destroy_custom_workflows
after_destroy :after_destroy_custom_workflows
end
end
module InstanceMethods
def before_save_custom_workflows
@version = self
@saved_attributes = attributes.dup
CustomWorkflow.run_shared_code(self)
CustomWorkflow.run_custom_workflows(:version, self, :before_save)
errors.empty? && (@saved_attributes == attributes || valid?)
ensure
@saved_attributes = nil
end
def after_save_custom_workflows
CustomWorkflow.run_custom_workflows(:version, self, :after_save)
end
def before_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:version, self, :before_destroy)
end
def after_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:version, self, :after_destroy)
end
end
end
end
end
unless Version.include?(RedmineCustomWorkflows::Patches::VersionPatch)
Version.send(:include, RedmineCustomWorkflows::Patches::VersionPatch)
end

View File

@ -0,0 +1,68 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
module RedmineCustomWorkflows
module Patches
module WikiContentPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
before_save :before_save_custom_workflows
after_save :after_save_custom_workflows
before_destroy :before_destroy_custom_workflows
after_destroy :after_destroy_custom_workflows
end
end
module InstanceMethods
def before_save_custom_workflows
@content = self
@saved_attributes = attributes.dup
CustomWorkflow.run_shared_code(self)
CustomWorkflow.run_custom_workflows(:wiki_content, self, :before_save)
errors.empty? && (@saved_attributes == attributes || valid?)
ensure
@saved_attributes = nil
end
def after_save_custom_workflows
CustomWorkflow.run_custom_workflows(:wiki_content, self, :after_save)
end
def before_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:wiki_content, self, :before_destroy)
end
def after_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:wiki_content, self, :after_destroy)
end
end
end
end
end
unless WikiContent.include?(RedmineCustomWorkflows::Patches::WikiContentPatch)
WikiContent.send(:include, RedmineCustomWorkflows::Patches::WikiContentPatch)
end

View File

@ -0,0 +1,51 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
module RedmineCustomWorkflows
module Patches
module WikiPagePatch
def self.included(base)
base.class_eval do
def self.attachments_callback(event, page, attachment)
page.instance_variable_set(:@page, page)
page.instance_variable_set(:@attachment, attachment)
CustomWorkflow.run_shared_code(page) if event.to_s.starts_with? 'before_'
CustomWorkflow.run_custom_workflows(:wiki_page_attachments, page, event)
end
[:before_add, :before_remove, :after_add, :after_remove].each do |observable|
send("#{observable}_for_attachments") << if Rails::VERSION::MAJOR >= 4
lambda { |event, page, attachment| WikiPage.attachments_callback(event, page, attachment) }
else
lambda { |page, attachment| WikiPage.attachments_callback(observable, page, attachment) }
end
end
end
end
end
end
end
unless WikiPage.include?(RedmineCustomWorkflows::Patches::WikiPagePatch)
WikiPage.send(:include, RedmineCustomWorkflows::Patches::WikiPagePatch)
end

View File

@ -1,57 +0,0 @@
module RedmineCustomWorkflows
module ProjectPatch
def self.included(base)
base.send :include, InstanceMethods
base.class_eval do
has_and_belongs_to_many :custom_workflows
safe_attributes :custom_workflow_ids, :if =>
lambda { |project, user| project.new_record? || user.allowed_to?(:manage_project_workflow, project) }
before_save :before_save_custom_workflows
after_save :after_save_custom_workflows
before_destroy :before_destroy_custom_workflows
after_destroy :after_destroy_custom_workflows
def self.attachments_callback(event, project, attachment)
project.instance_variable_set(:@project, project)
project.instance_variable_set(:@attachment, attachment)
CustomWorkflow.run_shared_code(project) if event.to_s.starts_with? 'before_'
CustomWorkflow.run_custom_workflows(:project_attachments, project, event)
end
[:before_add, :before_remove, :after_add, :after_remove].each do |observable|
send("#{observable}_for_attachments") << if Rails::VERSION::MAJOR >= 4
lambda { |event, project, attachment| Project.attachments_callback(event, project, attachment) }
else
lambda { |project, attachment| Project.attachments_callback(observable, project, attachment) }
end
end
end
end
module InstanceMethods
def before_save_custom_workflows
@project = self
@saved_attributes = attributes.dup
CustomWorkflow.run_shared_code(self)
CustomWorkflow.run_custom_workflows(:project, self, :before_save)
errors.empty? && (@saved_attributes == attributes || valid?)
ensure
@saved_attributes = nil
end
def after_save_custom_workflows
CustomWorkflow.run_custom_workflows(:project, self, :after_save)
end
def before_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:project, self, :before_destroy)
end
def after_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:project, self, :after_destroy)
end
end
end
end

View File

@ -1,14 +0,0 @@
module RedmineCustomWorkflows
module ProjectsHelperPatch
def project_settings_tabs
tabs = super
tabs << {:name => 'custom_workflows', :action => :manage_project_workflow, :partial => 'projects/settings/custom_workflow',
:label => :label_custom_workflow_plural} if User.current.allowed_to?(:manage_project_workflow, @project)
tabs
end
end
end
ProjectsHelper.send(:prepend, RedmineCustomWorkflows::ProjectsHelperPatch)

View File

@ -0,0 +1,52 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
module RedmineCustomWorkflows
module Test
class TestCase < ActionController::TestCase
# Allow us to override the fixtures method to implement fixtures for our plugin.
# Ultimately it allows for better integration without blowing redmine fixtures up,
# and allowing us to suppliment redmine fixtures if we need to.
def self.fixtures(*table_names)
dir = File.join( File.dirname(__FILE__), '../../../test/fixtures')
table_names.each do |x|
ActiveRecord::FixtureSet.create_fixtures(dir, x) if File.exist?("#{dir}/#{x}.yml")
end
super(table_names)
end
def setup
if ::Rails::VERSION::MAJOR >= 5
if ::Rails::VERSION::MINOR >= 1
@request = ActionController::TestRequest.create(self.class.controller_class)
else
@request = ActionController::TestRequest.create
end
else
@request = ActionController::TestRequest.new
end
@response = ActionController::TestResponse.new
end
end
end
end

View File

@ -0,0 +1,39 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
module RedmineCustomWorkflows
module Test
class UnitTest < ActiveSupport::TestCase
# Allow us to override the fixtures method to implement fixtures for our plugin.
# Ultimately it allows for better integration without blowing redmine fixtures up,
# and allowing us to suppliment redmine fixtures if we need to.
def self.fixtures(*table_names)
dir = File.join( File.dirname(__FILE__), '../../../test/fixtures')
table_names.each do |x|
Rails.logger.info ">>> #{dir}/#{x}.yml"
ActiveRecord::FixtureSet.create_fixtures(dir, x) if File.exist?("#{dir}/#{x}.yml")
end
super(table_names)
end
end
end
end

View File

@ -1,38 +0,0 @@
module RedmineCustomWorkflows
module TimeEntryPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
before_save :before_save_custom_workflows
after_save :after_save_custom_workflows
before_destroy :before_destroy_custom_workflows
after_destroy :after_destroy_custom_workflows
end
end
module InstanceMethods
def before_save_custom_workflows
@time_entry = self
@saved_attributes = attributes.dup
CustomWorkflow.run_shared_code(self)
CustomWorkflow.run_custom_workflows(:time_entry, self, :before_save)
errors.empty? && (@saved_attributes == attributes || valid?)
ensure
@saved_attributes = nil
end
def after_save_custom_workflows
CustomWorkflow.run_custom_workflows(:time_entry, self, :after_save)
end
def before_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:time_entry, self, :before_destroy)
end
def after_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:time_entry, self, :after_destroy)
end
end
end
end

View File

@ -1,38 +0,0 @@
module RedmineCustomWorkflows
module UserPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
before_save :before_save_custom_workflows
after_save :after_save_custom_workflows
before_destroy :before_destroy_custom_workflows
after_destroy :after_destroy_custom_workflows
end
end
module InstanceMethods
def before_save_custom_workflows
@user = self
@saved_attributes = attributes.dup
CustomWorkflow.run_shared_code(self)
CustomWorkflow.run_custom_workflows(:user, self, :before_save)
errors.empty? && (@saved_attributes == attributes || valid?)
ensure
@saved_attributes = nil
end
def after_save_custom_workflows
CustomWorkflow.run_custom_workflows(:user, self, :after_save)
end
def before_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:user, self, :before_destroy)
end
def after_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:user, self, :after_destroy)
end
end
end
end

View File

@ -1,38 +0,0 @@
module RedmineCustomWorkflows
module VersionPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
before_save :before_save_custom_workflows
after_save :after_save_custom_workflows
before_destroy :before_destroy_custom_workflows
after_destroy :after_destroy_custom_workflows
end
end
module InstanceMethods
def before_save_custom_workflows
@version = self
@saved_attributes = attributes.dup
CustomWorkflow.run_shared_code(self)
CustomWorkflow.run_custom_workflows(:version, self, :before_save)
errors.empty? && (@saved_attributes == attributes || valid?)
ensure
@saved_attributes = nil
end
def after_save_custom_workflows
CustomWorkflow.run_custom_workflows(:version, self, :after_save)
end
def before_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:version, self, :before_destroy)
end
def after_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:version, self, :after_destroy)
end
end
end
end

View File

@ -1,38 +0,0 @@
module RedmineCustomWorkflows
module WikiContentPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
before_save :before_save_custom_workflows
after_save :after_save_custom_workflows
before_destroy :before_destroy_custom_workflows
after_destroy :after_destroy_custom_workflows
end
end
module InstanceMethods
def before_save_custom_workflows
@content = self
@saved_attributes = attributes.dup
CustomWorkflow.run_shared_code(self)
CustomWorkflow.run_custom_workflows(:wiki_content, self, :before_save)
errors.empty? && (@saved_attributes == attributes || valid?)
ensure
@saved_attributes = nil
end
def after_save_custom_workflows
CustomWorkflow.run_custom_workflows(:wiki_content, self, :after_save)
end
def before_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:wiki_content, self, :before_destroy)
end
def after_destroy_custom_workflows
CustomWorkflow.run_custom_workflows(:wiki_content, self, :after_destroy)
end
end
end
end

View File

@ -1,27 +0,0 @@
module RedmineCustomWorkflows
module WikiPagePatch
def self.included(base)
base.send :include, InstanceMethods
base.class_eval do
def self.attachments_callback(event, page, attachment)
page.instance_variable_set(:@page, page)
page.instance_variable_set(:@attachment, attachment)
CustomWorkflow.run_shared_code(page) if event.to_s.starts_with? 'before_'
CustomWorkflow.run_custom_workflows(:wiki_page_attachments, page, event)
end
[:before_add, :before_remove, :after_add, :after_remove].each do |observable|
send("#{observable}_for_attachments") << if Rails::VERSION::MAJOR >= 4
lambda { |event, page, attachment| WikiPage.attachments_callback(event, page, attachment) }
else
lambda { |page, attachment| WikiPage.attachments_callback(observable, page, attachment) }
end
end
end
end
module InstanceMethods
end
end
end

7
test/ci/mysql.yml Normal file
View File

@ -0,0 +1,7 @@
test:
adapter: mysql2
database: test
username: root
encoding: utf8mb4
collation: utf8mb4_unicode_ci

5
test/ci/postgres.yml Normal file
View File

@ -0,0 +1,5 @@
test:
adapter: postgresql
database: test
encoding: utf8

View File

@ -0,0 +1,98 @@
#!/bin/bash
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
export REDMINE_GIT_REPO=git://github.com/redmine/redmine.git
export REDMINE_GIT_TAG=4.0-stable
clone()
{
# Exit if the cloning fails
set -e
rm -rf $PATH_TO_REDMINE
git clone -b $REDMINE_GIT_TAG --depth=100 --quiet $REDMINE_GIT_REPO $PATH_TO_REDMINE
}
test()
{
# Exit if a test fails
set -e
cd $PATH_TO_REDMINE
# Run tests within application
bundle exec rake redmine:plugins:test:units NAME=redmine_custom_workflows RAILS_ENV=test
bundle exec rake redmine:plugins:test:functionals NAME=redmine_custom_workflows RAILS_ENV=test
}
uninstall()
{
# Exit if the migration fails
set -e
cd $PATH_TO_REDMINE
# clean up database
bundle exec rake redmine:plugins:migrate NAME=redmine_custom_workflows VERSION=0 RAILS_ENV=test
}
install()
{
# Exit if the installation fails
set -e
# cd to redmine folder
cd $PATH_TO_REDMINE
echo current directory is `pwd`
# Create a link to the Custom Workflows plugin
ln -sf $PATH_TO_CUSTOMWORKFLOWS plugins/redmine_custom_workflows
# Copy database.yml
cp $WORKSPACE/database.yml config/
# Install gems
# Not ideal, but at present Travis-CI will not install with xapian enabled:
bundle install --without rmagick development RAILS_ENV=test
# Run Redmine database migrations
bundle exec rake db:migrate --trace RAILS_ENV=test
# Load Redmine database default data
bundle exec rake redmine:load_default_data REDMINE_LANG=en RAILS_ENV=test
# generate session store/secret token
bundle exec rake generate_secret_token RAILS_ENV=test
# Run the plugin database migrations
bundle exec rake redmine:plugins:migrate RAILS_ENV=test
}
while getopts :ictu opt
do case "$opt" in
c) clone; exit 0;;
i) install; exit 0;;
t) test; exit 0;;
u) uninstall; exit 0;;
[?]) echo "i: install; c: clone redmine; t: run tests; u: uninstall";;
esac
done

5
test/ci/sqlite.yml Normal file
View File

@ -0,0 +1,5 @@
test:
adapter: sqlite3
database: db/test.sqlite3
timeout: 500

21
test/fixtures/custom_workflows.yml vendored Normal file
View File

@ -0,0 +1,21 @@
---
custom_workflows_001:
id: 1
before_save: "Rails.logger.info '>>> before save'"
after_save: "Rails.logger.info '>>> after save'"
name: 'Issue CW test'
description: NULL
position: 1
is_for_all: 0
author: 'karel.picman@kontron.com'
created_at: 2018-12-20 14:01:27 +02:00
updated_at: 2018-12-20 14:01:27 +02:00
active: 1
observable: 'issue'
shared_code: NULL
before_add: NULL
after_add: NULL
before_remove: NULL
after_remove: NULL
before_destroy: "Rails.logger.info '>>> before destroy'"
after_destroy : "Rails.logger.info '>>> after destroy'"

View File

@ -0,0 +1,4 @@
---
custom_workflows_projects_001:
project_id: 1
custom_workflow_id: 1

View File

@ -0,0 +1,56 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
require File.expand_path('../../test_helper', __FILE__)
class CustomWorkflowsControllerTest < RedmineCustomWorkflows::Test::TestCase
fixtures :users, :email_addresses, :custom_workflows, :custom_workflows_projects, :projects, :roles,
:members, :member_roles
def setup
@cw1 = CustomWorkflow.find 1
@project1 = Project.find 1
@admin = User.find 1
@manager = User.find 2
User.current = nil
@request.session[:user_id] = @admin.id
end
def test_truth
assert_kind_of CustomWorkflow, @cw1
assert_kind_of Project, @project1
assert_kind_of User, @manager
assert_kind_of User, @admin
end
def test_index_admin
get :index
assert_response :success
end
def test_index_non_admin
@request.session[:user_id] = @manager.id
get :index
assert_response :forbidden
end
end

23
test/test_helper.rb Normal file
View File

@ -0,0 +1,23 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
# Load the normal Rails helper
require File.expand_path('../../../../test/test_helper', __FILE__)

View File

@ -0,0 +1,40 @@
# encoding: utf-8
#
# Redmine plugin for Custom Workflows
#
# Copyright Anton Argirov
# Copyright 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.
require File.expand_path('../../test_helper', __FILE__)
class CustomWorkflowTest < RedmineCustomWorkflows::Test::UnitTest
fixtures :projects, :custom_workflows, :custom_workflows_projects
def setup
@cw1 = CustomWorkflow.find 1
end
def test_truth
assert_kind_of CustomWorkflow, @cw1
end
def test_to_s
assert_equal @cw1.name, @cw1.to_s
end
end