From 3f901f6bbba9e425dde457bd1f0483b69d315f13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20Pi=C4=8Dman?= Date: Thu, 2 Apr 2020 15:43:51 +0200 Subject: [PATCH] Redmine look & feel --- README.md | 2 +- .../custom_workflows_controller.rb | 50 +-- app/models/custom_workflow.rb | 18 +- app/views/custom_workflows/_form.html.erb | 189 +++++----- app/views/custom_workflows/edit.html.erb | 29 +- app/views/custom_workflows/index.html.erb | 131 ++++--- app/views/custom_workflows/new.html.erb | 29 +- .../settings/_custom_workflow.html.erb | 25 +- assets/images/export.png | Bin 247 -> 0 bytes assets/images/import.png | Bin 259 -> 0 bytes assets/javascripts/tab_override.js | 353 ------------------ assets/stylesheets/custom_workflows.css | 41 +- config/locales/cs.yml | 9 +- config/locales/en.yml | 144 +++---- config/locales/pt-BR.yml | 122 +++--- config/locales/ru.yml | 144 +++---- config/routes.rb | 11 +- .../20110915084858_create_custom_workflows.rb | 6 +- .../20120601054047_alter_custom_workflows.rb | 6 +- ...054557_create_custom_workflows_projects.rb | 2 +- ...hange_custom_workflows_description_type.rb | 2 +- ...5222_add_after_save_to_custom_workflows.rb | 4 +- ...5252_add_is_for_all_to_custom_workflows.rb | 2 +- ...ake_after_save_and_before_save_nullable.rb | 4 +- ...50522134437_set_position_field_nullable.rb | 2 +- ...thor_and_timestamps_to_custom_workflows.rb | 2 +- ...40_add_active_field_to_custom_workflows.rb | 2 +- ...dd_observable_field_to_custom_workflows.rb | 2 +- ...ional_script_fields_to_custom_workflows.rb | 10 +- ...e_and_after_destroy_to_custom_workflows.rb | 4 +- init.rb | 2 +- lib/redmine_custom_workflows/hooks/hooks.rb | 12 +- .../patches/attachment_patch.rb | 10 +- .../patches/group_patch.rb | 16 +- .../patches/issue_patch.rb | 20 +- .../patches/project_patch.rb | 12 +- .../patches/time_entry_patch.rb | 6 +- .../patches/user_patch.rb | 10 +- .../patches/version_patch.rb | 10 +- .../patches/wiki_content_patch.rb | 10 +- .../patches/wiki_page_patch.rb | 6 +- test/ci/redmine_install.sh | 14 +- 42 files changed, 620 insertions(+), 853 deletions(-) delete mode 100644 assets/images/export.png delete mode 100644 assets/images/import.png delete mode 100644 assets/javascripts/tab_override.js diff --git a/README.md b/README.md index 7e9351c..6e7955d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Custom Workflows plug-in ======================== -The current version of Redmine CustomWorkflows is **1.0.2** [![Build Status](https://api.travis-ci.org/anteo/redmine_custom_workflows.png)](https://travis-ci.org/anteo/redmine_custom_workflows) +The current version of Redmine CustomWorkflows is **1.0.3 devel** [![Build Status](https://api.travis-ci.org/anteo/redmine_custom_workflows.png)](https://travis-ci.org/anteo/redmine_custom_workflows) This plug-in provides a great functionality for those who is familiar with the Ruby language. It allows to customize workflow by defining own rules for issues processing. It's possible: diff --git a/app/controllers/custom_workflows_controller.rb b/app/controllers/custom_workflows_controller.rb index 5bd4779..7095b5a 100644 --- a/app/controllers/custom_workflows_controller.rb +++ b/app/controllers/custom_workflows_controller.rb @@ -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 diff --git a/app/models/custom_workflow.rb b/app/models/custom_workflow.rb index 5ab98d6..f4f2a89 100644 --- a/app/models/custom_workflow.rb +++ b/app/models/custom_workflow.rb @@ -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) diff --git a/app/views/custom_workflows/_form.html.erb b/app/views/custom_workflows/_form.html.erb index c010167..3789d1e 100644 --- a/app/views/custom_workflows/_form.html.erb +++ b/app/views/custom_workflows/_form.html.erb @@ -1,22 +1,45 @@ +<% + # encoding: utf-8 + # + # Redmine plugin for Custom Workflows + # + # Copyright © 2015-19 Anton Argirov + # Copyright © 2019-20 Karel Pičman + # + # 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. +%> +
-

<%= f.text_field :name, :required => true, :size => 50 %>

-

<%= f.text_field :author, :size => 50, :label => :field_custom_workflow_author %> +

<%= f.text_field :name, required: true %>

+

<%= f.text_field :author, label: :field_custom_workflow_author %> <%= l(:text_custom_workflow_author) %>

<%= f.select :observable, - CustomWorkflow::OBSERVABLES.collect {|o| [l("custom_workflow_observable_#{o}"), o]}, {}, - :onchange => 'this.form.submit()', - :disabled => !@workflow.new_record? %>

-

<%= f.text_area :description, cols: 40, rows: 5 , class: 'wiki-edit' %>

+ CustomWorkflow::OBSERVABLES.collect { |o| [l("custom_workflow_observable_#{o}"), o] }, {}, + onchange: 'this.form.submit()', + disabled: !@workflow.new_record? %>

+

<%= f.text_area :description, class: 'wiki-edit' %>

<% if @workflow.has_projects_association? %>

<%= f.check_box :is_for_all, onclick: "checkAndDisable('custom_workflow_enabled_projects', this.checked);", label: :field_enabled_for_all_projects %>

<% end %> -

<%= f.check_box :active, :label => :field_custom_workflow_active %>

+

<%= f.check_box :active, label: l(:field_active) %>

<% if @workflow.has_projects_association? %> @@ -28,102 +51,94 @@ <%= l(:label_project_plural) %> <%= 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 %>
<% end %> -
- -
- <%= l(:label_workflow_scripts) %> - <% observable = @workflow.observable.to_sym %> -

- <%= l("text_custom_workflow_#{observable}_code_note") %> -

- <% 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?)) %> - - <% collapsed = (not (@workflow.before_remove.present? or @workflow.after_remove.present?)) %> - + <% collapsed = !(@workflow.before_remove.present? || @workflow.after_remove.present?) %> + - <% when *CustomWorkflow::SINGLE_OBSERVABLES %> - <% collapsed = (not (@workflow.before_save.present? or @workflow.after_save.present? or @workflow.errors[:base].present?)) %> - + <% when *CustomWorkflow::SINGLE_OBSERVABLES %> + <% collapsed = (not (@workflow.before_save.present? or @workflow.after_save.present? or @workflow.errors[:base].present?)) %> + - <% collapsed = (not (@workflow.before_destroy.present? or @workflow.after_destroy.present?)) %> - + <% collapsed = !(@workflow.before_destroy.present? || @workflow.after_destroy.present?) %> + - <% end %> -
- - + + <% end %> + + <%= wikitoolbar_for :custom_workflow_description %> - -<% content_for :header_tags do %> - <%= javascript_include_tag 'tab_override', plugin: 'redmine_custom_workflows' %> -<% end %> \ No newline at end of file diff --git a/app/views/custom_workflows/edit.html.erb b/app/views/custom_workflows/edit.html.erb index ffd0be0..91df0a7 100644 --- a/app/views/custom_workflows/edit.html.erb +++ b/app/views/custom_workflows/edit.html.erb @@ -1,10 +1,33 @@ +<% + # encoding: utf-8 + # + # Redmine plugin for Custom Workflows + # + # Copyright © 2015-19 Anton Argirov + # Copyright © 2019-20 Karel Pičman + # + # 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. +%> +

