From 24560c859872e0102562daa8d020ef5bc9be211d Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 22 Nov 2020 21:32:57 +0100 Subject: [PATCH] Actualizar plugin Checklists a 3.1.18 light --- plugins/redmine_checklists/Gemfile | 1 + .../app/controllers/checklists_controller.rb | 37 ++- .../app/helpers/checklists_helper.rb | 2 +- .../app/models/checklist.rb | 19 +- .../app/models/journal_checklist_history.rb | 23 +- .../views/checklists/_checklist_item.html.erb | 15 +- .../app/views/checklists/done.js.erb | 13 ++ .../app/views/issues/_checklist.html.erb | 9 +- .../views/issues/_checklist_fields.html.erb | 37 +-- .../app/views/projects/settings/.gitkeep | 0 .../settings/checklists/_general.html.erb | 6 + .../assets/javascripts/checklists.js | 219 ++++++++++++++---- .../assets/stylesheets/checklists.css | 69 +++++- .../redmine_checklists/config/locales/de.yml | 11 +- .../redmine_checklists/config/locales/en.yml | 12 +- .../redmine_checklists/config/locales/fr.yml | 5 + .../redmine_checklists/config/locales/it.yml | 45 ++++ .../redmine_checklists/config/locales/ru.yml | 13 ++ .../config/locales/zh-TW.yml | 32 +++ plugins/redmine_checklists/config/routes.rb | 2 +- .../db/migrate/001_create_checklists.rb | 4 +- .../002_add_time_stamps_to_checklists.rb | 4 +- .../003_create_checklist_template_category.rb | 4 +- .../migrate/004_create_checklist_templates.rb | 4 +- .../005_modify_checklist_subject_length.rb | 4 +- .../006_add_fields_to_checklist_template.rb | 4 +- .../007_add_is_section_to_checklists.rb | 24 ++ plugins/redmine_checklists/doc/CHANGELOG | 58 ++++- plugins/redmine_checklists/init.rb | 12 +- .../hooks/controller_issues_hook.rb | 4 +- .../hooks/views_issues_hook.rb | 2 +- .../hooks/views_layouts_hook.rb | 2 +- .../add_helpers_for_checklists_patch.rb | 2 +- .../2.1/redmine_api_test_patch.rb | 2 +- .../compatibility/application_helper_patch.rb | 38 +++ .../patches/compatibility/journal_patch.rb | 23 +- .../compatibility/open_struct_patch.rb | 2 +- .../patches/compatibility_patch.rb | 2 +- .../redmine_checklists/patches/issue_patch.rb | 52 +++-- .../patches/issue_query_patch.rb | 5 +- .../patches/issues_controller_patch.rb | 25 +- .../patches/issues_helper_patch.rb | 30 ++- .../patches/notifiable_patch.rb | 2 +- .../patches/project_patch.rb | 7 +- .../redmine_checklists/redmine_checklists.rb | 14 +- .../redmine_checklists/scripts/run_local.sh | 12 - .../test/fixtures/checklists.yml | 13 +- .../functional/checklists_controller_test.rb | 13 +- .../test/functional/issues_controller_test.rb | 120 ++++++---- .../integration/api_test/checklists_test.rb | 34 ++- .../test/integration/common_issue_test.rb | 20 +- .../redmine_checklists/test/test_helper.rb | 43 +++- .../test/unit/checklist_test.rb | 57 ++++- .../test/unit/issue_test.rb | 85 +++++++ .../test/unit/project_test.rb | 2 +- 55 files changed, 992 insertions(+), 307 deletions(-) create mode 100644 plugins/redmine_checklists/Gemfile delete mode 100644 plugins/redmine_checklists/app/views/projects/settings/.gitkeep create mode 100644 plugins/redmine_checklists/config/locales/it.yml create mode 100644 plugins/redmine_checklists/config/locales/zh-TW.yml create mode 100644 plugins/redmine_checklists/db/migrate/007_add_is_section_to_checklists.rb create mode 100644 plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility/application_helper_patch.rb delete mode 100755 plugins/redmine_checklists/scripts/run_local.sh create mode 100644 plugins/redmine_checklists/test/unit/issue_test.rb diff --git a/plugins/redmine_checklists/Gemfile b/plugins/redmine_checklists/Gemfile new file mode 100644 index 0000000..c6b5df6 --- /dev/null +++ b/plugins/redmine_checklists/Gemfile @@ -0,0 +1 @@ +gem 'redmine_crm' diff --git a/plugins/redmine_checklists/app/controllers/checklists_controller.rb b/plugins/redmine_checklists/app/controllers/checklists_controller.rb index ebd159c..c25e9cd 100644 --- a/plugins/redmine_checklists/app/controllers/checklists_controller.rb +++ b/plugins/redmine_checklists/app/controllers/checklists_controller.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -20,9 +20,9 @@ class ChecklistsController < ApplicationController unloadable - before_filter :find_checklist_item, :except => [:index, :create] - before_filter :find_issue_by_id, :only => [:index, :create] - before_filter :authorize, :except => [:done] + before_action :find_checklist_item, :except => [:index, :create] + before_action :find_issue_by_id, :only => [:index, :create] + before_action :authorize, :except => [:done] helper :issues accept_api_auth :index, :update, :destroy, :create, :show @@ -48,11 +48,13 @@ class ChecklistsController < ApplicationController end def create - @checklist_item = Checklist.new(params[:checklist]) + @checklist_item = Checklist.new + @checklist_item.safe_attributes = params[:checklist] @checklist_item.issue = @issue respond_to do |format| format.api { if @checklist_item.save + recalculate_issue_ratio(@checklist_item) render :action => 'show', :status => :created, :location => checklist_url(@checklist_item) else render_validation_errors(@checklist_item) @@ -62,9 +64,11 @@ class ChecklistsController < ApplicationController end def update + @checklist_item.safe_attributes = params[:checklist] respond_to do |format| format.api { - if @checklist_item.update_attributes(params[:checklist]) + if with_issue_journal { @checklist_item.save } + recalculate_issue_ratio(@checklist_item) render_api_ok else render_validation_errors(@checklist_item) @@ -75,12 +79,12 @@ class ChecklistsController < ApplicationController def done (render_403; return false) unless User.current.allowed_to?(:done_checklists, @checklist_item.issue.project) - @checklist_item.is_done = params[:is_done] == 'true' - if @checklist_item.save - if (Setting.issue_done_ratio == "issue_field") && RedmineChecklists.settings["issue_done_ratio"].to_i > 0 - Checklist.recalc_issue_done_ratio(@checklist_item.issue.id) - @checklist_item.issue.reload + with_issue_journal do + @checklist_item.is_done = params[:is_done] == 'true' + if @checklist_item.save + recalculate_issue_ratio(@checklist_item) + true end end respond_to do |format| @@ -104,4 +108,15 @@ class ChecklistsController < ApplicationController rescue ActiveRecord::RecordNotFound render_404 end + + def with_issue_journal(&block) + return unless yield + end + + def recalculate_issue_ratio(checklist_item) + if (Setting.issue_done_ratio == 'issue_field') && RedmineChecklists.issue_done_ratio? + Checklist.recalc_issue_done_ratio(checklist_item.issue.id) + checklist_item.issue.reload + end + end end diff --git a/plugins/redmine_checklists/app/helpers/checklists_helper.rb b/plugins/redmine_checklists/app/helpers/checklists_helper.rb index 9c0abd0..e939ba8 100644 --- a/plugins/redmine_checklists/app/helpers/checklists_helper.rb +++ b/plugins/redmine_checklists/app/helpers/checklists_helper.rb @@ -3,7 +3,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify diff --git a/plugins/redmine_checklists/app/models/checklist.rb b/plugins/redmine_checklists/app/models/checklist.rb index 70dbb7c..770b20e 100644 --- a/plugins/redmine_checklists/app/models/checklist.rb +++ b/plugins/redmine_checklists/app/models/checklist.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -22,10 +22,9 @@ class Checklist < ActiveRecord::Base include Redmine::SafeAttributes belongs_to :issue belongs_to :author, :class_name => "User", :foreign_key => "author_id" - has_one :comment, :as => :commented, :dependent => :delete - if ActiveRecord::VERSION::MAJOR >= 4 - attr_protected :id - end + + attr_protected :id if ActiveRecord::VERSION::MAJOR <= 4 + acts_as_event :datetime => :created_at, :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.issue_id}}, :type => 'issue issue-closed', @@ -51,17 +50,17 @@ class Checklist < ActiveRecord::Base :order_column => "#{table_name}.id" end - acts_as_list + rcrm_acts_as_list validates_presence_of :subject - validates_length_of :subject, :maximum => 512 + validates_length_of :subject, maximum: 512 validates_presence_of :position validates_numericality_of :position def self.recalc_issue_done_ratio(issue_id) issue = Issue.find(issue_id) - return false if (Setting.issue_done_ratio != "issue_field") || RedmineChecklists.settings["issue_done_ratio"].to_i < 1 || issue.checklists.empty? - done_checklist = issue.checklists.map{|c| c.is_done ? 1 : 0} + return false if (Setting.issue_done_ratio != 'issue_field') || !RedmineChecklists.issue_done_ratio? || issue.checklists.reject(&:is_section).empty? + done_checklist = issue.checklists.reject(&:is_section).map { |c| c.is_done ? 1 : 0 } done_ratio = (done_checklist.count(1) * 10) / done_checklist.count * 10 issue.update_attribute(:done_ratio, done_ratio) end @@ -71,7 +70,7 @@ class Checklist < ActiveRecord::Base (detail.value.is_a?(String) && detail.value.match(/^\[[ |x]\] .+$/).present?) end - safe_attributes 'subject', 'position', 'issue_id', 'is_done' + safe_attributes 'subject', 'position', 'issue_id', 'is_done', 'is_section' def editable_by?(usr = User.current) usr && (usr.allowed_to?(:edit_checklists, project) || (author == usr && usr.allowed_to?(:edit_own_checklists, project))) diff --git a/plugins/redmine_checklists/app/models/journal_checklist_history.rb b/plugins/redmine_checklists/app/models/journal_checklist_history.rb index bab6fa2..17eeca2 100644 --- a/plugins/redmine_checklists/app/models/journal_checklist_history.rb +++ b/plugins/redmine_checklists/app/models/journal_checklist_history.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -19,27 +19,24 @@ class JournalChecklistHistory def self.can_fixup?(journal_details) - unless journal_details.journal - return false - end + return false if journal_details.journal.nil? + issue = journal_details.journal.journalized - unless issue.is_a?(Issue) - return false - end + return false unless issue.is_a?(Issue) + prev_journal_scope = issue.journals.order('id DESC') prev_journal_scope = prev_journal_scope.where('id <> ?', journal_details.journal_id) if journal_details.journal_id prev_journal = prev_journal_scope.first - unless prev_journal - return false - end + return false unless prev_journal + return false if prev_journal.user_id != journal_details.journal.user_id return false if Time.zone.now > prev_journal.created_on + 1.minute - prev_journal.details.all?{ |x| x.prop_key == 'checklist'} && - journal_details.journal.details.all?{ |x| x.prop_key == 'checklist'} && + prev_journal.details.all? { |x| x.prop_key == 'checklist' } && + journal_details.journal.details.all? { |x| x.prop_key == 'checklist' } && journal_details.journal.notes.blank? && prev_journal.notes.blank? && - prev_journal.details.select{ |x| x.prop_key == 'checklist' }.size == 1 + prev_journal.details.select { |x| x.prop_key == 'checklist' }.size == 1 end def self.fixup(journal_details) diff --git a/plugins/redmine_checklists/app/views/checklists/_checklist_item.html.erb b/plugins/redmine_checklists/app/views/checklists/_checklist_item.html.erb index 19d094a..0855cdb 100644 --- a/plugins/redmine_checklists/app/views/checklists/_checklist_item.html.erb +++ b/plugins/redmine_checklists/app/views/checklists/_checklist_item.html.erb @@ -1,8 +1,11 @@ -
  • > - <%= check_box_tag 'checklist_item', "", checklist_item.is_done, - :disabled => !User.current.allowed_to?(:done_checklists, checklist_item.issue.project) && !User.current.allowed_to?(:edit_checklists, checklist_item.issue.project), - :data_url => url_for( {:controller => "checklists", :action => "done", :id => checklist_item.id} ), :class => 'checklist-checkbox' - %> +
  • + <% unless checklist_item.is_section %> + <%= check_box_tag 'checklist_item', '', checklist_item.is_done, + disabled: !User.current.allowed_to?(:done_checklists, checklist_item.issue.project) && !User.current.allowed_to?(:edit_checklists, checklist_item.issue.project), + data_url: url_for({ controller: 'checklists', action: 'done', id: checklist_item.id }), + class: 'checklist-checkbox', + id: "checklist-checkbox-#{checklist_item.id}" + %> + <% end %> <%= textilizable(checklist_item, :subject).gsub(/<\/?(p|h\d+|li|ul)>/, '').strip.html_safe %> -
  • diff --git a/plugins/redmine_checklists/app/views/checklists/done.js.erb b/plugins/redmine_checklists/app/views/checklists/done.js.erb index 9fc91bd..baf98be 100644 --- a/plugins/redmine_checklists/app/views/checklists/done.js.erb +++ b/plugins/redmine_checklists/app/views/checklists/done.js.erb @@ -2,3 +2,16 @@ $("#checklist_item_<%= @checklist_item.id %>").toggleClass('is-done-checklist-it $('#checklist_form .checklist-item#<%= @checklist_item.id %> input[type=checkbox]').trigger('click'); $('.issue .attributes table.progress').parent().html('<%= j(progress_bar(@checklist_item.issue.done_ratio, :width => '80px', :legend => "#{@checklist_item.issue.done_ratio}%")) %>'); $('#issue_done_ratio').val('<%= @checklist_item.issue.done_ratio %>'); + +var checkedCheckboxes = $('.checklist-checkbox:checkbox:checked'); + +if(localStorage.getItem("hide_closed_checklists") === '0' && checkedCheckboxes.length > 0){ + $("#checklist_item_<%= @checklist_item.id %>").fadeOut(1000).hide(15); + $('#switch_link').text('<%= l("label_checklist_show_closed") %>' + '(' + checkedCheckboxes.length + ')'); +} +if(checkedCheckboxes.length < 1 && localStorage.getItem("hide_closed_checklists") === '1'){ + $('#switch_link').hide(); +} +if(checkedCheckboxes.length > 0){ + $('#switch_link').show(); +} diff --git a/plugins/redmine_checklists/app/views/issues/_checklist.html.erb b/plugins/redmine_checklists/app/views/issues/_checklist.html.erb index edf30ee..b2abf2b 100644 --- a/plugins/redmine_checklists/app/views/issues/_checklist.html.erb +++ b/plugins/redmine_checklists/app/views/issues/_checklist.html.erb @@ -1,7 +1,9 @@ <% if !@issue.blank? && @issue.checklists.any? && User.current.allowed_to?(:view_checklists, @project) %>
    - +
    + <%= link_to l("label_checklist_hide_closed"), '#', id: 'switch_link' %> +

    <%=l(:label_checklist_plural)%>

    - - + <%= javascript_tag do %> + new Redmine.ChecklistToggle('<%= l("label_checklist_show_closed") %>', '<%= l("label_checklist_hide_closed") %>'); + <% end %> <% end %> diff --git a/plugins/redmine_checklists/app/views/issues/_checklist_fields.html.erb b/plugins/redmine_checklists/app/views/issues/_checklist_fields.html.erb index 92dd220..8cdcb4c 100644 --- a/plugins/redmine_checklists/app/views/issues/_checklist_fields.html.erb +++ b/plugins/redmine_checklists/app/views/issues/_checklist_fields.html.erb @@ -1,21 +1,26 @@ - - <%= f.check_box :is_done %> - - <%= f.object.subject %> + + <% unless f.object.is_section %> + <%= f.check_box :is_done %> + <% end %> + + + <%= textilizable(f.object, :subject).gsub(/<\/?(p|h\d+|li|ul)>/, '').strip.html_safe %> - - <%= text_field_tag nil, f.object.subject, :class => 'edit-box'%> - <%= f.hidden_field :subject, :class => 'checklist-subject-hidden' %> + + + <%= text_field_tag nil, f.object.subject, class: 'edit-box' %> + <%= f.hidden_field :subject, class: 'checklist-subject-hidden' %> - <%= submit_tag l(:button_save), :type => "button", :class => "item item-save small"%> - <% concat l(:button_cancel) - %> - <%= link_to_remove_checklist_fields "", f, - :class => "icon icon-del" %> - <%= f.hidden_field :position, :class => 'checklist-item-position' %> - <%= f.hidden_field :id, :class => 'checklist-item-id' %> - + + <%= submit_tag l(:button_save), type: 'button', class: 'item item-save small' %> + <% concat l(:button_cancel) %> + <%= link_to_remove_checklist_fields "", f, class: 'icon icon-del' %> + + <%= f.hidden_field :position, class: 'checklist-item-position' %> + <%= f.hidden_field :is_section, class: 'checklist-item-is_section' %> + <%= f.hidden_field :id, class: 'checklist-item-id' %> + +
    - diff --git a/plugins/redmine_checklists/app/views/projects/settings/.gitkeep b/plugins/redmine_checklists/app/views/projects/settings/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/plugins/redmine_checklists/app/views/settings/checklists/_general.html.erb b/plugins/redmine_checklists/app/views/settings/checklists/_general.html.erb index 44aea21..af66755 100644 --- a/plugins/redmine_checklists/app/views/settings/checklists/_general.html.erb +++ b/plugins/redmine_checklists/app/views/settings/checklists/_general.html.erb @@ -5,3 +5,9 @@ <%= check_box_tag 'settings[issue_done_ratio]', 1, @settings["issue_done_ratio"].to_i > 0 %>

    <% end %> + +

    + + <%= hidden_field_tag 'settings[block_issue_closing]', 0, :id => nil %> + <%= check_box_tag 'settings[block_issue_closing]', 1, @settings["block_issue_closing"].to_i > 0 %> +

    diff --git a/plugins/redmine_checklists/assets/javascripts/checklists.js b/plugins/redmine_checklists/assets/javascripts/checklists.js index 1123a42..d5263a0 100644 --- a/plugins/redmine_checklists/assets/javascripts/checklists.js +++ b/plugins/redmine_checklists/assets/javascripts/checklists.js @@ -110,15 +110,11 @@ Redmine.Checklist = $.klass({ event.returnValue = false }, - addChecklistFields: function(templateDiv) { + addChecklistFields: function() { var new_id = new Date().getTime(); var regexp = new RegExp("new_checklist", "g"); - if (templateDiv) { - appended = $(this.content.replace(regexp, new_id)).insertBefore(templateDiv) - } else { - appended = $(this.content.replace(regexp, new_id)).appendTo(this.root) - } - appended.find('.edit-box').focus() + appended = $(this.content.replace(regexp, new_id)).appendTo(this.root); + appended.find('.edit-box').focus(); }, findSpan: function(event) { @@ -129,13 +125,16 @@ Redmine.Checklist = $.klass({ return elem.prevAll('span.checklist-item.new') }, - transformItem: function(event, elem, valueToSet) { + transformItem: function(event, elem, valueToSet, isSection) { var checklistItem; if (event) { checklistItem = this.findSpan(event) - } else { + } else if (elem) { checklistItem = this.findSpanBefore(elem) + } else { + checklistItem = this.root.find('span.checklist-item.new') } + var val; if (valueToSet) { val = valueToSet @@ -143,11 +142,17 @@ Redmine.Checklist = $.klass({ } else { val = checklistItem.find('input.edit-box').val() } + checklistItem.find('.checklist-subject').text(val) checklistItem.find('.checklist-subject-hidden').val(val) checklistItem.removeClass('edit') checklistItem.removeClass('new') checklistItem.addClass('show') + + if (isSection) { + checklistItem.addClass('checklist-section'); + checklistItem.children('.checklist-item-is_section').val(true); + } }, resetItem: function(item) { @@ -157,12 +162,9 @@ Redmine.Checklist = $.klass({ }, addChecklistItem: function(event) { - this.preventEvent(event) - this.transformItem(event) - if ($('.template-wrapper').length) - this.addChecklistFields($('.template-wrapper')) - else - this.addChecklistFields() + this.preventEvent(event); + this.transformItem(event); + this.addChecklistFields(); }, canSave: function(span) { @@ -193,6 +195,57 @@ Redmine.Checklist = $.klass({ }, this)) }, + onClickAddChecklistItemMenuButton: function() { + $('#checklist-menu .add-checklist-item').on('click', $.proxy(function(event) { + this.preventEvent(event); + var span = $('#checklist_form_items > span.checklist-item.new'); + if (this.canSave(span)) { + this.transformItem(); + this.addChecklistFields(); + this.$plusButtonMenu.hide(); + } + }, this)) + }, + + onClickNewSectionMenuButton: function() { + $('#checklist-menu .add-checklist-section').on('click', $.proxy(function(event) { + this.preventEvent(event); + var span = $('#checklist_form_items > span.checklist-item.new'); + if (this.canSave(span)) { + this.transformItem(null, null, null, true); + this.addChecklistFields(); + this.$plusButtonMenu.hide(); + } + }, this)) + }, + + onMouseEnterLeavePlusButton: function() { + var hideMenuTimer; + var $menu = this.$plusButtonMenu; + + this.root.on('mouseenter', '.save-new-by-button', function() { + var $plusButton = $(this); + var position = $plusButton.position(); + $menu.css('left', (position.left + 'px')); + $menu.css('top', (position.top + $plusButton.height() + 'px')); + $menu.show(); + }); + + this.root.on('mouseleave', '.save-new-by-button', function() { + hideMenuTimer = setTimeout(function() { + $menu.hide(); + }, 500); + }); + + $('#checklist-menu').on('mouseenter', function() { + clearTimeout(hideMenuTimer); + }); + + $('#checklist-menu').on('mouseleave', function() { + $menu.hide(); + }); + }, + onIssueFormSubmitRemoveEmptyChecklistItems: function() { $('body').on('submit', '#issue-form', function(){ $('.checklist-subject-hidden').each(function(i, elem) { @@ -206,16 +259,19 @@ Redmine.Checklist = $.klass({ onChecklistRemove: function() { this.root.on('click', '.checklist-remove a', $.proxy(function(event){ - this.preventEvent(event) - removed = this.findSpan(event) - removed.find('.checklist-remove input[type=hidden]').val('1') - removed.fadeOut(200) - }, this)) + this.preventEvent(event); + var itemToRemove = this.findSpan(event); + var checkbox = itemToRemove.find(".checklist-remove input[type=hidden]"); + + if (checkbox.val() === "false") { + checkbox.val("1"); + itemToRemove.fadeOut(200); + } + }, this)); }, makeChecklistsSortable: function() { $('#checklist_form_items').sortable({ - revert: true, items: '.checklist-item.show', helper: "clone", stop: function (event, ui) { @@ -265,13 +321,33 @@ Redmine.Checklist = $.klass({ }, onChangeCheckbox: function(){ - this.root.on('change', 'input.checklist-checkbox', $.proxy(function(event){ + this.root.on('change', 'input.checklist-checkbox', $.proxy(function(event) { + this.darkenCompletedSections(); checkbox = $(event.target) url = checkbox.attr('data_url') $.ajax({type: "PUT", url: url, data: { is_done: checkbox.prop('checked') }, dataType: 'script'}) }, this)) }, + darkenCompletedSections: function() { + var isCompletedSection = true; + var reversedChecklistItems = $('#checklist_items li').get().reverse(); + + $(reversedChecklistItems).each(function(index, element) { + var $element = $(element); + if ($element.hasClass('checklist-section')) { + if (isCompletedSection) { + $element.addClass('completed-section') + } else { + $element.removeClass('completed-section') + } + isCompletedSection = true; + } else { + isCompletedSection = isCompletedSection && $element.children('.checklist-checkbox').is(':checked') + } + }) + }, + enableUniquenessValidation: function() { this.root.on('keyup', 'input.edit-box', $.proxy(function(event) { value = $(event.target).val() @@ -303,39 +379,39 @@ Redmine.Checklist = $.klass({ }, assignTemplateSelectedEvent: function() { - var item; - this.root.on('change', '#checklist_template', $.proxy(function(){ - value = $('#checklist_template').val() - selected = $('#checklist_template option[value='+value+']').data('template-items') - items = selected.split(/\n/) - for(i = 0; i 0) { + this.onMouseEnterLeavePlusButton(); + this.onClickAddChecklistItemMenuButton(); + this.assignTemplateSelectedEvent(); + this.onClickNewSectionMenuButton(); + } + } else { + this.darkenCompletedSections() + } + this.onIssueFormSubmitRemoveEmptyChecklistItems() this.onChecklistRemove() this.makeChecklistsSortable() @@ -343,12 +419,59 @@ Redmine.Checklist = $.klass({ this.onCheckboxChanged() this.onChangeCheckbox() this.enableUniquenessValidation() - this.assignTemplateSelectedEvent() - this.clickSelectTemplateLink() } }) $.fn.checklist = function(element){ new Redmine.Checklist(this); -} +}; + +Redmine.ChecklistToggle = $.klass({ + manageToggling: function (t_val) { + var checkedCheckboxes = $('.checklist-checkbox:checkbox:checked'); + + if(localStorage.getItem("hide_closed_checklists") === t_val){ + $($(checkedCheckboxes).closest('li')).hide(); + $(this.switch_link).text(this.show_text + '(' + checkedCheckboxes.length + ')'); + } else { + $($(checkedCheckboxes).closest('li')).show(); + $(this.switch_link).text(this.hide_text); + } + }, + switch_link_click: function(){ + var th = $(this)[0]; + this.switch_link.click(function (e) { + e.preventDefault(); + th.manageToggling("1"); + var setVal = (localStorage.getItem("hide_closed_checklists") === "1") ? "0" : "1"; + localStorage.setItem("hide_closed_checklists", setVal); + }); + }, + hide_switch_link: function(){ + if($('.checklist-checkbox:checkbox:checked').length < 1){ + this.switch_link.hide(); + } + }, + init: function(show_text, hide_text) { + this.show_text = show_text; + this.hide_text = hide_text; + this.switch_link = $('#switch_link'); + this.manageToggling("0"); + this.switch_link_click(); + this.hide_switch_link(); + } +}); + + +$(document).ready(function () { + if (typeof(contextMenuCheckSelectionBox) === 'function') { + var originContextMenuCheckSelectionBox = contextMenuCheckSelectionBox; + contextMenuCheckSelectionBox = function (tr, checked) { + var $td = tr.find('td.checklist_relations'); + var $checklist = $td.find('.checklist').detach(); + originContextMenuCheckSelectionBox(tr, checked); + $checklist.appendTo($td); + }; + } +}); diff --git a/plugins/redmine_checklists/assets/stylesheets/checklists.css b/plugins/redmine_checklists/assets/stylesheets/checklists.css index 030318f..a254bda 100644 --- a/plugins/redmine_checklists/assets/stylesheets/checklists.css +++ b/plugins/redmine_checklists/assets/stylesheets/checklists.css @@ -1,3 +1,7 @@ +#checklist_form_items input[type="checkbox"], +#checklist_items input[type="checkbox"] { + height: initial; +} div#checklist ul { list-style: none; @@ -10,6 +14,8 @@ div#checklist li { margin-left: 10px; } +.checklist-checkbox {height: inherit} + #checklist li:hover a.delete {opacity: 1;} #checklist a.delete {opacity: 0.4;} @@ -74,4 +80,65 @@ span.checklist-item.edit .checklist-show-only { div#checklist ol { display: inline-block; padding-left: 0; -} \ No newline at end of file +} + +.checklist-section { + padding-top: 10px; + font-weight: bold; + border-bottom-width: 1px; + border-bottom-style: solid; + border-bottom-color: #eee; +} + +.checklist-item.checklist-section > .checklist-checkbox { display: none; } + +#checklist_items li.checklist-section { + padding-bottom: 5px; + margin-bottom: 5px; +} + +.completed-section { color: #999; } + +.save-new-by-button { cursor: pointer; } + +table.list td.checklist_relations { text-align: left } + +/* ========================================================================= */ +/* Checklist context menu */ +/* ========================================================================= */ + +#checklist-menu ul, #checklist-menu li, #checklist-menu a { + display:block; + margin:0; + padding:0; + border:0; +} + +#checklist-menu { + display: none; + position: absolute; + font-size: 0.9em; +} + +#checklist-menu, #checklist-menu ul { + width: 150px; + border: 1px solid #ccc; + background: white; + list-style: none; + padding: 2px; + border-radius: 2px; +} + +#checklist-menu li { + position: relative; + padding: 1px; + border: 1px solid white; +} + +#checklist-menu a { + text-decoration: none !important; + padding: 2px 0px 2px 20px; +} + +#checklist-menu a:hover { color:#2A5685; } +#checklist-menu li:hover { border:1px solid #628db6; background-color:#eef5fd; border-radius:3px; } diff --git a/plugins/redmine_checklists/config/locales/de.yml b/plugins/redmine_checklists/config/locales/de.yml index 4a90806..7fdb430 100644 --- a/plugins/redmine_checklists/config/locales/de.yml +++ b/plugins/redmine_checklists/config/locales/de.yml @@ -25,5 +25,12 @@ de: label_checklist_changed_to: zu label_checklist_added: hinzugefügt label_checklist_done: als Erledigt markiert - label_checklist_undone: als Nicht Erledigt markiert - label_checklist_updated: Checklisten-Eintrag editiert \ No newline at end of file + label_checklist_undone: als Nicht erledigt markiert + label_checklist_updated: Checklisten-Eintrag editiert + label_checklist_status: Checklisten-Status + label_checklist_status_done: Erledigt + label_checklist_status_undone: Nicht erledigt + label_checklist_is_default: Standard + field_is_for_tracker: Tracker + label_checklists_must_be_completed: "Alle Checklisten-Einträge eines Tickets müssen vor dem Schließen erledigt werden." + label_checklist_block_issue_closing: "Schließen des Tickets blockieren" diff --git a/plugins/redmine_checklists/config/locales/en.yml b/plugins/redmine_checklists/config/locales/en.yml index 9562de9..b60cd28 100644 --- a/plugins/redmine_checklists/config/locales/en.yml +++ b/plugins/redmine_checklists/config/locales/en.yml @@ -1,5 +1,9 @@ # English strings go here for Rails i18n en: + activerecord: + attributes: + checklists: + subject: Checklist subject label_checklist_plural: Checklist field_checklist: Checklist label_checklist_save_log: Save changes to issue log @@ -15,10 +19,12 @@ en: field_template_items: Template items label_checklist_template: Checklist template label_add_checklists_from_template: Add from template + label_checklists_from_template: From template label_select_template: "-- Select template --" label_checklist_category_not_specified: "-- Not specified --" label_checklists_description: 'Multiple values allowed (one line for each value)' label_checklist_item: Checklist item + label_checklist_section: Checklist section label_checklist_deleted: deleted label_checklist_changed_from: changed from label_checklist_changed_to: to @@ -29,6 +35,10 @@ en: label_checklist_status: Checklist status label_checklist_status_done: Done label_checklist_status_undone: Undone - label_checklist_status: Checklist status label_checklist_is_default: Default field_is_for_tracker: Tracker + label_checklists_must_be_completed: All checklists of an issue must be done before closing + label_checklist_block_issue_closing: Block issue closing + label_checklist_show_closed: Show closed + label_checklist_hide_closed: Hide closed + label_checklist_new_section: New section diff --git a/plugins/redmine_checklists/config/locales/fr.yml b/plugins/redmine_checklists/config/locales/fr.yml index 6a1ed72..5c1fe44 100755 --- a/plugins/redmine_checklists/config/locales/fr.yml +++ b/plugins/redmine_checklists/config/locales/fr.yml @@ -2,3 +2,8 @@ fr: label_checklist_plural: Liste de Tâches field_checklist: Tâche + label_checklist_templates: Template de checklists + label_checklist_new_checklist_template: Ajouter un template + field_is_for_tracker: + label_checklist_is_default: Checklist par d faut + field_template_items: Eléments diff --git a/plugins/redmine_checklists/config/locales/it.yml b/plugins/redmine_checklists/config/locales/it.yml new file mode 100644 index 0000000..79dc3d5 --- /dev/null +++ b/plugins/redmine_checklists/config/locales/it.yml @@ -0,0 +1,45 @@ +# encoding: utf-8 +# Italian strings go here for Rails i18n +it: + activerecord: + attributes: + checklists: + subject: Checklist soggetto + label_checklist_plural: Checklist + field_checklist: Checklist + label_checklist_save_log: Salva le modifiche nel log delle segnalazioni + label_checklist_done_ratio: Imposta ratio checklist segnalazioni completate + permission_view_checklists: Visualizza la checklist + permission_done_checklists: Elementi checklist completati + permission_edit_checklists: Modifica elementi checklist + label_checklist_template_category_plural: Categorie di modelli + label_checklist_template_category_new: Nuova categoria + field_checklist_template_category: Categoria + label_checklist_templates: Modelli di checklist + label_checklist_new_checklist_template: Nuovo modello di checklist + field_template_items: Elementi del modello + label_checklist_template: Modello di checklist + label_add_checklists_from_template: Aggiungi dal modello + label_checklists_from_template: Dal modello + label_select_template: "- Seleziona modello -" + label_checklist_category_not_specified: "-- Non specificato --" + label_checklists_description: "Sono consentiti più valori (una riga per ciascun valore)" + label_checklist_item: Elemento della checklist + label_checklist_section: Sezione checklist + label_checklist_deleted: Eliminato + label_checklist_changed_from: Modificato da + label_checklist_changed_to: a + label_checklist_added: aggiunto + label_checklist_done: Impostato su Completato + label_checklist_undone: Impostato su Non completato + label_checklist_updated: Elemento della checklist aggiornato + label_checklist_status: Stato della checklist + label_checklist_status_done: Completato + label_checklist_status_undone: Non completato + label_checklist_is_default: Predefinito + field_is_for_tracker: Tracker + label_checklists_must_be_completed: Tutte le liste di controllo di una segnalazione devono essere eseguite prima della chiusura + label_checklist_block_issue_closing: Blocca segnalazione in chiusura + label_checklist_show_closed: Mostra completati + label_checklist_hide_closed: Nascondi completati + label_checklist_new_section: Nuova sezione diff --git a/plugins/redmine_checklists/config/locales/ru.yml b/plugins/redmine_checklists/config/locales/ru.yml index 7e3d5d6..8c7463f 100644 --- a/plugins/redmine_checklists/config/locales/ru.yml +++ b/plugins/redmine_checklists/config/locales/ru.yml @@ -1,5 +1,9 @@ # encoding: utf-8 ru: + activerecord: + attributes: + checklists: + subject: Заголовок чеклиста label_checklist_plural: Чеклист field_checklist: Чеклист label_checklist_save_log: Сохранять изменения в истории @@ -15,10 +19,12 @@ ru: field_template_items: Элементы шаблона label_checklist_template: Шаблон чеклистов label_add_checklists_from_template: Добавить из шаблона + label_checklists_from_template: Из шаблона label_select_template: "-- Выберите шаблон --" label_checklist_category_not_specified: "-- Без категории --" label_checklists_description: 'Для ввода нескольких значений вводите по одному на строку' label_checklist_item: Пункт чеклиста + label_checklist_section: Раздел чеклиста label_checklist_deleted: удалён label_checklist_changed_from: изменён с label_checklist_changed_to: на @@ -31,3 +37,10 @@ ru: label_checklist_status_undone: Не выполнен label_checklist_is_default: По умолчанию field_is_for_tracker: Трекер + label_checklist_show_closed: Показать закрытые + label_checklist_hide_closed: Скрыть закрытые + label_checklist_new_section: Новая секция + label_checklist_block_issue_closing: Запретить закрытие заявки + label_checklists: Чеклист + label_checklists_must_be_completed: Чтобы заявка закрылась, должны быть выполнены все пункты чеклиста + field_checklists: Чеклист diff --git a/plugins/redmine_checklists/config/locales/zh-TW.yml b/plugins/redmine_checklists/config/locales/zh-TW.yml new file mode 100644 index 0000000..2fe53c2 --- /dev/null +++ b/plugins/redmine_checklists/config/locales/zh-TW.yml @@ -0,0 +1,32 @@ +# encoding: utf-8 +# Simplified Chinese strings go here for Rails i18n +# Author: Steven.W +# Based on file: en.yml + +zh-TW: + label_checklist_plural: Checklist + field_checklist: Checklist + label_checklist_save_log: 保存檢查清單變更到問題日誌 + label_checklist_done_ratio: 設置列表完成比率 + permission_view_checklists: 查看Checklist + permission_done_checklists: 完成Checklist + permission_edit_checklists: 編輯Checklist + label_checklist_template_category_plural: 範本類別 + label_checklist_template_category_new: 新類別 + field_checklist_template_category: 類別 + label_checklist_templates: 檢查清單範本 + label_checklist_new_checklist_template: 新檢查清單範本 + field_template_items: 範本項 + label_checklist_template: 檢查清單範本 + label_add_checklists_from_template: 從範本新建 + label_select_template: "-- 選擇範本 --" + label_checklist_category_not_specified: "-- 未指定 --" + label_checklists_description: '允許多重值 (每一行的值)' + label_checklist_item: Checklist item + label_checklist_deleted: 刪除 + label_checklist_changed_from: 改變自 + label_checklist_changed_to: 到 + label_checklist_added: 添加 + label_checklist_done: 設置完成 + label_checklist_undone: 設置未完成 + label_checklist_updated: Checklist item編輯 \ No newline at end of file diff --git a/plugins/redmine_checklists/config/routes.rb b/plugins/redmine_checklists/config/routes.rb index 5658b9f..cc4e570 100644 --- a/plugins/redmine_checklists/config/routes.rb +++ b/plugins/redmine_checklists/config/routes.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify diff --git a/plugins/redmine_checklists/db/migrate/001_create_checklists.rb b/plugins/redmine_checklists/db/migrate/001_create_checklists.rb index ecfc807..fee2541 100644 --- a/plugins/redmine_checklists/db/migrate/001_create_checklists.rb +++ b/plugins/redmine_checklists/db/migrate/001_create_checklists.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -17,7 +17,7 @@ # You should have received a copy of the GNU General Public License # along with redmine_checklists. If not, see . -class CreateChecklists < ActiveRecord::Migration +class CreateChecklists < Rails.version < '5.1' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2] def self.up if ActiveRecord::Base.connection.table_exists? :issue_checklists diff --git a/plugins/redmine_checklists/db/migrate/002_add_time_stamps_to_checklists.rb b/plugins/redmine_checklists/db/migrate/002_add_time_stamps_to_checklists.rb index 1b428dc..f1f0444 100644 --- a/plugins/redmine_checklists/db/migrate/002_add_time_stamps_to_checklists.rb +++ b/plugins/redmine_checklists/db/migrate/002_add_time_stamps_to_checklists.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -17,7 +17,7 @@ # You should have received a copy of the GNU General Public License # along with redmine_checklists. If not, see . -class AddTimeStampsToChecklists < ActiveRecord::Migration +class AddTimeStampsToChecklists < Rails.version < '5.1' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2] def change add_column :checklists, :created_at, :timestamp add_column :checklists, :updated_at, :timestamp diff --git a/plugins/redmine_checklists/db/migrate/003_create_checklist_template_category.rb b/plugins/redmine_checklists/db/migrate/003_create_checklist_template_category.rb index fbe7518..3536dff 100644 --- a/plugins/redmine_checklists/db/migrate/003_create_checklist_template_category.rb +++ b/plugins/redmine_checklists/db/migrate/003_create_checklist_template_category.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -17,7 +17,7 @@ # You should have received a copy of the GNU General Public License # along with redmine_checklists. If not, see . -class CreateChecklistTemplateCategory < ActiveRecord::Migration +class CreateChecklistTemplateCategory < Rails.version < '5.1' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2] def self.up create_table :checklist_template_categories do |t| diff --git a/plugins/redmine_checklists/db/migrate/004_create_checklist_templates.rb b/plugins/redmine_checklists/db/migrate/004_create_checklist_templates.rb index f9fd3a7..56bee49 100644 --- a/plugins/redmine_checklists/db/migrate/004_create_checklist_templates.rb +++ b/plugins/redmine_checklists/db/migrate/004_create_checklist_templates.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -17,7 +17,7 @@ # You should have received a copy of the GNU General Public License # along with redmine_checklists. If not, see . -class CreateChecklistTemplates < ActiveRecord::Migration +class CreateChecklistTemplates < Rails.version < '5.1' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2] def self.up create_table :checklist_templates do |t| diff --git a/plugins/redmine_checklists/db/migrate/005_modify_checklist_subject_length.rb b/plugins/redmine_checklists/db/migrate/005_modify_checklist_subject_length.rb index 24467af..2fec00f 100644 --- a/plugins/redmine_checklists/db/migrate/005_modify_checklist_subject_length.rb +++ b/plugins/redmine_checklists/db/migrate/005_modify_checklist_subject_length.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -17,7 +17,7 @@ # You should have received a copy of the GNU General Public License # along with redmine_checklists. If not, see . -class ModifyChecklistSubjectLength < ActiveRecord::Migration +class ModifyChecklistSubjectLength < Rails.version < '5.1' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2] def self.up change_column :checklists, :subject, :string, :limit => 512 end diff --git a/plugins/redmine_checklists/db/migrate/006_add_fields_to_checklist_template.rb b/plugins/redmine_checklists/db/migrate/006_add_fields_to_checklist_template.rb index 24ef21f..cfda57f 100644 --- a/plugins/redmine_checklists/db/migrate/006_add_fields_to_checklist_template.rb +++ b/plugins/redmine_checklists/db/migrate/006_add_fields_to_checklist_template.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -17,7 +17,7 @@ # You should have received a copy of the GNU General Public License # along with redmine_checklists. If not, see . -class AddFieldsToChecklistTemplate < ActiveRecord::Migration +class AddFieldsToChecklistTemplate < Rails.version < '5.1' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2] def self.up add_column :checklist_templates, :is_default, :boolean, :default => false add_column :checklist_templates, :tracker_id, :integer diff --git a/plugins/redmine_checklists/db/migrate/007_add_is_section_to_checklists.rb b/plugins/redmine_checklists/db/migrate/007_add_is_section_to_checklists.rb new file mode 100644 index 0000000..c86fd1f --- /dev/null +++ b/plugins/redmine_checklists/db/migrate/007_add_is_section_to_checklists.rb @@ -0,0 +1,24 @@ +# This file is a part of Redmine Checklists (redmine_checklists) plugin, +# issue checklists management plugin for Redmine +# +# Copyright (C) 2011-2020 RedmineUP +# http://www.redmineup.com/ +# +# redmine_checklists 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 3 of the License, or +# (at your option) any later version. +# +# redmine_checklists 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 redmine_checklists. If not, see . + +class AddIsSectionToChecklists < (Rails.version < '5.1') ? ActiveRecord::Migration : ActiveRecord::Migration[4.2] + def change + add_column :checklists, :is_section, :boolean, default: false + end +end diff --git a/plugins/redmine_checklists/doc/CHANGELOG b/plugins/redmine_checklists/doc/CHANGELOG index d9c1ca9..d0b9c7c 100644 --- a/plugins/redmine_checklists/doc/CHANGELOG +++ b/plugins/redmine_checklists/doc/CHANGELOG @@ -1,9 +1,61 @@ == Redmine Checklists plugin changelog Redmine Checklists plugin - managing issue checklists plugin for Redmine -Copyright (C) 2011-2017 RedmineUP +Copyright (C) 2011-2020 RedmineUP http://www.redmineup.com/ +== 2020-08-17 v3.1.18 + +* Added italian locale +* Updated zh-tw locale +* Fixed size() method error +* Fixed initial install error +* Fixed checklist ration recalculate +* Fixed display checklist element with Markdown syntax +* Fixed done ratio recalculate on checklist API update +* Fixed API call journalizing + +== 2020-01-31 v3.1.17 + +* Redmine 4.1 compatibility fixes +* Fixed view permission bug +* Fixed template permissions bug +* Fixed context menu conflicts +* Fixed Agile support +* Fixed checklist copy bug +* Fixed locale bug +* Fixed project copy bug + +== 2019-04-29 v3.1.16 + +* Checklists sections + +== 2019-04-15 v3.1.15 + +* Redmine 4.0.3 support +* Added Hide link for closed items + +== 2018-12-20 v3.1.14 + +* Hotfix for Redmine 4 + +== 2018-12-18 v3.1.13 + +* Redmine 4 saving issue fixes + +== 2018-11-26 v3.1.12 + +* German translation update from Tobias Fischer +* Fixed diferent authors changes bug +* Fixed sortable animation bug + +== 2018-03-23 v3.1.11 + +* Redmine 4 support +* Setting for block issues with undone checklists +* Fixed bug with default template +* Fixed email notification bug + == 2017-10-12 v3.1.10 * Fixed email notification bug @@ -29,10 +81,10 @@ http://www.redmineup.com/ * Redmine 3.4 support * New checklists filters for issues table -* Save log by default +* Save log by default * Chinese translation update * Polish translation update -* Fixed bug with template editing +* Fixed bug with template editing == 2016-08-15 v3.1.5 diff --git a/plugins/redmine_checklists/init.rb b/plugins/redmine_checklists/init.rb index 274ce8e..5cb6116 100644 --- a/plugins/redmine_checklists/init.rb +++ b/plugins/redmine_checklists/init.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -20,7 +20,7 @@ require 'redmine' require 'redmine_checklists/redmine_checklists' -CHECKLISTS_VERSION_NUMBER = '3.1.10' +CHECKLISTS_VERSION_NUMBER = '3.1.18'.freeze CHECKLISTS_VERSION_TYPE = "Light version" Redmine::Plugin.register :redmine_checklists do @@ -31,7 +31,7 @@ Redmine::Plugin.register :redmine_checklists do url 'https://www.redmineup.com/pages/plugins/checklists' author_url 'mailto:support@redmineup.com' - requires_redmine :version_or_higher => '2.3' + requires_redmine :version_or_higher => '2.6' settings :default => { :save_log => true, @@ -40,9 +40,9 @@ Redmine::Plugin.register :redmine_checklists do Redmine::AccessControl.map do |map| map.project_module :issue_tracking do |map| - map.permission :view_checklists, {:checklists => [:show, :index]} - map.permission :done_checklists, {:checklists => :done} - map.permission :edit_checklists, {:checklists => [:done, :create, :destroy, :update]} + map.permission :view_checklists, { :checklists => [:show, :index] } + map.permission :done_checklists, { :checklists => :done } + map.permission :edit_checklists, { :checklists => [:done, :create, :destroy, :update] } end end diff --git a/plugins/redmine_checklists/lib/redmine_checklists/hooks/controller_issues_hook.rb b/plugins/redmine_checklists/lib/redmine_checklists/hooks/controller_issues_hook.rb index dc4ad0b..c6d5a74 100644 --- a/plugins/redmine_checklists/lib/redmine_checklists/hooks/controller_issues_hook.rb +++ b/plugins/redmine_checklists/lib/redmine_checklists/hooks/controller_issues_hook.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -22,7 +22,7 @@ module RedmineChecklists class ControllerIssuesHook < Redmine::Hook::ViewListener def controller_issues_edit_after_save(context = {}) - if (Setting.issue_done_ratio == "issue_field") && RedmineChecklists.settings["issue_done_ratio"].to_i > 0 + if (Setting.issue_done_ratio == 'issue_field') && RedmineChecklists.issue_done_ratio? Checklist.recalc_issue_done_ratio(context[:issue].id) end end diff --git a/plugins/redmine_checklists/lib/redmine_checklists/hooks/views_issues_hook.rb b/plugins/redmine_checklists/lib/redmine_checklists/hooks/views_issues_hook.rb index 201b5dd..320eb1b 100644 --- a/plugins/redmine_checklists/lib/redmine_checklists/hooks/views_issues_hook.rb +++ b/plugins/redmine_checklists/lib/redmine_checklists/hooks/views_issues_hook.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify diff --git a/plugins/redmine_checklists/lib/redmine_checklists/hooks/views_layouts_hook.rb b/plugins/redmine_checklists/lib/redmine_checklists/hooks/views_layouts_hook.rb index b72e26f..249de23 100644 --- a/plugins/redmine_checklists/lib/redmine_checklists/hooks/views_layouts_hook.rb +++ b/plugins/redmine_checklists/lib/redmine_checklists/hooks/views_layouts_hook.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify diff --git a/plugins/redmine_checklists/lib/redmine_checklists/patches/add_helpers_for_checklists_patch.rb b/plugins/redmine_checklists/lib/redmine_checklists/patches/add_helpers_for_checklists_patch.rb index b34bfc8..26b4976 100644 --- a/plugins/redmine_checklists/lib/redmine_checklists/patches/add_helpers_for_checklists_patch.rb +++ b/plugins/redmine_checklists/lib/redmine_checklists/patches/add_helpers_for_checklists_patch.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify diff --git a/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility/2.1/redmine_api_test_patch.rb b/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility/2.1/redmine_api_test_patch.rb index 09bb59f..909c7f3 100644 --- a/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility/2.1/redmine_api_test_patch.rb +++ b/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility/2.1/redmine_api_test_patch.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify diff --git a/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility/application_helper_patch.rb b/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility/application_helper_patch.rb new file mode 100644 index 0000000..0b2a2e1 --- /dev/null +++ b/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility/application_helper_patch.rb @@ -0,0 +1,38 @@ +# This file is a part of Redmine Checklists (redmine_checklists) plugin, +# issue checklists management plugin for Redmine +# +# Copyright (C) 2011-2020 RedmineUP +# http://www.redmineup.com/ +# +# redmine_checklists 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 3 of the License, or +# (at your option) any later version. +# +# redmine_checklists 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 redmine_checklists. If not, see . + +module RedmineChecklists + module Patches + module ApplicationHelperPatch + def self.included(base) # :nodoc: + base.class_eval do + unloadable # Send unloadable so it will not be unloaded in development + + def stocked_reorder_link(object, name = nil, url = {}, method = :post) + Redmine::VERSION.to_s > '3.3' ? reorder_handle(object, :param => name) : reorder_links(name, url, method) + end + end + end + end + end +end + +unless ApplicationHelper.included_modules.include?(RedmineChecklists::Patches::ApplicationHelperPatch) + ApplicationHelper.send(:include, RedmineChecklists::Patches::ApplicationHelperPatch) +end diff --git a/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility/journal_patch.rb b/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility/journal_patch.rb index 822d2f9..c6b72de 100644 --- a/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility/journal_patch.rb +++ b/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility/journal_patch.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -17,13 +17,11 @@ # You should have received a copy of the GNU General Public License # along with redmine_checklists. If not, see . - require_dependency 'journal' module RedmineChecklists module Patches module JournalPatch - def self.included(base) # :nodoc: base.send(:include, InstanceMethods) base.class_eval do @@ -40,7 +38,7 @@ module RedmineChecklists (Setting.notified_events.include?('issue_status_updated') && new_status.present?) || (Setting.notified_events.include?('issue_priority_updated') && new_value_for('priority_id').present?) ) - checklist_email_nootification(self).deliver + deliver_checklist_notification end end @@ -49,17 +47,24 @@ module RedmineChecklists end end - def checklist_email_nootification(journal) + def deliver_checklist_notification + if Redmine::VERSION.to_s >= '4.0' + (notified_watchers | notified_users).each do |user| + Mailer.issue_edit(user, self).deliver + end + else + checklist_email_notification(self).deliver + end + end + + def checklist_email_notification(journal) if Redmine::VERSION.to_s < '2.4' Mailer.issue_edit(journal) else - to_users = Redmine::VERSION.to_s <= '3.0' ? journal.notified_users : journal.recipients - cc_users = Redmine::VERSION.to_s <= '3.0' ? journal.notified_watchers - to_users : journal.watcher_recipients - to_users - Mailer.issue_edit(journal, to_users, cc_users) + Mailer.issue_edit(journal, journal.notified_users, journal.notified_watchers - journal.notified_users) end end end - end end end diff --git a/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility/open_struct_patch.rb b/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility/open_struct_patch.rb index e972994..3a9e43b 100644 --- a/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility/open_struct_patch.rb +++ b/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility/open_struct_patch.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify diff --git a/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility_patch.rb b/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility_patch.rb index c84b566..3b824da 100644 --- a/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility_patch.rb +++ b/plugins/redmine_checklists/lib/redmine_checklists/patches/compatibility_patch.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify diff --git a/plugins/redmine_checklists/lib/redmine_checklists/patches/issue_patch.rb b/plugins/redmine_checklists/lib/redmine_checklists/patches/issue_patch.rb index 79dca35..fd11daa 100644 --- a/plugins/redmine_checklists/lib/redmine_checklists/patches/issue_patch.rb +++ b/plugins/redmine_checklists/lib/redmine_checklists/patches/issue_patch.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -21,41 +21,46 @@ require_dependency 'issue' module RedmineChecklists module Patches - module IssuePatch def self.included(base) # :nodoc: base.send(:include, InstanceMethods) base.class_eval do unloadable # Send unloadable so it will not be unloaded in development attr_accessor :old_checklists + attr_accessor :removed_checklist_ids attr_reader :copied_from - alias_method_chain :copy, :checklist + alias_method :copy_without_checklist, :copy + alias_method :copy, :copy_with_checklist after_save :copy_subtask_checklists if ActiveRecord::VERSION::MAJOR >= 4 - has_many :checklists, lambda { order("#{Checklist.table_name}.position") }, :class_name => "Checklist", :dependent => :destroy, :inverse_of => :issue + has_many :checklists, lambda { order("#{Checklist.table_name}.position") }, :class_name => 'Checklist', :dependent => :destroy, :inverse_of => :issue else - has_many :checklists, :class_name => "Checklist", :dependent => :destroy, :inverse_of => :issue, - :order => 'position' + has_many :checklists, :class_name => 'Checklist', :dependent => :destroy, :inverse_of => :issue, :order => 'position' end - accepts_nested_attributes_for :checklists, :allow_destroy => true, :reject_if => proc { |attrs| attrs["subject"].blank? } + accepts_nested_attributes_for :checklists, :allow_destroy => true, :reject_if => proc { |attrs| attrs['subject'].blank? } + + validate :block_issue_closing_if_checklists_unclosed safe_attributes 'checklists_attributes', - :if => lambda {|issue, user| (user.allowed_to?(:done_checklists, issue.project) || - user.allowed_to?(:edit_checklists, issue.project))} - - def copy_checklists(arg) - issue = arg.is_a?(Issue) ? arg : Issue.visible.find(arg) - issue.checklists.each{ |checklist| Checklist.create(checklist.attributes.except('id','issue_id').merge(:issue => self)) } if issue - end + :if => lambda { |issue, user| (user.allowed_to?(:done_checklists, issue.project) || user.allowed_to?(:edit_checklists, issue.project)) } end end module InstanceMethods + def copy_checklists(arg) + issue = arg.is_a?(Issue) ? arg : Issue.visible.find(arg) + if issue + issue.checklists.each do |checklist| + Checklist.create(checklist.attributes.except('id', 'issue_id').merge(issue: self)) + end + end + end + def copy_subtask_checklists - return if !copy? || parent_id.nil? || checklists.any? + return if !copy? || parent_id.nil? || checklists.reload.any? copy_checklists(@copied_from) end @@ -64,6 +69,23 @@ module RedmineChecklists copy.copy_checklists(self) copy end + + def all_checklist_items_is_done? + (checklists - checklists.where(id: removed_checklist_ids)).reject(&:is_section).all?(&:is_done) + end + + def need_to_block_issue_closing? + RedmineChecklists.block_issue_closing? && + checklists.reject(&:is_section).any? && + status.is_closed? && + !all_checklist_items_is_done? + end + + def block_issue_closing_if_checklists_unclosed + if need_to_block_issue_closing? + errors.add(:checklists, l(:label_checklists_must_be_completed)) + end + end end end end diff --git a/plugins/redmine_checklists/lib/redmine_checklists/patches/issue_query_patch.rb b/plugins/redmine_checklists/lib/redmine_checklists/patches/issue_query_patch.rb index b08761f..3754e00 100644 --- a/plugins/redmine_checklists/lib/redmine_checklists/patches/issue_query_patch.rb +++ b/plugins/redmine_checklists/lib/redmine_checklists/patches/issue_query_patch.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -32,6 +32,7 @@ module RedmineChecklists end end -unless IssueQuery.included_modules.include?(RedmineChecklists::Patches::IssueQueryPatch) +if (ActiveRecord::Base.connection.tables.include?('queries') rescue false) && + IssueQuery.included_modules.exclude?(RedmineChecklists::Patches::IssueQueryPatch) IssueQuery.send(:include, RedmineChecklists::Patches::IssueQueryPatch) end diff --git a/plugins/redmine_checklists/lib/redmine_checklists/patches/issues_controller_patch.rb b/plugins/redmine_checklists/lib/redmine_checklists/patches/issues_controller_patch.rb index c2488fe..f7322cd 100644 --- a/plugins/redmine_checklists/lib/redmine_checklists/patches/issues_controller_patch.rb +++ b/plugins/redmine_checklists/lib/redmine_checklists/patches/issues_controller_patch.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -26,8 +26,9 @@ module RedmineChecklists base.class_eval do unloadable # Send unloadable so it will not be unloaded in development - alias_method_chain :build_new_issue_from_params, :checklist - before_filter :save_before_state, :only => [:update] + alias_method :build_new_issue_from_params_without_checklist, :build_new_issue_from_params + alias_method :build_new_issue_from_params, :build_new_issue_from_params_with_checklist + before_action :save_before_state, :only => [:update] end end @@ -44,6 +45,14 @@ module RedmineChecklists def save_before_state @issue.old_checklists = @issue.checklists.to_json + checklists_params = params[:issue].present? && params[:issue][:checklists_attributes].present? ? params[:issue][:checklists_attributes] : {} + @issue.removed_checklist_ids = + if checklists_params.present? + checklists_params = checklists_params.respond_to?(:to_unsafe_hash) ? checklists_params.to_unsafe_hash : checklists_params + checklists_params.map { |_k, v| v['id'].to_i if ['1', 'true'].include?(v['_destroy']) }.compact + else + [] + end end def fill_checklist_attributes @@ -60,14 +69,16 @@ module RedmineChecklists def add_checklists_to_params(checklists) params[:issue].blank? ? params[:issue] = { :checklists_attributes => {} } : params[:issue][:checklists_attributes] = {} checklists.each_with_index do |checklist_item, index| - params[:issue][:checklists_attributes][index.to_s] = { :is_done => checklist_item.is_done, - :subject => checklist_item.subject, - :position => checklist_item.position } + params[:issue][:checklists_attributes][index.to_s] = { + is_done: checklist_item.is_done, + subject: checklist_item.subject, + position: checklist_item.position, + is_section: checklist_item.is_section + } end end end end - end end diff --git a/plugins/redmine_checklists/lib/redmine_checklists/patches/issues_helper_patch.rb b/plugins/redmine_checklists/lib/redmine_checklists/patches/issues_helper_patch.rb index 439fed6..6707f4b 100644 --- a/plugins/redmine_checklists/lib/redmine_checklists/patches/issues_helper_patch.rb +++ b/plugins/redmine_checklists/lib/redmine_checklists/patches/issues_helper_patch.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -26,26 +26,18 @@ module RedmineChecklists base.class_eval do unloadable - alias_method_chain :details_to_strings, :checklists - alias_method_chain :render_email_issue_attributes, :checklists if Redmine::VERSION.to_s <= '2.4' && Redmine::VERSION.to_s >= '2.2' + alias_method :details_to_strings_without_checklists, :details_to_strings + alias_method :details_to_strings, :details_to_strings_with_checklists end end module InstanceMethods - def render_email_issue_attributes_with_checklists(issue, html = false) - journal = issue.journals.order(:id).last - return render_email_issue_attributes_without_checklists(issue, html) unless journal - details = journal.details - return render_email_issue_attributes_without_checklists(issue, html) unless details - checklist_details = details.select{ |x| x.prop_key == 'checklist'} - return render_email_issue_attributes_without_checklists(issue, html) unless checklist_details.any? - return render_email_issue_attributes_without_checklists(issue, html) + details_to_strings_with_checklists(checklist_details, !html).join(html ? "
    ".html_safe : "\n") - end - def details_to_strings_with_checklists(details, no_html = false, options = {}) details_checklist, details_other = details.partition{ |x| x.prop_key == 'checklist' } + return details_to_strings_without_checklists(details_other, no_html, options) unless User.current.allowed_to?(:view_checklists, @issue.project) + details_checklist.map do |detail| result = [] diff = Hash.new([]) @@ -56,15 +48,19 @@ module RedmineChecklists diff = JournalChecklistHistory.new(detail.old_value, detail.value).diff end + checklist_item_label = lambda do |item| + item[:is_section] ? l(:label_checklist_section) : l(:label_checklist_item) + end + if diff[:done].any? diff[:done].each do |item| - result << "#{ERB::Util.h l(:label_checklist_item)} #{ERB::Util.h item[:subject]} #{ERB::Util.h l(:label_checklist_done)}" + result << "#{ERB::Util.h l(:label_checklist_item)} #{ERB::Util.h item[:subject]} #{ERB::Util.h l(:label_checklist_done)}" end end if diff[:undone].any? diff[:undone].each do |item| - result << "#{ERB::Util.h l(:label_checklist_item)} #{ERB::Util.h item[:subject]} #{ERB::Util.h l(:label_checklist_undone)}" + result << "#{ERB::Util.h l(:label_checklist_item)} #{ERB::Util.h item[:subject]} #{ERB::Util.h l(:label_checklist_undone)}" end end @@ -72,8 +68,8 @@ module RedmineChecklists result = nil if result.blank? if result && no_html result = result.gsub /<\/li>
  • /, "\n" - result = result.gsub /]*checked[^>]*>/, '[x]' - result = result.gsub /]*>/, '[ ]' + result = result.gsub /]*checked[^>]*>/, '[x]' + result = result.gsub /]*>/, '[ ]' result = result.gsub /<[^>]*>/, '' result = CGI.unescapeHTML(result) end diff --git a/plugins/redmine_checklists/lib/redmine_checklists/patches/notifiable_patch.rb b/plugins/redmine_checklists/lib/redmine_checklists/patches/notifiable_patch.rb index 169c418..13f4e25 100644 --- a/plugins/redmine_checklists/lib/redmine_checklists/patches/notifiable_patch.rb +++ b/plugins/redmine_checklists/lib/redmine_checklists/patches/notifiable_patch.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify diff --git a/plugins/redmine_checklists/lib/redmine_checklists/patches/project_patch.rb b/plugins/redmine_checklists/lib/redmine_checklists/patches/project_patch.rb index 417631f..e8fbbc2 100644 --- a/plugins/redmine_checklists/lib/redmine_checklists/patches/project_patch.rb +++ b/plugins/redmine_checklists/lib/redmine_checklists/patches/project_patch.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -26,7 +26,8 @@ module RedmineChecklists base.send(:include, InstanceMethods) base.class_eval do unloadable # Send unloadable so it will not be unloaded in development - alias_method_chain :copy_issues, :checklist + alias_method :copy_issues_without_checklist, :copy_issues + alias_method :copy_issues, :copy_issues_with_checklist end end @@ -34,7 +35,7 @@ module RedmineChecklists def copy_issues_with_checklist(project) copy_issues_without_checklist(project) - issues.each{ |issue| issue.copy_checklists(issue.copied_from)} + issues.each{ |issue| issue.copy_checklists(issue.copied_from) if issue.reload.checklists.empty? } end end end diff --git a/plugins/redmine_checklists/lib/redmine_checklists/redmine_checklists.rb b/plugins/redmine_checklists/lib/redmine_checklists/redmine_checklists.rb index 101a3cc..d157c06 100644 --- a/plugins/redmine_checklists/lib/redmine_checklists/redmine_checklists.rb +++ b/plugins/redmine_checklists/lib/redmine_checklists/redmine_checklists.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -18,6 +18,8 @@ # along with redmine_checklists. If not, see . Rails.configuration.to_prepare do + require 'redmine_checklists/patches/compatibility/application_helper_patch' + require 'redmine_checklists/hooks/views_issues_hook' require 'redmine_checklists/hooks/views_layouts_hook' require 'redmine_checklists/hooks/controller_issues_hook' @@ -33,5 +35,13 @@ Rails.configuration.to_prepare do end module RedmineChecklists - def self.settings() Setting[:plugin_redmine_checklists].blank? ? {} : Setting[:plugin_redmine_checklists] end + def self.settings() Setting.plugin_redmine_checklists.blank? ? {} : Setting.plugin_redmine_checklists end + + def self.block_issue_closing? + settings['block_issue_closing'].to_i > 0 + end + + def self.issue_done_ratio? + settings['issue_done_ratio'].to_i > 0 + end end diff --git a/plugins/redmine_checklists/scripts/run_local.sh b/plugins/redmine_checklists/scripts/run_local.sh deleted file mode 100755 index dc77740..0000000 --- a/plugins/redmine_checklists/scripts/run_local.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -RUBY=$1 -DB=$2 -REDMINE=$3 - -docker run -t -i -v `pwd`:/var/www/$RUBY/$DB/$REDMINE/plugins/redmine_checklists \ - --env RUBY=$1 \ - --env DB=$2 \ - --env REDMINE=$3 \ - --env PLUGIN=redmine_checklists \ - redmineup/redmine_checklists \ - /root/run_local.sh diff --git a/plugins/redmine_checklists/test/fixtures/checklists.yml b/plugins/redmine_checklists/test/fixtures/checklists.yml index 573b24a..399383b 100644 --- a/plugins/redmine_checklists/test/fixtures/checklists.yml +++ b/plugins/redmine_checklists/test/fixtures/checklists.yml @@ -1,14 +1,25 @@ -# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html +--- +# === Checklist for Issue(1) === one: id: 1 is_done: false subject: First todo issue_id: 1 + two: id: 2 is_done: true subject: Second todo issue_id: 1 + +# === Checklist for Issue(2) === +section_one: + id: 4 + is_done: false + subject: New section + is_section: true + issue_id: 2 + three: id: 3 is_done: true diff --git a/plugins/redmine_checklists/test/functional/checklists_controller_test.rb b/plugins/redmine_checklists/test/functional/checklists_controller_test.rb index 69d6ffa..a887ecb 100644 --- a/plugins/redmine_checklists/test/functional/checklists_controller_test.rb +++ b/plugins/redmine_checklists/test/functional/checklists_controller_test.rb @@ -3,7 +3,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -44,8 +44,7 @@ class ChecklistsControllerTest < ActionController::TestCase :journals, :journal_details, :queries - RedmineChecklists::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_checklists).directory + '/test/fixtures/', - [:checklists]) + RedmineChecklists::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_checklists).directory + '/test/fixtures/', [:checklists]) def setup RedmineChecklists::TestCase.prepare @@ -61,7 +60,7 @@ class ChecklistsControllerTest < ActionController::TestCase # log_user('admin', 'admin') @request.session[:user_id] = 1 - xhr :put, :done, :is_done => 'true', :id => '1' + compatible_xhr_request :put, :done, :is_done => 'true', :id => '1' assert_response :success, 'Post done not working' assert_equal true, Checklist.find(1).is_done, 'Post done not working' end @@ -70,7 +69,7 @@ class ChecklistsControllerTest < ActionController::TestCase # log_user('admin', 'admin') @request.session[:user_id] = 5 - xhr :put, :done, :is_done => true, :id => "1" + compatible_xhr_request :put, :done, :is_done => true, :id => "1" assert_response 403, "Post done accessible for all" end @@ -78,7 +77,7 @@ class ChecklistsControllerTest < ActionController::TestCase # log_user('admin', 'admin') @request.session[:user_id] = 1 @controller = IssuesController.new - get :show, :id => @issue_1.id + compatible_request :get, :show, :id => @issue_1.id assert_select 'ul#checklist_items li#checklist_item_1', @checklist_1.subject, "Issue won't view for admin" end @@ -86,7 +85,7 @@ class ChecklistsControllerTest < ActionController::TestCase # log_user('anonymous', '') @request.session[:user_id] = 5 @controller = IssuesController.new - get :show, :id => @issue_1.id + compatible_request :get, :show, :id => @issue_1.id assert_select 'ul#checklist_items', false, "Issue view for anonymous" end end diff --git a/plugins/redmine_checklists/test/functional/issues_controller_test.rb b/plugins/redmine_checklists/test/functional/issues_controller_test.rb index c1b7449..28d08f9 100644 --- a/plugins/redmine_checklists/test/functional/issues_controller_test.rb +++ b/plugins/redmine_checklists/test/functional/issues_controller_test.rb @@ -3,7 +3,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -49,71 +49,56 @@ class IssuesControllerTest < ActionController::TestCase :journal_details, :queries - - RedmineChecklists::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_checklists).directory + '/test/fixtures/', - [:checklists]) - + RedmineChecklists::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_checklists).directory + '/test/fixtures/', [:checklists]) def setup @request.session[:user_id] = 1 + RedmineChecklists::TestCase.prepare end def test_new_issue_without_project - get :new + compatible_request :get, :new assert_response :success end if Redmine::VERSION.to_s > '3.0' def test_get_show_issue issue = Issue.find(1) assert_not_nil issue.checklists.first - get :show, :id => 1 + compatible_request(:get, :show, :id => 1) assert_response :success assert_select "ul#checklist_items li#checklist_item_1", /First todo/ - assert_select "ul#checklist_items li#checklist_item_1 input[checked=?]", "checked", {:count => 0} + assert_select "ul#checklist_items li#checklist_item_1 input[checked=?]", "checked", { :count => 0 } assert_select "ul#checklist_items li#checklist_item_2 input[checked=?]", "checked" end def test_get_edit_issue - get :edit, :id => 1 + compatible_request :get, :edit, :id => 1 assert_response :success end def test_get_copy_issue - get :new, :project_id => 1, :copy_from => 1 + compatible_request :get, :new, :project_id => 1, :copy_from => 1 assert_response :success - assert_select "span#checklist_form_items span.checklist-subject", {:count => 3} + assert_select "span#checklist_form_items span.checklist-subject", { :count => 3 } assert_select "span#checklist_form_items span.checklist-edit input[value=?]", "First todo" end def test_put_update_form parameters = {:tracker_id => 2, :checklists_attributes => { - "0" => {"is_done"=>"0", "subject"=>"First"}, + "0" => {"is_done"=>"0", "subject"=>"FirstChecklist"}, "1" => {"is_done"=>"0", "subject"=>"Second"}}} @request.session[:user_id] = 1 issue = Issue.find(1) if Redmine::VERSION.to_s > '2.3' && Redmine::VERSION.to_s < '3.0' - xhr :put, :update_form, - :issue => parameters, - :project_id => issue.project + compatible_xhr_request :put, :update_form, :issue => parameters, :project_id => issue.project else - xhr :put, :new, - :issue => parameters, - :project_id => issue.project + compatible_xhr_request :put, :new, :issue => parameters, :project_id => issue.project end assert_response :success assert_equal 'text/javascript', response.content_type - - if Redmine::VERSION.to_s < '3.0' - assert_template 'update_form' - else - assert_template 'new' - end - - issue = assigns(:issue) - assert_kind_of Issue, issue - assert_match 'First', issue.checklists.map(&:subject).join + assert_match 'FirstChecklist', response.body end def test_added_attachment_shows_in_log_once @@ -125,11 +110,10 @@ class IssuesControllerTest < ActionController::TestCase '1' => { 'is_done' => '0', 'subject' => 'Second' } } } @request.session[:user_id] = 1 issue = Issue.find(1) - post :update, - :issue => parameters, - :attachments => { '1' => { 'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file' } }, - :project_id => issue.project, - :id => issue.to_param + compatible_request :post, :update, :issue => parameters, + :attachments => { '1' => { 'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file' } }, + :project_id => issue.project, + :id => issue.to_param assert_response :redirect assert_equal 1, Journal.last.details.where(:property => 'attachment').count end @@ -144,7 +128,7 @@ class IssuesControllerTest < ActionController::TestCase :old_value => '[ ] TEST', :value => '[x] TEST') - post :show, :id => issue.id + compatible_request :post, :show, :id => issue.id assert_response :success last_journal = issue.journals.last assert_equal last_journal.details.size, 1 @@ -156,7 +140,7 @@ class IssuesControllerTest < ActionController::TestCase @request.session[:user_id] = 1 issue = Issue.find(1) journals_before = issue.journals.count - post :update, :issue => {}, :id => issue.to_param, :project_id => issue.project + compatible_request :post, :update, :issue => {}, :id => issue.to_param, :project_id => issue.project assert_response :redirect assert_equal journals_before, issue.reload.journals.count end @@ -164,11 +148,11 @@ class IssuesControllerTest < ActionController::TestCase def test_create_issue_without_checklists @request.session[:user_id] = 1 assert_difference 'Issue.count' do - post :create, :project_id => 1, :issue => { :tracker_id => 3, - :status_id => 2, - :subject => 'NEW issue without checklists', - :description => 'This is the description' - } + compatible_request :post, :create, :project_id => 1, :issue => { :tracker_id => 3, + :status_id => 2, + :subject => 'NEW issue without checklists', + :description => 'This is the description' + } end assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id @@ -176,18 +160,36 @@ class IssuesControllerTest < ActionController::TestCase assert_not_nil issue end + def test_create_issue_with_checklists + @request.session[:user_id] = 1 + assert_difference 'Issue.count' do + compatible_request :post, :create, :project_id => 1, :issue => { :tracker_id => 3, + :status_id => 2, + :subject => 'NEW issue with checklists', + :description => 'This is the description', + :checklists_attributes => { '0' => { 'is_done' => '0', 'subject' => 'item 001', 'position' => '1' } } + } + end + assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id + + issue = Issue.find_by_subject('NEW issue with checklists') + assert_equal 1, issue.checklists.count + assert_equal 'item 001', issue.checklists.last.subject + assert_not_nil issue + end + def test_create_issue_using_json old_value = Setting.rest_api_enabled Setting.rest_api_enabled = '1' @request.session[:user_id] = 1 assert_difference 'Issue.count' do - post :create, :format => :json, :project_id => 1, :issue => { :tracker_id => 3, - :status_id => 2, - :subject => 'NEW JSON issue', - :description => 'This is the description', - :checklists_attributes => [{:is_done => 0, :subject => 'JSON checklist'}] - }, - :key => User.find(1).api_key + compatible_request :post, :create, :format => :json, :project_id => 1, :issue => { :tracker_id => 3, + :status_id => 2, + :subject => 'NEW JSON issue', + :description => 'This is the description', + :checklists_attributes => [{ :is_done => 0, :subject => 'JSON checklist' }] + }, + :key => User.find(1).api_key end assert_response :created @@ -197,4 +199,28 @@ class IssuesControllerTest < ActionController::TestCase ensure Setting.rest_api_enabled = old_value end + + def test_history_displaying_for_checklist + @request.session[:user_id] = 1 + Setting[:plugin_redmine_checklists] = { save_log: 1, issue_done_ratio: 0 } + + issue = Issue.find(1) + journal = issue.journals.create!(user_id: 1) + journal.details.create!(:property => 'attr', + :prop_key => 'checklist', + :old_value => '[ ] TEST', + :value => '[x] TEST') + + # With permissions + @request.session[:user_id] = 1 + compatible_request :get, :show, id: issue.id + assert_response :success + assert_include 'changed from [ ] TEST to [x] TEST', response.body + + # Without permissions + @request.session[:user_id] = 5 + compatible_request :get, :show, id: issue.id + assert_response :success + assert_not_include 'changed from [ ] TEST to [x] TEST', response.body + end end diff --git a/plugins/redmine_checklists/test/integration/api_test/checklists_test.rb b/plugins/redmine_checklists/test/integration/api_test/checklists_test.rb index ecc788e..e5d3eb0 100644 --- a/plugins/redmine_checklists/test/integration/api_test/checklists_test.rb +++ b/plugins/redmine_checklists/test/integration/api_test/checklists_test.rb @@ -3,7 +3,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -19,7 +19,7 @@ # You should have received a copy of the GNU General Public License # along with redmine_checklists. If not, see . -require File.dirname(__FILE__) + '/../../test_helper' +require File.expand_path('../../../test_helper', __FILE__) class Redmine::ApiTest::ChecklistsTest < Redmine::ApiTest::Base fixtures :projects, @@ -46,27 +46,25 @@ class Redmine::ApiTest::ChecklistsTest < Redmine::ApiTest::Base :journal_details, :queries - RedmineChecklists::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_checklists).directory + '/test/fixtures/', - [:checklists]) + RedmineChecklists::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_checklists).directory + '/test/fixtures/', [:checklists]) def setup Setting.rest_api_enabled = '1' end def test_get_checklists_xml - get '/issues/1/checklists.xml', {}, credentials('admin') + compatible_api_request :get, '/issues/1/checklists.xml', {}, credentials('admin') assert_select 'checklists[type=array]' do assert_select 'checklist' do - assert_select 'id', :text => "1" - assert_select 'subject', :text => "First todo" + assert_select 'id', :text => '1' + assert_select 'subject', :text => 'First todo' end end - end def test_get_checklists_1_xml - get '/checklists/1.xml', {}, credentials('admin') + compatible_api_request :get, '/checklists/1.xml', {}, credentials('admin') assert_select 'checklist' do assert_select 'id', :text => '1' @@ -75,11 +73,11 @@ class Redmine::ApiTest::ChecklistsTest < Redmine::ApiTest::Base end def test_post_checklists_xml - parameters = {:checklist => {:issue_id => 1, - :subject => 'api_test_001', - :is_done => true}} + parameters = { :checklist => { :issue_id => 1, + :subject => 'api_test_001', + :is_done => true } } assert_difference('Checklist.count') do - post '/issues/1/checklists.xml', parameters, credentials('admin') + compatible_api_request :post, '/issues/1/checklists.xml', parameters, credentials('admin') end checklist = Checklist.order('id DESC').first @@ -91,25 +89,23 @@ class Redmine::ApiTest::ChecklistsTest < Redmine::ApiTest::Base end def test_put_checklists_1_xml - parameters = {:checklist => {:subject => 'Item_UPDATED'}} + parameters = { :checklist => { subject: 'Item_UPDATED', is_done: '1' } } assert_no_difference('Checklist.count') do - put '/checklists/1.xml', parameters, credentials('admin') + compatible_api_request :put, '/checklists/1.xml', parameters, credentials('admin') end checklist = Checklist.find(1) assert_equal parameters[:checklist][:subject], checklist.subject - end def test_delete_1_xml assert_difference 'Checklist.count', -1 do - delete '/checklists/1.xml', {}, credentials('admin') + compatible_api_request :delete, '/checklists/1.xml', {}, credentials('admin') end - assert_response :ok + assert ['200', '204'].include?(response.code) assert_equal '', @response.body assert_nil Checklist.find_by_id(1) end - end diff --git a/plugins/redmine_checklists/test/integration/common_issue_test.rb b/plugins/redmine_checklists/test/integration/common_issue_test.rb index c0f371e..2324f45 100644 --- a/plugins/redmine_checklists/test/integration/common_issue_test.rb +++ b/plugins/redmine_checklists/test/integration/common_issue_test.rb @@ -3,7 +3,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -44,23 +44,19 @@ class CommonIssueTest < RedmineChecklists::IntegrationTest :journals, :journal_details, :queries - RedmineChecklists::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_checklists).directory + '/test/fixtures/', - [:checklists]) - + RedmineChecklists::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_checklists).directory + '/test/fixtures/', [:checklists]) def setup RedmineChecklists::TestCase.prepare Setting.default_language = 'en' - @project_1 = Project.find(1) - @issue_1 = Issue.find(1) + @project_1 = Project.find(1) + @issue_1 = Issue.find(1) @checklist_1 = Checklist.find(1) - @request = ActionController::TestRequest.new - end + end - test "Global search with checklist" do - # log_user('admin', 'admin') - @request.session[:user_id] = 1 - get "/search?q=First" + def test_global_search_with_checklist + log_user('admin', 'admin') + compatible_request :get, '/search?q=First' assert_response :success end end diff --git a/plugins/redmine_checklists/test/test_helper.rb b/plugins/redmine_checklists/test/test_helper.rb index 2da9225..683ef93 100644 --- a/plugins/redmine_checklists/test/test_helper.rb +++ b/plugins/redmine_checklists/test/test_helper.rb @@ -3,7 +3,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -21,6 +21,39 @@ require File.expand_path(File.dirname(__FILE__) + '/../../../test/test_helper') +module RedmineChecklists + module TestHelper + def compatible_request(type, action, parameters = {}) + return send(type, action, :params => parameters) if Rails.version >= '5.1' + send(type, action, parameters) + end + + def compatible_xhr_request(type, action, parameters = {}) + return send(type, action, :params => parameters, :xhr => true) if Rails.version >= '5.1' + xhr type, action, parameters + end + + def compatible_api_request(type, action, parameters = {}, headers = {}) + return send(type, action, :params => parameters, :headers => headers) if Redmine::VERSION.to_s >= '3.4' + send(type, action, parameters, headers) + end + + def issues_in_list + ids = css_select('tr.issue td.id a').map { |tag| tag.to_s.gsub(/<.*?>/, '') }.map(&:to_i) + Issue.where(:id => ids).sort_by { |issue| ids.index(issue.id) } + end + + def with_checklists_settings(options, &block) + Setting.plugin_redmine_checklists.stubs(:[]).returns(nil) + options.each { |k, v| Setting.plugin_redmine_checklists.stubs(:[]).with(k).returns(v) } + yield + ensure + options.each { |_k, _v| Setting.plugin_redmine_checklists.unstub(:[]) } + end + end +end + +include RedmineChecklists::TestHelper if ActiveRecord::VERSION::MAJOR >= 4 class RedmineChecklists::IntegrationTest < Redmine::IntegrationTest; end @@ -29,7 +62,6 @@ else end class RedmineChecklists::TestCase - def self.create_fixtures(fixtures_directory, table_names, class_names = {}) if ActiveRecord::VERSION::MAJOR >= 4 ActiveRecord::FixtureSet.create_fixtures(fixtures_directory, table_names, class_names = {}) @@ -39,6 +71,11 @@ class RedmineChecklists::TestCase end def self.prepare + Role.find([1,2]).each do |r| # For anonymous + r.permissions << :view_checklists + r.save + end + Role.find(1, 2, 3, 4).each do |r| r.permissions << :edit_checklists r.save @@ -53,7 +90,5 @@ class RedmineChecklists::TestCase r.permissions << :manage_checklist_templates r.save end - end - end diff --git a/plugins/redmine_checklists/test/unit/checklist_test.rb b/plugins/redmine_checklists/test/unit/checklist_test.rb index 61a6d9f..2360079 100644 --- a/plugins/redmine_checklists/test/unit/checklist_test.rb +++ b/plugins/redmine_checklists/test/unit/checklist_test.rb @@ -3,7 +3,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify @@ -46,8 +46,7 @@ class ChecklistTest < ActiveSupport::TestCase :journal_details, :queries - RedmineChecklists::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_checklists).directory + '/test/fixtures/', - [:checklists]) + RedmineChecklists::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_checklists).directory + '/test/fixtures/', [:checklists]) def setup RedmineChecklists::TestCase.prepare Setting.default_language = 'en' @@ -56,11 +55,8 @@ class ChecklistTest < ActiveSupport::TestCase :status_id => 1, :priority => IssuePriority.first, :subject => 'Invoice Issue 1') @checklist_1 = Checklist.create(:subject => 'TEST1', :position => 1, :issue => @issue_1) - end - - test "should save checklist" do assert @checklist_1.save, "Checklist save error" end @@ -90,4 +86,53 @@ class ChecklistTest < ActiveSupport::TestCase assert_equal "[x] #{@checklist_1.subject}", @checklist_1.info, "Helper info broken" end + def test_should_correct_recalculate_rate + issues = [ + [Issue.create(project_id: 1, tracker_id: 1, author_id: 1, status_id: 1, priority: IssuePriority.first, subject: "TI #1", done_ratio: 0, + checklists_attributes: { + '0' => { subject: 'item 1', is_done: false }, + '1' => { subject: 'item 2', is_done: false }, + '2' => { subject: 'item 3', is_done: true }, + }), + 30], + [Issue.create(project_id: 1, tracker_id: 1, author_id: 1, status_id: 1, priority: IssuePriority.first, subject: "TI #2", done_ratio: 0, + checklists_attributes: { + '0' => { subject: 'item 1', is_done: false }, + '1' => { subject: 'item 2', is_done: true }, + '2' => { subject: 'item 3', is_done: true }, + }), + 60], + [Issue.create(project_id: 1, tracker_id: 1, author_id: 1, status_id: 1, priority: IssuePriority.first, subject: "TI #3", done_ratio: 0, + checklists_attributes: { + '0' => { subject: 'item 1', is_done: true }, + '1' => { subject: 'item 2', is_done: true }, + '2' => { subject: 'item 3', is_done: true }, + }), + 100], + [Issue.create(project_id: 1, tracker_id: 1, author_id: 1, status_id: 1, priority: IssuePriority.first, subject: "TI #4", done_ratio: 0, + checklists_attributes: { + '0' => { subject: 'item 1', is_done: false }, + '1' => { subject: 'item 2', is_done: false }, + '2' => { subject: 'section 1', is_done: true, is_section: true }, + '3' => { subject: 'item 3', is_done: true }, + }), + 30], + [Issue.create(project_id: 1, tracker_id: 1, author_id: 1, status_id: 1, priority: IssuePriority.first, subject: "TI #5", done_ratio: 0, + checklists_attributes: { + '0' => { subject: 'section 1', is_done: true, is_section: true } + }), + 0] + ] + + with_checklists_settings('issue_done_ratio' => '1') do + issues.each do |issue, after_ratio| + assert_equal 0, issue.done_ratio + Checklist.recalc_issue_done_ratio(issue.id) + issue.reload + assert_equal after_ratio, issue.done_ratio + end + end + ensure + issues.each { |issue, ratio| issue.destroy } + end end diff --git a/plugins/redmine_checklists/test/unit/issue_test.rb b/plugins/redmine_checklists/test/unit/issue_test.rb new file mode 100644 index 0000000..6dcd61f --- /dev/null +++ b/plugins/redmine_checklists/test/unit/issue_test.rb @@ -0,0 +1,85 @@ +# encoding: utf-8 +# +# This file is a part of Redmine Checklists (redmine_checklists) plugin, +# issue checklists management plugin for Redmine +# +# Copyright (C) 2011-2020 RedmineUP +# http://www.redmineup.com/ +# +# redmine_checklists 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 3 of the License, or +# (at your option) any later version. +# +# redmine_checklists 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 redmine_checklists. If not, see . + +require File.expand_path('../../test_helper', __FILE__) +include RedmineChecklists::TestHelper + +class IssueTest < ActiveSupport::TestCase + fixtures :projects, + :users, + :roles, + :members, + :member_roles, + :issues, + :issue_statuses, + :versions, + :trackers, + :projects_trackers, + :issue_categories, + :enabled_modules, + :enumerations, + :attachments, + :workflows, + :custom_fields, + :custom_values, + :custom_fields_projects, + :custom_fields_trackers, + :time_entries, + :journals, + :journal_details, + :queries + + RedmineChecklists::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_checklists).directory + '/test/fixtures/', [:checklists]) + def setup + RedmineChecklists::TestCase.prepare + Setting.default_language = 'en' + @project = Project.find(1) + @issue = Issue.create(:project => @project, :tracker_id => 1, :author_id => 1, + :status_id => 1, :priority => IssuePriority.first, + :subject => 'TestIssue') + @checklist_1 = Checklist.create(:subject => 'TEST1', :position => 1, :issue => @issue) + @checklist_2 = Checklist.create(:subject => 'TEST2', :position => 2, :issue => @issue, :is_done => true) + @issue.reload + end + + def test_issue_shouldnt_close_when_it_has_unfinished_checklists + with_checklists_settings('block_issue_closing' => '1') do + @issue.status_id = 5 + assert !@issue.valid? + end + end + + def test_validation_should_be_ignored_if_setting_disabled + with_checklists_settings('block_issue_closing' => '0') do + @issue.status_id = 5 + assert @issue.valid? + end + end + + def test_issue_should_close_when_all_checklists_finished + with_checklists_settings('block_issue_closing' => '1') do + @checklist_1.update_attributes(:is_done => true) + assert @issue.valid? + end + ensure + @checklist_1.update_attributes(:is_done => false) + end +end diff --git a/plugins/redmine_checklists/test/unit/project_test.rb b/plugins/redmine_checklists/test/unit/project_test.rb index 0db031c..621af31 100644 --- a/plugins/redmine_checklists/test/unit/project_test.rb +++ b/plugins/redmine_checklists/test/unit/project_test.rb @@ -3,7 +3,7 @@ # This file is a part of Redmine Checklists (redmine_checklists) plugin, # issue checklists management plugin for Redmine # -# Copyright (C) 2011-2017 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_checklists is free software: you can redistribute it and/or modify