mirror of
https://github.com/anteo/redmine_custom_workflows.git
synced 2026-01-26 00:04:20 +00:00
Redmine look & feel
This commit is contained in:
parent
640f3aa077
commit
3f901f6bbb
@ -1,7 +1,7 @@
|
||||
Custom Workflows plug-in
|
||||
========================
|
||||
|
||||
The current version of Redmine CustomWorkflows is **1.0.2** [](https://travis-ci.org/anteo/redmine_custom_workflows)
|
||||
The current version of Redmine CustomWorkflows is **1.0.3 devel** [](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:
|
||||
|
||||
@ -99,23 +99,9 @@ class CustomWorkflowsController < ApplicationController
|
||||
|
||||
def create
|
||||
@workflow = CustomWorkflow.new
|
||||
@workflow.before_save = params[:custom_workflow][:before_save]
|
||||
@workflow.after_save = params[:custom_workflow][:after_save]
|
||||
@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] == '1'
|
||||
@workflow.author = params[:custom_workflow][:author]
|
||||
@workflow.active = params[:custom_workflow][:active]
|
||||
@workflow.observable = params[:custom_workflow][:observable]
|
||||
@workflow.shared_code = params[:custom_workflow][:shared_code]
|
||||
@workflow.before_add = params[:custom_workflow][:before_add]
|
||||
@workflow.after_add = params[:custom_workflow][:after_add]
|
||||
@workflow.before_remove = params[:custom_workflow][:before_remove]
|
||||
@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]
|
||||
update_from_params
|
||||
respond_to do |format|
|
||||
if params.has_key?(:commit) && @workflow.save
|
||||
flash[:notice] = l(:notice_successful_create)
|
||||
@ -140,21 +126,7 @@ class CustomWorkflowsController < ApplicationController
|
||||
|
||||
def update
|
||||
respond_to do |format|
|
||||
@workflow.before_save = params[:custom_workflow][:before_save]
|
||||
@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] == '1'
|
||||
@workflow.author = params[:custom_workflow][:author]
|
||||
@workflow.active = params[:custom_workflow][:active]
|
||||
@workflow.shared_code = params[:custom_workflow][:shared_code]
|
||||
@workflow.before_add = params[:custom_workflow][:before_add]
|
||||
@workflow.after_add = params[:custom_workflow][:after_add]
|
||||
@workflow.before_remove = params[:custom_workflow][:before_remove]
|
||||
@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]
|
||||
update_from_params
|
||||
if params.has_key?(:commit) && @workflow.save
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
format.html { redirect_to(custom_workflows_path) }
|
||||
@ -180,4 +152,22 @@ class CustomWorkflowsController < ApplicationController
|
||||
render_404
|
||||
end
|
||||
|
||||
def update_from_params
|
||||
@workflow.before_save = params[:custom_workflow][:before_save]
|
||||
@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] == '1'
|
||||
@workflow.author = params[:custom_workflow][:author]
|
||||
@workflow.active = params[:custom_workflow][:active]
|
||||
@workflow.shared_code = params[:custom_workflow][:shared_code]
|
||||
@workflow.before_add = params[:custom_workflow][:before_add]
|
||||
@workflow.after_add = params[:custom_workflow][:after_add]
|
||||
@workflow.before_remove = params[:custom_workflow][:before_remove]
|
||||
@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]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -31,11 +31,11 @@ class CustomWorkflow < ActiveRecord::Base
|
||||
acts_as_list
|
||||
|
||||
validates_presence_of :name
|
||||
validates_uniqueness_of :name, :case_sensitive => false
|
||||
validates_format_of :author, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, :allow_blank => true
|
||||
validate :validate_syntax, :validate_scripts_presence, :if => Proc.new {|workflow| workflow.respond_to?(:observable) and workflow.active?}
|
||||
validates_uniqueness_of :name, case_sensitive: false
|
||||
validates_format_of :author, with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, allow_blank: true
|
||||
validate :validate_syntax, :validate_scripts_presence, if: Proc.new { |workflow| workflow.respond_to?(:observable) and workflow.active? }
|
||||
|
||||
scope :active, lambda { where(:active => true) }
|
||||
scope :active, lambda { where(active: true) }
|
||||
scope :for_project, (lambda do |project|
|
||||
where("is_for_all=? OR EXISTS (SELECT * FROM #{reflect_on_association(:projects).join_table} WHERE project_id=? AND custom_workflow_id=id)",
|
||||
true, project.id)
|
||||
@ -43,11 +43,11 @@ class CustomWorkflow < ActiveRecord::Base
|
||||
|
||||
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)
|
||||
attributes.delete 'exported_at'
|
||||
attributes.delete 'plugin_version'
|
||||
attributes.delete 'ruby_version'
|
||||
attributes.delete 'rails_version'
|
||||
CustomWorkflow.new attributes
|
||||
end
|
||||
|
||||
def self.log_message(str, object)
|
||||
|
||||
@ -1,22 +1,45 @@
|
||||
<%
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Redmine plugin for Custom Workflows
|
||||
#
|
||||
# Copyright © 2015-19 Anton Argirov
|
||||
# Copyright © 2019-20 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.
|
||||
%>
|
||||
|
||||
<div class="splitcontent">
|
||||
<div class="splitcontentleft">
|
||||
<div class="box tabular">
|
||||
<p><%= f.text_field :name, :required => true, :size => 50 %></p>
|
||||
<p><%= f.text_field :author, :size => 50, :label => :field_custom_workflow_author %>
|
||||
<p><%= f.text_field :name, required: true %></p>
|
||||
<p><%= f.text_field :author, label: :field_custom_workflow_author %>
|
||||
<em class="info"><%= l(:text_custom_workflow_author) %></em>
|
||||
</p>
|
||||
<p><%= f.select :observable,
|
||||
CustomWorkflow::OBSERVABLES.collect {|o| [l("custom_workflow_observable_#{o}"), o]}, {},
|
||||
:onchange => 'this.form.submit()',
|
||||
:disabled => !@workflow.new_record? %></p>
|
||||
<p><%= f.text_area :description, cols: 40, rows: 5 , class: 'wiki-edit' %></p>
|
||||
CustomWorkflow::OBSERVABLES.collect { |o| [l("custom_workflow_observable_#{o}"), o] }, {},
|
||||
onchange: 'this.form.submit()',
|
||||
disabled: !@workflow.new_record? %></p>
|
||||
<p><%= f.text_area :description, 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>
|
||||
<% end %>
|
||||
<p><%= f.check_box :active, :label => :field_custom_workflow_active %></p>
|
||||
<p><%= f.check_box :active, label: l(:field_active) %></p>
|
||||
</div>
|
||||
</div>
|
||||
<% if @workflow.has_projects_association? %>
|
||||
@ -28,102 +51,94 @@
|
||||
<%= l(:label_project_plural) %>
|
||||
</legend>
|
||||
<%= render_project_nested_lists(Project.visible.active) do |p| %>
|
||||
<%= content_tag('label',
|
||||
<%= 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') %>
|
||||
disabled: @workflow.is_for_all?) + ' ' + h(p), class: 'block' %>
|
||||
<% end %>
|
||||
<%= hidden_field_tag('custom_workflow[project_ids][]', '', id: nil) %>
|
||||
<%= hidden_field_tag 'custom_workflow[project_ids][]', '', id: nil %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div style="clear: left;"></div>
|
||||
|
||||
<fieldset class="box">
|
||||
<legend><%= l(:label_workflow_scripts) %></legend>
|
||||
<% observable = @workflow.observable.to_sym %>
|
||||
<p>
|
||||
<em class="info"><%= l("text_custom_workflow_#{observable}_code_note") %></em>
|
||||
</p>
|
||||
<% case observable %>
|
||||
<% when :shared %>
|
||||
<%= f.text_area :shared_code, :cols => 40, :rows => 20, :wrap => 'off', :class => 'custom_workflow_script' %>
|
||||
<% when *CustomWorkflow::COLLECTION_OBSERVABLES %>
|
||||
<% collapsed = (not (@workflow.before_add.present? or @workflow.after_add.present? or @workflow.errors[:base].present?)) %>
|
||||
<fieldset class="collapsible <%= collapsed ? 'collapsed' : '' %>">
|
||||
<legend onclick="toggleFieldset(this);"><%= l(:label_add_workflows) %></legend>
|
||||
<div style="<%= collapsed ? 'display: none' : '' %>">
|
||||
<div class="splitcontent">
|
||||
<div class="splitcontentleft">
|
||||
<%= f.text_area :before_add, :cols => 40, :rows => 20, :wrap => 'off', :class => 'custom_workflow_script' %>
|
||||
</div>
|
||||
<div class="splitcontentright">
|
||||
<%= f.text_area :after_add, :cols => 40, :rows => 20, :wrap => 'off', :class => 'custom_workflow_script' %>
|
||||
<div id="custom_workflow_scripts" class="box tabular">
|
||||
<fieldset>
|
||||
<legend><%= l(:label_workflow_scripts) %></legend>
|
||||
<% observable = @workflow.observable.to_sym %>
|
||||
<div class="custom-workflow-info">
|
||||
<em class="info"><%= l("text_custom_workflow_#{observable}_code_note") %></em>
|
||||
</div>
|
||||
<% case observable %>
|
||||
<% when :shared %>
|
||||
<%= f.text_area :shared_code, cols: 40, rows: 20, wrap: 'off', class: 'custom_workflow_script' %>
|
||||
<% when *CustomWorkflow::COLLECTION_OBSERVABLES %>
|
||||
<% collapsed = !(@workflow.before_add.present? || @workflow.after_add.present? || @workflow.errors[:base].present?) %>
|
||||
<fieldset class="collapsible <%= collapsed ? 'collapsed' : '' %>">
|
||||
<legend onclick="toggleFieldset(this);" class="icon icon-collapsed"><%= l(:label_add_workflows) %></legend>
|
||||
<div class="<%= collapsed ? 'custom-workflow-hidden' : '' %>">
|
||||
<div class="splitcontent">
|
||||
<div class="splitcontentleft">
|
||||
<%= f.text_area :before_add, cols: 40, rows: 20, wrap: 'off', class: 'custom_workflow_script' %>
|
||||
</div>
|
||||
<div class="splitcontentright">
|
||||
<%= f.text_area :after_add, cols: 40, rows: 20, wrap: 'off', class: 'custom_workflow_script' %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<% collapsed = (not (@workflow.before_remove.present? or @workflow.after_remove.present?)) %>
|
||||
<fieldset class="collapsible <%= collapsed ? 'collapsed' : '' %>">
|
||||
<legend onclick="toggleFieldset(this);"><%= l(:label_remove_workflows) %></legend>
|
||||
<div style="<%= collapsed ? 'display: none' : '' %>">
|
||||
<div class="splitcontent">
|
||||
<div class="splitcontentleft">
|
||||
<%= f.text_area :before_remove, :cols => 40, :rows => 20, :wrap => 'off', :class => 'custom_workflow_script' %>
|
||||
</div>
|
||||
<div class="splitcontentright">
|
||||
<%= f.text_area :after_remove, :cols => 40, :rows => 20, :wrap => 'off', :class => 'custom_workflow_script' %>
|
||||
</fieldset>
|
||||
<% collapsed = !(@workflow.before_remove.present? || @workflow.after_remove.present?) %>
|
||||
<fieldset class="collapsible <%= collapsed ? 'collapsed' : '' %>">
|
||||
<legend onclick="toggleFieldset(this);" class="icon icon-collapsed"><%= l(:label_remove_workflows) %></legend>
|
||||
<div class="<%= collapsed ? 'custom-workflow-hidden' : '' %>">
|
||||
<div class="splitcontent">
|
||||
<div class="splitcontentleft">
|
||||
<%= f.text_area :before_remove, cols: 40, rows: 20, wrap: 'off', class: 'custom_workflow_script' %>
|
||||
</div>
|
||||
<div class="splitcontentright">
|
||||
<%= f.text_area :after_remove, cols: 40, rows: 20, wrap: 'off', class: 'custom_workflow_script' %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<% when *CustomWorkflow::SINGLE_OBSERVABLES %>
|
||||
<% collapsed = (not (@workflow.before_save.present? or @workflow.after_save.present? or @workflow.errors[:base].present?)) %>
|
||||
<fieldset class="collapsible <%= collapsed ? 'collapsed' : '' %>">
|
||||
<legend onclick="toggleFieldset(this);"><%= l(:label_save_workflows) %></legend>
|
||||
<div style="<%= collapsed ? 'display: none' : '' %>">
|
||||
<div class="splitcontent">
|
||||
<div class="splitcontentleft">
|
||||
<%= f.text_area :before_save, :cols => 40, :rows => 20, :wrap => 'off', :class => 'custom_workflow_script' %>
|
||||
<% if observable == :issue %>
|
||||
<em class="info"><%= l(:text_custom_workflow_before_save_note) %></em>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="splitcontentright">
|
||||
<%= f.text_area :after_save, :cols => 40, :rows => 20, :wrap => 'off', :class => 'custom_workflow_script' %>
|
||||
<% if observable == :issue %>
|
||||
<em class="info"><%= l(:text_custom_workflow_after_save_note) %></em>
|
||||
<% end %>
|
||||
</fieldset>
|
||||
<% when *CustomWorkflow::SINGLE_OBSERVABLES %>
|
||||
<% collapsed = (not (@workflow.before_save.present? or @workflow.after_save.present? or @workflow.errors[:base].present?)) %>
|
||||
<fieldset class="collapsible <%= collapsed ? 'collapsed' : '' %>">
|
||||
<legend onclick="toggleFieldset(this);" class="icon icon-collapsed"><%= l(:label_save_workflows) %></legend>
|
||||
<div class="<%= collapsed ? 'custom-workflow-hidden' : '' %>">
|
||||
<div class="splitcontent">
|
||||
<div class="splitcontentleft">
|
||||
<%= f.text_area :before_save, cols: 40, rows: 20, wrap: 'off', class: 'custom_workflow_script' %>
|
||||
<% if observable == :issue %>
|
||||
<em class="info"><%= l(:text_custom_workflow_before_save_note) %></em>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="splitcontentright">
|
||||
<%= f.text_area :after_save, cols: 40, rows: 20, wrap: 'off', class: 'custom_workflow_script' %>
|
||||
<% if observable == :issue %>
|
||||
<em class="info"><%= l(:text_custom_workflow_after_save_note) %></em>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<% collapsed = (not (@workflow.before_destroy.present? or @workflow.after_destroy.present?)) %>
|
||||
<fieldset class="collapsible <%= collapsed ? 'collapsed' : '' %>">
|
||||
<legend onclick="toggleFieldset(this);"><%= l(:label_destroy_workflows) %></legend>
|
||||
<div style="<%= collapsed ? 'display: none' : '' %>">
|
||||
<div class="splitcontent">
|
||||
<div class="splitcontentleft">
|
||||
<%= f.text_area :before_destroy, :cols => 40, :rows => 20, :wrap => 'off', :class => 'custom_workflow_script' %>
|
||||
</div>
|
||||
<div class="splitcontentright">
|
||||
<%= f.text_area :after_destroy, :cols => 40, :rows => 20, :wrap => 'off', :class => 'custom_workflow_script' %>
|
||||
</fieldset>
|
||||
<% collapsed = !(@workflow.before_destroy.present? || @workflow.after_destroy.present?) %>
|
||||
<fieldset class="collapsible <%= collapsed ? 'collapsed' : '' %>">
|
||||
<legend onclick="toggleFieldset(this);" class="icon icon-collapsed"><%= l(:label_destroy_workflows) %></legend>
|
||||
<div class="<%= collapsed ? 'custom-workflow-hidden' : '' %>">
|
||||
<div class="splitcontent">
|
||||
<div class="splitcontentleft">
|
||||
<%= f.text_area :before_destroy, cols: 40, rows: 20, wrap: 'off', class: 'custom_workflow_script' %>
|
||||
</div>
|
||||
<div class="splitcontentright">
|
||||
<%= f.text_area :after_destroy, cols: 40, rows: 20, wrap: 'off', class: 'custom_workflow_script' %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
</fieldset>
|
||||
|
||||
<script>
|
||||
$('.custom_workflow_script').taboverride(2, true);
|
||||
</script>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<%= wikitoolbar_for :custom_workflow_description %>
|
||||
|
||||
<% content_for :header_tags do %>
|
||||
<%= javascript_include_tag 'tab_override', plugin: 'redmine_custom_workflows' %>
|
||||
<% end %>
|
||||
@ -1,10 +1,33 @@
|
||||
<%
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Redmine plugin for Custom Workflows
|
||||
#
|
||||
# Copyright © 2015-19 Anton Argirov
|
||||
# Copyright © 2019-20 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.
|
||||
%>
|
||||
|
||||
<h2><%= link_to l(:label_custom_workflow_plural), custom_workflows_path %> » <%= @workflow %></h2>
|
||||
|
||||
<%= error_messages_for 'workflow' %>
|
||||
|
||||
<%= labelled_form_for @workflow do |f| %>
|
||||
<%= render :partial => 'form', :locals => {:f => f} %>
|
||||
<%= submit_tag l(:button_save) %>
|
||||
<%= render partial: 'form', locals: { f: f } %>
|
||||
<%= submit_tag l(:button_save) %>
|
||||
<% end %>
|
||||
|
||||
<% html_title(l(:label_custom_workflow_plural), @workflow, l(:label_administration)) -%>
|
||||
<% html_title l(:label_custom_workflow_plural), @workflow, l(:label_administration) %>
|
||||
|
||||
@ -1,85 +1,94 @@
|
||||
<% html_title(l(:label_custom_workflow_plural)) -%>
|
||||
<%
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Redmine plugin for Custom Workflows
|
||||
#
|
||||
# Copyright © 2015-19 Anton Argirov
|
||||
# Copyright © 2019-20 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.
|
||||
%>
|
||||
|
||||
<% html_title l(:label_custom_workflow_plural) %>
|
||||
<div class="contextual">
|
||||
<%= link_to l(:label_custom_workflow_import), '#', :class => 'icon icon-import', :onclick => "showModal('import-dialog', '450px'); return false;" %>
|
||||
<%= link_to l(:label_custom_workflow_new), new_custom_workflow_path, :class => 'icon icon-add' %>
|
||||
<%= link_to l(:label_custom_workflow_new), new_custom_workflow_path, class: 'icon icon-add' %>
|
||||
<%= actions_dropdown do %>
|
||||
<%= link_to l(:label_custom_workflow_import), '#', class: 'icon icon-move',
|
||||
onclick: "showModal('import-dialog', '450px'); return false;" %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<h2><%=l(:label_custom_workflow_plural)%></h2>
|
||||
<h2><%= l(:label_custom_workflow_plural) %></h2>
|
||||
|
||||
<div class="autoscroll">
|
||||
<% if @workflows.any? %>
|
||||
<table class="custom-workflows list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><%= l(:field_name) %></th>
|
||||
<th><%= l(:field_description) %></th>
|
||||
<th><%= l(:field_observable) %></th>
|
||||
<th><%= l(:field_author) %></th>
|
||||
<th><%= l(:label_project_plural) %></th>
|
||||
<th><%= l(:button_sort) %></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @workflows.each do |workflow| %>
|
||||
<tr class="<%= cycle("odd", "even") %> <%= 'disabled' unless workflow.active? %>">
|
||||
<td class="name"><%= link_to(workflow.name, edit_custom_workflow_path(workflow)) %></td>
|
||||
<td class="description"><%= textilizable(workflow.description) %></td>
|
||||
<td class="observable"><%= l("custom_workflow_observable_#{workflow.observable}") %></td>
|
||||
<td class="author"><%= mail_to workflow.author if workflow.author.present? %></td>
|
||||
<td>
|
||||
<% if not workflow.has_projects_association? %>
|
||||
-
|
||||
<% elsif workflow.is_for_all? %>
|
||||
<%= l(:field_enabled_for_all_projects) %>
|
||||
<% elsif workflow.projects.empty? %>
|
||||
<%= l(:text_no_enabled_projects) %>
|
||||
<% else %>
|
||||
<%= workflow.projects.map(&:name).join(", ") %>
|
||||
<% end %>
|
||||
</td>
|
||||
<td align="center" nowrap>
|
||||
<%= reorder_handle(workflow, url: url_for(action: 'reorder', id: workflow) ) %>
|
||||
</td>
|
||||
<td class="buttons">
|
||||
<div class="icon"></div>
|
||||
<% if workflow.active? %>
|
||||
<%= link_to(l(:button_custom_workflow_deactivate), custom_workflow_status_path(workflow, active: false), class: 'icon icon-lock', method: :post) %>
|
||||
<% else %>
|
||||
<%= link_to(l(:button_custom_workflow_activate), custom_workflow_status_path(workflow, active: true), class: 'icon icon-unlock', method: :post) %>
|
||||
<% end %>
|
||||
<br/>
|
||||
<%= link_to(l(:label_custom_workflow_export), export_custom_workflow_path(workflow), class: 'icon icon-export', method: :get) %>
|
||||
<br/>
|
||||
<%= link_to(l(:button_delete), workflow, class: 'icon icon-del', data: { confirm: l(:text_are_you_sure) }, confirm: l(:text_are_you_sure), method: :delete) %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="custom-workflows list" data-hascontextmenu="true">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><%= l(:field_name) %></th>
|
||||
<th><%= l(:field_observable) %></th>
|
||||
<th><%= l(:field_author) %></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @workflows.each do |workflow| %>
|
||||
<tr class="<%= cycle('odd', 'even') %> <%= 'disabled' unless workflow.active? %>">
|
||||
<td class="name"><%= link_to workflow.name, edit_custom_workflow_path(workflow) %></td>
|
||||
<td class="observable"><%= l("custom_workflow_observable_#{workflow.observable}") %></td>
|
||||
<td class="author"><%= mail_to workflow.author if workflow.author.present? %></td>
|
||||
<td class="buttons">
|
||||
<%= reorder_handle workflow, url: url_for(action: 'reorder', id: workflow) %>
|
||||
<% if workflow.active? %>
|
||||
<%= link_to l(:button_custom_workflow_deactivate), custom_workflow_status_path(workflow, active: false),
|
||||
class: 'icon icon-lock', method: :post %>
|
||||
<% else %>
|
||||
<%= link_to l(:button_activate), custom_workflow_status_path(workflow, active: true),
|
||||
class: 'icon icon-unlock', method: :post %>
|
||||
<% end %>
|
||||
<%= link_to l(:label_custom_workflow_export), 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) },
|
||||
confirm: l(:text_are_you_sure), method: :delete %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% else %>
|
||||
<p class="nodata"><%= l(:label_no_data) %></p>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div id="import-dialog" style="display: none">
|
||||
<div id="import-dialog" class="custom-workflow-hidden">
|
||||
<h3 class="title"><%= l(:label_custom_workflow_import) %></h3>
|
||||
<%= form_tag import_custom_workflow_path, :multipart => true do %>
|
||||
<p>
|
||||
<%= l(:field_custom_workflow_file) %>:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<%= file_field_tag 'file', :accept => 'application/xml' %>
|
||||
<%= file_field_tag 'file', accept: 'application/xml' %>
|
||||
</p>
|
||||
|
||||
<p class="buttons">
|
||||
<%= submit_tag l(:button_import), :name => nil, :onclick => "hideModal(this);" %>
|
||||
<%= submit_tag l(:button_cancel), :name => nil, :onclick => "hideModal(this);", :type => 'button' %>
|
||||
<%= submit_tag l(:button_import), name: nil, onclick: 'hideModal(this);' %>
|
||||
<%= submit_tag l(:button_cancel), name: nil, onclick: 'hideModal(this);', type: 'button' %>
|
||||
</p>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= javascript_tag do %>
|
||||
$(function() { $("table.custom-workflows tbody").positionedItems(); });
|
||||
$(function() {
|
||||
$("table.custom-workflows tbody").positionedItems();
|
||||
});
|
||||
<% end %>
|
||||
|
||||
@ -1,10 +1,33 @@
|
||||
<%
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Redmine plugin for Custom Workflows
|
||||
#
|
||||
# Copyright © 2015-19 Anton Argirov
|
||||
# Copyright © 2019-20 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.
|
||||
%>
|
||||
|
||||
<h2><%= link_to l(:label_custom_workflow_plural), custom_workflows_path %> » <%= l(:label_custom_workflow_new) %></h2>
|
||||
|
||||
<%= error_messages_for 'workflow' %>
|
||||
|
||||
<%= labelled_form_for @workflow do |f| %>
|
||||
<%= render :partial => 'form', :locals => {:f => f} %>
|
||||
<%= submit_tag l(:button_create) %>
|
||||
<%= render partial: 'form', locals: { f: f } %>
|
||||
<%= submit_tag l(:button_create) %>
|
||||
<% end %>
|
||||
|
||||
<% html_title(l(:label_custom_workflow_plural), l(:label_custom_workflow_new), l(:label_administration)) -%>
|
||||
<% html_title l(:label_custom_workflow_plural), l(:label_custom_workflow_new), l(:label_administration) %>
|
||||
|
||||
@ -1,3 +1,26 @@
|
||||
<%
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Redmine plugin for Custom Workflows
|
||||
#
|
||||
# Copyright © 2015-19 Anton Argirov
|
||||
# Copyright © 2019-20 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.
|
||||
%>
|
||||
|
||||
<%= form_for @project do %>
|
||||
<%= hidden_field_tag :tab, 'custom_workflow' %>
|
||||
<%= hidden_field_tag 'project[custom_workflow_ids][]', '' %>
|
||||
@ -18,7 +41,7 @@
|
||||
<% end %>
|
||||
</label>
|
||||
</dt>
|
||||
<dd class="<%= 'disabled' unless w.active? %>"><em><%= textilizable(w.description) %></em></dd>
|
||||
<dd class="<%= 'disabled' unless w.active? %>"><em><%= textilizable w.description %></em></dd>
|
||||
<% end %>
|
||||
</dl>
|
||||
<% else %>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 247 B |
Binary file not shown.
|
Before Width: | Height: | Size: 259 B |
@ -1,353 +0,0 @@
|
||||
/* encoding: utf-8
|
||||
*
|
||||
* Redmine plugin for Custom Workflows
|
||||
*
|
||||
* Copyright © 2015-19 Anton Argirov
|
||||
* Copyright © 2019-20 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() {
|
||||
$(this).data('taboverride', new TabOverride(this, tabSize, autoIndent));
|
||||
});
|
||||
};
|
||||
|
||||
function TabOverride(element, tabSize, autoIndent) {
|
||||
let ta = document.createElement('textarea');
|
||||
ta.value = '\n';
|
||||
|
||||
this.newline = ta.value;
|
||||
this.newlineLen = this.newline.length;
|
||||
this.autoIndent = autoIndent;
|
||||
this.inWhitespace = false;
|
||||
this.element = element;
|
||||
this.setTabSize(tabSize);
|
||||
|
||||
$(element).on('keypress', $.proxy(this.overrideKeyPress, this));
|
||||
$(element).on('keydown', $.proxy(this.overrideKeyDown, this));
|
||||
}
|
||||
|
||||
TabOverride.prototype = {
|
||||
/**
|
||||
* Returns the current tab size. 0 represents the tab character.
|
||||
*
|
||||
* @return {Number} the size (length) of the tab string or 0 for the tab character
|
||||
*
|
||||
* @name getTabSize
|
||||
* @function
|
||||
*/
|
||||
getTabSize:function () {
|
||||
return this.aTab === '\t' ? 0 : this.aTab.length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the tab size for all elements that have Tab Override enabled.
|
||||
* 0 represents the tab character.
|
||||
*
|
||||
* @param {Number} size the tab size (default = 0)
|
||||
*
|
||||
* @name setTabSize
|
||||
* @function
|
||||
*/
|
||||
setTabSize:function (size) {
|
||||
if (!size) { // size is 0 or not specified (or falsy)
|
||||
this.aTab = '\t';
|
||||
} else if (typeof size === 'number' && size > 0) {
|
||||
this.aTab = '';
|
||||
for (let i = 0; i < size; i += 1) {
|
||||
this.aTab += ' ';
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Prevents the default action for the keyPress event when tab or enter are
|
||||
* pressed. Opera (and Firefox) also fire a keypress event when the tab or
|
||||
* enter key is pressed. Opera requires that the default action be prevented
|
||||
* on this event or the textarea will lose focus.
|
||||
*
|
||||
* @param {Event} e the event object
|
||||
* @private
|
||||
*/
|
||||
overrideKeyPress:function (e) {
|
||||
let key = e.keyCode;
|
||||
if ((key === 9 || (key === 13 && this.autoIndent && !this.inWhitespace)) && !e.ctrlKey && !e.altKey) {
|
||||
e.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Inserts / removes tabs and newlines on the keyDown event for the tab or enter key.
|
||||
*
|
||||
* @param {Event} e the event object
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
overrideKeyDown:function (e) {
|
||||
let key = e.keyCode, // the key code for the key that was pressed
|
||||
tab, // the string representing a tab
|
||||
tabLen, // the length of a tab
|
||||
text, // initial text in the textarea
|
||||
range, // the IE TextRange object
|
||||
tempRange, // used to calculate selection start and end positions in IE
|
||||
preNewlines, // the number of newline character sequences before the selection start (for IE)
|
||||
selNewlines, // the number of newline character sequences within the selection (for IE)
|
||||
initScrollTop, // initial scrollTop value used to fix scrolling in Firefox
|
||||
selStart, // the selection start position
|
||||
selEnd, // the selection end position
|
||||
sel, // the selected text
|
||||
startLine, // for multi-line selections, the first character position of the first line
|
||||
endLine, // for multi-line selections, the last character position of the last line
|
||||
numTabs, // the number of tabs inserted / removed in the selection
|
||||
startTab, // if a tab was removed from the start of the first line
|
||||
preTab, // if a tab was removed before the start of the selection
|
||||
whitespace, // the whitespace at the beginning of the first selected line
|
||||
whitespaceLen; // the length of the whitespace at the beginning of the first selected line
|
||||
|
||||
// don't do any unnecessary work
|
||||
if ((key !== 9 && (key !== 13 || !this.autoIndent)) || e.ctrlKey || e.altKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize variables used for tab and enter keys
|
||||
this.inWhitespace = false; // this will be set to true if enter is pressed in the leading whitespace
|
||||
text = this.element.value;
|
||||
|
||||
// this is really just for Firefox, but will be used by all browsers that support
|
||||
// selectionStart and selectionEnd - whenever the textarea value property is reset,
|
||||
// Firefox scrolls back to the top - this is used to set it back to the original value
|
||||
// scrollTop is nonstandard, but supported by all modern browsers
|
||||
initScrollTop = this.element.scrollTop;
|
||||
|
||||
// get the text selection
|
||||
// prefer the nonstandard document.selection way since it allows for
|
||||
// automatic scrolling to the cursor via the range.select() method
|
||||
if (document.selection) { // IE
|
||||
range = document.selection.createRange();
|
||||
sel = range.text;
|
||||
tempRange = range.duplicate();
|
||||
tempRange.moveToElementText(this.element);
|
||||
tempRange.setEndPoint('EndToEnd', range);
|
||||
selEnd = tempRange.text.length;
|
||||
selStart = selEnd - sel.length;
|
||||
|
||||
// whenever the value of the textarea is changed, the range needs to be reset
|
||||
// IE <9 (and Opera) use both \r and \n for newlines - this adds an extra character
|
||||
// that needs to be accounted for when doing position calculations with ranges
|
||||
// these values are used to offset the selection start and end positions
|
||||
if (this.newlineLen > 1) {
|
||||
preNewlines = text.slice(0, selStart).split(this.newline).length - 1;
|
||||
selNewlines = sel.split(this.newline).length - 1;
|
||||
} else {
|
||||
preNewlines = selNewlines = 0;
|
||||
}
|
||||
} else if (typeof this.element.selectionStart !== 'undefined') {
|
||||
selStart = this.element.selectionStart;
|
||||
selEnd = this.element.selectionEnd;
|
||||
sel = text.slice(selStart, selEnd);
|
||||
} else {
|
||||
return; // cannot access textarea selection - do nothing
|
||||
}
|
||||
|
||||
// tab key - insert / remove tab
|
||||
if (key === 9) {
|
||||
// initialize tab variables
|
||||
tab = this.aTab;
|
||||
tabLen = tab.length;
|
||||
numTabs = 0;
|
||||
startTab = 0;
|
||||
preTab = 0;
|
||||
|
||||
// multi-line selection
|
||||
if (selStart !== selEnd && sel.indexOf('\n') !== -1) {
|
||||
if (text.charAt(selEnd - 1) === '\n') {
|
||||
selEnd = selEnd - this.newlineLen;
|
||||
sel = text.slice(selStart, selEnd);
|
||||
}
|
||||
// for multiple lines, only insert / remove tabs from the beginning of each line
|
||||
|
||||
// find the start of the first selected line
|
||||
if (selStart === 0 || text.charAt(selStart - 1) === '\n') {
|
||||
// the selection starts at the beginning of a line
|
||||
startLine = selStart;
|
||||
} else {
|
||||
// the selection starts after the beginning of a line
|
||||
// set startLine to the beginning of the first partially selected line
|
||||
// subtract 1 from selStart in case the cursor is at the newline character,
|
||||
// for instance, if the very end of the previous line was selected
|
||||
// add 1 to get the next character after the newline
|
||||
// if there is none before the selection, lastIndexOf returns -1
|
||||
// when 1 is added to that it becomes 0 and the first character is used
|
||||
startLine = text.lastIndexOf('\n', selStart - 1) + 1;
|
||||
}
|
||||
|
||||
// find the end of the last selected line
|
||||
if (selEnd === text.length || text.charAt(selEnd) === '\n') {
|
||||
// the selection ends at the end of a line
|
||||
endLine = selEnd;
|
||||
} else {
|
||||
// the selection ends before the end of a line
|
||||
// set endLine to the end of the last partially selected line
|
||||
endLine = text.indexOf('\n', selEnd);
|
||||
if (endLine === -1) {
|
||||
endLine = text.length;
|
||||
}
|
||||
}
|
||||
// if the shift key was pressed, remove tabs instead of inserting them
|
||||
if (e.shiftKey) {
|
||||
if (text.slice(startLine).indexOf(tab) === 0) {
|
||||
// is this tab part of the selection?
|
||||
if (startLine === selStart) {
|
||||
// it is, remove it
|
||||
sel = sel.slice(tabLen);
|
||||
} else {
|
||||
// the tab comes before the selection
|
||||
preTab = tabLen;
|
||||
}
|
||||
startTab = tabLen;
|
||||
}
|
||||
|
||||
this.element.value = text.slice(0, startLine) + text.slice(startLine + preTab, selStart) +
|
||||
sel.replace(new RegExp('\n' + tab, 'g'), function () {
|
||||
numTabs += 1;
|
||||
return '\n';
|
||||
}) + text.slice(selEnd);
|
||||
|
||||
// set start and end points
|
||||
if (range) { // IE
|
||||
// setting end first makes calculations easier
|
||||
range.collapse();
|
||||
range.moveEnd('character', selEnd - startTab - (numTabs * tabLen) - selNewlines - preNewlines);
|
||||
range.moveStart('character', selStart - preTab - preNewlines);
|
||||
range.select();
|
||||
} else {
|
||||
// set start first for Opera
|
||||
this.element.selectionStart = selStart - preTab; // preTab is 0 or tabLen
|
||||
// move the selection end over by the total number of tabs removed
|
||||
this.element.selectionEnd = selEnd - startTab - (numTabs * tabLen);
|
||||
}
|
||||
} else { // no shift key
|
||||
numTabs = 1; // for the first tab
|
||||
// insert tabs at the beginning of each line of the selection
|
||||
this.element.value = text.slice(0, startLine) + tab + text.slice(startLine, selStart) +
|
||||
sel.replace(/\n/g, function () {
|
||||
numTabs += 1;
|
||||
return '\n' + tab;
|
||||
}) + text.slice(selEnd);
|
||||
|
||||
// set start and end points
|
||||
if (range) { // IE
|
||||
range.collapse();
|
||||
range.moveEnd('character', selEnd + (numTabs * tabLen) - selNewlines - preNewlines);
|
||||
range.moveStart('character', selStart + tabLen - preNewlines);
|
||||
range.select();
|
||||
} else {
|
||||
// the selection start is always moved by 1 character
|
||||
this.element.selectionStart = selStart + (selStart == startLine ? 0 : tabLen);
|
||||
// move the selection end over by the total number of tabs inserted
|
||||
this.element.selectionEnd = selEnd + (numTabs * tabLen);
|
||||
this.element.scrollTop = initScrollTop;
|
||||
}
|
||||
}
|
||||
} else { // single line selection
|
||||
// if the shift key was pressed, remove a tab instead of inserting one
|
||||
if (e.shiftKey) {
|
||||
// if the character before the selection is a tab, remove it
|
||||
if (text.slice(selStart - tabLen).indexOf(tab) === 0) {
|
||||
this.element.value = text.slice(0, selStart - tabLen) + text.slice(selStart);
|
||||
|
||||
// set start and end points
|
||||
if (range) { // IE
|
||||
// collapses range and moves it by -1 tab
|
||||
range.move('character', selStart - tabLen - preNewlines);
|
||||
range.select();
|
||||
} else {
|
||||
this.element.selectionEnd = this.element.selectionStart = selStart - tabLen;
|
||||
this.element.scrollTop = initScrollTop;
|
||||
}
|
||||
}
|
||||
} else { // no shift key - insert a tab
|
||||
if (range) { // IE
|
||||
range.text = tab;
|
||||
range.select();
|
||||
} else {
|
||||
this.element.value = text.slice(0, selStart) + tab + text.slice(selEnd);
|
||||
this.element.selectionEnd = this.element.selectionStart = selStart + tabLen;
|
||||
this.element.scrollTop = initScrollTop;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (this.autoIndent) { // Enter key
|
||||
// insert a newline and copy the whitespace from the beginning of the line
|
||||
// find the start of the first selected line
|
||||
if (selStart === 0 || text.charAt(selStart - 1) === '\n') {
|
||||
// the selection starts at the beginning of a line
|
||||
// do nothing special
|
||||
this.inWhitespace = true;
|
||||
return;
|
||||
} else {
|
||||
// see explanation under "multi-line selection" above
|
||||
startLine = text.lastIndexOf('\n', selStart - 1) + 1;
|
||||
}
|
||||
|
||||
// find the end of the first selected line
|
||||
endLine = text.indexOf('\n', selStart);
|
||||
|
||||
// if no newline is found, set endLine to the end of the text
|
||||
if (endLine === -1) {
|
||||
endLine = text.length;
|
||||
}
|
||||
|
||||
// get the whitespace at the beginning of the first selected line (spaces and tabs only)
|
||||
whitespace = text.slice(startLine, endLine).match(/^[ \t]*/)[0];
|
||||
whitespaceLen = whitespace.length;
|
||||
|
||||
// the cursor (selStart) is in the whitespace at beginning of the line
|
||||
// do nothing special
|
||||
if (selStart < startLine + whitespaceLen) {
|
||||
this.inWhitespace = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (range) { // IE
|
||||
// insert the newline and whitespace
|
||||
range.text = '\n' + whitespace;
|
||||
range.select();
|
||||
} else {
|
||||
// insert the newline and whitespace
|
||||
this.element.value = text.slice(0, selStart) + '\n' + whitespace + text.slice(selEnd);
|
||||
// Opera uses \r\n for a newline, instead of \n,
|
||||
// so use newlineLen instead of a hard-coded value
|
||||
this.element.selectionEnd = this.element.selectionStart = selStart + this.newlineLen + whitespaceLen;
|
||||
this.element.scrollTop = initScrollTop;
|
||||
}
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
})(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');
|
||||
}
|
||||
}
|
||||
@ -23,44 +23,27 @@
|
||||
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.root {
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Icons */
|
||||
.icon-import {
|
||||
background-image: url(../images/export.png);
|
||||
.custom-workflow-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.icon-export {
|
||||
background-image: url(../images/import.png);
|
||||
.custom-workflow-info {
|
||||
text-align: justify;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
div#custom_workflow_scripts label {
|
||||
font-weight: normal;
|
||||
text-align: left;
|
||||
margin-left: 0;
|
||||
width: auto;
|
||||
}
|
||||
@ -27,7 +27,6 @@ cs:
|
||||
label_custom_workflow_plural: Uživatelské procesy
|
||||
label_custom_workflow_new: Vytvořit uživatelský proces
|
||||
label_workflow_scripts: Skript procesu
|
||||
label_enabled_projects: Povoleno pro projekt(y)
|
||||
label_custom_workflow_export: Export
|
||||
label_custom_workflow_import: Importovat proces
|
||||
label_save_workflows: Uložení sledovaných objektů
|
||||
@ -35,8 +34,6 @@ cs:
|
||||
label_add_workflows: Přidání sledovaných objektů do sezanmu
|
||||
label_remove_workflows: Odstranění sledovaných objektů za seznamu
|
||||
|
||||
button_import: Import
|
||||
button_custom_workflow_activate: Aktivovat
|
||||
button_custom_workflow_deactivate: Deaktivovat
|
||||
|
||||
field_after_save: Skript spuštěný po uložení sledovaného objektu
|
||||
@ -49,11 +46,9 @@ cs:
|
||||
field_before_remove: Skript spuštěný před odstraněním sledovaného objektu ze seznamu
|
||||
field_shared_code: Sdílený kód
|
||||
field_observable: Sledovaný objekt
|
||||
field_is_enabled: Povoleno
|
||||
field_enabled_for_all_projects: Povoleno pro všechny projekty
|
||||
field_custom_workflow_author: Autorův e-mail
|
||||
field_custom_workflow_file: Select the XML file previously exported process
|
||||
field_custom_workflow_active: Aktivní
|
||||
field_custom_workflow:
|
||||
script: Skript
|
||||
|
||||
@ -70,8 +65,8 @@ cs:
|
||||
scripts_absent: Musí být definován alespoň jeden skript
|
||||
|
||||
text_select_project_custom_workflows: Vyberte uživatelský skript projektu
|
||||
text_custom_workflow_before_save_note: "Zde můžete měnit vlastnosti úkolu. Ve skriptu nevytvářejte ani neměňte
|
||||
související úkoly. Pro ukončení skriptu chybou použijte: `raise WorkflowError, 'Zpráva uživateli'`."
|
||||
text_custom_workflow_before_save_note: Zde můžete měnit vlastnosti úkolu. Ve skriptu nevytvářejte ani neměňte
|
||||
související úkoly. Pro ukončení skriptu chybou použijte `raise WorkflowError, 'Zpráva uživateli'`.
|
||||
text_custom_workflow_after_save_note: Zde můžete aktualizovat nebo vytvářet souvissející úkoly. Mějte na paměti, že
|
||||
tento skript bude také vykonán pro nově vytvořené úkoly. Takže nezapomeňte udělat vhodné kontroly pro zabránění
|
||||
rekurzivnímu volání.
|
||||
|
||||
@ -20,87 +20,101 @@
|
||||
# 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"
|
||||
project_module_custom_workflows_module: Custom workflows
|
||||
permission_manage_project_workflow: Manage project custom workflows
|
||||
|
||||
label_custom_workflow: "Custom workflows"
|
||||
label_custom_workflow_plural: "Custom workflows"
|
||||
label_custom_workflow_new: "Create a custom workflow"
|
||||
label_workflow_scripts: "Workflow scripts"
|
||||
label_enabled_projects: "Enabled for project(s)"
|
||||
label_custom_workflow_export: "Export"
|
||||
label_custom_workflow_import: "Import workflow"
|
||||
label_save_workflows: "Saving observable objects"
|
||||
label_destroy_workflows: "Destroying observable objects"
|
||||
label_add_workflows: "Adding observable objects to collection"
|
||||
label_remove_workflows: "Removing observable objects from collection"
|
||||
label_custom_workflow: Custom workflow
|
||||
label_custom_workflow_plural: Custom workflows
|
||||
label_custom_workflow_new: Create a custom workflow
|
||||
label_workflow_scripts: Workflow scripts
|
||||
label_custom_workflow_export: Export
|
||||
label_custom_workflow_import: Import workflow
|
||||
label_save_workflows: Saving observable objects
|
||||
label_destroy_workflows: Destroying observable objects
|
||||
label_add_workflows: Adding observable objects to collection
|
||||
label_remove_workflows: Removing observable objects from collection
|
||||
|
||||
button_import: "Import"
|
||||
button_custom_workflow_activate: "Activate"
|
||||
button_custom_workflow_deactivate: "Deactivate"
|
||||
button_custom_workflow_deactivate: Deactivate
|
||||
|
||||
field_after_save: "Workflow script executable after saving observable object"
|
||||
field_before_save: "Workflow script executable before saving observable object"
|
||||
field_after_destroy: "Workflow script executable after destroying observable object"
|
||||
field_before_destroy: "Workflow script executable before destroying observable object"
|
||||
field_after_add: "Workflow script executable after adding observable object to collection"
|
||||
field_before_add: "Workflow script executable before adding observable object to collection"
|
||||
field_after_remove: "Workflow script executable after removing observable object from collection"
|
||||
field_before_remove: "Workflow script executable before removing observable object from collection"
|
||||
field_shared_code: "Shared code"
|
||||
field_observable: "Observable object"
|
||||
field_is_enabled: "Enabled"
|
||||
field_enabled_for_all_projects: "Enabled for all projects"
|
||||
field_custom_workflow_author: "Author's e-mail"
|
||||
field_custom_workflow_file: "Select the XML file previously exported process"
|
||||
field_custom_workflow_active: "Active"
|
||||
field_after_save: Workflow script executable after saving observable object
|
||||
field_before_save: Workflow script executable before saving observable object
|
||||
field_after_destroy: Workflow script executable after destroying observable object
|
||||
field_before_destroy: Workflow script executable before destroying observable object
|
||||
field_after_add: Workflow script executable after adding observable object to collection
|
||||
field_before_add: Workflow script executable before adding observable object to collection
|
||||
field_after_remove: Workflow script executable after removing observable object from collection
|
||||
field_before_remove: Workflow script executable before removing observable object from collection
|
||||
field_shared_code: Shared code
|
||||
field_observable: Observable object
|
||||
field_enabled_for_all_projects: Enabled for all projects
|
||||
field_custom_workflow_author: Author's e-mail
|
||||
field_custom_workflow_file: Select the XML file previously exported process
|
||||
field_custom_workflow:
|
||||
script: "Workflow script"
|
||||
script: Workflow script
|
||||
|
||||
notice_successful_import: "Custom workflow has successfully imported"
|
||||
notice_successful_status_change: "Status has successfully changed"
|
||||
error_failed_import: "Error importing custom workflow (unknown format? please see log)"
|
||||
notice_successful_import: Custom workflow has successfully imported
|
||||
notice_successful_status_change: Status has successfully changed
|
||||
error_failed_import: Error importing custom workflow (unknown format? please see log)
|
||||
|
||||
activerecord:
|
||||
errors:
|
||||
messages:
|
||||
invalid_script: "contains error: %{error}"
|
||||
custom_workflow_error: "Custom workflow error (please contact administrator)"
|
||||
custom_workflow_error: Custom workflow error (Please contact an administrator)
|
||||
new_status_invalid: "transition from '%{old_status}' to '%{new_status}' is prohibited"
|
||||
scripts_absent: "At least one script should be defined"
|
||||
scripts_absent: At least one script should be defined
|
||||
|
||||
text_select_project_custom_workflows: Select project custom workflows
|
||||
text_custom_workflow_before_save_note: You can change properties of the issues here. Do not create or update related issues in this script. To finish with error, use raise WorkflowError, "Message to user".
|
||||
text_custom_workflow_after_save_note: You can update or create related issues here. Note that this script will be also executed for the newly created issues. So make appropriate checks to prevent infinite recursion.
|
||||
text_custom_workflow_issue_code_note: Scripts are executed in the context of Issue object like ordinary before_save and after_save callbacks. So use methods and properties of the issue directly (or through "self"). Instance variables (@variable) are also allowed and may be used if needed.
|
||||
text_custom_workflow_shared_code_note: This code will run before any other workflow and may contain shared code, e.g. functions and classes needed by other workflows
|
||||
text_custom_workflow_user_code_note: Scripts are executed in the context of User object when user object changes (destroys). Use methods and properties of the user directly (or through "self")
|
||||
text_custom_workflow_group_code_note: Scripts are executed in the context of Group object when group object changes (destroys). Use methods and properties of the group directly (or through "self")
|
||||
text_custom_workflow_group_users_code_note: These scripts are executed when user being added to group/removed from group. Use variables @user and @group to access appropriate objects in your scripts.
|
||||
text_custom_workflow_attachment_code_note: Scripts are executed in the context of Attachment object when attachment object changes (destroys). Use methods and properties of the attachment object directly (or through "self"). Note that these scripts will affect all attachment types (issue, document, wiki pages and etc), so you should check 'container_type' field additionally in your script or select specific "... Attachments" observable object.
|
||||
text_custom_workflow_issue_attachments_code_note: These scripts are executed when attachment being added to issue/removed from issue. Use variables @issue and @attachment to access appropriate objects in your scripts.
|
||||
text_custom_workflow_project_code_note: Scripts are executed in the context of Project object when project object changes (destroys). Use methods and properties of the project directly (or through "self")
|
||||
text_custom_workflow_project_attachments_code_note: These scripts are executed when a file being added to project/removed from project. Use variables @project and @attachment to access appropriate objects in your scripts.
|
||||
text_custom_workflow_wiki_content_code_note: Scripts are executed in the context of Wiki Content object when project object changes (destroys). Use methods and properties of the project directly (or through "self")
|
||||
text_custom_workflow_wiki_page_attachments_code_note: These scripts are executed when a file being added to wiki page/removed from wiki page. Use variables @page and @attachment to access appropriate objects in your scripts.
|
||||
text_custom_workflow_time_entry_code_note: Scripts are executed in the context of TimeEntry object when time enty object changes (destroys). Use methods and properties of the time entry directly (or through "self")
|
||||
text_custom_workflow_version_code_note: Scripts are executed in the context of Version object when version object changes (destroys). Use methods and properties of the version directly (or through "self")
|
||||
text_custom_workflow_before_save_note: You can change properties of the issues here. Do not create or update related
|
||||
issues in this script. To finish with error, use `raise WorkflowError, 'Message to user'`.
|
||||
text_custom_workflow_after_save_note: You can update or create related issues here. Note that this script will be
|
||||
also executed for the newly created issues. So make appropriate checks to prevent infinite recursion.
|
||||
|
||||
text_custom_workflow_issue_code_note: Scripts are executed in the context of Issue object like ordinary
|
||||
before_save and after_save callbacks. So use methods and properties of the issue directly (or through `self`).
|
||||
Instance variables (@variable) are also allowed and may be used if needed.
|
||||
text_custom_workflow_shared_code_note: This code will run before any other workflow and may contain shared code,
|
||||
e.g. functions and classes needed by other workflows
|
||||
text_custom_workflow_user_code_note: Scripts are executed in the context of User object when user object changes
|
||||
(destroys). Use methods and properties of the user directly (or through `self`)
|
||||
text_custom_workflow_group_code_note: Scripts are executed in the context of Group object when group object changes
|
||||
(destroys). Use methods and properties of the group directly (or through `self`)
|
||||
text_custom_workflow_group_users_code_note: These scripts are executed when user being added to group/removed from
|
||||
group. Use variables @user and @group to access appropriate objects in your scripts.
|
||||
text_custom_workflow_attachment_code_note: Scripts are executed in the context of Attachment object when attachment
|
||||
object changes (destroys). Use methods and properties of the attachment object directly (or through `self`). Note that
|
||||
these scripts will affect all attachment types (issue, document, wiki pages and etc), so you should check
|
||||
'container_type' field additionally in your script or select specific '... Attachments' observable object.
|
||||
text_custom_workflow_issue_attachments_code_note: These scripts are executed when attachment being added to
|
||||
issue/removed from issue. Use variables @issue and @attachment to access appropriate objects in your scripts.
|
||||
text_custom_workflow_project_code_note: Scripts are executed in the context of Project object when project object
|
||||
changes (destroys). Use methods and properties of the project directly (or through `self`)
|
||||
text_custom_workflow_project_attachments_code_note: These scripts are executed when a file being added to
|
||||
project/removed from project. Use variables @project and @attachment to access appropriate objects in your scripts.
|
||||
text_custom_workflow_wiki_content_code_note: Scripts are executed in the context of Wiki Content object when project
|
||||
object changes (destroys). Use methods and properties of the project directly (or through `self`)
|
||||
text_custom_workflow_wiki_page_attachments_code_note: These scripts are executed when a file being added to wiki
|
||||
page/removed from wiki page. Use variables @page and @attachment to access appropriate objects in your scripts.
|
||||
text_custom_workflow_time_entry_code_note: Scripts are executed in the context of TimeEntry object when time enty
|
||||
object changes (destroys). Use methods and properties of the time entry directly (or through `self`)
|
||||
text_custom_workflow_version_code_note: Scripts are executed in the context of Version object when version object
|
||||
changes (destroys). Use methods and properties of the version directly (or through `self`)
|
||||
|
||||
text_no_enabled_projects: No projects
|
||||
text_custom_workflow_author: Will be included in exported XML
|
||||
text_custom_workflow_disabled: disabled by admin
|
||||
text_custom_workflow_is_for_all: enabled for all projects
|
||||
|
||||
custom_workflow_observable_shared: "<shared code>"
|
||||
custom_workflow_observable_issue: "Issue"
|
||||
custom_workflow_observable_issue_attachments: "Issue Attachments"
|
||||
custom_workflow_observable_group: "Group"
|
||||
custom_workflow_observable_user: "User"
|
||||
custom_workflow_observable_attachment: "Attachment"
|
||||
custom_workflow_observable_project: "Project"
|
||||
custom_workflow_observable_project_attachments: "Project Attachments / Files"
|
||||
custom_workflow_observable_wiki_content: "Wiki Content"
|
||||
custom_workflow_observable_wiki_page_attachments: "Wiki Page Attachments"
|
||||
custom_workflow_observable_group_users: "Group Users"
|
||||
custom_workflow_observable_time_entry: "Time Entry"
|
||||
custom_workflow_observable_version: "Version"
|
||||
custom_workflow_observable_shared: <shared code>
|
||||
custom_workflow_observable_issue: Issue
|
||||
custom_workflow_observable_issue_attachments: Issue Attachments
|
||||
custom_workflow_observable_group: Group
|
||||
custom_workflow_observable_user: User
|
||||
custom_workflow_observable_attachment: Attachment
|
||||
custom_workflow_observable_project: Project
|
||||
custom_workflow_observable_project_attachments: Project Attachments / Files
|
||||
custom_workflow_observable_wiki_content: Wiki Content
|
||||
custom_workflow_observable_wiki_page_attachments: Wiki Page Attachments
|
||||
custom_workflow_observable_group_users: Group Users
|
||||
custom_workflow_observable_time_entry: Time Entry
|
||||
custom_workflow_observable_version: Version
|
||||
|
||||
@ -20,63 +20,101 @@
|
||||
# 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"
|
||||
project_module_custom_workflows_module: Fluxo de Trabalho Personalizado
|
||||
permission_manage_project_workflow: Gerenciar fluxos de trabalho personalizados de projeto
|
||||
|
||||
label_custom_workflow: "Fluxo de Trabalho personalizado"
|
||||
label_custom_workflow_plural: "Fluxos de Trabalho personalizados"
|
||||
label_custom_workflow_new: "Criar um fluxo de trabalho personalizado"
|
||||
label_workflow_scripts: "Scripts de fluxo de trabalho"
|
||||
label_enabled_projects: "Habilitado para o(s) projeto(s)"
|
||||
label_custom_workflow_export: "Exportar"
|
||||
label_custom_workflow_import: "Importar fluxo de trabalho"
|
||||
label_custom_workflow: Fluxo de Trabalho personalizado
|
||||
label_custom_workflow_plural: Fluxos de Trabalho personalizados
|
||||
label_custom_workflow_new: Criar um fluxo de trabalho personalizado
|
||||
label_workflow_scripts: Scripts de fluxo de trabalho
|
||||
label_custom_workflow_export: Exportar
|
||||
label_custom_workflow_import: Importar fluxo de trabalho
|
||||
label_save_workflows: Saving observable objects
|
||||
label_destroy_workflows: Destroying observable objects
|
||||
label_add_workflows: Adding observable objects to collection
|
||||
label_remove_workflows: Removing observable objects from collection
|
||||
|
||||
button_import: "Importar"
|
||||
button_custom_workflow_activate: "Ativar"
|
||||
button_custom_workflow_deactivate: "Desativar"
|
||||
button_custom_workflow_deactivate: Desativar
|
||||
|
||||
field_after_save: "Workflow script executable after saving observable object"
|
||||
field_before_save: "Workflow script executable before saving observable object"
|
||||
field_after_add: "Workflow script executable after adding observable object to collection"
|
||||
field_before_add: "Workflow script executable before adding observable object to collection"
|
||||
field_after_remove: "Workflow script executable after removing observable object from collection"
|
||||
field_before_remove: "Workflow script executable before removing observable object from collection"
|
||||
field_shared_code: "Shared code"
|
||||
field_observable: "Observable object"
|
||||
field_is_enabled: "Ativado"
|
||||
field_enabled_for_all_projects: "Ativado para todos os projetos"
|
||||
field_custom_workflow_author: "E-mail do autor"
|
||||
field_custom_workflow_file: "Selecione o arquivo XML exportado anteriormente"
|
||||
field_custom_workflow_active: "Ativo"
|
||||
field_after_save: Workflow script executable after saving observable object
|
||||
field_before_save: Workflow script executable before saving observable object
|
||||
field_after_destroy: Workflow script executable after destroying observable object
|
||||
field_before_destroy: Workflow script executable before destroying observable object
|
||||
field_after_add: Workflow script executable after adding observable object to collection
|
||||
field_before_add: Workflow script executable before adding observable object to collection
|
||||
field_after_remove: Workflow script executable after removing observable object from collection
|
||||
field_before_remove: Workflow script executable before removing observable object from collection
|
||||
field_shared_code: Shared code
|
||||
field_observable: Observable object
|
||||
field_enabled_for_all_projects: Ativado para todos os projetos
|
||||
field_custom_workflow_author: E-mail do autor
|
||||
field_custom_workflow_file: Selecione o arquivo XML exportado anteriormente
|
||||
field_custom_workflow:
|
||||
script: "Script do Fluxo de Trabalho"
|
||||
script: Script do Fluxo de Trabalho
|
||||
|
||||
notice_successful_import: "Fluxo de Trabalho Personalizado foi importado com sucesso"
|
||||
notice_successful_status_change: "Situação foi alterada com sucesso"
|
||||
error_failed_import: "Erro ao importar o fluxo de trabalho customizado (Formato desconhecido? Por favor verifique o log)"
|
||||
notice_successful_import: Fluxo de Trabalho Personalizado foi importado com sucesso
|
||||
notice_successful_status_change: Situação foi alterada com sucesso
|
||||
error_failed_import: Erro ao importar o fluxo de trabalho customizado (Formato desconhecido? Por favor verifique o log)
|
||||
|
||||
activerecord:
|
||||
errors:
|
||||
messages:
|
||||
invalid_script: "contém erro: %{error}"
|
||||
custom_workflow_error: "Erro no fluxo de trabalho customizado (por favor contate o administrador)"
|
||||
custom_workflow_error: Erro no fluxo de trabalho customizado (Por favor contate o administrador)
|
||||
new_status_invalid: "Transição de '%{old_status}' para '%{new_status}' é proibida"
|
||||
scripts_absent: At least one script should be defined
|
||||
|
||||
text_select_project_custom_workflows: Selecione o projeto para os fluxos de trabalho
|
||||
text_custom_workflow_before_save_note: Você pode alterar as propriedades das tarefas aqui. Não crie ou atualize tarefas relacionadas neste script. Para terminar com o erro, utilize a exceção WorkflowError, "Mensagem para o usuário".
|
||||
text_custom_workflow_after_save_note: Você pode atualizar ou criar tarefas relacionadas aqui. Note que esse script também será executado para as tarefas criadas recentemente. Então, faça as verificações adequadas para evitar que entre em recursividade infinita.
|
||||
text_custom_workflow_issue_code_note: Ambos os scripts são executados no contexto da tarefa pelas chamadas before_save com retornos para a chamada after_save. Portanto, use métodos e propriedades da tarefa diretamente (ou através de "self"). Variáveis de instância (@variable) também são permitidos e podem ser utilizados, se necessário.
|
||||
text_custom_workflow_shared_code_note: This code will run before any other workflow and may contain shared code, e.g. functions and classes needed by other workflows.
|
||||
text_custom_workflow_user_code_note: Both scripts are executed in the context of the user object when user object changes. Use methods and properties of the user directly (or through "self")
|
||||
text_custom_workflow_group_code_note: Both scripts are executed in the context of the group object when group object changes. Use methods and properties of the group directly (or through "self")
|
||||
text_custom_workflow_group_users_code_note: These scripts are executed when user being added to group/removed from group. Use variables @user and @group to access appropriate objects in your scripts.
|
||||
text_custom_workflow_before_save_note: Você pode alterar as propriedades das tarefas aqui. Não crie ou atualize
|
||||
tarefas relacionadas neste script. Para terminar com o erro, utilize a `raise WorkflowError, 'Mensagem para o usuário'`.
|
||||
text_custom_workflow_after_save_note: Você pode atualizar ou criar tarefas relacionadas aqui. Note que esse script
|
||||
também será executado para as tarefas criadas recentemente. Então, faça as verificações adequadas para evitar que
|
||||
entre em recursividade infinita.
|
||||
text_custom_workflow_issue_code_note: Ambos os scripts são executados no contexto da tarefa pelas chamadas before_save
|
||||
com retornos para a chamada after_save. Portanto, use métodos e propriedades da tarefa diretamente
|
||||
(ou através de "self"). Variáveis de instância (@variable) também são permitidos e podem ser utilizados, se necessário.
|
||||
text_custom_workflow_shared_code_note: This code will run before any other workflow and may contain shared code,
|
||||
e.g. functions and classes needed by other workflows.
|
||||
text_custom_workflow_user_code_note: Both scripts are executed in the context of the user object when user object
|
||||
changes. Use methods and properties of the user directly (or through `self`)
|
||||
text_custom_workflow_group_code_note: Both scripts are executed in the context of the group object when group object
|
||||
changes. Use methods and properties of the group directly (or through `self`)
|
||||
text_custom_workflow_group_users_code_note: These scripts are executed when user being added to group/removed from
|
||||
group. Use variables @user and @group to access appropriate objects in your scripts.
|
||||
text_custom_workflow_attachment_code_note: Scripts are executed in the context of Attachment object when attachment
|
||||
object changes (destroys). Use methods and properties of the attachment object directly (or through `self`). Note that
|
||||
these scripts will affect all attachment types (issue, document, wiki pages and etc), so you should check
|
||||
'container_type' field additionally in your script or select specific '... Attachments' observable object.
|
||||
text_custom_workflow_issue_attachments_code_note: These scripts are executed when attachment being added to
|
||||
issue/removed from issue. Use variables @issue and @attachment to access appropriate objects in your scripts.
|
||||
text_custom_workflow_project_code_note: Scripts are executed in the context of Project object when project object
|
||||
changes (destroys). Use methods and properties of the project directly (or through `self`)
|
||||
text_custom_workflow_project_attachments_code_note: These scripts are executed when a file being added to
|
||||
project/removed from project. Use variables @project and @attachment to access appropriate objects in your scripts.
|
||||
text_custom_workflow_wiki_content_code_note: Scripts are executed in the context of Wiki Content object when project
|
||||
object changes (destroys). Use methods and properties of the project directly (or through `self`)
|
||||
text_custom_workflow_wiki_page_attachments_code_note: These scripts are executed when a file being added to wiki
|
||||
page/removed from wiki page. Use variables @page and @attachment to access appropriate objects in your scripts.
|
||||
text_custom_workflow_time_entry_code_note: Scripts are executed in the context of TimeEntry object when time enty
|
||||
object changes (destroys). Use methods and properties of the time entry directly (or through `self`)
|
||||
text_custom_workflow_version_code_note: Scripts are executed in the context of Version object when version object
|
||||
changes (destroys). Use methods and properties of the version directly (or through `self`)
|
||||
|
||||
text_no_enabled_projects: Não há projeto
|
||||
text_custom_workflow_author: Será incluído no XML exportado
|
||||
text_custom_workflow_disabled: desabilitado por admin
|
||||
text_custom_workflow_is_for_all: Ativado para todos os projetos
|
||||
|
||||
custom_workflow_observable_shared: "<shared code>"
|
||||
custom_workflow_observable_issue: "Issue"
|
||||
custom_workflow_observable_group: "Group"
|
||||
custom_workflow_observable_user: "User"
|
||||
custom_workflow_observable_group_users: "Group Users"
|
||||
custom_workflow_observable_shared: <shared code>
|
||||
custom_workflow_observable_issue: Issue
|
||||
custom_workflow_observable_issue_attachments: Issue Attachments
|
||||
custom_workflow_observable_group: Group
|
||||
custom_workflow_observable_user: User
|
||||
custom_workflow_observable_attachment: Attachment
|
||||
custom_workflow_observable_project: Project
|
||||
custom_workflow_observable_project_attachments: Project Attachments / Files
|
||||
custom_workflow_observable_wiki_content: Wiki Content
|
||||
custom_workflow_observable_wiki_page_attachments: Wiki Page Attachments
|
||||
custom_workflow_observable_group_users: Group Users
|
||||
custom_workflow_observable_time_entry: Time Entry
|
||||
custom_workflow_observable_version: Version
|
||||
|
||||
@ -20,87 +20,101 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
ru:
|
||||
project_module_custom_workflows_module: "Пользовательские рабочие процессы"
|
||||
permission_manage_project_workflow: "Управление пользовательскими рабочими процессами в проекте"
|
||||
project_module_custom_workflows_module: Пользовательские рабочие процессы
|
||||
permission_manage_project_workflow: Управление пользовательскими рабочими процессами в проекте
|
||||
|
||||
label_custom_workflow: "Пользовательский рабочий процесс"
|
||||
label_custom_workflow_plural: "Пользовательские рабочие процессы"
|
||||
label_custom_workflow_new: "Новый процесс"
|
||||
label_workflow_scripts: "Сценарии"
|
||||
label_enabled_projects: "Разрешен в проектах"
|
||||
label_custom_workflow_export: "Экспорт"
|
||||
label_custom_workflow_import: "Импорт процесса"
|
||||
label_save_workflows: "Сохранение наблюдаемых объектов"
|
||||
label_destroy_workflows: "Уничтожение наблюдаемых объектов"
|
||||
label_add_workflows: "Добавление наблюдаемых объектов в коллекцию"
|
||||
label_remove_workflows: "Удаление наблюдаемых объектов из коллекции"
|
||||
label_custom_workflow: Пользовательский рабочий процесс
|
||||
label_custom_workflow_plural: Пользовательские рабочие процессы
|
||||
label_custom_workflow_new: Новый процесс
|
||||
label_workflow_scripts: Сценарии
|
||||
label_custom_workflow_export: Экспорт
|
||||
label_custom_workflow_import: Импорт процесса
|
||||
label_save_workflows: Сохранение наблюдаемых объектов
|
||||
label_destroy_workflows: Уничтожение наблюдаемых объектов
|
||||
label_add_workflows: Добавление наблюдаемых объектов в коллекцию
|
||||
label_remove_workflows: Удаление наблюдаемых объектов из коллекции
|
||||
|
||||
button_import: "Импортировать"
|
||||
button_custom_workflow_activate: "Активировать"
|
||||
button_custom_workflow_deactivate: "Деактивировать"
|
||||
button_custom_workflow_deactivate: Деактивировать
|
||||
|
||||
field_after_save: "Сценарий выполняемый после сохранения наблюдаемого объекта"
|
||||
field_before_save: "Сценарий выполняемый перед сохранением наблюдаемого объекта"
|
||||
field_after_destroy: "Сценарий выполняемый после уничтожения наблюдаемого объекта"
|
||||
field_before_destroy: "Сценарий выполняемый перед уничтожением наблюдаемого объекта"
|
||||
field_after_add: "Сценарий выполняемый после добавления наблюдаемого объекта в коллекцию"
|
||||
field_before_add: "Сценарий выполняемый перед добавлением наблюдаемого объекта в коллекцию"
|
||||
field_after_remove: "Сценарий выполняемый после удаления наблюдаемого объекта из коллекции"
|
||||
field_before_remove: "Сценарий выполняемый перед удалением наблюдаемого объекта из коллекции"
|
||||
field_shared_code: "Общий код"
|
||||
field_observable: "Наблюдаемый объект"
|
||||
field_is_enabled: "Разрешено"
|
||||
field_enabled_for_all_projects: "Разрешен для всех проектов"
|
||||
field_custom_workflow_author: "E-Mail адрес автора"
|
||||
field_custom_workflow_file: "Выберите XML файл ранее экспортированного процесса"
|
||||
field_custom_workflow_active: "Активен"
|
||||
field_after_save: Сценарий выполняемый после сохранения наблюдаемого объекта
|
||||
field_before_save: Сценарий выполняемый перед сохранением наблюдаемого объекта
|
||||
field_after_destroy: Сценарий выполняемый после уничтожения наблюдаемого объекта
|
||||
field_before_destroy: Сценарий выполняемый перед уничтожением наблюдаемого объекта
|
||||
field_after_add: Сценарий выполняемый после добавления наблюдаемого объекта в коллекцию
|
||||
field_before_add: Сценарий выполняемый перед добавлением наблюдаемого объекта в коллекцию
|
||||
field_after_remove: Сценарий выполняемый после удаления наблюдаемого объекта из коллекции
|
||||
field_before_remove: Сценарий выполняемый перед удалением наблюдаемого объекта из коллекции
|
||||
field_shared_code: Общий код
|
||||
field_observable: Наблюдаемый объект
|
||||
field_enabled_for_all_projects: Разрешен для всех проектов
|
||||
field_custom_workflow_author: E-Mail адрес автора
|
||||
field_custom_workflow_file: Выберите XML файл ранее экспортированного процесса
|
||||
field_custom_workflow:
|
||||
script: "Сценарий"
|
||||
script: Сценарий
|
||||
|
||||
notice_successful_import: "Рабочий процесс успешно импортирован"
|
||||
notice_successful_status_change: "Статус успешно изменен"
|
||||
error_failed_import: "Ошибка импорта рабочего процесса (неверный формат? смотри журнал)"
|
||||
notice_successful_import: Рабочий процесс успешно импортирован
|
||||
notice_successful_status_change: Статус успешно изменен
|
||||
error_failed_import: Ошибка импорта рабочего процесса (неверный формат? смотри журнал)
|
||||
|
||||
activerecord:
|
||||
errors:
|
||||
messages:
|
||||
invalid_script: "содержит ошибку: %{error}"
|
||||
custom_workflow_error: "Ошибка в сценарии рабочего процесса (обратитесь к администратору)"
|
||||
custom_workflow_error: Ошибка в сценарии рабочего процесса (Обратитесь к администратору)
|
||||
new_status_invalid: "- переход от '%{old_status}' к '%{new_status}' невозможен"
|
||||
scripts_absent: "Хотя бы один скрипт должен быть определен"
|
||||
scripts_absent: Хотя бы один скрипт должен быть определен
|
||||
|
||||
text_select_project_custom_workflows: Выберите процессы для данного проекта
|
||||
text_custom_workflow_before_save_note: Здесь вы можете изменять свойства задачи. Не создавайте и не обновляйте связанные задачи в этом сценарии. Чтобы завершить сценарий с произвольной ошибкой, используйте raise WorkflowError, "Message to user".
|
||||
text_custom_workflow_after_save_note: Вы можете обновлять и создавать задачи (в том числе и связанные задачи) здесь. Обратите внимание, что данный сценарий будет также выполняться и для вновь создаваемых задач. Поэтому используйте дополнительные проверки, чтобы избежать бесконечной рекурсии.
|
||||
text_custom_workflow_issue_code_note: Эти сценарии исполняются в контексте задачи, как и обычные обратные вызовы before_save и after_save. Поэтому используйте методы и свойства задачи (Issue) напрямую или через ключевое слово self.
|
||||
text_custom_workflow_shared_code_note: Этот код будет исполняться перед любым другим процессом и может содержать общий код, например, функции и классы, необходимые для работы других процессов.
|
||||
text_custom_workflow_user_code_note: Эти сценарии исполняются в контексте объекта пользователя когда объект пользователя изменяется (удаляется). Используйте методы и свойства объекта пользователя (User) напрямую или через ключевое слово self.
|
||||
text_custom_workflow_group_code_note: Эти сценарии исполняются в контексте объекта группы когда объект группы изменяется (удаляется). Используйте методы и свойства объекта группы (Group) напрямую или через ключевое слово self.
|
||||
text_custom_workflow_group_users_code_note: Эти сценарии выполняются когда пользователь добавляется в группу/удаляется из группы. Используйте переменные @user и @group для доступа к соответствующим объектам из Ваших сценариев.
|
||||
text_custom_workflow_attachment_code_note: Эти сценарии исполняются в контексте объекта вложения когда объект вложения изменяется (удаляется). Используйте методы и свойства объекта вложения (Attachment) напрямую или через ключевое слово self. Обратите внимание на то, что данные сценарии выполняются при сохранении (удалении) вложения любого типа (задача, документ, страница Wiki и т.д.), поэтому следует дополнительно проверять в коде поле container_type либо в качестве наблюдаемого объекта выбрать конкретный тип вложения.
|
||||
text_custom_workflow_issue_attachments_code_note: Эти сценарии выполняются когда вложение прикладывается к задаче/удаляется из задачи. Используйте переменные @issue и @attachment для доступа к соответствующим объектам из Ваших сценариев.
|
||||
text_custom_workflow_project_code_note: Эти сценарии исполняются в контексте объекта проекта когда объект проекта изменяется (удаляется). Используйте методы и свойства объекта группы (Project) напрямую или через ключевое слово self.
|
||||
text_custom_workflow_project_attachments_code_note: Эти сценарии выполняются когда файл загружается в проект/удаляется из проекта. Используйте переменные @project и @attachment для доступа к соответствующим объектам из Ваших сценариев.
|
||||
text_custom_workflow_wiki_content_code_note: Эти сценарии исполняются в контексте объекта Wiki содержания когда объект Wiki содержания изменяется (удаляется). Используйте методы и свойства объекта содержания Wiki (WikiContent) напрямую или через ключевое слово self.
|
||||
text_custom_workflow_wiki_page_attachments_code_note: Эти сценарии выполняются когда файл загружается на Wiki страницу/удаляется с Wiki страницы. Используйте переменные @page и @attachment для доступа к соответствующим объектам из Ваших сценариев.
|
||||
text_custom_workflow_time_entry_code_note: Эти сценарии исполняются в контексте объекта затраченного времени когда объект изменяется (удаляется). Используйте методы и свойства объекта затраченного времени (TimeEntry) напрямую или через ключевое слово self.
|
||||
text_custom_workflow_version_code_note: Эти сценарии исполняются в контексте объекта версии когда объект изменяется (удаляется). Используйте методы и свойства объекта версии (Version) напрямую или через ключевое слово self.
|
||||
text_custom_workflow_before_save_note: Здесь вы можете изменять свойства задачи. Не создавайте и не обновляйте
|
||||
связанные задачи в этом сценарии. Чтобы завершить сценарий с произвольной ошибкой, используйте `raise WorkflowError, 'Message to user'`.
|
||||
text_custom_workflow_after_save_note: Вы можете обновлять и создавать задачи (в том числе и связанные задачи) здесь.
|
||||
Обратите внимание, что данный сценарий будет также выполняться и для вновь создаваемых задач. Поэтому используйте
|
||||
дополнительные проверки, чтобы избежать бесконечной рекурсии.
|
||||
text_custom_workflow_issue_code_note: Эти сценарии исполняются в контексте задачи, как и обычные обратные вызовы
|
||||
before_save и after_save. Поэтому используйте методы и свойства задачи (Issue) напрямую или через ключевое слово
|
||||
self.
|
||||
text_custom_workflow_shared_code_note: Этот код будет исполняться перед любым другим процессом и может содержать общий
|
||||
код, например, функции и классы, необходимые для работы других процессов.
|
||||
text_custom_workflow_user_code_note: Эти сценарии исполняются в контексте объекта пользователя когда объект
|
||||
пользователя изменяется (удаляется). Используйте методы и свойства объекта пользователя (User) напрямую или через ключевое слово `self`.
|
||||
text_custom_workflow_group_code_note: Эти сценарии исполняются в контексте объекта группы когда объект группы
|
||||
изменяется (удаляется). Используйте методы и свойства объекта группы (Group) напрямую или через ключевое слово `self`.
|
||||
text_custom_workflow_group_users_code_note: Эти сценарии выполняются когда пользователь добавляется в группу/удаляется
|
||||
из группы. Используйте переменные @user и @group для доступа к соответствующим объектам из Ваших сценариев.
|
||||
text_custom_workflow_attachment_code_note: Эти сценарии исполняются в контексте объекта вложения когда объект вложения
|
||||
изменяется (удаляется). Используйте методы и свойства объекта вложения (Attachment) напрямую или через ключевое
|
||||
слово self. Обратите внимание на то, что данные сценарии выполняются при сохранении (удалении) вложения любого типа
|
||||
(задача, документ, страница Wiki и т.д.), поэтому следует дополнительно проверять в коде поле container_type либо в качестве наблюдаемого объекта выбрать конкретный тип вложения.
|
||||
text_custom_workflow_issue_attachments_code_note: Эти сценарии выполняются когда вложение прикладывается
|
||||
к задаче/удаляется из задачи. Используйте переменные @issue и @attachment для доступа к соответствующим объектам из Ваших сценариев.
|
||||
text_custom_workflow_project_code_note: Эти сценарии исполняются в контексте объекта проекта когда объект проекта
|
||||
изменяется (удаляется). Используйте методы и свойства объекта группы (Project) напрямую или через ключевое слово `self`.
|
||||
text_custom_workflow_project_attachments_code_note: Эти сценарии выполняются когда файл загружается в проект/удаляется
|
||||
из проекта. Используйте переменные @project и @attachment для доступа к соответствующим объектам из Ваших сценариев.
|
||||
text_custom_workflow_wiki_content_code_note: Эти сценарии исполняются в контексте объекта Wiki содержания когда объект
|
||||
Wiki содержания изменяется (удаляется). Используйте методы и свойства объекта содержания Wiki (WikiContent) напрямую или через ключевое слово self.
|
||||
text_custom_workflow_wiki_page_attachments_code_note: Эти сценарии выполняются когда файл загружается на Wiki
|
||||
страницу/удаляется с Wiki страницы. Используйте переменные @page и @attachment для доступа к соответствующим объектам из Ваших сценариев.
|
||||
text_custom_workflow_time_entry_code_note: Эти сценарии исполняются в контексте объекта затраченного времени когда
|
||||
объект изменяется (удаляется). Используйте методы и свойства объекта затраченного времени (TimeEntry) напрямую или через ключевое слово self.
|
||||
text_custom_workflow_version_code_note: Эти сценарии исполняются в контексте объекта версии когда объект изменяется
|
||||
(удаляется). Используйте методы и свойства объекта версии (Version) напрямую или через ключевое слово `self`.
|
||||
|
||||
text_no_enabled_projects: Нет проектов
|
||||
text_custom_workflow_author: Будет использован в XML файле при экспорте
|
||||
text_custom_workflow_disabled: отключен администратором
|
||||
text_custom_workflow_is_for_all: разрешен для всех проектов
|
||||
|
||||
custom_workflow_observable_shared: "<общий код>"
|
||||
custom_workflow_observable_issue: "Задача"
|
||||
custom_workflow_observable_issue_attachments: "Вложения задач"
|
||||
custom_workflow_observable_group: "Группа"
|
||||
custom_workflow_observable_user: "Пользователь"
|
||||
custom_workflow_observable_attachment: "Вложение"
|
||||
custom_workflow_observable_project: "Проект"
|
||||
custom_workflow_observable_project_attachments: "Вложения проекта / Файлы"
|
||||
custom_workflow_observable_wiki_content: "Содержание Wiki"
|
||||
custom_workflow_observable_wiki_page_attachments: "Вложения страниц Wiki"
|
||||
custom_workflow_observable_group_users: "Пользователи группы"
|
||||
custom_workflow_observable_time_entry: "Затраченное время"
|
||||
custom_workflow_observable_version: "Версия"
|
||||
custom_workflow_observable_shared: <общий код>
|
||||
custom_workflow_observable_issue: Задача
|
||||
custom_workflow_observable_issue_attachments: Вложения задач
|
||||
custom_workflow_observable_group: Группа
|
||||
custom_workflow_observable_user: Пользователь
|
||||
custom_workflow_observable_attachment: Вложение
|
||||
custom_workflow_observable_project: Проект
|
||||
custom_workflow_observable_project_attachments: Вложения проекта / Файлы
|
||||
custom_workflow_observable_wiki_content: Содержание Wiki
|
||||
custom_workflow_observable_wiki_page_attachments: Вложения страниц Wiki
|
||||
custom_workflow_observable_group_users: Пользователи группы
|
||||
custom_workflow_observable_time_entry: Затраченное время
|
||||
custom_workflow_observable_version: Версия
|
||||
|
||||
@ -28,9 +28,10 @@ RedmineApp::Application.routes.draw do
|
||||
end
|
||||
end
|
||||
|
||||
post '/custom_workflows/import', :to => 'custom_workflows#import', :as => 'import_custom_workflow'
|
||||
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'
|
||||
put '/custom_workflows/:id/reorder', :to => 'custom_workflows#reorder'
|
||||
post '/custom_workflows/import', to: 'custom_workflows#import', as: 'import_custom_workflow'
|
||||
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'
|
||||
put '/custom_workflows/:id/reorder', to: 'custom_workflows#reorder'
|
||||
|
||||
end
|
||||
|
||||
@ -22,12 +22,12 @@
|
||||
class CreateCustomWorkflows < ActiveRecord::Migration[4.2]
|
||||
|
||||
def change
|
||||
create_table :custom_workflows, :force => true do |t|
|
||||
create_table :custom_workflows, force: true do |t|
|
||||
t.references :project
|
||||
t.text :script, :null => true, :default => nil
|
||||
t.text :script, null: true, default: nil
|
||||
t.boolean :is_enabled
|
||||
end
|
||||
add_index :custom_workflows, [:project_id], :unique => true
|
||||
add_index :custom_workflows, [:project_id], unique: true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -24,9 +24,9 @@ class AlterCustomWorkflows < ActiveRecord::Migration[4.2]
|
||||
def self.up
|
||||
remove_column :custom_workflows, :project_id
|
||||
remove_column :custom_workflows, :is_enabled
|
||||
add_column :custom_workflows, :name, :string, :null => false, :default => ''
|
||||
add_column :custom_workflows, :description, :string, :null => false, :default => ''
|
||||
add_column :custom_workflows, :position, :integer, :null => false, :default => 1
|
||||
add_column :custom_workflows, :name, :string, null: false, default: ''
|
||||
add_column :custom_workflows, :description, :string, null: false, default: ''
|
||||
add_column :custom_workflows, :position, :integer, null: false, default: 1
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
class CreateCustomWorkflowsProjects < ActiveRecord::Migration[4.2]
|
||||
|
||||
def change
|
||||
create_table :custom_workflows_projects, :force => true, :id => false do |t|
|
||||
create_table :custom_workflows_projects, force: true, id: false do |t|
|
||||
t.references :project
|
||||
t.references :custom_workflow
|
||||
end
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
|
||||
class ChangeCustomWorkflowsDescriptionType < ActiveRecord::Migration[4.2]
|
||||
def self.up
|
||||
change_column :custom_workflows, :description, :text, :null => true, :default => nil
|
||||
change_column :custom_workflows, :description, :text, null: true, default: nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -23,8 +23,8 @@ class AddAfterSaveToCustomWorkflows < ActiveRecord::Migration[4.2]
|
||||
|
||||
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
|
||||
change_column :custom_workflows, :before_save, :text, null: true
|
||||
add_column :custom_workflows, :after_save, :text, null: true, after: :before_save
|
||||
end
|
||||
|
||||
def down
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
class AddIsForAllToCustomWorkflows < ActiveRecord::Migration[4.2]
|
||||
|
||||
def change
|
||||
add_column :custom_workflows, :is_for_all, :boolean, :null => false, :default => false
|
||||
add_column :custom_workflows, :is_for_all, :boolean, null: false, default: false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -22,8 +22,8 @@
|
||||
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
|
||||
change_column :custom_workflows, :before_save, :text, null: true, default: nil
|
||||
change_column :custom_workflows, :after_save, :text, null: true, default: nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
class SetPositionFieldNullable < ActiveRecord::Migration[4.2]
|
||||
|
||||
def up
|
||||
change_column :custom_workflows, :position, :integer, :null => true
|
||||
change_column :custom_workflows, :position, :integer, null: true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
class AddAuthorAndTimestampsToCustomWorkflows < ActiveRecord::Migration[4.2]
|
||||
|
||||
def change
|
||||
add_column :custom_workflows, :author, :string, :null => true
|
||||
add_column :custom_workflows, :author, :string, null: true
|
||||
add_timestamps :custom_workflows
|
||||
end
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
class AddActiveFieldToCustomWorkflows < ActiveRecord::Migration[4.2]
|
||||
|
||||
def change
|
||||
add_column :custom_workflows, :active, :boolean, :null => false, :default => true
|
||||
add_column :custom_workflows, :active, :boolean, null: false, default: true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
class AddObservableFieldToCustomWorkflows < ActiveRecord::Migration[4.2]
|
||||
|
||||
def change
|
||||
add_column :custom_workflows, :observable, :string, :null => false, :default => 'issue'
|
||||
add_column :custom_workflows, :observable, :string, null: false, default: 'issue'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -22,11 +22,11 @@
|
||||
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
|
||||
add_column :custom_workflows, :after_add, :text, :null => true
|
||||
add_column :custom_workflows, :before_remove, :text, :null => true
|
||||
add_column :custom_workflows, :after_remove, :text, :null => true
|
||||
add_column :custom_workflows, :shared_code, :text, null: true
|
||||
add_column :custom_workflows, :before_add, :text, null: true
|
||||
add_column :custom_workflows, :after_add, :text, null: true
|
||||
add_column :custom_workflows, :before_remove, :text, null: true
|
||||
add_column :custom_workflows, :after_remove, :text, null: true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -22,8 +22,8 @@
|
||||
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
|
||||
add_column :custom_workflows, :before_destroy, :text, null: true
|
||||
add_column :custom_workflows, :after_destroy, :text, null: true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
2
init.rb
2
init.rb
@ -36,7 +36,7 @@ Redmine::Plugin.register :redmine_custom_workflows do
|
||||
|
||||
requires_redmine version_or_higher: '4.1.0'
|
||||
|
||||
permission :manage_project_workflow, {}, :require => :member
|
||||
permission :manage_project_workflow, {}, require: :member
|
||||
end
|
||||
|
||||
unless Redmine::Plugin.installed?(:easy_extensions)
|
||||
|
||||
@ -24,19 +24,11 @@ module RedmineCustomWorkflows
|
||||
|
||||
class Hooks < Redmine::Hook::ViewListener
|
||||
|
||||
def view_layouts_base_html_head(context)
|
||||
return if defined?(EasyExtensions)
|
||||
def view_layouts_base_html_head(context={})
|
||||
return unless context[:controller].class.name.match?(/^(CustomWorkflows|Projects)/)
|
||||
"\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
|
||||
@ -36,8 +36,8 @@ module RedmineCustomWorkflows
|
||||
def before_save_custom_workflows
|
||||
@attachment = self
|
||||
@saved_attributes = attributes.dup
|
||||
CustomWorkflow.run_shared_code(self)
|
||||
CustomWorkflow.run_custom_workflows(:attachment, self, :before_save)
|
||||
CustomWorkflow.run_shared_code self
|
||||
CustomWorkflow.run_custom_workflows :attachment, self, :before_save
|
||||
throw :abort if errors.any?
|
||||
errors.empty? && (@saved_attributes == attributes || valid?)
|
||||
ensure
|
||||
@ -45,15 +45,15 @@ module RedmineCustomWorkflows
|
||||
end
|
||||
|
||||
def after_save_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:attachment, self, :after_save)
|
||||
CustomWorkflow.run_custom_workflows :attachment, self, :after_save
|
||||
end
|
||||
|
||||
def before_destroy_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:attachment, self, :before_destroy)
|
||||
CustomWorkflow.run_custom_workflows :attachment, self, :before_destroy
|
||||
end
|
||||
|
||||
def after_destroy_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:attachment, self, :after_destroy)
|
||||
CustomWorkflow.run_custom_workflows :attachment, self, :after_destroy
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -32,10 +32,10 @@ module RedmineCustomWorkflows
|
||||
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)
|
||||
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)
|
||||
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
|
||||
@ -50,8 +50,8 @@ module RedmineCustomWorkflows
|
||||
def before_save_custom_workflows
|
||||
@group = self
|
||||
@saved_attributes = attributes.dup
|
||||
CustomWorkflow.run_shared_code(self)
|
||||
CustomWorkflow.run_custom_workflows(:group, self, :before_save)
|
||||
CustomWorkflow.run_shared_code self
|
||||
CustomWorkflow.run_custom_workflows :group, self, :before_save
|
||||
throw :abort if errors.any?
|
||||
errors.empty? && (@saved_attributes == attributes || valid?)
|
||||
ensure
|
||||
@ -59,15 +59,15 @@ module RedmineCustomWorkflows
|
||||
end
|
||||
|
||||
def after_save_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:group, self, :after_save)
|
||||
CustomWorkflow.run_custom_workflows :group, self, :after_save
|
||||
end
|
||||
|
||||
def before_destroy_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:group, self, :before_destroy)
|
||||
CustomWorkflow.run_custom_workflows :group, self, :before_destroy
|
||||
end
|
||||
|
||||
def after_destroy_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:group, self, :after_destroy)
|
||||
CustomWorkflow.run_custom_workflows :group, self, :after_destroy
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -33,10 +33,10 @@ module RedmineCustomWorkflows
|
||||
validate :validate_status
|
||||
|
||||
def self.attachments_callback(event, issue, attachment)
|
||||
issue.instance_variable_set(:@issue, issue)
|
||||
issue.instance_variable_set(:@attachment, 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)
|
||||
CustomWorkflow.run_custom_workflows :issue_attachments, issue, event
|
||||
end
|
||||
|
||||
[:before_add, :before_remove, :after_add, :after_remove].each do |observable|
|
||||
@ -57,15 +57,15 @@ module RedmineCustomWorkflows
|
||||
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
|
||||
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)
|
||||
CustomWorkflow.run_shared_code self
|
||||
CustomWorkflow.run_custom_workflows :issue, self, :before_save
|
||||
throw :abort if errors.any?
|
||||
errors.empty? && (@saved_attributes == attributes || valid?)
|
||||
ensure
|
||||
@ -73,15 +73,15 @@ module RedmineCustomWorkflows
|
||||
end
|
||||
|
||||
def after_save_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:issue, self, :after_save)
|
||||
CustomWorkflow.run_custom_workflows :issue, self, :after_save
|
||||
end
|
||||
|
||||
def before_destroy_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:issue, self, :before_destroy)
|
||||
CustomWorkflow.run_custom_workflows :issue, self, :before_destroy
|
||||
end
|
||||
|
||||
def after_destroy_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:issue, self, :after_destroy)
|
||||
CustomWorkflow.run_custom_workflows :issue, self, :after_destroy
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -27,7 +27,7 @@ module RedmineCustomWorkflows
|
||||
def self.included(base)
|
||||
base.class_eval do
|
||||
has_and_belongs_to_many :custom_workflows
|
||||
safe_attributes :custom_workflow_ids, :if =>
|
||||
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
|
||||
@ -51,8 +51,8 @@ module RedmineCustomWorkflows
|
||||
def before_save_custom_workflows
|
||||
@project = self
|
||||
@saved_attributes = attributes.dup
|
||||
CustomWorkflow.run_shared_code(self)
|
||||
CustomWorkflow.run_custom_workflows(:project, self, :before_save)
|
||||
CustomWorkflow.run_shared_code self
|
||||
CustomWorkflow.run_custom_workflows :project, self, :before_save
|
||||
throw :abort if errors.any?
|
||||
errors.empty? && (@saved_attributes == attributes || valid?)
|
||||
ensure
|
||||
@ -60,15 +60,15 @@ module RedmineCustomWorkflows
|
||||
end
|
||||
|
||||
def after_save_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:project, self, :after_save)
|
||||
CustomWorkflow.run_custom_workflows :project, self, :after_save
|
||||
end
|
||||
|
||||
def before_destroy_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:project, self, :before_destroy)
|
||||
CustomWorkflow.run_custom_workflows :project, self, :before_destroy
|
||||
end
|
||||
|
||||
def after_destroy_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:project, self, :after_destroy)
|
||||
CustomWorkflow.run_custom_workflows :project, self, :after_destroy
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -45,15 +45,15 @@ module RedmineCustomWorkflows
|
||||
end
|
||||
|
||||
def after_save_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:time_entry, self, :after_save)
|
||||
CustomWorkflow.run_custom_workflows :time_entry, self, :after_save
|
||||
end
|
||||
|
||||
def before_destroy_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:time_entry, self, :before_destroy)
|
||||
CustomWorkflow.run_custom_workflows :time_entry, self, :before_destroy
|
||||
end
|
||||
|
||||
def after_destroy_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:time_entry, self, :after_destroy)
|
||||
CustomWorkflow.run_custom_workflows :time_entry, self, :after_destroy
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -36,8 +36,8 @@ module RedmineCustomWorkflows
|
||||
def before_save_custom_workflows
|
||||
@user = self
|
||||
@saved_attributes = attributes.dup
|
||||
CustomWorkflow.run_shared_code(self)
|
||||
CustomWorkflow.run_custom_workflows(:user, self, :before_save)
|
||||
CustomWorkflow.run_shared_code self
|
||||
CustomWorkflow.run_custom_workflows :user, self, :before_save
|
||||
throw :abort if errors.any?
|
||||
errors.empty? && (@saved_attributes == attributes || valid?)
|
||||
ensure
|
||||
@ -45,15 +45,15 @@ module RedmineCustomWorkflows
|
||||
end
|
||||
|
||||
def after_save_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:user, self, :after_save)
|
||||
CustomWorkflow.run_custom_workflows :user, self, :after_save
|
||||
end
|
||||
|
||||
def before_destroy_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:user, self, :before_destroy)
|
||||
CustomWorkflow.run_custom_workflows :user, self, :before_destroy
|
||||
end
|
||||
|
||||
def after_destroy_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:user, self, :after_destroy)
|
||||
CustomWorkflow.run_custom_workflows :user, self, :after_destroy
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -36,8 +36,8 @@ module RedmineCustomWorkflows
|
||||
def before_save_custom_workflows
|
||||
@version = self
|
||||
@saved_attributes = attributes.dup
|
||||
CustomWorkflow.run_shared_code(self)
|
||||
CustomWorkflow.run_custom_workflows(:version, self, :before_save)
|
||||
CustomWorkflow.run_shared_code self
|
||||
CustomWorkflow.run_custom_workflows :version, self, :before_save
|
||||
throw :abort if errors.any?
|
||||
errors.empty? && (@saved_attributes == attributes || valid?)
|
||||
ensure
|
||||
@ -45,15 +45,15 @@ module RedmineCustomWorkflows
|
||||
end
|
||||
|
||||
def after_save_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:version, self, :after_save)
|
||||
CustomWorkflow.run_custom_workflows :version, self, :after_save
|
||||
end
|
||||
|
||||
def before_destroy_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:version, self, :before_destroy)
|
||||
CustomWorkflow.run_custom_workflows :version, self, :before_destroy
|
||||
end
|
||||
|
||||
def after_destroy_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:version, self, :after_destroy)
|
||||
CustomWorkflow.run_custom_workflows :version, self, :after_destroy
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -36,8 +36,8 @@ module RedmineCustomWorkflows
|
||||
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)
|
||||
CustomWorkflow.run_shared_code self
|
||||
CustomWorkflow.run_custom_workflows :wiki_content, self, :before_save
|
||||
throw :abort if errors.any?
|
||||
errors.empty? && (@saved_attributes == attributes || valid?)
|
||||
ensure
|
||||
@ -45,15 +45,15 @@ module RedmineCustomWorkflows
|
||||
end
|
||||
|
||||
def after_save_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:wiki_content, self, :after_save)
|
||||
CustomWorkflow.run_custom_workflows :wiki_content, self, :after_save
|
||||
end
|
||||
|
||||
def before_destroy_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:wiki_content, self, :before_destroy)
|
||||
CustomWorkflow.run_custom_workflows :wiki_content, self, :before_destroy
|
||||
end
|
||||
|
||||
def after_destroy_custom_workflows
|
||||
CustomWorkflow.run_custom_workflows(:wiki_content, self, :after_destroy)
|
||||
CustomWorkflow.run_custom_workflows :wiki_content, self, :after_destroy
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -27,10 +27,10 @@ module RedmineCustomWorkflows
|
||||
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)
|
||||
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)
|
||||
CustomWorkflow.run_custom_workflows :wiki_page_attachments, page, event
|
||||
end
|
||||
|
||||
[:before_add, :before_remove, :after_add, :after_remove].each do |observable|
|
||||
|
||||
@ -28,8 +28,8 @@ 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
|
||||
rm -rf ${PATH_TO_REDMINE}
|
||||
git clone -b ${REDMINE_GIT_TAG} --depth=100 --quiet ${REDMINE_GIT_REPO} ${PATH_TO_REDMINE}
|
||||
}
|
||||
|
||||
test()
|
||||
@ -37,7 +37,7 @@ test()
|
||||
# Exit if a test fails
|
||||
set -e
|
||||
|
||||
cd $PATH_TO_REDMINE
|
||||
cd ${PATH_TO_REDMINE}
|
||||
|
||||
# Run tests within application
|
||||
bundle exec rake redmine:plugins:test:units NAME=redmine_custom_workflows RAILS_ENV=test
|
||||
@ -49,7 +49,7 @@ uninstall()
|
||||
# Exit if the migration fails
|
||||
set -e
|
||||
|
||||
cd $PATH_TO_REDMINE
|
||||
cd ${PATH_TO_REDMINE}
|
||||
|
||||
# clean up database
|
||||
bundle exec rake redmine:plugins:migrate NAME=redmine_custom_workflows VERSION=0 RAILS_ENV=test
|
||||
@ -61,14 +61,14 @@ install()
|
||||
set -e
|
||||
|
||||
# cd to redmine folder
|
||||
cd $PATH_TO_REDMINE
|
||||
cd ${PATH_TO_REDMINE}
|
||||
echo current directory is `pwd`
|
||||
|
||||
# Create a link to the Custom Workflows plugin
|
||||
ln -sf $PATH_TO_CUSTOM_WORKFLOWS plugins/redmine_custom_workflows
|
||||
ln -sf ${PATH_TO_CUSTOM_WORKFLOWS} plugins/redmine_custom_workflows
|
||||
|
||||
# Copy database.yml
|
||||
cp $WORKSPACE/database.yml config/
|
||||
cp ${WORKSPACE}/database.yml config/
|
||||
|
||||
# Install gems
|
||||
# Not ideal, but at present Travis-CI will not install with xapian enabled:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user