<%= link_to l(:label_custom_workflow_plural), custom_workflows_path %> » <%= @workflow %>

<%= 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) %> diff --git a/app/views/custom_workflows/index.html.erb b/app/views/custom_workflows/index.html.erb index b94195e..f03aa4e 100644 --- a/app/views/custom_workflows/index.html.erb +++ b/app/views/custom_workflows/index.html.erb @@ -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 + # + # 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) %>
- <%= 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 %>
-

<%=l(:label_custom_workflow_plural)%>

+

<%= l(:label_custom_workflow_plural) %>

<% if @workflows.any? %> - - - - - - - - - - - - - - <% @workflows.each do |workflow| %> - <%= 'disabled' unless workflow.active? %>"> - - - - - - - - - <% end %> - -
<%= l(:field_name) %><%= l(:field_description) %><%= l(:field_observable) %><%= l(:field_author) %><%= l(:label_project_plural) %><%= l(:button_sort) %>
<%= link_to(workflow.name, edit_custom_workflow_path(workflow)) %><%= textilizable(workflow.description) %><%= l("custom_workflow_observable_#{workflow.observable}") %><%= mail_to workflow.author if workflow.author.present? %> - <% 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 %> - - <%= 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_custom_workflow_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-export', method: :get) %> -
- <%= link_to(l(:button_delete), workflow, class: 'icon icon-del', data: { confirm: l(:text_are_you_sure) }, confirm: l(:text_are_you_sure), method: :delete) %> -
+ + + + + + + + + + + <% @workflows.each do |workflow| %> + + + + + + + <% end %> + +
<%= l(:field_name) %><%= l(:field_observable) %><%= l(:field_author) %>
<%= link_to workflow.name, edit_custom_workflow_path(workflow) %><%= l("custom_workflow_observable_#{workflow.observable}") %><%= mail_to workflow.author if workflow.author.present? %> + <%= 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 %> +
<% else %>

<%= l(:label_no_data) %>

<% end %>
- -