diff --git a/app/controllers/checklists_controller.rb b/app/controllers/checklists_controller.rb
index 66589ce..c25e9cd 100644
--- a/app/controllers/checklists_controller.rb
+++ b/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-2018 RedmineUP
+# Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/
#
# redmine_checklists is free software: you can redistribute it and/or modify
@@ -54,6 +54,7 @@ def create
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)
@@ -66,7 +67,8 @@ def update
@checklist_item.safe_attributes = params[:checklist]
respond_to do |format|
format.api {
- if @checklist_item.save
+ if with_issue_journal { @checklist_item.save }
+ recalculate_issue_ratio(@checklist_item)
render_api_ok
else
render_validation_errors(@checklist_item)
@@ -77,12 +79,12 @@ def update
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|
@@ -106,4 +108,15 @@ def find_checklist_item
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/app/helpers/checklists_helper.rb b/app/helpers/checklists_helper.rb
index 031af3e..e939ba8 100644
--- a/app/helpers/checklists_helper.rb
+++ b/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-2018 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/app/models/checklist.rb b/app/models/checklist.rb
index 763a2d2..770b20e 100644
--- a/app/models/checklist.rb
+++ b/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-2018 RedmineUP
+# Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/
#
# redmine_checklists is free software: you can redistribute it and/or modify
@@ -53,14 +53,14 @@ class Checklist < ActiveRecord::Base
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
@@ -70,7 +70,7 @@ def self.old_format?(detail)
(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/app/models/journal_checklist_history.rb b/app/models/journal_checklist_history.rb
index 27b3bd8..17eeca2 100644
--- a/app/models/journal_checklist_history.rb
+++ b/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-2018 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/app/views/checklists/_checklist_item.html.erb b/app/views/checklists/_checklist_item.html.erb
index 19d094a..0855cdb 100644
--- a/app/views/checklists/_checklist_item.html.erb
+++ b/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/app/views/checklists/done.js.erb b/app/views/checklists/done.js.erb
index 9fc91bd..baf98be 100644
--- a/app/views/checklists/done.js.erb
+++ b/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/app/views/issues/_checklist.html.erb b/app/views/issues/_checklist.html.erb
index edf30ee..b2abf2b 100644
--- a/app/views/issues/_checklist.html.erb
+++ b/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)%>
@@ -11,6 +13,7 @@
<% end %>
-
-
+ <%= javascript_tag do %>
+ new Redmine.ChecklistToggle('<%= l("label_checklist_show_closed") %>', '<%= l("label_checklist_hide_closed") %>');
+ <% end %>
<% end %>
diff --git a/app/views/issues/_checklist_fields.html.erb b/app/views/issues/_checklist_fields.html.erb
index 92dd220..8cdcb4c 100644
--- a/app/views/issues/_checklist_fields.html.erb
+++ b/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/assets/javascripts/checklists.js b/assets/javascripts/checklists.js
index 1bdb224..d5263a0 100644
--- a/assets/javascripts/checklists.js
+++ b/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) {
@@ -219,7 +272,6 @@ Redmine.Checklist = $.klass({
makeChecklistsSortable: function() {
$('#checklist_form_items').sortable({
- revert: true,
items: '.checklist-item.show',
helper: "clone",
stop: function (event, ui) {
@@ -269,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()
@@ -307,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()
@@ -347,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/assets/stylesheets/checklists.css b/assets/stylesheets/checklists.css
index 030318f..a254bda 100644
--- a/assets/stylesheets/checklists.css
+++ b/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/config/locales/de.yml b/config/locales/de.yml
index 4a90806..7fdb430 100644
--- a/config/locales/de.yml
+++ b/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/config/locales/en.yml b/config/locales/en.yml
index 4052f03..b60cd28 100644
--- a/config/locales/en.yml
+++ b/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,8 +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
\ No newline at end of file
+ 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/config/locales/fr.yml b/config/locales/fr.yml
index 6a1ed72..5c1fe44 100755
--- a/config/locales/fr.yml
+++ b/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/config/locales/it.yml b/config/locales/it.yml
new file mode 100644
index 0000000..79dc3d5
--- /dev/null
+++ b/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/config/locales/ru.yml b/config/locales/ru.yml
index 7e3d5d6..8c7463f 100644
--- a/config/locales/ru.yml
+++ b/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/config/locales/zh-TW.yml b/config/locales/zh-TW.yml
new file mode 100644
index 0000000..2fe53c2
--- /dev/null
+++ b/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/config/routes.rb b/config/routes.rb
index f42c4d5..cc4e570 100644
--- a/config/routes.rb
+++ b/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-2018 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/db/migrate/001_create_checklists.rb b/db/migrate/001_create_checklists.rb
index f5a56c3..fee2541 100644
--- a/db/migrate/001_create_checklists.rb
+++ b/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-2018 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/db/migrate/002_add_time_stamps_to_checklists.rb b/db/migrate/002_add_time_stamps_to_checklists.rb
index db3f1a4..f1f0444 100644
--- a/db/migrate/002_add_time_stamps_to_checklists.rb
+++ b/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-2018 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/db/migrate/003_create_checklist_template_category.rb b/db/migrate/003_create_checklist_template_category.rb
index 700930e..3536dff 100644
--- a/db/migrate/003_create_checklist_template_category.rb
+++ b/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-2018 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/db/migrate/004_create_checklist_templates.rb b/db/migrate/004_create_checklist_templates.rb
index 89b7a07..56bee49 100644
--- a/db/migrate/004_create_checklist_templates.rb
+++ b/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-2018 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/db/migrate/005_modify_checklist_subject_length.rb b/db/migrate/005_modify_checklist_subject_length.rb
index 7707d7c..2fec00f 100644
--- a/db/migrate/005_modify_checklist_subject_length.rb
+++ b/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-2018 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/db/migrate/006_add_fields_to_checklist_template.rb b/db/migrate/006_add_fields_to_checklist_template.rb
index f5a75fa..cfda57f 100644
--- a/db/migrate/006_add_fields_to_checklist_template.rb
+++ b/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-2018 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/lib/redmine_checklists/redmine_checklist_setting.rb b/db/migrate/007_add_is_section_to_checklists.rb
similarity index 78%
rename from lib/redmine_checklists/redmine_checklist_setting.rb
rename to db/migrate/007_add_is_section_to_checklists.rb
index a876100..c86fd1f 100644
--- a/lib/redmine_checklists/redmine_checklist_setting.rb
+++ b/db/migrate/007_add_is_section_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-2018 RedmineUP
+# Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/
#
# redmine_checklists is free software: you can redistribute it and/or modify
@@ -17,10 +17,8 @@
# You should have received a copy of the GNU General Public License
# along with redmine_checklists. If not, see .
-module RedmineChecklists
- class RedmineChecklistSetting
- def self.block_issue_closing?
- Setting.plugin_redmine_checklists['block_issue_closing'].to_i > 0
- end
- end
-end
+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/doc/CHANGELOG b/doc/CHANGELOG
index c86364d..d0b9c7c 100644
--- a/doc/CHANGELOG
+++ b/doc/CHANGELOG
@@ -1,12 +1,57 @@
== Redmine Checklists plugin changelog
Redmine Checklists plugin - managing issue checklists plugin for Redmine
-Copyright (C) 2011-2018 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
-* Rails 4 support
+* Redmine 4 support
* Setting for block issues with undone checklists
* Fixed bug with default template
* Fixed email notification bug
@@ -36,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/init.rb b/init.rb
index 3f5c659..5cb6116 100644
--- a/init.rb
+++ b/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-2018 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.11'.freeze
+CHECKLISTS_VERSION_NUMBER = '3.1.18'.freeze
CHECKLISTS_VERSION_TYPE = "Light version"
Redmine::Plugin.register :redmine_checklists do
@@ -31,7 +31,7 @@
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,
diff --git a/lib/redmine_checklists/hooks/controller_issues_hook.rb b/lib/redmine_checklists/hooks/controller_issues_hook.rb
index 26851fc..c6d5a74 100644
--- a/lib/redmine_checklists/hooks/controller_issues_hook.rb
+++ b/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-2018 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 Hooks
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/lib/redmine_checklists/hooks/views_issues_hook.rb b/lib/redmine_checklists/hooks/views_issues_hook.rb
index 3923d25..320eb1b 100644
--- a/lib/redmine_checklists/hooks/views_issues_hook.rb
+++ b/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-2018 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/lib/redmine_checklists/hooks/views_layouts_hook.rb b/lib/redmine_checklists/hooks/views_layouts_hook.rb
index 7631101..249de23 100644
--- a/lib/redmine_checklists/hooks/views_layouts_hook.rb
+++ b/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-2018 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/lib/redmine_checklists/patches/add_helpers_for_checklists_patch.rb b/lib/redmine_checklists/patches/add_helpers_for_checklists_patch.rb
index 750e2d0..26b4976 100644
--- a/lib/redmine_checklists/patches/add_helpers_for_checklists_patch.rb
+++ b/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-2018 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/lib/redmine_checklists/patches/compatibility/2.1/redmine_api_test_patch.rb b/lib/redmine_checklists/patches/compatibility/2.1/redmine_api_test_patch.rb
index d7ad48c..909c7f3 100644
--- a/lib/redmine_checklists/patches/compatibility/2.1/redmine_api_test_patch.rb
+++ b/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-2018 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/lib/redmine_checklists/patches/compatibility/application_controller_patch.rb b/lib/redmine_checklists/patches/compatibility/application_controller_patch.rb
deleted file mode 100644
index 22a5595..0000000
--- a/lib/redmine_checklists/patches/compatibility/application_controller_patch.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# This file is a part of Redmine Checklists (redmine_checklists) plugin,
-# issue checklists management plugin for Redmine
-#
-# Copyright (C) 2011-2018 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 ApplicationControllerPatch
- def self.included(base) # :nodoc:
- base.extend(ClassMethods)
- base.class_eval do
- unloadable # Send unloadable so it will not be unloaded in development
- end
- end
-
- module ClassMethods
- def before_action(*filters, &block)
- before_filter(*filters, &block)
- end
- end
- end
- end
-end
-
-unless ApplicationController.included_modules.include?(RedmineChecklists::Patches::ApplicationControllerPatch)
- ApplicationController.send(:include, RedmineChecklists::Patches::ApplicationControllerPatch)
-end
diff --git a/lib/redmine_checklists/patches/compatibility/application_helper_patch.rb b/lib/redmine_checklists/patches/compatibility/application_helper_patch.rb
index a627386..0b2a2e1 100644
--- a/lib/redmine_checklists/patches/compatibility/application_helper_patch.rb
+++ b/lib/redmine_checklists/patches/compatibility/application_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-2018 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/lib/redmine_checklists/patches/compatibility/journal_patch.rb b/lib/redmine_checklists/patches/compatibility/journal_patch.rb
index b5dd698..c6b72de 100644
--- a/lib/redmine_checklists/patches/compatibility/journal_patch.rb
+++ b/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-2018 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 @@ def send_notification
(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,7 +47,17 @@ def detail_for_attribute(attribute)
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
@@ -57,7 +65,6 @@ def checklist_email_nootification(journal)
end
end
end
-
end
end
end
diff --git a/lib/redmine_checklists/patches/compatibility/open_struct_patch.rb b/lib/redmine_checklists/patches/compatibility/open_struct_patch.rb
index d0d27e1..3a9e43b 100644
--- a/lib/redmine_checklists/patches/compatibility/open_struct_patch.rb
+++ b/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-2018 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/lib/redmine_checklists/patches/compatibility_patch.rb b/lib/redmine_checklists/patches/compatibility_patch.rb
index 3e1460e..3b824da 100644
--- a/lib/redmine_checklists/patches/compatibility_patch.rb
+++ b/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-2018 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/lib/redmine_checklists/patches/issue_patch.rb b/lib/redmine_checklists/patches/issue_patch.rb
index ab57df5..fd11daa 100644
--- a/lib/redmine_checklists/patches/issue_patch.rb
+++ b/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-2018 RedmineUP
+# Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/
#
# redmine_checklists is free software: you can redistribute it and/or modify
@@ -46,23 +46,21 @@ def self.included(base) # :nodoc:
safe_attributes 'checklists_attributes',
:if => lambda { |issue, user| (user.allowed_to?(:done_checklists, issue.project) || user.allowed_to?(:edit_checklists, issue.project)) }
+ end
+ end
- 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
-
- def block_issue_closing_if_checklists_unclosed
- if RedmineChecklistSetting.block_issue_closing? && checklists.any? && status.is_closed?
- errors.add(:checklists, l(:label_checklists_must_be_completed)) unless (checklists - checklists.where(:id => removed_checklist_ids)).all?(&:is_done)
+ 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
- end
- module InstanceMethods
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
@@ -71,6 +69,23 @@ def copy_with_checklist(attributes = nil, copy_options = {})
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/lib/redmine_checklists/patches/issue_query_patch.rb b/lib/redmine_checklists/patches/issue_query_patch.rb
index be23e88..3754e00 100644
--- a/lib/redmine_checklists/patches/issue_query_patch.rb
+++ b/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-2018 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 InstanceMethods
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/lib/redmine_checklists/patches/issues_controller_patch.rb b/lib/redmine_checklists/patches/issues_controller_patch.rb
index 7298ac2..f7322cd 100644
--- a/lib/redmine_checklists/patches/issues_controller_patch.rb
+++ b/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-2018 RedmineUP
+# Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/
#
# redmine_checklists is free software: you can redistribute it and/or modify
@@ -69,9 +69,12 @@ def fill_checklist_attributes
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
diff --git a/lib/redmine_checklists/patches/issues_helper_patch.rb b/lib/redmine_checklists/patches/issues_helper_patch.rb
index 4efeb55..6707f4b 100644
--- a/lib/redmine_checklists/patches/issues_helper_patch.rb
+++ b/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-2018 RedmineUP
+# Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/
#
# redmine_checklists is free software: you can redistribute it and/or modify
@@ -28,28 +28,16 @@ def self.included(base)
alias_method :details_to_strings_without_checklists, :details_to_strings
alias_method :details_to_strings, :details_to_strings_with_checklists
- if Redmine::VERSION.to_s >= '2.2' && Redmine::VERSION.to_s <= '2.4'
- alias_method :render_email_issue_attributes_without_checklists, :render_email_issue_attributes
- alias_method :render_email_issue_attributes, :render_email_issue_attributes_with_checklists
- end
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([])
@@ -60,15 +48,19 @@ def details_to_strings_with_checklists(details, no_html = false, options = {})
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
@@ -76,8 +68,8 @@ def details_to_strings_with_checklists(details, no_html = false, options = {})
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/lib/redmine_checklists/patches/notifiable_patch.rb b/lib/redmine_checklists/patches/notifiable_patch.rb
index 0d353bd..13f4e25 100644
--- a/lib/redmine_checklists/patches/notifiable_patch.rb
+++ b/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-2018 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/lib/redmine_checklists/patches/project_patch.rb b/lib/redmine_checklists/patches/project_patch.rb
index 944fc23..e8fbbc2 100644
--- a/lib/redmine_checklists/patches/project_patch.rb
+++ b/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-2018 RedmineUP
+# Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/
#
# redmine_checklists is free software: you can redistribute it and/or modify
@@ -35,7 +35,7 @@ module InstanceMethods
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/lib/redmine_checklists/redmine_checklists.rb b/lib/redmine_checklists/redmine_checklists.rb
index fb69b88..d157c06 100644
--- a/lib/redmine_checklists/redmine_checklists.rb
+++ b/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-2018 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,6 @@
Rails.configuration.to_prepare do
require 'redmine_checklists/patches/compatibility/application_helper_patch'
- require 'redmine_checklists/patches/compatibility/application_controller_patch' if Rails::VERSION::MAJOR < 4
require 'redmine_checklists/hooks/views_issues_hook'
require 'redmine_checklists/hooks/views_layouts_hook'
@@ -36,5 +35,13 @@
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/scripts/run_local.sh b/scripts/run_local.sh
deleted file mode 100755
index dc77740..0000000
--- a/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/test/fixtures/checklists.yml b/test/fixtures/checklists.yml
index 573b24a..399383b 100644
--- a/test/fixtures/checklists.yml
+++ b/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/test/functional/checklists_controller_test.rb b/test/functional/checklists_controller_test.rb
index 3ac9bed..a887ecb 100644
--- a/test/functional/checklists_controller_test.rb
+++ b/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-2018 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/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb
index 0cd30c4..28d08f9 100644
--- a/test/functional/issues_controller_test.rb
+++ b/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-2018 RedmineUP
+# Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/
#
# redmine_checklists is free software: you can redistribute it and/or modify
@@ -53,6 +53,7 @@ class IssuesControllerTest < ActionController::TestCase
def setup
@request.session[:user_id] = 1
+ RedmineChecklists::TestCase.prepare
end
def test_new_issue_without_project
@@ -159,6 +160,24 @@ def test_create_issue_without_checklists
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'
@@ -180,4 +199,28 @@ def test_create_issue_using_json
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/test/integration/api_test/checklists_test.rb b/test/integration/api_test/checklists_test.rb
index 613b7b5..e5d3eb0 100644
--- a/test/integration/api_test/checklists_test.rb
+++ b/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-2018 RedmineUP
+# Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/
#
# redmine_checklists is free software: you can redistribute it and/or modify
@@ -89,7 +89,7 @@ def test_post_checklists_xml
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
compatible_api_request :put, '/checklists/1.xml', parameters, credentials('admin')
@@ -104,7 +104,7 @@ def test_delete_1_xml
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
diff --git a/test/integration/common_issue_test.rb b/test/integration/common_issue_test.rb
index 8321387..2324f45 100644
--- a/test/integration/common_issue_test.rb
+++ b/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-2018 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/test/test_helper.rb b/test/test_helper.rb
index c457c3c..683ef93 100644
--- a/test/test_helper.rb
+++ b/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-2018 RedmineUP
+# Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/
#
# redmine_checklists is free software: you can redistribute it and/or modify
@@ -71,6 +71,11 @@ def self.create_fixtures(fixtures_directory, table_names, class_names = {})
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
diff --git a/test/unit/checklist_test.rb b/test/unit/checklist_test.rb
index 75d7c92..2360079 100644
--- a/test/unit/checklist_test.rb
+++ b/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-2018 RedmineUP
+# Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/
#
# redmine_checklists is free software: you can redistribute it and/or modify
@@ -86,4 +86,53 @@ def setup
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/test/unit/issue_test.rb b/test/unit/issue_test.rb
index cbf31d8..24ff68f 100644
--- a/test/unit/issue_test.rb
+++ b/test/unit/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-2018 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/test/unit/project_test.rb b/test/unit/project_test.rb
index baf52b1..621af31 100644
--- a/test/unit/project_test.rb
+++ b/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-2018 RedmineUP
+# Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/
#
# redmine_checklists is free software: you can redistribute it and/or modify