EasyRedmine compatibility

This commit is contained in:
Karel Pičman 2019-08-09 12:59:07 +02:00
parent bcfaf1c3e8
commit 5590a27c49
17 changed files with 379 additions and 236 deletions

View File

@ -21,7 +21,10 @@
source 'https://rubygems.org'
# In order to the plugin in Redmine < 4 (Rails < 5), comment out the following lines
# I don't know how to check Redmine or better Rails version here :-(
gem 'acts_as_list'
gem 'activemodel-serializers-xml'
# Redmine extensions
unless %w(easyproject easy_gantt).any? { |plugin| Dir.exist?(File.expand_path("../../#{plugin}", __FILE__)) }
gem 'redmine_extensions', '~> 0.2.5'
end

40
after_init.rb Normal 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_dependency File.dirname(__FILE__) + '/lib/redmine_custom_workflows.rb'
ActiveSupport::Dependencies.autoload_paths << File.join(File.dirname(__FILE__), 'app')
def custom_workflows_init
# 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-custom-workflows'}
end
end
if Redmine::Plugin.installed?(:easy_extensions)
ActiveSupport.on_load(:easyproject, yield: true) do
custom_workflows_init
end
else
custom_workflows_init
end

View File

@ -0,0 +1,64 @@
/*
* Redmine plugin for Document Management System "Features"
*
* 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.
*/
#tab-content-custom_workflows .disabled {
color: silver;
}
table.list.custom-workflows td {
vertical-align: middle;
}
table.list.custom-workflows td.description {
text-align: left;
width: 40%;
}
table.list.custom-workflows td.buttons {
white-space: normal;
width: 10%;
text-align: left;
}
table.list.custom-workflows tr.disabled {
color: silver;
}
#custom_workflow_description, #custom_workflow_name {
width: 98%;
}
.custom_workflow_script {
width: 98%;
font-size: 11px;
}
#custom_workflow_enabled_projects ul {
max-height: 200px;
overflow-y: auto;
}
/* Icons */
.icon-export { background-image: url(../images/export.png); }
.icon-import { background-image: url(../images/import.png); }
.icon-active { background-image: url(../images/active.png); }
.icon-inactive { background-image: url(../images/inactive.png); }
.icon-custom-workflows { background-image: url(../../../images/ticket_go.png); }

View File

@ -23,38 +23,43 @@ class CreateExampleWorkflow < ActiveRecord::Migration[4.2]
def up
CustomWorkflow.reset_column_information
old = CustomWorkflow.where(:name => 'Duration/Done Ratio/Status correlation').first
name = 'Duration/Done Ratio/Status correlation'
old = CustomWorkflow.where(name: name).first
old.destroy if old
cw = CustomWorkflow.new
cw.name = name
cw.author = 'anton.argirov@gmail.com'
cw.description = %{
Set up a correlation between the start date, due date, done ratio and status of issues.
CustomWorkflow.create!(:name => 'Duration/Done Ratio/Status correlation', :author => 'anton.argirov@gmail.com', :description => <<EOD, :before_save => <<EOS)
Set up a correlation between the start date, due date, done ratio and status of issues.
* If done ratio is changed to 100% and status is "In Process", status changes to "Resolved"
* If status is "New", "Resolved" or "Feedback" and done ratio is changed to value less than 100%, status changes to "In process"
* If status is changed to "In process" and start date is not set, then it sets to current date
* If status is changed to "Resolved" and end date is not set, then it set to due date
* If done ratio is changed to 100% and status is "In Process", status changes to "Resolved"
* If status is "New", "Resolved" or "Feedback" and done ratio is changed to value less than 100%, status changes to "In process"
* If status is changed to "In process" and start date is not set, then it sets to current date
* If status is changed to "Resolved" and end date is not set, then it set to due date
To use this script properly, turn off "Use current date as start date for new issues" option in the settings as this script already do it own way.
EOD
if @issue.done_ratio_changed?
if @issue.done_ratio==100 && @issue.status_id==2
@issue.status_id=3
elsif [1,3,4].include?(@issue.status_id) && @issue.done_ratio<100
@issue.status_id=2
To use this script properly, turn off "Use current date as start date for new issues" option in the settings as this script already do it own way.
}
cw.before_save = %{
if @issue.done_ratio_changed?
if (@issue.done_ratio == 100) && (@issue.status_id == 2)
@issue.status_id = 3
elsif [1,3,4].include?(@issue.status_id) && (@issue.done_ratio < 100)
@issue.status_id = 2
end
end
end
if @issue.status_id_changed?
if @issue.status_id==2
if @issue.status_id_changed?
if @issue.status_id == 2
@issue.start_date ||= Time.now
end
if @issue.status_id==3
if @issue.status_id == 3
@issue.done_ratio = 100
@issue.start_date ||= @issue.created_on
@issue.due_date ||= Time.now
end
end
EOS
end
}
cw.save!
end
end

