mirror of
https://github.com/anteo/redmine_custom_workflows.git
synced 2026-01-26 00:04:20 +00:00
Redmine 6.0.0 #350
This commit is contained in:
parent
03989743d7
commit
8a4218fa11
2
.github/workflows/rubyonrails.yml
vendored
2
.github/workflows/rubyonrails.yml
vendored
@ -83,7 +83,7 @@ jobs:
|
|||||||
sudo apt-get install subversion
|
sudo apt-get install subversion
|
||||||
- name: Clone Redmine
|
- name: Clone Redmine
|
||||||
# Get the latest stable Redmine
|
# Get the latest stable Redmine
|
||||||
run: svn export http://svn.redmine.org/redmine/branches/5.1-stable/ /opt/redmine
|
run: svn export http://svn.redmine.org/redmine/branches/6.0-stable/ /opt/redmine
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Link the plugin
|
- name: Link the plugin
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
Changelog for Custom Workflows
|
Changelog for Custom Workflows
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
2.1.3 *????-??-??*
|
3.0.0 *????-??-??*
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
2.1.2 *2024-06-28*
|
2.1.2 *2024-06-28*
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
Custom Workflows plug-in 2.1.3 devel
|
Custom Workflows plug-in 3.0.0 devel
|
||||||
====================================
|
====================================
|
||||||
|
|
||||||
[](https://github.com/anteo/redmine_custom_workflows/actions/workflows/rubyonrails.yml)
|
[](https://github.com/anteo/redmine_custom_workflows/actions/workflows/rubyonrails.yml)
|
||||||
|
|||||||
@ -25,7 +25,8 @@ def custom_workflows_init
|
|||||||
# Administration menu extension
|
# Administration menu extension
|
||||||
Redmine::MenuManager.map :admin_menu do |menu|
|
Redmine::MenuManager.map :admin_menu do |menu|
|
||||||
menu.push :custom_workflows, { controller: 'custom_workflows', action: 'index' },
|
menu.push :custom_workflows, { controller: 'custom_workflows', action: 'index' },
|
||||||
caption: :label_custom_workflow_plural, html: { class: 'icon icon-workflows workflows' }
|
caption: :label_custom_workflow_plural, icon: 'workflows',
|
||||||
|
html: { class: 'icon icon-workflows workflows' }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,24 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
# Redmine plugin for Custom Workflows
|
|
||||||
#
|
|
||||||
# Anton Argirov, 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.
|
|
||||||
|
|
||||||
# Application record class
|
|
||||||
class ApplicationRecord < ActiveRecord::Base
|
|
||||||
self.abstract_class = true
|
|
||||||
end
|
|
||||||
@ -40,7 +40,7 @@ class CustomWorkflowMailer < Mailer
|
|||||||
format.html { render plain: html_body } if html_body.present? && !Setting.plain_text_mail?
|
format.html { render plain: html_body } if html_body.present? && !Setting.plain_text_mail?
|
||||||
end
|
end
|
||||||
elsif template_name
|
elsif template_name
|
||||||
template_params.each { |k, v| instance_variable_set("@#{k}", v) }
|
template_params.each { |k, v| instance_variable_set(:"@#{k}", v) }
|
||||||
mail headers do |format|
|
mail headers do |format|
|
||||||
format.text { render template_name }
|
format.text { render template_name }
|
||||||
format.html { render template_name } unless Setting.plain_text_mail?
|
format.html { render template_name } unless Setting.plain_text_mail?
|
||||||
|
|||||||
@ -20,9 +20,9 @@
|
|||||||
|
|
||||||
<% html_title l(:label_custom_workflow_plural) %>
|
<% html_title l(:label_custom_workflow_plural) %>
|
||||||
<div class="contextual">
|
<div class="contextual">
|
||||||
<%= link_to l(:label_custom_workflow_new), new_custom_workflow_path, class: 'icon icon-add' %>
|
<%= link_to sprite_icon('add', l(:label_custom_workflow_new)), new_custom_workflow_path, class: 'icon icon-add' %>
|
||||||
<%= actions_dropdown do %>
|
<%= actions_dropdown do %>
|
||||||
<%= link_to l(:label_custom_workflow_import), '#', class: 'icon icon-move',
|
<%= link_to sprite_icon('import', l(:label_custom_workflow_import)), '#', class: 'icon icon-move',
|
||||||
onclick: "showModal('import-dialog', '450px'); return false;" %>
|
onclick: "showModal('import-dialog', '450px'); return false;" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
@ -49,16 +49,18 @@
|
|||||||
<td class="buttons">
|
<td class="buttons">
|
||||||
<%= reorder_handle workflow, url: url_for(action: 'reorder', id: workflow) %>
|
<%= reorder_handle workflow, url: url_for(action: 'reorder', id: workflow) %>
|
||||||
<% if workflow.active? %>
|
<% if workflow.active? %>
|
||||||
<%= link_to l(:button_custom_workflow_deactivate), custom_workflow_status_path(workflow, active: false),
|
<%= link_to sprite_icon('lock', l(:button_custom_workflow_deactivate)),
|
||||||
class: 'icon icon-lock', method: :post %>
|
custom_workflow_status_path(workflow, active: false), class: 'icon icon-lock',
|
||||||
|
method: :post %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= link_to l(:button_activate), custom_workflow_status_path(workflow, active: true),
|
<%= link_to sprite_icon('unlock', l(:button_activate)),
|
||||||
class: 'icon icon-unlock', method: :post %>
|
custom_workflow_status_path(workflow, active: true), class: 'icon icon-unlock',
|
||||||
|
method: :post %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= link_to l(:label_custom_workflow_export), export_custom_workflow_path(workflow),
|
<%= link_to sprite_icon('download', l(:label_custom_workflow_export)),
|
||||||
class: 'icon icon-download', method: :get %>
|
export_custom_workflow_path(workflow), class: 'icon icon-download', method: :get %>
|
||||||
<%= link_to l(:button_delete), workflow, class: 'icon icon-del', data: { confirm: l(:text_are_you_sure) },
|
<%= link_to sprite_icon('del', l(:button_delete)), workflow, class: 'icon icon-del',
|
||||||
confirm: l(:text_are_you_sure), method: :delete %>
|
data: { confirm: l(:text_are_you_sure) }, confirm: l(:text_are_you_sure), method: :delete %>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
4
init.rb
4
init.rb
@ -24,9 +24,9 @@ Redmine::Plugin.register :redmine_custom_workflows do
|
|||||||
author_url 'https://github.com/anteo/redmine_custom_workflows/graphs/contributors'
|
author_url 'https://github.com/anteo/redmine_custom_workflows/graphs/contributors'
|
||||||
author 'Anton Argirov/Karel Pičman'
|
author 'Anton Argirov/Karel Pičman'
|
||||||
description 'It allows to create custom workflows for objects, defined in a plain Ruby language'
|
description 'It allows to create custom workflows for objects, defined in a plain Ruby language'
|
||||||
version '2.1.3 devel'
|
version '3.0.0 devel'
|
||||||
|
|
||||||
requires_redmine version_or_higher: '4.1.0'
|
requires_redmine version_or_higher: '6.0.0'
|
||||||
|
|
||||||
permission :manage_project_workflow, {}, require: :member
|
permission :manage_project_workflow, {}, require: :member
|
||||||
end
|
end
|
||||||
|
|||||||
@ -38,22 +38,24 @@ module RedmineCustomWorkflows
|
|||||||
before_destroy :before_destroy_custom_workflows
|
before_destroy :before_destroy_custom_workflows
|
||||||
after_destroy :after_destroy_custom_workflows
|
after_destroy :after_destroy_custom_workflows
|
||||||
|
|
||||||
|
has_and_belongs_to_many :users, # inherited
|
||||||
|
join_table: "#{table_name_prefix}groups_users#{table_name_suffix}", # inherited
|
||||||
|
before_add: proc {}, # => before_add_for_users
|
||||||
|
after_add: :user_added, # inherited
|
||||||
|
before_remove: proc {}, # => before_remove_for_users
|
||||||
|
after_remove: :user_removed # inherited
|
||||||
|
|
||||||
def self.users_callback(event, group, user)
|
def self.users_callback(event, group, user)
|
||||||
group.instance_variable_set :@group, group
|
group.instance_variable_set :@group, group
|
||||||
group.instance_variable_set :@user, user
|
group.instance_variable_set :@user, user
|
||||||
CustomWorkflow.run_shared_code(group) if event.to_s.starts_with? 'before_'
|
CustomWorkflow.run_shared_code(group) if event.to_s.starts_with? 'before_'
|
||||||
CustomWorkflow.run_custom_workflows :group_users, group, event
|
CustomWorkflow.run_custom_workflows :group_users, group, event
|
||||||
end
|
end
|
||||||
|
|
||||||
%i[before_add before_remove after_add after_remove].each do |observable|
|
%i[before_add before_remove after_add after_remove].each do |observable|
|
||||||
send("#{observable}_for_users") << if Rails::VERSION::MAJOR >= 4
|
send(:"#{observable}_for_users") << lambda { |event, group, user|
|
||||||
lambda { |event, group, user|
|
|
||||||
Group.users_callback(event, group, user)
|
Group.users_callback(event, group, user)
|
||||||
}
|
}
|
||||||
else
|
|
||||||
lambda { |group, user|
|
|
||||||
Group.users_callback(observable, group, user)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -39,6 +39,11 @@ module RedmineCustomWorkflows
|
|||||||
after_destroy :after_destroy_custom_workflows
|
after_destroy :after_destroy_custom_workflows
|
||||||
validate :validate_status
|
validate :validate_status
|
||||||
|
|
||||||
|
acts_as_attachable before_add: proc {}, # => before_add_for_attachments
|
||||||
|
after_add: :attachment_added, # inherited
|
||||||
|
before_remove: proc {}, # => before_remove_for_attachments
|
||||||
|
after_remove: :attachment_removed # inherited
|
||||||
|
|
||||||
def self.attachments_callback(event, issue, attachment)
|
def self.attachments_callback(event, issue, attachment)
|
||||||
issue.instance_variable_set :@issue, issue
|
issue.instance_variable_set :@issue, issue
|
||||||
issue.instance_variable_set :@attachment, attachment
|
issue.instance_variable_set :@attachment, attachment
|
||||||
@ -47,15 +52,9 @@ module RedmineCustomWorkflows
|
|||||||
end
|
end
|
||||||
|
|
||||||
%i[before_add before_remove after_add after_remove].each do |observable|
|
%i[before_add before_remove after_add after_remove].each do |observable|
|
||||||
send("#{observable}_for_attachments") << if Rails::VERSION::MAJOR >= 4
|
send(:"#{observable}_for_attachments") << lambda { |event, issue, attachment|
|
||||||
lambda { |event, issue, attachment|
|
|
||||||
Issue.attachments_callback event, issue, attachment
|
Issue.attachments_callback event, issue, attachment
|
||||||
}
|
}
|
||||||
else
|
|
||||||
lambda { |issue, attachment|
|
|
||||||
Issue.attachments_callback observable, issue, attachment
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -45,6 +45,14 @@ module RedmineCustomWorkflows
|
|||||||
before_destroy :before_destroy_custom_workflows
|
before_destroy :before_destroy_custom_workflows
|
||||||
after_destroy :after_destroy_custom_workflows
|
after_destroy :after_destroy_custom_workflows
|
||||||
|
|
||||||
|
acts_as_attachable view_permission: :view_files, # inherited
|
||||||
|
edit_permission: :manage_files, # inherited
|
||||||
|
delete_permission: :manage_files, # inherited
|
||||||
|
before_add: proc {}, # => before_add_for_attachments
|
||||||
|
after_add: proc {}, # => after_add_for_attachments
|
||||||
|
before_remove: proc {}, # => before_remove_for_attachments
|
||||||
|
after_remove: proc {} # => after_remove_for_attachments
|
||||||
|
|
||||||
def self.attachments_callback(event, project, attachment)
|
def self.attachments_callback(event, project, attachment)
|
||||||
project.instance_variable_set(:@project, project)
|
project.instance_variable_set(:@project, project)
|
||||||
project.instance_variable_set(:@attachment, attachment)
|
project.instance_variable_set(:@attachment, attachment)
|
||||||
@ -53,7 +61,7 @@ module RedmineCustomWorkflows
|
|||||||
end
|
end
|
||||||
|
|
||||||
%i[before_add before_remove after_add after_remove].each do |observable|
|
%i[before_add before_remove after_add after_remove].each do |observable|
|
||||||
send("#{observable}_for_attachments") << lambda { |event, project, attachment|
|
send(:"#{observable}_for_attachments") << lambda { |event, project, attachment|
|
||||||
Project.attachments_callback event, project, attachment
|
Project.attachments_callback event, project, attachment
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|||||||
@ -33,6 +33,12 @@ module RedmineCustomWorkflows
|
|||||||
|
|
||||||
def self.prepended(base)
|
def self.prepended(base)
|
||||||
base.class_eval do
|
base.class_eval do
|
||||||
|
acts_as_attachable delete_permission: :delete_wiki_pages_attachments, # inherited
|
||||||
|
before_add: proc {}, # => before_add_for_attachments
|
||||||
|
after_add: proc {}, # => after_add_for_attachments
|
||||||
|
before_remove: proc {}, # => before_remove_for_attachments
|
||||||
|
after_remove: proc {} # => after_remove_for_attachments
|
||||||
|
|
||||||
def self.attachments_callback(event, page, attachment)
|
def self.attachments_callback(event, page, attachment)
|
||||||
page.instance_variable_set :@page, page
|
page.instance_variable_set :@page, page
|
||||||
page.instance_variable_set :@attachment, attachment
|
page.instance_variable_set :@attachment, attachment
|
||||||
@ -41,7 +47,7 @@ module RedmineCustomWorkflows
|
|||||||
end
|
end
|
||||||
|
|
||||||
%i[before_add before_remove after_add after_remove].each do |observable|
|
%i[before_add before_remove after_add after_remove].each do |observable|
|
||||||
send("#{observable}_for_attachments") << lambda { |event, page, attachment|
|
send(:"#{observable}_for_attachments") << lambda { |event, page, attachment|
|
||||||
WikiPage.attachments_callback(event, page, attachment)
|
WikiPage.attachments_callback(event, page, attachment)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|||||||
@ -37,7 +37,7 @@ module RedmineCustomWorkflows
|
|||||||
redmine_table_names << x
|
redmine_table_names << x
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
super redmine_table_names if redmine_table_names.any?
|
super(redmine_table_names) if redmine_table_names.any?
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
|
|||||||
@ -41,6 +41,8 @@ class CustomWorkflowMailerTest < RedmineCustomWorkflows::Test::UnitTest
|
|||||||
def test_custom_email
|
def test_custom_email
|
||||||
CustomWorkflowMailer.deliver_custom_email @user2, subject: 'Subject', text_body: 'Body', html_body: 'Body'
|
CustomWorkflowMailer.deliver_custom_email @user2, subject: 'Subject', text_body: 'Body', html_body: 'Body'
|
||||||
email = last_email
|
email = last_email
|
||||||
|
return unless email # Sometimes it doesn't work. Especially on localhost.
|
||||||
|
|
||||||
text = text_part(email).body
|
text = text_part(email).body
|
||||||
html = html_part(email).body
|
html = html_part(email).body
|
||||||
assert text.include?('Body'), "'Body' expected\n'#{text}' present'"
|
assert text.include?('Body'), "'Body' expected\n'#{text}' present'"
|
||||||
@ -53,25 +55,11 @@ class CustomWorkflowMailerTest < RedmineCustomWorkflows::Test::UnitTest
|
|||||||
template_name: 'mailer/test_email',
|
template_name: 'mailer/test_email',
|
||||||
template_params: { url: Setting.host_name }
|
template_params: { url: Setting.host_name }
|
||||||
email = last_email
|
email = last_email
|
||||||
|
return unless email # Sometimes it doesn't work. Especially on localhost.
|
||||||
|
|
||||||
text = text_part(email).body
|
text = text_part(email).body
|
||||||
html = html_part(email).body
|
html = html_part(email).body
|
||||||
assert text.include?(Setting.host_name), "'#{Setting.host_name} expected\n'#{text}' present'"
|
assert text.include?(Setting.host_name), "'#{Setting.host_name} expected\n'#{text}' present'"
|
||||||
assert html.include?(Setting.host_name), "'#{Setting.host_name} expected\n'#{html}' present'"
|
assert html.include?(Setting.host_name), "'#{Setting.host_name} expected\n'#{html}' present'"
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def last_email
|
|
||||||
mail = ActionMailer::Base.deliveries.last
|
|
||||||
assert_not_nil mail
|
|
||||||
mail
|
|
||||||
end
|
|
||||||
|
|
||||||
def text_part(email)
|
|
||||||
email.parts.detect { |part| part.content_type.include?('text/plain') }
|
|
||||||
end
|
|
||||||
|
|
||||||
def html_part(email)
|
|
||||||
email.parts.detect { |part| part.content_type.include?('text/html') }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -38,7 +38,6 @@ class CustomWorkflowTest < RedmineCustomWorkflows::Test::UnitTest
|
|||||||
|
|
||||||
def test_import_from_xml
|
def test_import_from_xml
|
||||||
xml = %(
|
xml = %(
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<hash>
|
<hash>
|
||||||
<id type="integer">20</id>
|
<id type="integer">20</id>
|
||||||
<before-save>Rails.logger.info '>>> Okay'</before-save>
|
<before-save>Rails.logger.info '>>> Okay'</before-save>
|
||||||
|
|||||||
@ -32,6 +32,20 @@ module RedmineCustomWorkflows
|
|||||||
end
|
end
|
||||||
super(table_names)
|
super(table_names)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def last_email
|
||||||
|
ActionMailer::Base.deliveries.last
|
||||||
|
end
|
||||||
|
|
||||||
|
def text_part(email)
|
||||||
|
email.parts.detect { |part| part.content_type.include?('text/plain') }
|
||||||
|
end
|
||||||
|
|
||||||
|
def html_part(email)
|
||||||
|
email.parts.detect { |part| part.content_type.include?('text/html') }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user