diff --git a/.travis.yml b/.travis.yml index da09599..fb9cd69 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,40 +5,18 @@ services: - postgresql rvm: - - 1.9.3 - - 2.0.0 + - 2.3.1 gemfile: - $REDMINE_PATH/Gemfile env: - - REDMINE_VER=2.1.6 DB=mysql - - REDMINE_VER=2.2.4 DB=mysql - - REDMINE_VER=2.3.3 DB=mysql - - REDMINE_VER=2.3.4 DB=mysql - - REDMINE_VER=2.4.4 DB=mysql - - REDMINE_VER=2.5.0 DB=mysql - - REDMINE_VER=2.1.6 DB=postgresql - - REDMINE_VER=2.2.4 DB=postgresql - - REDMINE_VER=2.3.3 DB=postgresql - - REDMINE_VER=2.3.4 DB=postgresql - - REDMINE_VER=2.4.4 DB=postgresql - - REDMINE_VER=2.5.0 DB=postgresql - -matrix: - exclude: - - rvm: 2.0.0 - env: REDMINE_VER=2.1.6 DB=mysql - gemfile: $REDMINE_PATH/Gemfile - - rvm: 2.0.0 - env: REDMINE_VER=2.2.4 DB=mysql - gemfile: $REDMINE_PATH/Gemfile - - rvm: 2.0.0 - env: REDMINE_VER=2.1.6 DB=postgresql - gemfile: $REDMINE_PATH/Gemfile - - rvm: 2.0.0 - env: REDMINE_VER=2.2.4 DB=postgresql - gemfile: $REDMINE_PATH/Gemfile + - REDMINE_VER=3.1.7 DB=mysql + - REDMINE_VER=3.2.4 DB=mysql + - REDMINE_VER=3.3.1 DB=mysql + - REDMINE_VER=3.1.7 DB=postgresql + - REDMINE_VER=3.2.4 DB=postgresql + - REDMINE_VER=3.3.1 DB=postgresql before_install: - export PLUGIN_NAME=redmine_issue_checklist @@ -49,10 +27,10 @@ before_install: - cd $REDMINE_PATH before_script: - - rake db:create - - rake db:migrate - - rake redmine:plugins:migrate + - bundle exec rake db:create + - bundle exec rake db:migrate + - bundle exec rake redmine:plugins:migrate script: - - rake redmine:plugins:test NAME=$PLUGIN_NAME + - bundle exec rake redmine:plugins:test NAME=$PLUGIN_NAME RUBYOPT="-W0" diff --git a/README.md b/README.md index 17ce3ca..66fe423 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Redmine Issue Checklist Plugin -[![Build Status](https://travis-ci.org/Undev/redmine_issue_checklist.png?branch=master)](https://travis-ci.org/Undev/redmine_issue_checklist) -[![Code Climate](https://codeclimate.com/github/Undev/redmine_issue_checklist.png)](https://codeclimate.com/github/Undev/redmine_issue_checklist) +[![Build Status](https://travis-ci.org/Restream/redmine_issue_checklist.svg?branch=master)](https://travis-ci.org/Restream/redmine_issue_checklist) +[![Code Climate](https://codeclimate.com/github/Restream/redmine_issue_checklist/badges/gpa.svg)](https://codeclimate.com/github/Restream/redmine_issue_checklist) This plugin enables you to add checklists to Redmine issues. @@ -9,7 +9,7 @@ The initial author of the plugin is [Kirill Bezrukov](http://www.redminecrm.com/ ## Compatibility -This plugin version is compatible only with Redmine 2.0 and later. +This plugin version is compatible only with Redmine 3.0 and later. ## Installation @@ -24,12 +24,11 @@ This plugin version is compatible only with Redmine 2.0 and later. Copy the plugin from GitHub using the following commands: - git clone https://github.com/Undev/redmine_issue_checklist.git plugins/redmine_issue_checklist + git clone https://github.com/Restream/redmine_issue_checklist.git plugins/redmine_issue_checklist 2. Update the Gemfile.lock file by running the following commands: - rm Gemfile.lock - bundle install + bundle install 3. This plugin requires a migration. Run the following command to upgrade your database (make a database backup before): @@ -44,19 +43,19 @@ Now you should be able to see the plugin in **Administration > Plugins**. The Redmine Issue Checklist plugin enables you to add checklists to Redmine issues. You can configure the plugin to track the checklist changes in the issue log and change the issue done ratio based on the checklist progress. To do this, go to **Administration > Plugins**, clik**Configure** and select the corresponding check boxes. -![plugin settings](issue_checklist_1.PNG) +![plugin settings](doc/issue_checklist_1.png) To add a checklist to an issue, enter the checklist item text into the the **Checklist** field in the issue description and click the **+** button. -![checklist item](issue_checklist_2.PNG) +![checklist item](doc/issue_checklist_2.png) You can add as many checklist items as you need. To rearrange the checklist, drag and drop the items in the desired order. To delete an item, click the trash bin icon. -![checklist item](issue_checklist_3.PNG) +![checklist item](doc/issue_checklist_3.png) To mark the completed checklist items, select the corresponding check boxes. The plugin will display the changes in the issue log and change the issue done ratio, if you have configured it accordingly. -![progress](issue_checklist_4.PNG) +![progress](doc/issue_checklist_4.png) To manage checklist-related permissions, go to **Administration > Roles and permissions**, click the role name and select or clear the required check boxes. -![permissions](issue_checklist_5.PNG) +![permissions](doc/issue_checklist_5.png) ## Testing diff --git a/app/controllers/issue_checklists_controller.rb b/app/controllers/issue_checklists_controller.rb index 45a1411..5b59a3c 100644 --- a/app/controllers/issue_checklists_controller.rb +++ b/app/controllers/issue_checklists_controller.rb @@ -1,57 +1,57 @@ class IssueChecklistsController < ApplicationController - - before_filter :find_checklist_item - + + before_action :find_checklist_item + def done (render_403; return false) unless User.current.allowed_to?(:done_checklists, @checklist_item.issue.project) - old_checklist_item = @checklist_item.dup + old_checklist_item = @checklist_item.dup @checklist_item.is_done = !@checklist_item.is_done - + if @checklist_item.save if RedmineIssueChecklist.settings[:save_log] && old_checklist_item.info != @checklist_item.info - journal = Journal.new(:journalized => @checklist_item.issue, :user => User.current) - journal.details << JournalDetail.new(:property => 'attr', - :prop_key => 'checklist', - # :old_value => old_checklist_item.info, - :value => @checklist_item.info) + journal = Journal.new(journalized: @checklist_item.issue, user: User.current) + journal.details << JournalDetail.new( + property: 'attr', + prop_key: 'checklist', + # old_value: old_checklist_item.info, + value: @checklist_item.info) journal.save end - - if (Setting.issue_done_ratio == "issue_field") && RedmineIssueChecklist.settings[:issue_done_ratio] - done_checklist = @checklist_item.issue.checklist.map{|c| c.is_done ? 1 : 0} + + if (Setting.issue_done_ratio == 'issue_field') && RedmineIssueChecklist.settings[:issue_done_ratio] + done_checklist = @checklist_item.issue.checklist.map { |c| c.is_done ? 1 : 0 } @checklist_item.issue.done_ratio = (done_checklist.count(1) * 10) / done_checklist.count * 10 @checklist_item.issue.save end end respond_to do |format| format.js - format.html {redirect_to :back } + format.html { redirect_to :back } end - - end - + + end + def delete (render_403; return false) unless User.current.allowed_to?(:edit_checklists, @checklist_item.issue.project) - + @checklist_item.delete respond_to do |format| - format.js do - render :update do |page| - page["checklist_item_#{@checklist_item.id}"].visual_effect :fade + format.js do + render :update do |page| + page["checklist_item_#{@checklist_item.id}"].visual_effect :fade end - end - format.html {redirect_to :back } + end + format.html { redirect_to :back } end - - end - + + end + private - + def find_checklist_item - @checklist_item = IssueChecklist.find(params[:checklist_item_id]) - @project = @checklist_item.issue.project + @checklist_item = IssueChecklist.find(params[:checklist_item_id]) + @project = @checklist_item.issue.project end - - + end diff --git a/app/models/issue_checklist.rb b/app/models/issue_checklist.rb index 79f387b..cf5ce49 100644 --- a/app/models/issue_checklist.rb +++ b/app/models/issue_checklist.rb @@ -1,34 +1,33 @@ class IssueChecklist < ActiveRecord::Base belongs_to :issue - belongs_to :author, :class_name => "User", :foreign_key => "author_id" - has_one :comment, :as => :commented, :dependent => :delete + belongs_to :author, class_name: 'User', foreign_key: 'author_id' + has_one :comment, as: :commented, dependent: :delete acts_as_list attr_accessible :is_done, :subject attr_protected :id validates_presence_of :subject - + # after_save :recalc_issue_done_ratio - + def editable_by?(usr=User.current) usr && (usr.allowed_to?(:edit_checklists, project) || (self.author == usr && usr.allowed_to?(:edit_own_checklists, project))) end - + def project - self.issue.project if self.issue - end - + self.issue.project if self.issue + end + def info "[#{self.is_done ? 'x' : ' ' }] #{self.subject.strip}" end - + def recalc_issue_done_ratio - return false if (Setting.issue_done_ratio != "issue_field") || !RedmineIssueChecklist.settings[:issue_done_ratio] - done_checklist = issue.checklist.map{|c| c.is_done ? 1 : 0} + return false if (Setting.issue_done_ratio != 'issue_field') || !RedmineIssueChecklist.settings[:issue_done_ratio] + done_checklist = issue.checklist.map { |c| c.is_done ? 1 : 0 } issue.done_ratio = (done_checklist.count(1) * 10) / done_checklist.count * 10 issue.save end - - + end diff --git a/app/views/issue_checklists/_checklist_item.html.erb b/app/views/issue_checklists/_checklist_item.html.erb index 6f8c383..52722be 100644 --- a/app/views/issue_checklists/_checklist_item.html.erb +++ b/app/views/issue_checklists/_checklist_item.html.erb @@ -1,6 +1,7 @@ -
<%=l(:label_issue_checklist_plural)%>
- -<%= l(:label_issue_checklist_plural) %>
+ +- - - <%= text_field_tag 'new_checklist', '', - :id => 'add_checklist_item_input' %> - <%= link_to '', '#', - :id => 'add_checklist_item_button', - :class => "tag-add icon icon-add" %> - <%= file_field_tag 'import_checklist', - :id => 'import_checklist_items_input', - :accept => 'text/plain' %> +
+ + + <%= text_field_tag 'new_checklist', '', + id: 'add_checklist_item_input' %> + <%= link_to '', '#', + id: 'add_checklist_item_button', + class: 'tag-add icon icon-add' %> + <%= file_field_tag 'import_checklist', + id: 'import_checklist_items_input', + accept: 'text/plain' %> - <%= javascript_tag "observeIssueChecklistField('checklist_form_items', 'add_checklist_item_input', 'add_checklist_item_button', 'import_checklist_items_input');" %> - <%= javascript_tag "createIssueChecklist(#{@issue.checklist.collect{|cli| {:is_done => cli.is_done, :subject => cli.subject, :id => cli.id}}.to_json.html_safe});" %> -
-- - <%= check_box_tag 'settings[issue_done_ratio]', 1, @settings[:issue_done_ratio] %> -
+<% if Setting.issue_done_ratio == 'issue_field' %> ++ + <%= check_box_tag 'settings[issue_done_ratio]', 1, @settings[:issue_done_ratio] %> +
<% end %> diff --git a/assets/javascripts/issue_checklist.js b/assets/javascripts/issue_checklist.js index 3788935..50f8e01 100644 --- a/assets/javascripts/issue_checklist.js +++ b/assets/javascripts/issue_checklist.js @@ -1,85 +1,89 @@ -window.onload = function() { - Sortable.create('checklist_form_items',{tag:'span'}); +window.onload = function () { + Sortable.create('checklist_form_items', {tag: 'span'}); }; var Redmine = Redmine || {}; Redmine.IssueChecklist = Class.create({ - initialize: function(element, input, button) { - this.element = $(element); - this.input = $(input); - this.button = $(button); - this.checklist = new Hash(); - - Event.observe(this.button, 'click', this.readChecklist.bindAsEventListener(this)); - Event.observe(this.input, 'keypress', this.onKeyPress.bindAsEventListener(this)); - }, - - readChecklist: function(event) { - this.addChecklistItem(this.input.value); - this.input.value = ''; - Event.stop(event); - }, - - onKeyPress: function(event) { - if (Event.KEY_RETURN == event.keyCode) { - this.readChecklist(event); - Event.stop(event); - } - }, - - addChecklistItem: function(сhecklistItem, isDone) { - if (сhecklistItem.blank()) return; - - isDone = isDone || false; - - var hidden = new Element('input', {'type': 'hidden', 'name': 'check_list_items[][subject]', 'value': сhecklistItem.strip()}); - var button = new Element('span', {'href': '#', 'class': 'delete icon icon-del' }); - var checkbox = new Element('input', {'type': 'checkbox', 'name': 'check_list_items[][is_done]', 'value': '1'}); - var label = new Element('span', { 'class': 'checklist-item' }).insert(hidden).insert(checkbox).insert(сhecklistItem.strip()).insert(button); - - if (isDone == true) { - checkbox.setAttribute('checked', 'checked'); - label.addClassName('is-done-checklist-item'); - } - - this.checklist.set(сhecklistItem, 1); - this.element.insert({ 'bottom': label }); - - Event.observe(button, 'click', function(){ - this.checklist.unset(сhecklistItem); - label.remove(); - // Event.stop(event); - }.bind(this)); - - Event.observe(checkbox, 'click', function(){ - if (checkbox.checked == true) { - label.addClassName('is-done-checklist-item'); - } - else { - label.removeClassName('is-done-checklist-item'); - } - - }.bind(this)); - - }, - - addChecklist: function(checklist) { - for (var i = 0; i < checklist.length; i++) { - this.addChecklistItem(checklist[i]['subject'], checklist[i]['is_done']); - } - }, - - getChecklist: function() { - return this.checklist; - }, + initialize: function (element, input, button) { + this.element = $(element); + this.input = $(input); + this.button = $(button); + this.checklist = new Hash(); + + Event.observe(this.button, 'click', this.readChecklist.bindAsEventListener(this)); + Event.observe(this.input, 'keypress', this.onKeyPress.bindAsEventListener(this)); + }, + + readChecklist: function (event) { + this.addChecklistItem(this.input.value); + this.input.value = ''; + Event.stop(event); + }, + + onKeyPress: function (event) { + if (Event.KEY_RETURN == event.keyCode) { + this.readChecklist(event); + Event.stop(event); + } + }, + + addChecklistItem: function (сhecklistItem, isDone) { + if (сhecklistItem.blank()) return; + + isDone = isDone || false; + + var hidden = new Element('input', { + 'type': 'hidden', + 'name': 'check_list_items[][subject]', + 'value': сhecklistItem.strip() + }); + var button = new Element('span', {'href': '#', 'class': 'delete icon icon-del'}); + var checkbox = new Element('input', {'type': 'checkbox', 'name': 'check_list_items[][is_done]', 'value': '1'}); + var label = new Element('span', {'class': 'checklist-item'}).insert(hidden).insert(checkbox).insert(сhecklistItem.strip()).insert(button); + + if (isDone == true) { + checkbox.setAttribute('checked', 'checked'); + label.addClassName('is-done-checklist-item'); + } + + this.checklist.set(сhecklistItem, 1); + this.element.insert({'bottom': label}); + + Event.observe(button, 'click', function () { + this.checklist.unset(сhecklistItem); + label.remove(); + // Event.stop(event); + }.bind(this)); + + Event.observe(checkbox, 'click', function () { + if (checkbox.checked == true) { + label.addClassName('is-done-checklist-item'); + } + else { + label.removeClassName('is-done-checklist-item'); + } + + }.bind(this)); + + }, + + addChecklist: function (checklist) { + for (var i = 0; i < checklist.length; i++) { + this.addChecklistItem(checklist[i]['subject'], checklist[i]['is_done']); + } + }, + + getChecklist: function () { + return this.checklist; + }, }); function observeIssueChecklistField(element, input, add_button) { - issueChecklist = new Redmine.IssueChecklist(element, input, add_button); + issueChecklist = new Redmine.IssueChecklist(element, input, add_button); } function createIssueChecklist(checkList) { - issueChecklist.addChecklist(checkList); + issueChecklist.addChecklist(checkList); } diff --git a/assets/javascripts/issue_checklist.prototype.js b/assets/javascripts/issue_checklist.prototype.js index 62fe2f3..9fbaa4d 100644 --- a/assets/javascripts/issue_checklist.prototype.js +++ b/assets/javascripts/issue_checklist.prototype.js @@ -1,102 +1,108 @@ -window.onload = function() { - Sortable.create('checklist_form_items',{tag:'span'}); +window.onload = function () { + Sortable.create('checklist_form_items', {tag: 'span'}); }; var Redmine = Redmine || {}; Redmine.IssueChecklist = Class.create({ - initialize: function(element, input, button) { - this.element = $(element); - this.input = $(input); - this.button = $(button); - this.checklist = new Hash(); - - Event.observe(this.button, 'click', this.readChecklist.bindAsEventListener(this)); - Event.observe(this.input, 'keypress', this.onKeyPress.bindAsEventListener(this)); - }, - - readChecklist: function(event) { - this.addChecklistItem(this.input.value); - this.input.value = ''; - Event.stop(event); - }, - - onKeyPress: function(event) { - if (Event.KEY_RETURN == event.keyCode) { - this.readChecklist(event); - Event.stop(event); - } - }, - - addChecklistItem: function(сhecklistItem, isDone) { - if (сhecklistItem.blank()) return; - - isDone = isDone || false; - - var hidden = new Element('input', {'type': 'hidden', 'name': 'check_list_items[][subject]', 'value': сhecklistItem.strip()}); - var button = new Element('span', {'href': '#', 'class': 'delete icon icon-del' }); - var checkbox = new Element('input', {'type': 'checkbox', 'name': 'check_list_items[][is_done]', 'value': '1'}); - var label = new Element('span', { 'class': 'checklist-item' }).insert(hidden).insert(checkbox).insert(сhecklistItem.strip()).insert(button); - - if (isDone == true) { - checkbox.setAttribute('checked', 'checked'); - label.addClassName('is-done-checklist-item'); - } - - this.checklist.set(сhecklistItem, 1); - this.element.insert({ 'bottom': label }); - - Event.observe(button, 'click', function(){ - this.checklist.unset(сhecklistItem); - label.remove(); - // Event.stop(event); - }.bind(this)); - Event.observe(checkbox, 'click', function(){ - if (checkbox.checked == true) { - label.addClassName('is-done-checklist-item'); - } - else { - label.removeClassName('is-done-checklist-item'); - } - - }.bind(this)); - - }, - - addChecklist: function(checklist) { - for (var i = 0; i < checklist.length; i++) { - this.addChecklistItem(checklist[i]['subject'], checklist[i]['is_done']); - } - }, - - getChecklist: function() { - return this.checklist; - }, + initialize: function (element, input, button) { + this.element = $(element); + this.input = $(input); + this.button = $(button); + this.checklist = new Hash(); + + Event.observe(this.button, 'click', this.readChecklist.bindAsEventListener(this)); + Event.observe(this.input, 'keypress', this.onKeyPress.bindAsEventListener(this)); + }, + + readChecklist: function (event) { + this.addChecklistItem(this.input.value); + this.input.value = ''; + Event.stop(event); + }, + + onKeyPress: function (event) { + if (Event.KEY_RETURN == event.keyCode) { + this.readChecklist(event); + Event.stop(event); + } + }, + + addChecklistItem: function (сhecklistItem, isDone) { + if (сhecklistItem.blank()) return; + + isDone = isDone || false; + + var hidden = new Element('input', { + 'type': 'hidden', + 'name': 'check_list_items[][subject]', + 'value': сhecklistItem.strip() + }); + var button = new Element('span', {'href': '#', 'class': 'delete icon icon-del'}); + var checkbox = new Element('input', {'type': 'checkbox', 'name': 'check_list_items[][is_done]', 'value': '1'}); + var label = new Element('span', {'class': 'checklist-item'}).insert(hidden).insert(checkbox).insert(сhecklistItem.strip()).insert(button); + + if (isDone == true) { + checkbox.setAttribute('checked', 'checked'); + label.addClassName('is-done-checklist-item'); + } + + this.checklist.set(сhecklistItem, 1); + this.element.insert({'bottom': label}); + + Event.observe(button, 'click', function () { + this.checklist.unset(сhecklistItem); + label.remove(); + // Event.stop(event); + }.bind(this)); + Event.observe(checkbox, 'click', function () { + if (checkbox.checked == true) { + label.addClassName('is-done-checklist-item'); + } + else { + label.removeClassName('is-done-checklist-item'); + } + + }.bind(this)); + + }, + + addChecklist: function (checklist) { + for (var i = 0; i < checklist.length; i++) { + this.addChecklistItem(checklist[i]['subject'], checklist[i]['is_done']); + } + }, + + getChecklist: function () { + return this.checklist; + }, }); function observeIssueChecklistField(element, input, add_button) { - issueChecklist = new Redmine.IssueChecklist(element, input, add_button); + issueChecklist = new Redmine.IssueChecklist(element, input, add_button); } function createIssueChecklist(checkList) { - issueChecklist.addChecklist(checkList); + issueChecklist.addChecklist(checkList); } -function checklist_item_done(elem,url,id){ - new Ajax.Request(url, - { - method:'get', - onSuccess: function(transport){ - var response = transport.responseText || "no response text"; - eval(response) - }, - onFailure: function(){ alert('Something went wrong...') } - }); - - var checkbox = $(elem) - if (checkbox) - if (checkbox.checked) - checkbox.up().addClassName('is-done-checklist-item'); - else - checkbox.up().removeClassName('is-done-checklist-item'); +function checklist_item_done(elem, url, id) { + new Ajax.Request(url, + { + method: 'get', + onSuccess: function (transport) { + var response = transport.responseText || "no response text"; + eval(response) + }, + onFailure: function () { + alert('Something went wrong...') + } + }); + + var checkbox = $(elem) + if (checkbox) + if (checkbox.checked) + checkbox.up().addClassName('is-done-checklist-item'); + else + checkbox.up().removeClassName('is-done-checklist-item'); } \ No newline at end of file diff --git a/assets/stylesheets/issue_checklist.css b/assets/stylesheets/issue_checklist.css index a2885ee..8aa2ff2 100644 --- a/assets/stylesheets/issue_checklist.css +++ b/assets/stylesheets/issue_checklist.css @@ -1,8 +1,8 @@ div#issue_checklist ul { - list-style: none; - padding-left: 0px; - margin-bottom: 0px; + list-style: none; + padding-left: 0px; + margin-bottom: 0px; } div#issue_checklist li { @@ -10,7 +10,6 @@ div#issue_checklist li { margin-left: 10px; } - input#checklist_item { margin-right: 10px; } @@ -20,22 +19,37 @@ input#checklist_item { margin-left: 5px; } -#issue_checklist li:hover a.delete {opacity: 1;} -#issue_checklist a.delete {opacity: 0.4;} +#issue_checklist li:hover a.delete { + opacity: 1; +} + +#issue_checklist a.delete { + opacity: 0.4; +} span.checklist-item { display: block; margin-bottom: 5px; -} +} span.checklist-item.is-done-checklist-item, #issue_checklist_items li.is-done-checklist-item { text-decoration: line-through; color: #999; } -span.checklist-item .delete { margin-left: 2px; opacity: 0.4;} -span.checklist-item:hover .delete {opacity: 1;} +span.checklist-item .delete { + margin-left: 2px; + opacity: 0.4; +} -span.checklist-item input { margin-right: 6px; } +span.checklist-item:hover .delete { + opacity: 1; +} -#add_checklist_item_input { width: 40%;} +span.checklist-item input { + margin-right: 6px; +} + +#add_checklist_item_input { + width: 40%; +} diff --git a/config/routes.rb b/config/routes.rb index eeda13a..89cbbf2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,3 @@ - match "checklist/done/:checklist_item_id", to: 'issue_checklists#done', via: [:get, :post] - match "checklist/delete/:checklist_item_id", to: 'issue_checklists#delete', via: [:get, :post] + match 'checklist/done/:checklist_item_id', to: 'issue_checklists#done', via: [:get, :post] + match 'checklist/delete/:checklist_item_id', to: 'issue_checklists#delete', via: [:get, :post] diff --git a/db/migrate/20111010202847_create_issue_checklists.rb b/db/migrate/20111010202847_create_issue_checklists.rb index 8d71e33..e03181b 100644 --- a/db/migrate/20111010202847_create_issue_checklists.rb +++ b/db/migrate/20111010202847_create_issue_checklists.rb @@ -1,10 +1,10 @@ class CreateIssueChecklists < ActiveRecord::Migration def self.up create_table :issue_checklists do |t| - t.boolean :is_done, :default => false + t.boolean :is_done, default: false t.string :subject - t.integer :position, :default => 1 - t.references :issue, :null => false + t.integer :position, default: 1 + t.references :issue, null: false end end diff --git a/issue_checklist_1.PNG b/doc/issue_checklist_1.png similarity index 100% rename from issue_checklist_1.PNG rename to doc/issue_checklist_1.png diff --git a/issue_checklist_2.PNG b/doc/issue_checklist_2.png similarity index 100% rename from issue_checklist_2.PNG rename to doc/issue_checklist_2.png diff --git a/issue_checklist_3.PNG b/doc/issue_checklist_3.png similarity index 100% rename from issue_checklist_3.PNG rename to doc/issue_checklist_3.png diff --git a/issue_checklist_4.PNG b/doc/issue_checklist_4.png similarity index 100% rename from issue_checklist_4.PNG rename to doc/issue_checklist_4.png diff --git a/issue_checklist_5.PNG b/doc/issue_checklist_5.png similarity index 100% rename from issue_checklist_5.PNG rename to doc/issue_checklist_5.png diff --git a/init.rb b/init.rb index f7a6682..741a036 100644 --- a/init.rb +++ b/init.rb @@ -10,18 +10,18 @@ url 'http://redminecrm.com' author_url 'mailto:kirbez@redminecrm.com' - requires_redmine :version_or_higher => '2.0.0' + requires_redmine version_or_higher: '2.0.0' - settings :default => { - :save_log => false, - :issue_done_ratio => false - }, :partial => 'settings/issue_checklist' + settings default: { + save_log: false, + issue_done_ratio: false + }, partial: 'settings/issue_checklist' Redmine::AccessControl.map do |map| map.project_module :issue_tracking do |map| map.permission :view_checklists, {} - map.permission :done_checklists, {:issue_checklist => :done} - map.permission :edit_checklists, {:issue_checklist => :delete, :issue_checklist => :done} + map.permission :done_checklists, { issue_checklist: :done } + map.permission :edit_checklists, { issue_checklist: :delete, issue_checklist: :done } end end diff --git a/lib/redmine_issue_checklist/hooks/views_issues_hook.rb b/lib/redmine_issue_checklist/hooks/views_issues_hook.rb index 1ceee97..3dbd606 100644 --- a/lib/redmine_issue_checklist/hooks/views_issues_hook.rb +++ b/lib/redmine_issue_checklist/hooks/views_issues_hook.rb @@ -1,8 +1,8 @@ module RedmineIssueChecklist module Hooks - class ViewsIssuesHook < Redmine::Hook::ViewListener - render_on :view_issues_show_description_bottom, :partial => "issues/checklist" - render_on :view_issues_form_details_bottom, :partial => "issues/checklist_form" - end + class ViewsIssuesHook < Redmine::Hook::ViewListener + render_on :view_issues_show_description_bottom, partial: 'issues/checklist' + render_on :view_issues_form_details_bottom, partial: 'issues/checklist_form' + end end end diff --git a/lib/redmine_issue_checklist/patches/issue_patch.rb b/lib/redmine_issue_checklist/patches/issue_patch.rb index 733208d..7d485b5 100644 --- a/lib/redmine_issue_checklist/patches/issue_patch.rb +++ b/lib/redmine_issue_checklist/patches/issue_patch.rb @@ -9,7 +9,7 @@ def self.included(base) # :nodoc: base.send(:include, InstanceMethods) base.class_eval do alias_method_chain :copy_from, :checklist - has_many :checklist, :class_name => "IssueChecklist", :dependent => :destroy + has_many :checklist, class_name: 'IssueChecklist', dependent: :destroy end end @@ -17,8 +17,8 @@ def self.included(base) # :nodoc: module InstanceMethods def copy_from_with_checklist(arg, options={}) copy_from_without_checklist(arg, options) - issue = arg.is_a?(Issue) ? arg : Issue.visible.find(arg) - self.checklist = issue.checklist.map{|cl| cl.dup } + issue = arg.is_a?(Issue) ? arg : Issue.visible.find(arg) + self.checklist = issue.checklist.map { |cl| cl.dup } self.checklist.each do |object| object.is_done = nil end @@ -31,16 +31,18 @@ def update_checklist_items(checklist_items, create_journal = false) old_checklist = checklist.collect(&:info).join(', ') checklist.destroy_all - checklist << checklist_items.uniq.collect { |cli| IssueChecklist.new(:is_done => cli[:is_done], - :subject => cli[:subject]) } + checklist << checklist_items.uniq.collect do |cli| + IssueChecklist.new(is_done: cli[:is_done], subject: cli[:subject]) + end new_checklist = checklist.collect(&:info).join(', ') if current_journal && create_journal && (new_checklist != old_checklist) - current_journal.details << JournalDetail.new(:property => 'attr', - :prop_key => 'checklist', - :old_value => old_checklist, - :value => new_checklist) + current_journal.details << JournalDetail.new( + property: 'attr', + prop_key: 'checklist', + old_value: old_checklist, + value: new_checklist) end end diff --git a/lib/redmine_issue_checklist/redmine_issue_checklist.rb b/lib/redmine_issue_checklist/redmine_issue_checklist.rb index 45b332d..261ae65 100644 --- a/lib/redmine_issue_checklist/redmine_issue_checklist.rb +++ b/lib/redmine_issue_checklist/redmine_issue_checklist.rb @@ -1,9 +1,8 @@ - require 'redmine_issue_checklist/hooks/views_issues_hook' require 'redmine_issue_checklist/hooks/model_issue_hook' Rails.configuration.to_prepare do - require 'redmine_issue_checklist/patches/issue_patch' + require 'redmine_issue_checklist/patches/issue_patch' require 'redmine_issue_checklist/patches/issues_controller_patch' end diff --git a/test/functional/issue_checklists_controller_test.rb b/test/functional/issue_checklists_controller_test.rb index e2ad845..1189d8a 100644 --- a/test/functional/issue_checklists_controller_test.rb +++ b/test/functional/issue_checklists_controller_test.rb @@ -2,58 +2,58 @@ class IssueChecklistsControllerTest < ActionController::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, - :issue_checklists + :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, + :issue_checklists def setup RedmineIssueChecklist::TestCase.prepare Setting.default_language = 'en' end - # test "should not post new by deny user" do + # test "should not post new by deny user" do # @request.session[:user_id] = 5 - # - # xhr :post, :new, :issue_id => 1, :new_checklist_item => "New checklist item" + # + # xhr :post, :new, issue_id: 1, new_checklist_item: "New checklist item" # assert_response 401 - # end + # end - test "should post done" do - # log_user('admin', 'admin') + test 'should post done' do + # log_user('admin', 'admin') @request.session[:user_id] = 1 - - xhr :post, :done, :is_done => true, :checklist_item_id => "1" + + xhr :post, :done, is_done: true, checklist_item_id: '1' assert_response :success assert_equal true, IssueChecklist.find(1).is_done - end + end - test "should not post done by deny user" do - # log_user('admin', 'admin') + test 'should not post done by deny user' do + # log_user('admin', 'admin') @request.session[:user_id] = 5 - - xhr :post, :done, :is_done => true, :checklist_item_id => "1" + + xhr :post, :done, is_done: true, checklist_item_id: '1' assert_response 403 - end + end end diff --git a/test/functional/redmine_issue_checklist/settings_controller_test.rb b/test/functional/redmine_issue_checklist/settings_controller_test.rb index dc9b6b6..f60f971 100644 --- a/test/functional/redmine_issue_checklist/settings_controller_test.rb +++ b/test/functional/redmine_issue_checklist/settings_controller_test.rb @@ -10,7 +10,7 @@ def test_plugin_settings User.current = User.find(1) @request.session[:user_id] = 1 # admin Setting.plugin_redmine_issue_checklist = '' - get :plugin, :id => 'redmine_issue_checklist' + get :plugin, id: 'redmine_issue_checklist' assert_response :success end diff --git a/test/test_helper.rb b/test/test_helper.rb index ba78232..418e7ef 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -3,21 +3,21 @@ #Engines::Testing.set_fixture_path ActiveRecord::Fixtures.create_fixtures(File.dirname(__FILE__) + '/fixtures/', File.basename('issue_checklists', '.*')) -class RedmineIssueChecklist::TestCase +class RedmineIssueChecklist::TestCase def self.prepare - Role.find(1, 2, 3, 4).each do |r| + Role.find(1, 2, 3, 4).each do |r| r.permissions << :edit_checklists r.save end - - Role.find(3, 4).each do |r| + + Role.find(3, 4).each do |r| r.permissions << :done_checklists r.save - end - - Project.find(1, 2, 3, 4, 5).each do |project| - EnabledModule.create(:project => project, :name => 'issue_checklist') end - end - + + Project.find(1, 2, 3, 4, 5).each do |project| + EnabledModule.create(project: project, name: 'issue_checklist') + end + end + end