21
init.rb
View File

@ -19,24 +19,25 @@
# 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
if Redmine::Plugin.installed?(:easy_extensions)
name 'Easy Custom Workflow plugin'
url 'https://www.easyredmine.com'
author_url 'https://www.easyredmine.com'
else
name 'Redmine Custom Workflow plugin'
url 'https://www.redmine.org/plugins/custom-workflows'
author_url 'https://github.com/danmunn/redmine_custom_workflows/graphs/contributors'
end
author 'Anton Argirov/Karel Pičman'
description 'Allows to create custom workflows for issues, defined in the plain Ruby language'
description 'Allows to create custom workflows for objects, defined in the plain Ruby language'
version '1.0.1'
url 'http://www.redmine.org/plugins/custom-workflows'
requires_redmine version_or_higher: '4.0.0'
permission :manage_project_workflow, {}, :require => :member
end
require_dependency File.dirname(__FILE__) + '/lib/redmine_custom_workflows.rb'
# 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'}
unless Redmine::Plugin.installed?(:easy_extensions)
require_relative 'after_init'
end

View File

@ -22,9 +22,20 @@
module RedmineCustomWorkflows
class Hooks < Redmine::Hook::ViewListener
def view_layouts_base_html_head(context)
stylesheet_link_tag :style, :plugin => 'redmine_custom_workflows'
return if defined?(EasyExtensions)
"\n".html_safe + stylesheet_link_tag('custom_workflows.css', plugin: :redmine_custom_workflows)
end
def easy_extensions_javascripts_hook(context={})
context[:template].require_asset('tab_override.js')
end
def easy_extensions_stylesheets_hook(context={})
context[:template].require_asset('custom_workflows.css')
end
end
end

View File

@ -24,7 +24,6 @@ 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
@ -33,8 +32,6 @@ module RedmineCustomWorkflows
end
end
module InstanceMethods
def before_save_custom_workflows
@attachment = self
@saved_attributes = attributes.dup
@ -59,11 +56,9 @@ module RedmineCustomWorkflows
end
end
end
end
end
unless Attachment.include?(RedmineCustomWorkflows::Patches::AttachmentPatch)
Attachment.send(:include, RedmineCustomWorkflows::Patches::AttachmentPatch)
end
# Apply patch
RedmineExtensions::PatchManager.register_model_patch 'Attachment',
'RedmineCustomWorkflows::Patches::AttachmentPatch'

View File

@ -24,7 +24,6 @@ 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
@ -47,8 +46,6 @@ module RedmineCustomWorkflows
end
end
module InstanceMethods
def before_save_custom_workflows
@group = self
@saved_attributes = attributes.dup
@ -73,11 +70,9 @@ module RedmineCustomWorkflows
end
end
end
end
end
unless Group.include?(RedmineCustomWorkflows::Patches::GroupPatch)
Group.send(:include, RedmineCustomWorkflows::Patches::GroupPatch)
end
# Apply patch
RedmineExtensions::PatchManager.register_model_patch 'Group',
'RedmineCustomWorkflows::Patches::GroupPatch'

View File

@ -24,7 +24,6 @@ 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
@ -49,8 +48,6 @@ module RedmineCustomWorkflows
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)
@ -87,11 +84,9 @@ module RedmineCustomWorkflows
end
end
end
end
end
unless Issue.include?(RedmineCustomWorkflows::Patches::IssuePatch)
Issue.send(:include, RedmineCustomWorkflows::Patches::IssuePatch)
end
# Apply patch
RedmineExtensions::PatchManager.register_model_patch 'Issue',
'RedmineCustomWorkflows::Patches::IssuePatch'

View File

@ -0,0 +1,54 @@
# 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.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
RedmineExtensions::PatchManager.register_model_patch 'Mailer',
'RedmineCustomWorkflows::Patches::MailerPatch'

View File

@ -24,7 +24,6 @@ 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 =>
@ -48,8 +47,6 @@ module RedmineCustomWorkflows
end
end
module InstanceMethods
def before_save_custom_workflows
@project = self
@saved_attributes = attributes.dup
@ -74,11 +71,9 @@ module RedmineCustomWorkflows
end
end
end
end
end
unless Project.include?(RedmineCustomWorkflows::Patches::ProjectPatch)
Project.send(:include, RedmineCustomWorkflows::Patches::ProjectPatch)
end
# Apply patch
RedmineExtensions::PatchManager.register_model_patch 'Project',
'RedmineCustomWorkflows::Patches::ProjectPatch'

View File

@ -34,4 +34,9 @@ module RedmineCustomWorkflows
end
end
ProjectsController.send :helper, RedmineCustomWorkflows::Patches::ProjectsHelperPatch
if Redmine::Plugin.installed?(:easy_extensions)
RedmineExtensions::PatchManager.register_helper_patch 'ProjectsHelper',
'RedmineCustomWorkflows::Patches::ProjectsHelperPatch', prepend: true
else
ProjectsController.send :helper, RedmineCustomWorkflows::Patches::ProjectsHelperPatch
end

View File

@ -24,7 +24,6 @@ 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
@ -33,8 +32,6 @@ module RedmineCustomWorkflows
end
end
module InstanceMethods
def before_save_custom_workflows
@time_entry = self
@saved_attributes = attributes.dup
@ -59,11 +56,9 @@ module RedmineCustomWorkflows
end
end
end
end
end
unless TimeEntry.include?(RedmineCustomWorkflows::Patches::TimeEntryPatch)
TimeEntry.send(:include, RedmineCustomWorkflows::Patches::TimeEntryPatch)
end
# Apply patch
RedmineExtensions::PatchManager.register_model_patch 'TimeEntry',
'RedmineCustomWorkflows::Patches::TimeEntryPatch'

View File

@ -24,7 +24,6 @@ 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
@ -33,8 +32,6 @@ module RedmineCustomWorkflows
end
end
module InstanceMethods
def before_save_custom_workflows
@user = self
@saved_attributes = attributes.dup
@ -59,11 +56,9 @@ module RedmineCustomWorkflows
end
end
end
end
end
unless User.include?(RedmineCustomWorkflows::Patches::UserPatch)
User.send(:include, RedmineCustomWorkflows::Patches::UserPatch)
end
# Apply patch
RedmineExtensions::PatchManager.register_model_patch 'User',
'RedmineCustomWorkflows::Patches::UserPatch'

View File

@ -24,7 +24,6 @@ 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
@ -33,8 +32,6 @@ module RedmineCustomWorkflows
end
end
module InstanceMethods
def before_save_custom_workflows
@version = self
@saved_attributes = attributes.dup
@ -59,11 +56,9 @@ module RedmineCustomWorkflows
end
end
end
end
end
unless Version.include?(RedmineCustomWorkflows::Patches::VersionPatch)
Version.send(:include, RedmineCustomWorkflows::Patches::VersionPatch)
end
# Apply patch
RedmineExtensions::PatchManager.register_model_patch 'Version',
'RedmineCustomWorkflows::Patches::VersionPatch'

View File

@ -24,7 +24,6 @@ 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
@ -33,8 +32,6 @@ module RedmineCustomWorkflows
end
end
module InstanceMethods
def before_save_custom_workflows
@content = self
@saved_attributes = attributes.dup
@ -59,11 +56,9 @@ module RedmineCustomWorkflows
end
end
end
end
end
unless WikiContent.include?(RedmineCustomWorkflows::Patches::WikiContentPatch)
WikiContent.send(:include, RedmineCustomWorkflows::Patches::WikiContentPatch)
end
# Apply patch
RedmineExtensions::PatchManager.register_model_patch 'WikiContent',
'RedmineCustomWorkflows::Patches::WikiContentPatch'

View File

@ -42,6 +42,6 @@ module RedmineCustomWorkflows
end
end
unless WikiPage.include?(RedmineCustomWorkflows::Patches::WikiPagePatch)
WikiPage.send(:include, RedmineCustomWorkflows::Patches::WikiPagePatch)
end
# Apply patch
RedmineExtensions::PatchManager.register_model_patch 'WikiPage',
'RedmineCustomWorkflows::Patches::WikiPagePatch'