From 1be47c8e23eed265f9ac11df9e20bbbab56d75a7 Mon Sep 17 00:00:00 2001 From: Gregor Schmidt Date: Thu, 31 Mar 2011 12:03:34 +0200 Subject: [PATCH 01/46] removing theme-ing support --- app/helpers/rb_common_helper.rb | 14 -------------- app/views/layouts/rb.html.erb | 4 ++-- app/views/rb_master_backlogs/show.html.erb | 4 ++-- app/views/rb_taskboards/show.html.erb | 4 ++-- app/views/shared/_backlogs_header.html.erb | 4 ++-- assets/stylesheets/{rb_default => }/global.css | 0 .../stylesheets/{rb_default => }/global_print.css | 0 .../stylesheets/{rb_default => }/images/ajax.gif | Bin .../{rb_default => }/images/bouncer.gif | Bin .../stylesheets/{rb_default => }/images/error.png | Bin .../{rb_default => }/images/indicator.gif | Bin .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin .../images/ui-bg_flat_75_ffffff_40x100.png | Bin .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin .../images/ui-bg_glass_65_ffffff_1x400.png | Bin .../images/ui-bg_glass_75_dadada_1x400.png | Bin .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin .../images/ui-icons_222222_256x240.png | Bin .../images/ui-icons_2e83ff_256x240.png | Bin .../images/ui-icons_454545_256x240.png | Bin .../images/ui-icons_888888_256x240.png | Bin .../images/ui-icons_cd0a0a_256x240.png | Bin .../{rb_default => }/images/warning.png | Bin assets/stylesheets/{rb_default => }/jquery-ui.css | 0 .../{rb_default => }/master_backlog.css | 0 .../{rb_default => }/master_backlog_print.css | 0 .../stylesheets/{rb_default => }/statistics.css | 0 assets/stylesheets/{rb_default => }/taskboard.css | 0 .../{rb_default => }/taskboard_print.css | 0 31 files changed, 8 insertions(+), 22 deletions(-) rename assets/stylesheets/{rb_default => }/global.css (100%) rename assets/stylesheets/{rb_default => }/global_print.css (100%) rename assets/stylesheets/{rb_default => }/images/ajax.gif (100%) rename assets/stylesheets/{rb_default => }/images/bouncer.gif (100%) rename assets/stylesheets/{rb_default => }/images/error.png (100%) rename assets/stylesheets/{rb_default => }/images/indicator.gif (100%) rename assets/stylesheets/{rb_default => }/images/ui-bg_flat_0_aaaaaa_40x100.png (100%) rename assets/stylesheets/{rb_default => }/images/ui-bg_flat_75_ffffff_40x100.png (100%) rename assets/stylesheets/{rb_default => }/images/ui-bg_glass_55_fbf9ee_1x400.png (100%) rename assets/stylesheets/{rb_default => }/images/ui-bg_glass_65_ffffff_1x400.png (100%) rename assets/stylesheets/{rb_default => }/images/ui-bg_glass_75_dadada_1x400.png (100%) rename assets/stylesheets/{rb_default => }/images/ui-bg_glass_75_e6e6e6_1x400.png (100%) rename assets/stylesheets/{rb_default => }/images/ui-bg_glass_95_fef1ec_1x400.png (100%) rename assets/stylesheets/{rb_default => }/images/ui-bg_highlight-soft_75_cccccc_1x100.png (100%) rename assets/stylesheets/{rb_default => }/images/ui-icons_222222_256x240.png (100%) rename assets/stylesheets/{rb_default => }/images/ui-icons_2e83ff_256x240.png (100%) rename assets/stylesheets/{rb_default => }/images/ui-icons_454545_256x240.png (100%) rename assets/stylesheets/{rb_default => }/images/ui-icons_888888_256x240.png (100%) rename assets/stylesheets/{rb_default => }/images/ui-icons_cd0a0a_256x240.png (100%) rename assets/stylesheets/{rb_default => }/images/warning.png (100%) rename assets/stylesheets/{rb_default => }/jquery-ui.css (100%) rename assets/stylesheets/{rb_default => }/master_backlog.css (100%) rename assets/stylesheets/{rb_default => }/master_backlog_print.css (100%) rename assets/stylesheets/{rb_default => }/statistics.css (100%) rename assets/stylesheets/{rb_default => }/taskboard.css (100%) rename assets/stylesheets/{rb_default => }/taskboard_print.css (100%) diff --git a/app/helpers/rb_common_helper.rb b/app/helpers/rb_common_helper.rb index 49e04d022a..7c110b7240 100644 --- a/app/helpers/rb_common_helper.rb +++ b/app/helpers/rb_common_helper.rb @@ -81,20 +81,6 @@ module RbCommonHelper story.new_record? ? "" : h(story.description).gsub(/<(\/?pre)>/, '<\1>') end - def theme_name - 'rb_default' - end - - # TODO: get rid of theme_stylesheet_link_tag, no themeing neccessary, when - # view becomes part of default layout - def theme_stylesheet_link_tag(*args) - themed_args = args.select{ |a| a.class!=Hash }.map{ |s| "#{theme_name}/#{s.to_s}"} - options = args.select{ |a| a.class==Hash}.first || { } - options[:plugin] = 'redmine_backlogs' - themed_args << options - stylesheet_link_tag *themed_args - end - def tracker_id_or_empty(story) story.new_record? ? "" : story.tracker_id end diff --git a/app/views/layouts/rb.html.erb b/app/views/layouts/rb.html.erb index 33a6ab2db0..493e5ec263 100644 --- a/app/views/layouts/rb.html.erb +++ b/app/views/layouts/rb.html.erb @@ -5,8 +5,8 @@ -<%= theme_stylesheet_link_tag 'global.css', 'jquery-ui.css', :media => 'print,screen' %> -<%= theme_stylesheet_link_tag 'global_print.css', :media => 'print' %> +<%= stylesheet_link_tag 'global.css', 'jquery-ui.css', :media => 'print,screen', :plugin => 'redmine_backlogs' %> +<%= stylesheet_link_tag 'global_print.css', :media => 'print', :plugin => 'redmine_backlogs' %> <%= javascript_include_tag 'jquery-1.4.2.min.js', 'jquery-ui-1.8rc3.custom.min.js', 'jquery.jeditable.mini.js', 'jquery.cookie.js', 'common.js', :plugin => 'redmine_backlogs' %> diff --git a/app/views/rb_master_backlogs/show.html.erb b/app/views/rb_master_backlogs/show.html.erb index 71b6465ee0..7a6ee2e7ab 100644 --- a/app/views/rb_master_backlogs/show.html.erb +++ b/app/views/rb_master_backlogs/show.html.erb @@ -18,8 +18,8 @@ :format => :js) %> <%= stylesheet_link_tag 'jqplot.css', :plugin => 'redmine_backlogs' %> - <%= theme_stylesheet_link_tag 'master_backlog.css', :media => 'print,screen' %> - <%= theme_stylesheet_link_tag 'master_backlog_print.css', :media => 'print' %> + <%= stylesheet_link_tag 'master_backlog.css', :media => 'print,screen', :plugin => 'redmine_backlogs' %> + <%= stylesheet_link_tag 'master_backlog_print.css', :media => 'print', :plugin => 'redmine_backlogs' %> <% end %>
diff --git a/app/views/rb_taskboards/show.html.erb b/app/views/rb_taskboards/show.html.erb index 804d897c34..b83b94e5fc 100644 --- a/app/views/rb_taskboards/show.html.erb +++ b/app/views/rb_taskboards/show.html.erb @@ -17,8 +17,8 @@ :sprint_id => @sprint) %> <%= stylesheet_link_tag 'jqplot.css', :plugin => 'redmine_backlogs' %> - <%= theme_stylesheet_link_tag 'taskboard.css', :media => 'print,screen' %> - <%= theme_stylesheet_link_tag 'taskboard_print.css', :media => 'print' %> + <%= stylesheet_link_tag 'taskboard.css', :media => 'print,screen', :plugin => 'redmine_backlogs' %> + <%= stylesheet_link_tag 'taskboard_print.css', :media => 'print', :plugin => 'redmine_backlogs' %> <% end %>
diff --git a/app/views/shared/_backlogs_header.html.erb b/app/views/shared/_backlogs_header.html.erb index b4471a6f41..6dc6338a2b 100644 --- a/app/views/shared/_backlogs_header.html.erb +++ b/app/views/shared/_backlogs_header.html.erb @@ -1,6 +1,6 @@ <% content_for :header_tags do %> - <%= theme_stylesheet_link_tag 'global.css', 'jquery-ui.css', :media => 'print,screen' %> - <%= theme_stylesheet_link_tag 'global_print.css', :media => 'print' %> + <%= stylesheet_link_tag 'global.css', 'jquery-ui.css', :media => 'print,screen', :plugin => 'redmine_backlogs' %> + <%= stylesheet_link_tag 'global_print.css', :media => 'print', :plugin => 'redmine_backlogs' %> <%= javascript_include_tag 'lib/jquery-1.5.1.min.js', 'lib/jquery-ui-1.8.11.custom.min.js', diff --git a/assets/stylesheets/rb_default/global.css b/assets/stylesheets/global.css similarity index 100% rename from assets/stylesheets/rb_default/global.css rename to assets/stylesheets/global.css diff --git a/assets/stylesheets/rb_default/global_print.css b/assets/stylesheets/global_print.css similarity index 100% rename from assets/stylesheets/rb_default/global_print.css rename to assets/stylesheets/global_print.css diff --git a/assets/stylesheets/rb_default/images/ajax.gif b/assets/stylesheets/images/ajax.gif similarity index 100% rename from assets/stylesheets/rb_default/images/ajax.gif rename to assets/stylesheets/images/ajax.gif diff --git a/assets/stylesheets/rb_default/images/bouncer.gif b/assets/stylesheets/images/bouncer.gif similarity index 100% rename from assets/stylesheets/rb_default/images/bouncer.gif rename to assets/stylesheets/images/bouncer.gif diff --git a/assets/stylesheets/rb_default/images/error.png b/assets/stylesheets/images/error.png similarity index 100% rename from assets/stylesheets/rb_default/images/error.png rename to assets/stylesheets/images/error.png diff --git a/assets/stylesheets/rb_default/images/indicator.gif b/assets/stylesheets/images/indicator.gif similarity index 100% rename from assets/stylesheets/rb_default/images/indicator.gif rename to assets/stylesheets/images/indicator.gif diff --git a/assets/stylesheets/rb_default/images/ui-bg_flat_0_aaaaaa_40x100.png b/assets/stylesheets/images/ui-bg_flat_0_aaaaaa_40x100.png similarity index 100% rename from assets/stylesheets/rb_default/images/ui-bg_flat_0_aaaaaa_40x100.png rename to assets/stylesheets/images/ui-bg_flat_0_aaaaaa_40x100.png diff --git a/assets/stylesheets/rb_default/images/ui-bg_flat_75_ffffff_40x100.png b/assets/stylesheets/images/ui-bg_flat_75_ffffff_40x100.png similarity index 100% rename from assets/stylesheets/rb_default/images/ui-bg_flat_75_ffffff_40x100.png rename to assets/stylesheets/images/ui-bg_flat_75_ffffff_40x100.png diff --git a/assets/stylesheets/rb_default/images/ui-bg_glass_55_fbf9ee_1x400.png b/assets/stylesheets/images/ui-bg_glass_55_fbf9ee_1x400.png similarity index 100% rename from assets/stylesheets/rb_default/images/ui-bg_glass_55_fbf9ee_1x400.png rename to assets/stylesheets/images/ui-bg_glass_55_fbf9ee_1x400.png diff --git a/assets/stylesheets/rb_default/images/ui-bg_glass_65_ffffff_1x400.png b/assets/stylesheets/images/ui-bg_glass_65_ffffff_1x400.png similarity index 100% rename from assets/stylesheets/rb_default/images/ui-bg_glass_65_ffffff_1x400.png rename to assets/stylesheets/images/ui-bg_glass_65_ffffff_1x400.png diff --git a/assets/stylesheets/rb_default/images/ui-bg_glass_75_dadada_1x400.png b/assets/stylesheets/images/ui-bg_glass_75_dadada_1x400.png similarity index 100% rename from assets/stylesheets/rb_default/images/ui-bg_glass_75_dadada_1x400.png rename to assets/stylesheets/images/ui-bg_glass_75_dadada_1x400.png diff --git a/assets/stylesheets/rb_default/images/ui-bg_glass_75_e6e6e6_1x400.png b/assets/stylesheets/images/ui-bg_glass_75_e6e6e6_1x400.png similarity index 100% rename from assets/stylesheets/rb_default/images/ui-bg_glass_75_e6e6e6_1x400.png rename to assets/stylesheets/images/ui-bg_glass_75_e6e6e6_1x400.png diff --git a/assets/stylesheets/rb_default/images/ui-bg_glass_95_fef1ec_1x400.png b/assets/stylesheets/images/ui-bg_glass_95_fef1ec_1x400.png similarity index 100% rename from assets/stylesheets/rb_default/images/ui-bg_glass_95_fef1ec_1x400.png rename to assets/stylesheets/images/ui-bg_glass_95_fef1ec_1x400.png diff --git a/assets/stylesheets/rb_default/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/assets/stylesheets/images/ui-bg_highlight-soft_75_cccccc_1x100.png similarity index 100% rename from assets/stylesheets/rb_default/images/ui-bg_highlight-soft_75_cccccc_1x100.png rename to assets/stylesheets/images/ui-bg_highlight-soft_75_cccccc_1x100.png diff --git a/assets/stylesheets/rb_default/images/ui-icons_222222_256x240.png b/assets/stylesheets/images/ui-icons_222222_256x240.png similarity index 100% rename from assets/stylesheets/rb_default/images/ui-icons_222222_256x240.png rename to assets/stylesheets/images/ui-icons_222222_256x240.png diff --git a/assets/stylesheets/rb_default/images/ui-icons_2e83ff_256x240.png b/assets/stylesheets/images/ui-icons_2e83ff_256x240.png similarity index 100% rename from assets/stylesheets/rb_default/images/ui-icons_2e83ff_256x240.png rename to assets/stylesheets/images/ui-icons_2e83ff_256x240.png diff --git a/assets/stylesheets/rb_default/images/ui-icons_454545_256x240.png b/assets/stylesheets/images/ui-icons_454545_256x240.png similarity index 100% rename from assets/stylesheets/rb_default/images/ui-icons_454545_256x240.png rename to assets/stylesheets/images/ui-icons_454545_256x240.png diff --git a/assets/stylesheets/rb_default/images/ui-icons_888888_256x240.png b/assets/stylesheets/images/ui-icons_888888_256x240.png similarity index 100% rename from assets/stylesheets/rb_default/images/ui-icons_888888_256x240.png rename to assets/stylesheets/images/ui-icons_888888_256x240.png diff --git a/assets/stylesheets/rb_default/images/ui-icons_cd0a0a_256x240.png b/assets/stylesheets/images/ui-icons_cd0a0a_256x240.png similarity index 100% rename from assets/stylesheets/rb_default/images/ui-icons_cd0a0a_256x240.png rename to assets/stylesheets/images/ui-icons_cd0a0a_256x240.png diff --git a/assets/stylesheets/rb_default/images/warning.png b/assets/stylesheets/images/warning.png similarity index 100% rename from assets/stylesheets/rb_default/images/warning.png rename to assets/stylesheets/images/warning.png diff --git a/assets/stylesheets/rb_default/jquery-ui.css b/assets/stylesheets/jquery-ui.css similarity index 100% rename from assets/stylesheets/rb_default/jquery-ui.css rename to assets/stylesheets/jquery-ui.css diff --git a/assets/stylesheets/rb_default/master_backlog.css b/assets/stylesheets/master_backlog.css similarity index 100% rename from assets/stylesheets/rb_default/master_backlog.css rename to assets/stylesheets/master_backlog.css diff --git a/assets/stylesheets/rb_default/master_backlog_print.css b/assets/stylesheets/master_backlog_print.css similarity index 100% rename from assets/stylesheets/rb_default/master_backlog_print.css rename to assets/stylesheets/master_backlog_print.css diff --git a/assets/stylesheets/rb_default/statistics.css b/assets/stylesheets/statistics.css similarity index 100% rename from assets/stylesheets/rb_default/statistics.css rename to assets/stylesheets/statistics.css diff --git a/assets/stylesheets/rb_default/taskboard.css b/assets/stylesheets/taskboard.css similarity index 100% rename from assets/stylesheets/rb_default/taskboard.css rename to assets/stylesheets/taskboard.css diff --git a/assets/stylesheets/rb_default/taskboard_print.css b/assets/stylesheets/taskboard_print.css similarity index 100% rename from assets/stylesheets/rb_default/taskboard_print.css rename to assets/stylesheets/taskboard_print.css From b722867e9947b2ae81fbbeb720e8e31d106851f0 Mon Sep 17 00:00:00 2001 From: Gregor Schmidt Date: Thu, 31 Mar 2011 12:33:34 +0200 Subject: [PATCH 02/46] adding i18n for column width --- app/views/rb_taskboards/show.html.erb | 2 +- config/locales/de.yml | 1 + config/locales/en.yml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/views/rb_taskboards/show.html.erb b/app/views/rb_taskboards/show.html.erb index b83b94e5fc..490151002b 100644 --- a/app/views/rb_taskboards/show.html.erb +++ b/app/views/rb_taskboards/show.html.erb @@ -28,7 +28,7 @@ <%# TODO i18n %> - +
diff --git a/config/locales/de.yml b/config/locales/de.yml index 93bd11619c..5c8c7ba7ba 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -88,6 +88,7 @@ de: show_statistics: 'Scrum Statistiken anzeigen' show_burndown_chart: 'Burndown-Chart' add_new_story: 'Neue Story' + column_with: "Spaltenbreite:" project_module_backlogs: Backlogs (Beta) diff --git a/config/locales/en.yml b/config/locales/en.yml index c1f46e9f2d..60c4bbd007 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -106,6 +106,7 @@ en: show_statistics: 'Show Scrum statistics' show_burndown_chart: 'Burndown Chart' add_new_story: 'New Story' + column_with: "Column width:" project_module_backlogs: Backlogs (Beta) From a19a7bba2cb693b3b2418e23134d7b5752877f8f Mon Sep 17 00:00:00 2001 From: Gregor Schmidt Date: Thu, 31 Mar 2011 12:33:53 +0200 Subject: [PATCH 03/46] changing menu styling to better match overall color scheme --- assets/stylesheets/master_backlog.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/stylesheets/master_backlog.css b/assets/stylesheets/master_backlog.css index 3ed9c80840..7fdcf1e151 100644 --- a/assets/stylesheets/master_backlog.css +++ b/assets/stylesheets/master_backlog.css @@ -110,7 +110,7 @@ } #rb .backlog .header .menu .item.hover, #rb .backlog .header .menu .item:hover { - background-color:#CC0000; + background-color: #999; } #rb .backlog .header .menu .item a { display:block; From 70857733687794c11cb0dfebdc30bc940ce92637 Mon Sep 17 00:00:00 2001 From: Gregor Schmidt Date: Thu, 31 Mar 2011 14:09:27 +0200 Subject: [PATCH 04/46] using redmine helper instead of custom breadcrumb --- app/views/rb_taskboards/show.html.erb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/views/rb_taskboards/show.html.erb b/app/views/rb_taskboards/show.html.erb index 490151002b..03ee68d027 100644 --- a/app/views/rb_taskboards/show.html.erb +++ b/app/views/rb_taskboards/show.html.erb @@ -26,17 +26,13 @@ <%= l(:label_burndown) %> <% end %> - <%# TODO i18n %> - +<%= breadcrumb(link_to l(:label_backlogs), rb_master_backlog_path(@project)) %>

<%= link_to @sprint.name, rb_taskboard_path(@sprint) %> From 0541bad731aeb51787f8592f0f9f5816c4b8abb3 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Fri, 25 Mar 2011 21:09:41 +0100 Subject: [PATCH 05/46] #3178: adding explicit method to task to request whether it is really an impediment --- app/models/task.rb | 4 +++ spec/factories/task_factory.rb | 3 ++ spec/models/tasks_spec.rb | 54 ++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 spec/factories/task_factory.rb create mode 100644 spec/models/tasks_spec.rb diff --git a/app/models/task.rb b/app/models/task.rb index 0dc60e26ed..0d7c5c57d0 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -51,6 +51,10 @@ class Task < Issue return tasks end + def impediment? + parent_issue_id.nil? + end + def update_with_relationships(params, is_impediment = false) attribs = params.clone.delete_if { |k, v| !safe_attribute_names.include?(k) } diff --git a/spec/factories/task_factory.rb b/spec/factories/task_factory.rb new file mode 100644 index 0000000000..f056afd9cb --- /dev/null +++ b/spec/factories/task_factory.rb @@ -0,0 +1,3 @@ +Factory.define(:task, :parent => :issue, :class => Task) do |t| + t.association :tracker, :factory => :tracker_task +end \ No newline at end of file diff --git a/spec/models/tasks_spec.rb b/spec/models/tasks_spec.rb new file mode 100644 index 0000000000..d4c89451bd --- /dev/null +++ b/spec/models/tasks_spec.rb @@ -0,0 +1,54 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe Task do + let(:user) { @user ||= Factory.create(:user) } + let(:tracker_feature) { @tracker_feature ||= Factory.create(:tracker_feature) } + let(:tracker_task) { @tracker_task ||= Factory.create(:tracker_task) } + let(:issue_priority) { @issue_priority ||= Factory.create(:priority) } + let(:task) { Factory.build(:task, :tracker => tracker_task, + :project => project, + :author => user, + :priority => issue_priority, + :status => issue_status) } + let(:feature) { Factory.build(:issue, :tracker => tracker_feature, + :project => project, + :author => user, + :priority => issue_priority, + :status => issue_status) } + let(:version) { @version ||= Factory.create(:version, :project => project) } + let(:project) { @project ||= Factory.create(:project) } + let(:issue_status) { @status ||= Factory.create(:issue_status) } + + before(:each) do + Setting.plugin_redmine_backlogs = {"points_burn_direction" => "down", + "wiki_template" => "", + "card_spec" => "Sattleford VM-5040", + "story_trackers" => [tracker_feature.id.to_s], + "task_tracker" => tracker_task.id.to_s } + end + + describe "Instance Methods" do + before(:each) do + + end + + describe :impediment? do + describe "WITHOUT parent" do + before(:each) do + end + + it { task.should be_impediment } + end + + describe "WITH parent" do + before(:each) do + feat = feature + feat.save + task.parent_issue_id = feat.id + end + + it { task.should_not be_impediment } + end + end + end +end \ No newline at end of file From 68d7230d8e68594217fa14e3ae79100a7ce38ec9 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Fri, 25 Mar 2011 21:29:14 +0100 Subject: [PATCH 06/46] #3178: creating explicit impediment class, only copy and paste for now --- app/controllers/rb_impediments_controller.rb | 6 +-- app/models/impediment.rb | 41 ++++++++++++++++++++ app/models/task.rb | 26 ------------- 3 files changed, 44 insertions(+), 29 deletions(-) create mode 100644 app/models/impediment.rb diff --git a/app/controllers/rb_impediments_controller.rb b/app/controllers/rb_impediments_controller.rb index 5bf9866761..c9cf551fbe 100644 --- a/app/controllers/rb_impediments_controller.rb +++ b/app/controllers/rb_impediments_controller.rb @@ -2,7 +2,7 @@ class RbImpedimentsController < RbApplicationController unloadable def create - @impediment = Task.create_with_relationships(params, User.current.id, @project.id, true) + @impediment = Impediment.create_with_relationships(params, User.current.id, @project.id) result = @impediment.errors.length status = (result == 0 ? 200 : 400) @include_meta = true @@ -13,8 +13,8 @@ class RbImpedimentsController < RbApplicationController end def update - @impediment = Task.find_by_id(params[:id]) - result = @impediment.update_with_relationships(params, true) + @impediment = Impediment.find_by_id(params[:id]) + result = @impediment.update_with_relationships(params) status = (result ? 200 : 400) @include_meta = true diff --git a/app/models/impediment.rb b/app/models/impediment.rb new file mode 100644 index 0000000000..9a80e3e032 --- /dev/null +++ b/app/models/impediment.rb @@ -0,0 +1,41 @@ +class Impediment < Task + unloadable + + def self.create_with_relationships(params, user_id, project_id) + super(params, user_id, project_id, true) + end + + def self.find_all_updated_since(since, project_id) + super(since, project_id, true) + end + + def update_with_relationships(params) + super(params, true) + end + + def update_blocked_list(for_blocking) + # Existing relationships not in for_blocking should be removed from the 'blocks' list + relations_from.find(:all, :conditions => "relation_type='blocks'").each{ |ir| + ir.destroy unless for_blocking.include?( ir[:issue_to_id] ) + } + + already_blocking = relations_from.find(:all, :conditions => "relation_type='blocks'").map{|ir| ir.issue_to_id} + + # Non-existing relationships that are in for_blocking should be added to the 'blocks' list + for_blocking.select{ |id| !already_blocking.include?(id) }.each{ |id| + ir = relations_from.new(:relation_type=>'blocks') + ir[:issue_to_id] = id + ir.save! + } + reload + end + + def validate_blocks_list(list) + if list.split(/\D+/).length==0 + errors.add :blocks, :must_have_comma_delimited_list + false + else + true + end + end +end \ No newline at end of file diff --git a/app/models/task.rb b/app/models/task.rb index 0d7c5c57d0..3a55aa7dec 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -75,32 +75,6 @@ class Task < Issue end end - def update_blocked_list(for_blocking) - # Existing relationships not in for_blocking should be removed from the 'blocks' list - relations_from.find(:all, :conditions => "relation_type='blocks'").each{ |ir| - ir.destroy unless for_blocking.include?( ir[:issue_to_id] ) - } - - already_blocking = relations_from.find(:all, :conditions => "relation_type='blocks'").map{|ir| ir.issue_to_id} - - # Non-existing relationships that are in for_blocking should be added to the 'blocks' list - for_blocking.select{ |id| !already_blocking.include?(id) }.each{ |id| - ir = relations_from.new(:relation_type=>'blocks') - ir[:issue_to_id] = id - ir.save! - } - reload - end - - def validate_blocks_list(list) - if list.split(/\D+/).length==0 - errors.add :blocks, :must_have_comma_delimited_list - false - else - true - end - end - # assumes the task is already under the same story as 'id' def move_after(id) id = nil if id.respond_to?('blank?') && id.blank? From ecfaf2bb77e50ba8e544f9fab2ea89dff43712fa Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Fri, 25 Mar 2011 21:44:40 +0100 Subject: [PATCH 07/46] refactoring in task class --- app/models/task.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/models/task.rb b/app/models/task.rb index 3a55aa7dec..9fea750e55 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -5,8 +5,7 @@ class Task < Issue def self.tracker task_tracker = Setting.plugin_redmine_backlogs[:task_tracker] - return nil if task_tracker.blank? - return Integer(task_tracker) + task_tracker.blank? ? nil : task_tracker.to_i end def self.create_with_relationships(params, user_id, project_id, is_impediment = false) From 455310381879e985a7a8db3e000ed06fd483c354 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Fri, 25 Mar 2011 22:03:33 +0100 Subject: [PATCH 08/46] splitting up tasks and impediments, impediments remain a subclass of taks but a lot of methods are overwritten. Also refactored method of creating blocking relationship. --- app/models/impediment.rb | 119 ++++++++++++++++++++++++++++----- app/models/task.rb | 9 +-- spec/models/impediment_spec.rb | 5 ++ 3 files changed, 107 insertions(+), 26 deletions(-) create mode 100644 spec/models/impediment_spec.rb diff --git a/app/models/impediment.rb b/app/models/impediment.rb index 9a80e3e032..2d07f94ef7 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -1,41 +1,124 @@ class Impediment < Task unloadable + acts_as_list :scope => :project + + attr_accessor :blocks_ids_list + + before_validation :update_blocked_list, :unless => Proc.new { |i| i.blocks_ids_list.nil? } + def self.create_with_relationships(params, user_id, project_id) - super(params, user_id, project_id, true) + task = new + + task.author_id = user_id + task.project_id = project_id + task.tracker_id = Task.tracker + + task.safe_attributes = params + task.remaining_hours = 0 if IssueStatus.find(params[:status_id]).is_closed? + + task.blocks_ids = params[:blocks] + + if task.save + task.move_after params[:prev] + end + + return task end def self.find_all_updated_since(since, project_id) super(since, project_id, true) end + def blocks_ids=(ids) + blocks_ids_list = [ids] if ids.is_a?(Integer) + blocks_ids_list = ids.split(/\D+/).map{|id| id.to_i} if ids.is_a?(String) + blocks_ids_list = ids.map {|id| id.to_i} if ids.is_a?(Array) + end + + def blocks_ids + blocks_ids_list + end + def update_with_relationships(params) - super(params, true) + attribs = params.clone.delete_if { |k, v| !safe_attribute_names.include?(k) } + + attribs[:remaining_hours] = 0 if IssueStatus.find(params[:status_id]).is_closed? + + blocks_ids = params[:blocks] if params[:blocks] #if blocks param was not sent, that means the impediment was just dragged + + if valid? && result = journalized_update_attributes!(attribs) + move_after params[:prev] + result + else + false + end + #blocks_ids = + #valid_relationships = params[:blocks] ? validate_blocks_list(params[:blocks]) : true #if blocks param was not sent, that means the impediment was just dragged + +# if valid_relationships && result = journalized_update_attributes!(attribs) +# move_after params[:prev] +# update_blocked_list params[:blocks].split(/\D+/) if params[:blocks] +# result +# else +# false +# end end - def update_blocked_list(for_blocking) + def move_after(prev_id) + # remove so the potential 'prev' has a correct position + remove_from_list + + begin + prev = self.class.find(prev_id) + rescue ActiveRecord::RecordNotFound + prev = nil + end + + # if it's the first story, move it to the 1st position + if prev.blank? + insert_at + move_to_top + + # if its predecessor has no position (shouldn't happen), make it + # the last story + elsif !prev.in_list? + insert_at + move_to_bottom + + # there's a valid predecessor + else + insert_at(prev.position + 1) + end + end + + def update_blocked_list + for_blocking = blocks_ids_list # Existing relationships not in for_blocking should be removed from the 'blocks' list + remove_from_blocks_list + # Non-existing relationships that are in for_blocking should be added to the 'blocks' list + add_to_blocks_list + + reload + end + + def remove_from_blocks_list relations_from.find(:all, :conditions => "relation_type='blocks'").each{ |ir| - ir.destroy unless for_blocking.include?( ir[:issue_to_id] ) + relations_from.reject{|rel| !blocks_ids.include?(rel.issue_to_id) } # ir.destroy unless blocks_ids.include?( ir[:issue_to_id] ) } + end - already_blocking = relations_from.find(:all, :conditions => "relation_type='blocks'").map{|ir| ir.issue_to_id} + def add_to_blocks_list + currently_blocking = relations_from.find(:all, :conditions => "relation_type='blocks'").map{|ir| ir.issue_to_id} - # Non-existing relationships that are in for_blocking should be added to the 'blocks' list - for_blocking.select{ |id| !already_blocking.include?(id) }.each{ |id| - ir = relations_from.new(:relation_type=>'blocks') - ir[:issue_to_id] = id - ir.save! + blocks_ids.select{ |id| !currently_blocking.include?(id) }.each{ |id| + relations_from.build(:relation_type=>'blocks', :issue_to_id => id) } - reload end - def validate_blocks_list(list) - if list.split(/\D+/).length==0 - errors.add :blocks, :must_have_comma_delimited_list - false - else - true - end + def validate_blocks_list(block_list) + ids = block_list.split(/\D+/) + errors.add :blocks, :must_have_comma_delimited_list if ids.length==0 + errors.add :blocks, :can_only_contain_tasks_of_current_sprint if Task.find(ids).any?{|t| t.impediment? || t.fixed_version != self.fixed_version } end end \ No newline at end of file diff --git a/app/models/task.rb b/app/models/task.rb index 9fea750e55..fa6c4e79ba 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -59,15 +59,8 @@ class Task < Issue attribs[:remaining_hours] = 0 if IssueStatus.find(params[:status_id]).is_closed? - valid_relationships = if is_impediment && params[:blocks] #if blocks param was not sent, that means the impediment was just dragged - validate_blocks_list(params[:blocks]) - else - true - end - - if valid_relationships && result = journalized_update_attributes!(attribs) + if result = journalized_update_attributes!(attribs) move_after params[:prev] - update_blocked_list params[:blocks].split(/\D+/) if params[:blocks] result else false diff --git a/spec/models/impediment_spec.rb b/spec/models/impediment_spec.rb new file mode 100644 index 0000000000..eacb426117 --- /dev/null +++ b/spec/models/impediment_spec.rb @@ -0,0 +1,5 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe Impediment do + +end \ No newline at end of file From 83d965d2207651ed1ed43200db4012ae9b35bdff Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Sat, 26 Mar 2011 20:15:02 +0100 Subject: [PATCH 09/46] Simplifying searching of impediments for a sprint --- app/models/sprint.rb | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/app/models/sprint.rb b/app/models/sprint.rb index e003c67d15..8641f88fb8 100644 --- a/app/models/sprint.rb +++ b/app/models/sprint.rb @@ -274,19 +274,7 @@ class Sprint < Version end def impediments - return Issue.find(:all, - :conditions => ["id in ( - select issue_from_id - from issue_relations ir - join issues blocked - on blocked.id = ir.issue_to_id - and blocked.tracker_id in (?) - and blocked.fixed_version_id = (?) - where ir.relation_type = 'blocks' - )", - Story.trackers + [Task.tracker], - self.id] - ) #.sort {|a,b| a.closed? == b.closed? ? a.updated_on <=> b.updated_on : (a.closed? ? 1 : -1) } + Issue.find(:all, :conditions => ["parent_id is NULL AND fixed_version_id = ? AND tracker_id = ?", self, Task.tracker]) end end From d3b6e1e5b393e85ef3d998bd1fcd2a9baab1e4b3 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Sun, 27 Mar 2011 12:47:49 +0200 Subject: [PATCH 10/46] #3178: adding and removing from blocks list of impediment now reliant --- app/models/impediment.rb | 55 +++++++++++++++------------------------- 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index 2d07f94ef7..aa0d858a05 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -3,9 +3,7 @@ class Impediment < Task acts_as_list :scope => :project - attr_accessor :blocks_ids_list - - before_validation :update_blocked_list, :unless => Proc.new { |i| i.blocks_ids_list.nil? } + before_validation :update_blocks_list, :unless => Proc.new { |i| i.blocks_ids.nil? } def self.create_with_relationships(params, user_id, project_id) task = new @@ -31,13 +29,13 @@ class Impediment < Task end def blocks_ids=(ids) - blocks_ids_list = [ids] if ids.is_a?(Integer) - blocks_ids_list = ids.split(/\D+/).map{|id| id.to_i} if ids.is_a?(String) - blocks_ids_list = ids.map {|id| id.to_i} if ids.is_a?(Array) + @blocks_ids_list = [ids] if ids.is_a?(Integer) + @blocks_ids_list = ids.split(/\D+/).map{|id| id.to_i} if ids.is_a?(String) + @blocks_ids_list = ids.map {|id| id.to_i} if ids.is_a?(Array) end def blocks_ids - blocks_ids_list + @blocks_ids_list end def update_with_relationships(params) @@ -45,24 +43,13 @@ class Impediment < Task attribs[:remaining_hours] = 0 if IssueStatus.find(params[:status_id]).is_closed? - blocks_ids = params[:blocks] if params[:blocks] #if blocks param was not sent, that means the impediment was just dragged + attribs[:blocks_ids] = params[:blocks] if params[:blocks] #if blocks param was not sent, that means the impediment was just dragged - if valid? && result = journalized_update_attributes!(attribs) - move_after params[:prev] - result - else - false - end - #blocks_ids = - #valid_relationships = params[:blocks] ? validate_blocks_list(params[:blocks]) : true #if blocks param was not sent, that means the impediment was just dragged - -# if valid_relationships && result = journalized_update_attributes!(attribs) -# move_after params[:prev] -# update_blocked_list params[:blocks].split(/\D+/) if params[:blocks] -# result -# else -# false -# end + result = journalized_update_attributes(attribs) + + move_after params[:prev] if result + + result end def move_after(prev_id) @@ -92,28 +79,26 @@ class Impediment < Task end end - def update_blocked_list - for_blocking = blocks_ids_list + private + + def update_blocks_list # Existing relationships not in for_blocking should be removed from the 'blocks' list remove_from_blocks_list - # Non-existing relationships that are in for_blocking should be added to the 'blocks' list add_to_blocks_list - - reload end def remove_from_blocks_list - relations_from.find(:all, :conditions => "relation_type='blocks'").each{ |ir| - relations_from.reject{|rel| !blocks_ids.include?(rel.issue_to_id) } # ir.destroy unless blocks_ids.include?( ir[:issue_to_id] ) - } + self.relations_from = self.relations_from.reject{|rel| rel.relation_type == IssueRelation::TYPE_BLOCKS && !blocks_ids.include?(rel.issue_to_id) } end def add_to_blocks_list - currently_blocking = relations_from.find(:all, :conditions => "relation_type='blocks'").map{|ir| ir.issue_to_id} + currently_blocking = relations_from.select{|rel| rel.relation_type == IssueRelation::TYPE_BLOCKS}.collect(&:issue_to_id) - blocks_ids.select{ |id| !currently_blocking.include?(id) }.each{ |id| - relations_from.build(:relation_type=>'blocks', :issue_to_id => id) + self.blocks_ids.select{ |id| !currently_blocking.include?(id) }.each{ |id| + rel = relations_from.build(:relation_type => IssueRelation::TYPE_BLOCKS) + rel.issue_to_id = id } + true end def validate_blocks_list(block_list) From 2f76defb94b05c5c5a8aae2f7cc7aa31d674f8fd Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Sun, 27 Mar 2011 13:01:55 +0200 Subject: [PATCH 11/46] #3178: validating that blocking relations of an impediment point to issue of impediments sprint --- app/models/impediment.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index aa0d858a05..00ea10203a 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -101,9 +101,11 @@ class Impediment < Task true end - def validate_blocks_list(block_list) - ids = block_list.split(/\D+/) - errors.add :blocks, :must_have_comma_delimited_list if ids.length==0 - errors.add :blocks, :can_only_contain_tasks_of_current_sprint if Task.find(ids).any?{|t| t.impediment? || t.fixed_version != self.fixed_version } + def validate + validate_blocks_list + end + + def validate_blocks_list + errors.add :blocks, :can_only_contain_tasks_of_current_sprint if relations_from.any?{|rel| rel.relation_type == IssueRelation::TYPE_BLOCKS && rel.issue_to.fixed_version != self.fixed_version } end end \ No newline at end of file From 1119d1bdcea9785dcb2659579b3a8937629cddcc Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Sun, 27 Mar 2011 13:48:29 +0200 Subject: [PATCH 12/46] adding find method to Impediment so that only impediments are found on issue table; using method in sprint --- app/models/impediment.rb | 15 +++++++++++++++ app/models/sprint.rb | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index 00ea10203a..724b61311d 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -24,6 +24,21 @@ class Impediment < Task return task end + def self.find(*args) + if args[1] && args[1][:conditions] + if args[1][:conditions].is_a?(Hash) + args[1][:conditions][:parent_id] = nil + args[1][:conditions][:tracker_id] = self.tracker + elsif args[1][:conditions].is_a?(Array) + args[1][:conditions][0] += " AND parent_id is NULL AND tracker_id = #{self.tracker}" + end + else + args << {:conditions => {:parent_id => nil, :tracker_id => self.tracker}} + end + + super + end + def self.find_all_updated_since(since, project_id) super(since, project_id, true) end diff --git a/app/models/sprint.rb b/app/models/sprint.rb index 8641f88fb8..86c8e861cc 100644 --- a/app/models/sprint.rb +++ b/app/models/sprint.rb @@ -274,7 +274,7 @@ class Sprint < Version end def impediments - Issue.find(:all, :conditions => ["parent_id is NULL AND fixed_version_id = ? AND tracker_id = ?", self, Task.tracker]) + Impediment.find(:all, :conditions => {:fixed_version_id => self}) end end From 70bf42dd4f163202d1e89406b585a0f90525bd57 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Mon, 28 Mar 2011 08:52:16 +0200 Subject: [PATCH 13/46] #3178: correcting attribute for impediment relation error message --- app/models/impediment.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index 724b61311d..ea644459fb 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -121,6 +121,6 @@ class Impediment < Task end def validate_blocks_list - errors.add :blocks, :can_only_contain_tasks_of_current_sprint if relations_from.any?{|rel| rel.relation_type == IssueRelation::TYPE_BLOCKS && rel.issue_to.fixed_version != self.fixed_version } + errors.add :blocks_ids, :can_only_contain_tasks_of_current_sprint if relations_from.any?{|rel| rel.relation_type == IssueRelation::TYPE_BLOCKS && rel.issue_to.fixed_version != self.fixed_version } end end \ No newline at end of file From fd55e3c187fe390e11196f6190a3438cf8574413 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Mon, 28 Mar 2011 08:54:10 +0200 Subject: [PATCH 14/46] #3178: handling case where no relations_from was defined before, minor refactoring --- app/models/impediment.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index ea644459fb..0f54ae342b 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -98,6 +98,7 @@ class Impediment < Task def update_blocks_list # Existing relationships not in for_blocking should be removed from the 'blocks' list + relations_from = [] if relations_from.nil? remove_from_blocks_list add_to_blocks_list end @@ -109,11 +110,10 @@ class Impediment < Task def add_to_blocks_list currently_blocking = relations_from.select{|rel| rel.relation_type == IssueRelation::TYPE_BLOCKS}.collect(&:issue_to_id) - self.blocks_ids.select{ |id| !currently_blocking.include?(id) }.each{ |id| - rel = relations_from.build(:relation_type => IssueRelation::TYPE_BLOCKS) - rel.issue_to_id = id + (self.blocks_ids - currently_blocking).each{ |id| + rel = IssueRelation.new(:relation_type => IssueRelation::TYPE_BLOCKS, :issue_to => Issue.find(id), :issue_from => self) + self.relations_from << rel } - true end def validate From 823eb1a9bb508c140a5c88df0f056f409958492c Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Mon, 28 Mar 2011 08:54:55 +0200 Subject: [PATCH 15/46] #3178: using a transaction and two save to create an impediment with the appropriate "blocks"-relationship --- app/models/impediment.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index 0f54ae342b..8ac1fa6deb 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -15,9 +15,13 @@ class Impediment < Task task.safe_attributes = params task.remaining_hours = 0 if IssueStatus.find(params[:status_id]).is_closed? - task.blocks_ids = params[:blocks] - - if task.save + #an issue relation can not be established between new nodes because their relationship can not be + #evaluated and issue relations between parent and descendant are prohibited. Therefore we need to + #save two times in a transaction + task.transaction do + task.save + task.blocks_ids = params[:blocks] + task.save task.move_after params[:prev] end From 6f31f47cd28ba1ff899a933c0ae0c3e5eb8ba68d Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Mon, 28 Mar 2011 12:39:36 +0200 Subject: [PATCH 16/46] #3178: cukefix: using Impediment class to create impediments --- features/step_definitions/_given_steps.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/step_definitions/_given_steps.rb b/features/step_definitions/_given_steps.rb index 66182d738a..979619508b 100644 --- a/features/step_definitions/_given_steps.rb +++ b/features/step_definitions/_given_steps.rb @@ -179,7 +179,7 @@ Given /^the [pP]roject(?: "([^\"]*)")? has the following impediments:$/ do |proj # NOTE: We're bypassing the controller here because we're just # setting up the database for the actual tests. The actual tests, # however, should NOT bypass the controller - Task.create_with_relationships(params, author.id, project.id) + Impediment.create_with_relationships(params, author.id, project.id) end end From 2a6e9b495708b4eeffb765876a1dccf31ad2828b Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Tue, 29 Mar 2011 08:58:13 +0200 Subject: [PATCH 17/46] #3178: different symbol for error message when blocks of an impediment is invalid --- app/models/impediment.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index 8ac1fa6deb..c857a83770 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -7,7 +7,6 @@ class Impediment < Task def self.create_with_relationships(params, user_id, project_id) task = new - task.author_id = user_id task.project_id = project_id task.tracker_id = Task.tracker @@ -125,6 +124,6 @@ class Impediment < Task end def validate_blocks_list - errors.add :blocks_ids, :can_only_contain_tasks_of_current_sprint if relations_from.any?{|rel| rel.relation_type == IssueRelation::TYPE_BLOCKS && rel.issue_to.fixed_version != self.fixed_version } + errors.add :blocks_ids, :can_only_contain_issues_of_current_sprint if relations_from.any?{|rel| rel.relation_type == IssueRelation::TYPE_BLOCKS && rel.issue_to.fixed_version != self.fixed_version } end end \ No newline at end of file From 04160038f3c74f8ae7417119e5d9c5e1354f9dfb Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Tue, 29 Mar 2011 08:59:19 +0200 Subject: [PATCH 18/46] #3178: spec for Impediment.create_with_relationship with an issue of same version --- spec/models/impediment_spec.rb | 76 ++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/spec/models/impediment_spec.rb b/spec/models/impediment_spec.rb index eacb426117..469f22fd76 100644 --- a/spec/models/impediment_spec.rb +++ b/spec/models/impediment_spec.rb @@ -1,5 +1,81 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe Impediment do + let(:user) { @user ||= Factory.create(:user) } + let(:role) { @role ||= Factory.create(:role, :permissions => [:edit_issues]) } + let(:tracker_feature) { @tracker_feature ||= Factory.create(:tracker_feature) } + let(:tracker_task) { @tracker_task ||= Factory.create(:tracker_task) } + let(:issue_priority) { @issue_priority ||= Factory.create(:priority, :is_default => true) } + let(:task) { Factory.build(:task, :tracker => tracker_task, + :project => project, + :author => user, + :priority => issue_priority, + :status => issue_status1) } + let(:feature) { Factory.build(:issue, :tracker => tracker_feature, + :project => project, + :author => user, + :priority => issue_priority, + :status => issue_status1) } + let(:version) { @version ||= Factory.create(:version, :project => project) } + + let(:project) do + unless @project + @project = Factory.build(:project) + @project.members = [Factory.build(:member, :principal => user, + :project => @project, + :roles => [role])] + end + @project + end + + let(:issue_status1) { @status1 ||= Factory.create(:issue_status, :name => "status 1", :is_default => true) } + let(:issue_status2) { @status2 ||= Factory.create(:issue_status, :name => "status 2") } + let(:tracker_workflow) { @workflow ||= Workflow.create(:tracker_id => tracker_task.id, + :old_status => issue_status1, + :new_status => issue_status2, + :role => role) } + + before(:each) do + Setting.plugin_redmine_backlogs = {:points_burn_direction => "down", + :wiki_template => "", + :card_spec => "Sattleford VM-5040", + :story_trackers => [tracker_feature.id.to_s], + :task_tracker => tracker_task.id.to_s } + + User.current = user + project.save + tracker_workflow.save + end + + describe "class methods" do + describe :create_with_relationships do + describe "WITH a blocking relationship to a story" do + before(:each) do + feature.save + @impediment_subject = "Impediment A" + @impediment = Impediment.create_with_relationships({:subject => @impediment_subject, + :assigned_to_id => user.id, + :blocks => feature.id.to_s, + :status_id => issue_status1.id, + :fixed_version_id => version.id}, + user.id, + project.id) + + end + + it { @impediment.should_not be_new_record } + it { @impediment.subject.should eql @impediment_subject } + it { @impediment.author.should eql user } + it { @impediment.project.should eql project } + it { @impediment.fixed_version.should eql version } + it { @impediment.status.should eql issue_status1 } + it { @impediment.tracker.should eql tracker_task } + it { @impediment.assigned_to.should eql user } + it { @impediment.should have(1).relations_from } + it { @impediment.relations_from[0].issue_to.should eql feature } + it { @impediment.relations_from[0].relation_type.should eql IssueRelation::TYPE_BLOCKS } + end + end + end end \ No newline at end of file From 3f14b6fd36fe7028f93b0da1267a99916d3bf5d0 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Tue, 29 Mar 2011 10:56:49 +0200 Subject: [PATCH 19/46] #3178: patching awesome_nested_set for issues so that it can handle the ancestor/descendant-relationship of new_record and existing record --- lib/backlogs_issue_patch.rb | 60 ++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/lib/backlogs_issue_patch.rb b/lib/backlogs_issue_patch.rb index 6e911f89ab..acbe9064bd 100644 --- a/lib/backlogs_issue_patch.rb +++ b/lib/backlogs_issue_patch.rb @@ -5,20 +5,22 @@ module Backlogs def self.included(base) # :nodoc: base.extend(ClassMethods) base.send(:include, InstanceMethods) - + base.class_eval do unloadable alias_method_chain :move_to_project_without_transaction, :autolink alias_method_chain :recalculate_attributes_for, :remaining_hours + alias_method_chain :is_descendant_of?, :new_record + alias_method_chain :is_ancestor_of?, :new_record before_validation :backlogs_before_validation after_save :backlogs_after_save end end - + module ClassMethods end - + module InstanceMethods def move_to_project_without_transaction_with_autolink(new_project, new_tracker = nil, options = {}) newissue = move_to_project_without_transaction_without_autolink(new_project, new_tracker, options) @@ -29,33 +31,49 @@ module Backlogs relation.issue_to = newissue relation.save end - + return newissue end - + def journalized_update_attributes!(attribs) self.init_journal(User.current) return self.update_attributes!(attribs) end - + def journalized_update_attributes(attribs) self.init_journal(User.current) return self.update_attributes(attribs) end - + def journalized_update_attribute(attrib, v) self.init_journal(User.current) self.update_attribute(attrib, v) end - + def is_story? return Story.trackers.include?(self.tracker_id) end - + def is_task? return (self.parent_id && self.tracker_id == Task.tracker) end - + + def is_descendant_of_with_new_record?(other) + if self.new_record? + self.parent && (self.parent == other || self.parent.is_decendant_of?(other)) + else + is_descendant_of_without_new_record?(other) + end + end + + def is_ancestor_of_with_new_record?(other) + if self.new_record? + false + else + is_ancestor_of_without_new_record?(other) + end + end + def story if self.is_story? return self @@ -63,13 +81,13 @@ module Backlogs return self.ancestors.find_by_tracker_id(Story.trackers) end end - + def blocks # return issues that I block that aren't closed return [] if closed? relations_from.collect {|ir| ir.relation_type == 'blocks' && !ir.issue_to.closed? ? ir.issue_to : nil}.compact end - + def blockers # return issues that block me return [] if closed? @@ -78,23 +96,23 @@ module Backlogs def velocity_based_estimate return nil if !self.is_story? || ! self.story_points || self.story_points <= 0 - + dpp = self.project.scrum_statistics.info[:average_days_per_point] return nil if ! dpp - + return Integer(self.story_points * dpp) end - + def recalculate_attributes_for_with_remaining_hours(issue_id) recalculate_attributes_for_without_remaining_hours(issue_id) - + if issue_id && p = Issue.find_by_id(issue_id) if p.left != (p.right + 1) # this node has children p.update_attribute(:remaining_hours, p.leaves.sum(:remaining_hours).to_f) end end end - + def backlogs_before_validation if self.tracker_id == Task.tracker self.estimated_hours = self.remaining_hours if self.estimated_hours.blank? && ! self.remaining_hours.blank? @@ -108,9 +126,9 @@ module Backlogs ## Normally one of the _before_save hooks ought to take ## care of this, but appearantly neither root_id nor ## parent_id are set at that point - + touched_sprints = [] - + if self.is_story? # raw sql here because it's efficient and not # doing so causes an update loop when Issue calls @@ -125,7 +143,7 @@ module Backlogs touched_sprints = [self.fixed_version_id, self.fixed_version_id_was].compact.uniq touched_sprints = touched_sprints.collect{|s| Sprint.find(s)}.compact - + elsif not Task.tracker.nil? begin story = self.story @@ -136,7 +154,7 @@ module Backlogs touched_sprints = [self.root_id, self.root_id_was].compact.uniq.collect{|s| Story.find(s).fixed_version}.compact end end - + touched_sprints.each {|sprint| sprint.touch_burndown } From bdae7ca0f2f752dc0af399ed4155ddc7cd99d2f9 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Tue, 29 Mar 2011 11:02:35 +0200 Subject: [PATCH 20/46] #3178: impediments with an empty blocks list are invalid --- app/models/impediment.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index c857a83770..ee07f2efb7 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -124,6 +124,7 @@ class Impediment < Task end def validate_blocks_list + errors.add :blocks_ids, :must_block_at_least_one_issue if relations_from.size == 0 errors.add :blocks_ids, :can_only_contain_issues_of_current_sprint if relations_from.any?{|rel| rel.relation_type == IssueRelation::TYPE_BLOCKS && rel.issue_to.fixed_version != self.fixed_version } end end \ No newline at end of file From a6b0bad9fc880396260d9fb5dcaa9487bf48fb39 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Tue, 29 Mar 2011 11:04:09 +0200 Subject: [PATCH 21/46] #3178: using patched awesome_nested_set (fcc6230) to fix bug that would prevent creation of new impediments --- app/models/impediment.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index ee07f2efb7..5b0de09585 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -14,13 +14,9 @@ class Impediment < Task task.safe_attributes = params task.remaining_hours = 0 if IssueStatus.find(params[:status_id]).is_closed? - #an issue relation can not be established between new nodes because their relationship can not be - #evaluated and issue relations between parent and descendant are prohibited. Therefore we need to - #save two times in a transaction - task.transaction do - task.save - task.blocks_ids = params[:blocks] - task.save + task.blocks_ids = params[:blocks] + + if task.save task.move_after params[:prev] end From 5512c6f75866e32f591c44dbf8a52e18ef6c90c8 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Tue, 29 Mar 2011 11:05:10 +0200 Subject: [PATCH 22/46] #3178: impediment spec * specing creation without a blocked issue * using shared_example_groups --- spec/models/impediment_spec.rb | 62 ++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/spec/models/impediment_spec.rb b/spec/models/impediment_spec.rb index 469f22fd76..94788535fd 100644 --- a/spec/models/impediment_spec.rb +++ b/spec/models/impediment_spec.rb @@ -43,38 +43,72 @@ describe Impediment do :task_tracker => tracker_task.id.to_s } User.current = user + issue_priority.save project.save tracker_workflow.save end describe "class methods" do describe :create_with_relationships do - describe "WITH a blocking relationship to a story" do - before(:each) do - feature.save - @impediment_subject = "Impediment A" - @impediment = Impediment.create_with_relationships({:subject => @impediment_subject, - :assigned_to_id => user.id, - :blocks => feature.id.to_s, - :status_id => issue_status1.id, - :fixed_version_id => version.id}, - user.id, - project.id) - - end + before(:each) do + @impediment_subject = "Impediment A" + end - it { @impediment.should_not be_new_record } + shared_examples_for "impediment creation" do it { @impediment.subject.should eql @impediment_subject } it { @impediment.author.should eql user } it { @impediment.project.should eql project } it { @impediment.fixed_version.should eql version } + it { @impediment.priority.should eql issue_priority} it { @impediment.status.should eql issue_status1 } it { @impediment.tracker.should eql tracker_task } it { @impediment.assigned_to.should eql user } + end + + shared_examples_for "impediment creation with 1 blocking relationship" do + it_should_behave_like "impediment creation" it { @impediment.should have(1).relations_from } it { @impediment.relations_from[0].issue_to.should eql feature } it { @impediment.relations_from[0].relation_type.should eql IssueRelation::TYPE_BLOCKS } end + + describe "WITH a blocking relationship to a story" do + describe "WITH the story having the same version" do + before(:each) do + feature.fixed_version = version + feature.save + @impediment = Impediment.create_with_relationships({:subject => @impediment_subject, + :assigned_to_id => user.id, + :blocks => feature.id.to_s, + :status_id => issue_status1.id, + :fixed_version_id => version.id}, + user.id, + project.id) + + end + + it_should_behave_like "impediment creation with 1 blocking relationship" + it { @impediment.should_not be_new_record } + it { @impediment.relations_from[0].should_not be_new_record } + end + end + + describe "WITHOUT a blocking relationship defined" do + before(:each) do + @impediment = Impediment.create_with_relationships({:subject => @impediment_subject, + :assigned_to_id => user.id, + :blocks => "", + :status_id => issue_status1.id, + :fixed_version_id => version.id}, + user.id, + project.id) + end + + it { @impediment.should be_new_record } + it_should_behave_like "impediment creation" + it { @impediment.should have(0).relations_from } + it { @impediment.errors[:blocks_ids].should eql I18n.t(:must_block_at_least_one_issue, :scope => [:activerecord, :errors, :models, :impediment, :attributes, :blocks_ids]) } + end end end From a4a04ebe016028e9ec9f60a22cccd87ac4f08e53 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Tue, 29 Mar 2011 11:20:55 +0200 Subject: [PATCH 23/46] #3178: impediment spec * specing creation of impediment, blocking a story that is not in the current sprint --- spec/models/impediment_spec.rb | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/spec/models/impediment_spec.rb b/spec/models/impediment_spec.rb index 94788535fd..521bbd4b22 100644 --- a/spec/models/impediment_spec.rb +++ b/spec/models/impediment_spec.rb @@ -16,7 +16,7 @@ describe Impediment do :author => user, :priority => issue_priority, :status => issue_status1) } - let(:version) { @version ||= Factory.create(:version, :project => project) } + let(:version) { Factory.create(:version, :project => project) } let(:project) do unless @project @@ -91,6 +91,25 @@ describe Impediment do it { @impediment.should_not be_new_record } it { @impediment.relations_from[0].should_not be_new_record } end + + describe "WITH the story having another version" do + before(:each) do + feature.fixed_version = Factory.create(:version, :project => project, :name => "another version") + feature.save + @impediment = Impediment.create_with_relationships({:subject => @impediment_subject, + :assigned_to_id => user.id, + :blocks => feature.id.to_s, + :status_id => issue_status1.id, + :fixed_version_id => version.id}, + user.id, + project.id) + end + + it_should_behave_like "impediment creation with 1 blocking relationship" + it { @impediment.should be_new_record } + it { @impediment.relations_from[0].should be_new_record } + it { @impediment.errors[:blocks_ids].should eql I18n.t(:can_only_contain_issues_of_current_sprint, :scope => [:activerecord, :errors, :models, :impediment, :attributes, :blocks_ids]) } + end end describe "WITHOUT a blocking relationship defined" do @@ -104,8 +123,8 @@ describe Impediment do project.id) end - it { @impediment.should be_new_record } it_should_behave_like "impediment creation" + it { @impediment.should be_new_record } it { @impediment.should have(0).relations_from } it { @impediment.errors[:blocks_ids].should eql I18n.t(:must_block_at_least_one_issue, :scope => [:activerecord, :errors, :models, :impediment, :attributes, :blocks_ids]) } end From a0aeb66cd88be15ee6e9e7f57ef974d6bec4505e Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Tue, 29 Mar 2011 14:54:07 +0200 Subject: [PATCH 24/46] #3178: factory for impediment --- spec/factories/impediment_factory.rb | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 spec/factories/impediment_factory.rb diff --git a/spec/factories/impediment_factory.rb b/spec/factories/impediment_factory.rb new file mode 100644 index 0000000000..7f630f48a2 --- /dev/null +++ b/spec/factories/impediment_factory.rb @@ -0,0 +1,4 @@ +Factory.define(:impediment, :parent => :issue, :class => Impediment) do |t| + t.association :tracker, :factory => :tracker_task + t.subject "Impeding progress" +end \ No newline at end of file From b6f574dad68356ee85b5502dfe80bff2a255575a Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Tue, 29 Mar 2011 14:59:58 +0200 Subject: [PATCH 25/46] #3178: refactoring impediment * blocking issue relations are only created after save of impediment * validation is carried out on blocks_ids not on real relations * blocks_ids does always have a value --- app/models/impediment.rb | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index 5b0de09585..5d2e296348 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -3,7 +3,7 @@ class Impediment < Task acts_as_list :scope => :project - before_validation :update_blocks_list, :unless => Proc.new { |i| i.blocks_ids.nil? } + after_save :update_blocks_list def self.create_with_relationships(params, user_id, project_id) task = new @@ -49,7 +49,7 @@ class Impediment < Task end def blocks_ids - @blocks_ids_list + @blocks_ids_list ||= relations_from.select{ |rel| rel.relation_type == IssueRelation::TYPE_BLOCKS } end def update_with_relationships(params) @@ -96,22 +96,20 @@ class Impediment < Task private def update_blocks_list - # Existing relationships not in for_blocking should be removed from the 'blocks' list relations_from = [] if relations_from.nil? remove_from_blocks_list add_to_blocks_list end def remove_from_blocks_list - self.relations_from = self.relations_from.reject{|rel| rel.relation_type == IssueRelation::TYPE_BLOCKS && !blocks_ids.include?(rel.issue_to_id) } + self.relations_from.delete(self.relations_from.select{|rel| rel.relation_type == IssueRelation::TYPE_BLOCKS && !blocks_ids.include?(rel.issue_to_id) }) end def add_to_blocks_list currently_blocking = relations_from.select{|rel| rel.relation_type == IssueRelation::TYPE_BLOCKS}.collect(&:issue_to_id) (self.blocks_ids - currently_blocking).each{ |id| - rel = IssueRelation.new(:relation_type => IssueRelation::TYPE_BLOCKS, :issue_to => Issue.find(id), :issue_from => self) - self.relations_from << rel + self.relations_from.create(:relation_type => IssueRelation::TYPE_BLOCKS, :issue_to => Issue.find(id), :issue_from => self) } end @@ -120,7 +118,7 @@ class Impediment < Task end def validate_blocks_list - errors.add :blocks_ids, :must_block_at_least_one_issue if relations_from.size == 0 - errors.add :blocks_ids, :can_only_contain_issues_of_current_sprint if relations_from.any?{|rel| rel.relation_type == IssueRelation::TYPE_BLOCKS && rel.issue_to.fixed_version != self.fixed_version } + errors.add :blocks_ids, :must_block_at_least_one_issue if blocks_ids.size == 0 + errors.add :blocks_ids, :can_only_contain_issues_of_current_sprint if Issue.find(blocks_ids).any?{|i| i.fixed_version != self.fixed_version } end end \ No newline at end of file From f389dfd97803356711cc3ab1d053c32f90f5af0a Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Tue, 29 Mar 2011 15:03:06 +0200 Subject: [PATCH 26/46] #3178: impediment specs for update_with_relationships * with a valid new story * with a story that is not in the same version * with no blocking relationship --- spec/models/impediment_spec.rb | 114 ++++++++++++++++++++++++++++++--- 1 file changed, 106 insertions(+), 8 deletions(-) diff --git a/spec/models/impediment_spec.rb b/spec/models/impediment_spec.rb index 521bbd4b22..b8595a6246 100644 --- a/spec/models/impediment_spec.rb +++ b/spec/models/impediment_spec.rb @@ -7,10 +7,10 @@ describe Impediment do let(:tracker_task) { @tracker_task ||= Factory.create(:tracker_task) } let(:issue_priority) { @issue_priority ||= Factory.create(:priority, :is_default => true) } let(:task) { Factory.build(:task, :tracker => tracker_task, - :project => project, - :author => user, - :priority => issue_priority, - :status => issue_status1) } + :project => project, + :author => user, + :priority => issue_priority, + :status => issue_status1) } let(:feature) { Factory.build(:issue, :tracker => tracker_feature, :project => project, :author => user, @@ -44,6 +44,7 @@ describe Impediment do User.current = user issue_priority.save + issue_status1.save project.save tracker_workflow.save end @@ -72,6 +73,11 @@ describe Impediment do it { @impediment.relations_from[0].relation_type.should eql IssueRelation::TYPE_BLOCKS } end + shared_examples_for "impediment creation with no blocking relationship" do + it_should_behave_like "impediment creation" + it { @impediment.should have(0).relations_from } + end + describe "WITH a blocking relationship to a story" do describe "WITH the story having the same version" do before(:each) do @@ -105,9 +111,8 @@ describe Impediment do project.id) end - it_should_behave_like "impediment creation with 1 blocking relationship" + it_should_behave_like "impediment creation with no blocking relationship" it { @impediment.should be_new_record } - it { @impediment.relations_from[0].should be_new_record } it { @impediment.errors[:blocks_ids].should eql I18n.t(:can_only_contain_issues_of_current_sprint, :scope => [:activerecord, :errors, :models, :impediment, :attributes, :blocks_ids]) } end end @@ -123,12 +128,105 @@ describe Impediment do project.id) end - it_should_behave_like "impediment creation" + it_should_behave_like "impediment creation with no blocking relationship" it { @impediment.should be_new_record } - it { @impediment.should have(0).relations_from } it { @impediment.errors[:blocks_ids].should eql I18n.t(:must_block_at_least_one_issue, :scope => [:activerecord, :errors, :models, :impediment, :attributes, :blocks_ids]) } end end end + describe "instance methods" do + describe :update_with_relationships do + before(:each) do + feature.fixed_version = version + feature.save + @impediment = Factory.create(:impediment, + :author => user, + :fixed_version => version, + :assigned_to => user, + :priority => issue_priority, + :project => project, + :tracker => tracker_task, + :status => issue_status1, + :blocks_ids => feature.id.to_s) + @impediment.save + end + + shared_examples_for "impediment update" do + it { @impediment.author.should eql user } + it { @impediment.project.should eql project } + it { @impediment.fixed_version.should eql version } + it { @impediment.priority.should eql issue_priority} + it { @impediment.status.should eql issue_status1 } + it { @impediment.tracker.should eql tracker_task } + it { @impediment.blocks_ids.should eql @blocks.split(/\D+/).map{|id| id.to_i} } + end + + shared_examples_for "impediment update with changed blocking relationship" do + it_should_behave_like "impediment update" + it { @impediment.should have(1).relations_from } + it { @impediment.relations_from[0].should_not be_new_record } + it { @impediment.relations_from[0].issue_to.should eql @story } + it { @impediment.relations_from[0].relation_type.should eql IssueRelation::TYPE_BLOCKS } + end + + shared_examples_for "impediment update with unchanged blocking relationship" do + it_should_behave_like "impediment update" + it { @impediment.should have(1).relations_from } + it { @impediment.relations_from[0].should_not be_changed } + it { @impediment.relations_from[0].issue_to.should eql feature } + it { @impediment.relations_from[0].relation_type.should eql IssueRelation::TYPE_BLOCKS } + end + + describe "WHEN changing the blocking relationship to another story" do + before(:each) do + @story = Factory.build(:issue, :subject => "another story", + :tracker => tracker_feature, + :project => project, + :author => user, + :priority => issue_priority, + :status => issue_status1) + end + + describe "WITH the story having the same version" do + before(:each) do + @story.fixed_version = version + @story.save + @blocks = @story.id.to_s + @impediment.update_with_relationships({:blocks => @blocks, + :status_id => issue_status1.id.to_s}) + end + + it_should_behave_like "impediment update with changed blocking relationship" + it { @impediment.should_not be_changed } + end + + describe "WITH the story having another version" do + before(:each) do + @story.fixed_version = Factory.create(:version, :project => project, :name => "another version") + @story.save + @blocks = @story.id.to_s + @impediment.update_with_relationships({:blocks => @blocks, + :status_id => issue_status1.id.to_s}) + end + + it_should_behave_like "impediment update with unchanged blocking relationship" + it { @impediment.should be_changed } + it { @impediment.errors[:blocks_ids].should eql I18n.t(:can_only_contain_issues_of_current_sprint, :scope => [:activerecord, :errors, :models, :impediment, :attributes, :blocks_ids]) } + end + end + + describe "WITHOUT a blocking relationship defined" do + before(:each) do + @blocks = "" + @impediment.update_with_relationships({:blocks => @blocks, + :status_id => issue_status1.id.to_s}) + end + + it_should_behave_like "impediment update with unchanged blocking relationship" + it { @impediment.should be_changed } + it { @impediment.errors[:blocks_ids].should eql I18n.t(:must_block_at_least_one_issue, :scope => [:activerecord, :errors, :models, :impediment, :attributes, :blocks_ids]) } + end + end + end end \ No newline at end of file From f664e8550310c7221c535344c5216d6ecbcce56e Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Tue, 29 Mar 2011 15:30:00 +0200 Subject: [PATCH 27/46] #3178: impediment spec blocks_ids * array/string/integer --- spec/models/impediment_spec.rb | 41 ++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/spec/models/impediment_spec.rb b/spec/models/impediment_spec.rb index b8595a6246..d31fb28793 100644 --- a/spec/models/impediment_spec.rb +++ b/spec/models/impediment_spec.rb @@ -34,6 +34,14 @@ describe Impediment do :old_status => issue_status1, :new_status => issue_status2, :role => role) } + let(:impediment) { Factory.build(:impediment, :author => user, + :fixed_version => version, + :assigned_to => user, + :priority => issue_priority, + :project => project, + :tracker => tracker_task, + :status => issue_status1, + :blocks_ids => feature.id.to_s)} before(:each) do Setting.plugin_redmine_backlogs = {:points_burn_direction => "down", @@ -140,15 +148,7 @@ describe Impediment do before(:each) do feature.fixed_version = version feature.save - @impediment = Factory.create(:impediment, - :author => user, - :fixed_version => version, - :assigned_to => user, - :priority => issue_priority, - :project => project, - :tracker => tracker_task, - :status => issue_status1, - :blocks_ids => feature.id.to_s) + @impediment = impediment @impediment.save end @@ -228,5 +228,28 @@ describe Impediment do it { @impediment.errors[:blocks_ids].should eql I18n.t(:must_block_at_least_one_issue, :scope => [:activerecord, :errors, :models, :impediment, :attributes, :blocks_ids]) } end end + + describe "blocks_ids=/blocks_ids" do + describe "WITH an integer" do + it do + impediment.blocks_ids = 2 + impediment.blocks_ids.should eql [2] + end + end + + describe "WITH a string" do + it do + impediment.blocks_ids = "1, 2, 3" + impediment.blocks_ids.should eql [1,2,3] + end + end + + describe "WITH an array" do + it do + impediment.blocks_ids = [1,2,3] + impediment.blocks_ids.should eql [1,2,3] + end + end + end end end \ No newline at end of file From cb8f343439bb3b68cf9cf2e856e6a89ef181968a Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Tue, 29 Mar 2011 15:39:58 +0200 Subject: [PATCH 28/46] #3178: cleaning up task model, removed impediment creation and updating because this is now handled by impediment class --- app/models/task.rb | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/app/models/task.rb b/app/models/task.rb index fa6c4e79ba..47743ec014 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -8,7 +8,7 @@ class Task < Issue task_tracker.blank? ? nil : task_tracker.to_i end - def self.create_with_relationships(params, user_id, project_id, is_impediment = false) + def self.create_with_relationships(params, user_id, project_id) task = new task.author_id = user_id @@ -18,15 +18,8 @@ class Task < Issue task.safe_attributes = params task.remaining_hours = 0 if IssueStatus.find(params[:status_id]).is_closed? - valid_relationships = if is_impediment - task.validate_blocks_list(params[:blocks]) - else - true - end - - if valid_relationships && task.save + if task.save task.move_after params[:prev] - task.update_blocked_list params[:blocks].split(/\D+/) if params[:blocks] end return task @@ -59,12 +52,11 @@ class Task < Issue attribs[:remaining_hours] = 0 if IssueStatus.find(params[:status_id]).is_closed? - if result = journalized_update_attributes!(attribs) - move_after params[:prev] - result - else - false - end + result = journalized_update_attributes!(attribs) + + move_after params[:prev] if result + + result end # assumes the task is already under the same story as 'id' From bf3430004d750ff50ccf7dd209c7bce8f0b6e421 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Tue, 29 Mar 2011 20:35:15 +0200 Subject: [PATCH 29/46] #3178: blocks_ids will be ids of issues with which a blocking relation is defined until new ids are provided --- app/models/impediment.rb | 6 ++---- spec/models/impediment_spec.rb | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index 5d2e296348..1a6f040233 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -49,16 +49,14 @@ class Impediment < Task end def blocks_ids - @blocks_ids_list ||= relations_from.select{ |rel| rel.relation_type == IssueRelation::TYPE_BLOCKS } + @blocks_ids_list ||= relations_from.select{ |rel| rel.relation_type == IssueRelation::TYPE_BLOCKS }.collect(&:issue_to_id) end def update_with_relationships(params) - attribs = params.clone.delete_if { |k, v| !safe_attribute_names.include?(k) } + attribs = params.reject { |k, v| !safe_attribute_names.include?(k.to_s) } attribs[:remaining_hours] = 0 if IssueStatus.find(params[:status_id]).is_closed? - attribs[:blocks_ids] = params[:blocks] if params[:blocks] #if blocks param was not sent, that means the impediment was just dragged - result = journalized_update_attributes(attribs) move_after params[:prev] if result diff --git a/spec/models/impediment_spec.rb b/spec/models/impediment_spec.rb index d31fb28793..902281dc6c 100644 --- a/spec/models/impediment_spec.rb +++ b/spec/models/impediment_spec.rb @@ -250,6 +250,21 @@ describe Impediment do impediment.blocks_ids.should eql [1,2,3] end end + + describe "WITH only prior blockers defined" do + before(:each) do + feature.fixed_version = version + feature.save + task.fixed_version = version + task.save + + impediment.relations_from = [IssueRelation.new(:issue_from => impediment, :issue_to => feature, :relation_type => IssueRelation::TYPE_BLOCKS), + IssueRelation.new(:issue_from => impediment, :issue_to => task, :relation_type => IssueRelation::TYPE_BLOCKS)] + true + end + + it { impediment.blocks_ids.should eql [feature.id, task.id] } + end end end end \ No newline at end of file From a21e3b5a68a859821409c5341e4a747ecdfdd798 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Tue, 29 Mar 2011 22:58:55 +0200 Subject: [PATCH 30/46] #3178: including permissions for create_ and update_with_relationship --- app/models/impediment.rb | 13 +++++++++++-- spec/models/impediment_spec.rb | 12 +++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index 1a6f040233..1dbd1046ff 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -5,8 +5,15 @@ class Impediment < Task after_save :update_blocks_list + safe_attributes "blocks", #change to blocks_ids once ui can be manipulated + :if => lambda {|impediment, user| + (impediment.new_record? && user.allowed_to?(:create_impediments, impediment.project)) || + user.allowed_to?(:update_impediments, impediment.project) + } + def self.create_with_relationships(params, user_id, project_id) task = new + task.author_id = user_id task.project_id = project_id task.tracker_id = Task.tracker @@ -14,8 +21,6 @@ class Impediment < Task task.safe_attributes = params task.remaining_hours = 0 if IssueStatus.find(params[:status_id]).is_closed? - task.blocks_ids = params[:blocks] - if task.save task.move_after params[:prev] end @@ -42,6 +47,10 @@ class Impediment < Task super(since, project_id, true) end + def blocks=(ids) + self.blocks_ids = ids + end + def blocks_ids=(ids) @blocks_ids_list = [ids] if ids.is_a?(Integer) @blocks_ids_list = ids.split(/\D+/).map{|id| id.to_i} if ids.is_a?(String) diff --git a/spec/models/impediment_spec.rb b/spec/models/impediment_spec.rb index 902281dc6c..5c0f8f5bdd 100644 --- a/spec/models/impediment_spec.rb +++ b/spec/models/impediment_spec.rb @@ -2,7 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe Impediment do let(:user) { @user ||= Factory.create(:user) } - let(:role) { @role ||= Factory.create(:role, :permissions => [:edit_issues]) } + let(:role) { @role ||= Factory.create(:role) } let(:tracker_feature) { @tracker_feature ||= Factory.create(:tracker_feature) } let(:tracker_task) { @tracker_task ||= Factory.create(:tracker_task) } let(:issue_priority) { @issue_priority ||= Factory.create(:priority, :is_default => true) } @@ -40,8 +40,7 @@ describe Impediment do :priority => issue_priority, :project => project, :tracker => tracker_task, - :status => issue_status1, - :blocks_ids => feature.id.to_s)} + :status => issue_status1)} before(:each) do Setting.plugin_redmine_backlogs = {:points_burn_direction => "down", @@ -61,6 +60,8 @@ describe Impediment do describe :create_with_relationships do before(:each) do @impediment_subject = "Impediment A" + role.permissions = [:create_impediments] + role.save end shared_examples_for "impediment creation" do @@ -146,9 +147,14 @@ describe Impediment do describe "instance methods" do describe :update_with_relationships do before(:each) do + role.permissions = [:update_impediments] + role.save + feature.fixed_version = version feature.save + @impediment = impediment + @impediment.blocks_ids = feature.id.to_s @impediment.save end From 2ef65cc407680b305d29e4876ab3f5d12235f0b6 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Wed, 30 Mar 2011 08:18:41 +0200 Subject: [PATCH 31/46] #3178: removing create_with_relationship from impediment class - method is inherited from task. Signature of create_with_relationship looses user.id - User.current is always the author --- app/controllers/rb_impediments_controller.rb | 2 +- app/controllers/rb_tasks_controller.rb | 2 +- app/models/impediment.rb | 17 ----------------- app/models/task.rb | 4 ++-- features/step_definitions/_given_steps.rb | 8 ++++---- spec/models/impediment_spec.rb | 5 +---- 6 files changed, 9 insertions(+), 29 deletions(-) diff --git a/app/controllers/rb_impediments_controller.rb b/app/controllers/rb_impediments_controller.rb index c9cf551fbe..6819b2fb9f 100644 --- a/app/controllers/rb_impediments_controller.rb +++ b/app/controllers/rb_impediments_controller.rb @@ -2,7 +2,7 @@ class RbImpedimentsController < RbApplicationController unloadable def create - @impediment = Impediment.create_with_relationships(params, User.current.id, @project.id) + @impediment = Impediment.create_with_relationships(params, @project.id) result = @impediment.errors.length status = (result == 0 ? 200 : 400) @include_meta = true diff --git a/app/controllers/rb_tasks_controller.rb b/app/controllers/rb_tasks_controller.rb index 36eb28a52e..64ab19ebab 100644 --- a/app/controllers/rb_tasks_controller.rb +++ b/app/controllers/rb_tasks_controller.rb @@ -2,7 +2,7 @@ class RbTasksController < RbApplicationController unloadable def create - @task = Task.create_with_relationships(params, User.current.id, @project.id) + @task = Task.create_with_relationships(params, @project.id) result = @task.errors.length status = (result == 0 ? 200 : 400) @include_meta = true diff --git a/app/models/impediment.rb b/app/models/impediment.rb index 1dbd1046ff..5a15c22e32 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -11,23 +11,6 @@ class Impediment < Task user.allowed_to?(:update_impediments, impediment.project) } - def self.create_with_relationships(params, user_id, project_id) - task = new - - task.author_id = user_id - task.project_id = project_id - task.tracker_id = Task.tracker - - task.safe_attributes = params - task.remaining_hours = 0 if IssueStatus.find(params[:status_id]).is_closed? - - if task.save - task.move_after params[:prev] - end - - return task - end - def self.find(*args) if args[1] && args[1][:conditions] if args[1][:conditions].is_a?(Hash) diff --git a/app/models/task.rb b/app/models/task.rb index 47743ec014..1528dd62de 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -8,10 +8,10 @@ class Task < Issue task_tracker.blank? ? nil : task_tracker.to_i end - def self.create_with_relationships(params, user_id, project_id) + def self.create_with_relationships(params, project_id) task = new - task.author_id = user_id + task.author = User.current task.project_id = project_id task.tracker_id = Task.tracker diff --git a/features/step_definitions/_given_steps.rb b/features/step_definitions/_given_steps.rb index 979619508b..42225331fa 100644 --- a/features/step_definitions/_given_steps.rb +++ b/features/step_definitions/_given_steps.rb @@ -150,7 +150,7 @@ end Given /^the [pP]roject(?: "([^\"]*)")? has the following tasks:$/ do |project_name, table| project = get_project(project_name) - author = User.find(:first) + User.current = User.find(:first) table.hashes.each do |task| story = Story.find(:first, :conditions => { :subject => task['parent'] }) @@ -160,14 +160,14 @@ Given /^the [pP]roject(?: "([^\"]*)")? has the following tasks:$/ do |project_na # NOTE: We're bypassing the controller here because we're just # setting up the database for the actual tests. The actual tests, # however, should NOT bypass the controller - Task.create_with_relationships(params, author, project.id) + Task.create_with_relationships(params, project.id) end end Given /^the [pP]roject(?: "([^\"]*)")? has the following impediments:$/ do |project_name, table| project = get_project(project_name) - author = User.find(:first) + User.current = User.find(:first) table.hashes.each do |impediment| sprint = Sprint.find(:first, :conditions => { :name => impediment['sprint'] }) @@ -179,7 +179,7 @@ Given /^the [pP]roject(?: "([^\"]*)")? has the following impediments:$/ do |proj # NOTE: We're bypassing the controller here because we're just # setting up the database for the actual tests. The actual tests, # however, should NOT bypass the controller - Impediment.create_with_relationships(params, author.id, project.id) + Impediment.create_with_relationships(params, project.id) end end diff --git a/spec/models/impediment_spec.rb b/spec/models/impediment_spec.rb index 5c0f8f5bdd..e2b5c9c480 100644 --- a/spec/models/impediment_spec.rb +++ b/spec/models/impediment_spec.rb @@ -66,7 +66,7 @@ describe Impediment do shared_examples_for "impediment creation" do it { @impediment.subject.should eql @impediment_subject } - it { @impediment.author.should eql user } + it { @impediment.author.should eql User.current } it { @impediment.project.should eql project } it { @impediment.fixed_version.should eql version } it { @impediment.priority.should eql issue_priority} @@ -97,7 +97,6 @@ describe Impediment do :blocks => feature.id.to_s, :status_id => issue_status1.id, :fixed_version_id => version.id}, - user.id, project.id) end @@ -116,7 +115,6 @@ describe Impediment do :blocks => feature.id.to_s, :status_id => issue_status1.id, :fixed_version_id => version.id}, - user.id, project.id) end @@ -133,7 +131,6 @@ describe Impediment do :blocks => "", :status_id => issue_status1.id, :fixed_version_id => version.id}, - user.id, project.id) end From 38d25f8355667c11bebc907819395717e47b34d4 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Wed, 30 Mar 2011 08:21:00 +0200 Subject: [PATCH 32/46] #3178: time_remaining is always set to 0 if status is a closing one --- app/models/task.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/models/task.rb b/app/models/task.rb index 1528dd62de..268e00ac2d 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -16,7 +16,6 @@ class Task < Issue task.tracker_id = Task.tracker task.safe_attributes = params - task.remaining_hours = 0 if IssueStatus.find(params[:status_id]).is_closed? if task.save task.move_after params[:prev] @@ -43,6 +42,11 @@ class Task < Issue return tasks end + def status_id=(id) + super + task.remaining_hours = 0 if IssueStatus.find(id).is_closed? + end + def impediment? parent_issue_id.nil? end @@ -50,7 +54,6 @@ class Task < Issue def update_with_relationships(params, is_impediment = false) attribs = params.clone.delete_if { |k, v| !safe_attribute_names.include?(k) } - attribs[:remaining_hours] = 0 if IssueStatus.find(params[:status_id]).is_closed? result = journalized_update_attributes!(attribs) From ca51ba6a08e8af8de2e134744c2f13c0fe72fb1f Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Wed, 30 Mar 2011 08:21:21 +0200 Subject: [PATCH 33/46] #3178: refactoring task --- app/models/task.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/models/task.rb b/app/models/task.rb index 268e00ac2d..799d06d98e 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -52,8 +52,7 @@ class Task < Issue end def update_with_relationships(params, is_impediment = false) - attribs = params.clone.delete_if { |k, v| !safe_attribute_names.include?(k) } - + attribs = params.reject { |k, v| !safe_attribute_names.include?(k.to_s) } result = journalized_update_attributes!(attribs) From 02f64ae3add01359334e57258843aad2389e5c72 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Wed, 30 Mar 2011 08:22:03 +0200 Subject: [PATCH 34/46] #3178: impediments are displayed in the order in which the user sorted them even after a reload --- app/views/rb_taskboards/show.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/rb_taskboards/show.html.erb b/app/views/rb_taskboards/show.html.erb index 03ee68d027..d460d065c8 100644 --- a/app/views/rb_taskboards/show.html.erb +++ b/app/views/rb_taskboards/show.html.erb @@ -56,7 +56,7 @@ <% @statuses.each do |status| %> <%= render :partial => "rb_impediments/impediment", - :collection => @sprint.impediments.select { |impediment| impediment.status_id == status.id } %> + :collection => @sprint.impediments.select{ |i| i.status_id == status.id }.sort_by {|i| i.position } %> <% end %> From a98879078aee710982796dbd0fccb3c6b34a18d6 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Wed, 30 Mar 2011 08:49:53 +0200 Subject: [PATCH 35/46] #3178: fixing bug in task when story_id is set, removing explicitly setting required_time to 0 in impediment update method as this is handled by status_id= --- app/models/impediment.rb | 2 -- app/models/task.rb | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index 5a15c22e32..354e6b33b9 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -47,8 +47,6 @@ class Impediment < Task def update_with_relationships(params) attribs = params.reject { |k, v| !safe_attribute_names.include?(k.to_s) } - attribs[:remaining_hours] = 0 if IssueStatus.find(params[:status_id]).is_closed? - result = journalized_update_attributes(attribs) move_after params[:prev] if result diff --git a/app/models/task.rb b/app/models/task.rb index 799d06d98e..ddbd7896c5 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -44,7 +44,7 @@ class Task < Issue def status_id=(id) super - task.remaining_hours = 0 if IssueStatus.find(id).is_closed? + self.remaining_hours = 0 if IssueStatus.find(id).is_closed? end def impediment? From b8ac770c564095892c7e5580e12c724dcbb8574e Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Wed, 30 Mar 2011 08:51:10 +0200 Subject: [PATCH 36/46] #3178: add TODO comment to move move_after method that is using acts_as_list in story and impediment into a module --- app/models/impediment.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index 354e6b33b9..4eb10fbd88 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -55,6 +55,11 @@ class Impediment < Task end def move_after(prev_id) + #our super's, move after is using awesome_nested_set which is inapproriate for impediments. + #Impediments always have a parent_id of nil, it is their defining criteria. + #Therefore we use the acts_as_list method + #TODO: create a module to be included by story and impediment, for now this code is just copy&paste + # remove so the potential 'prev' has a correct position remove_from_list From 0815343b316703c32fbd93ea78cce27e40a1caf9 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Wed, 30 Mar 2011 09:00:45 +0200 Subject: [PATCH 37/46] #3178: removing update_with_relationships from impediment class, using supers (Task). Also removing exception throwing from task.update_with_relationships --- app/models/impediment.rb | 10 ---------- app/models/task.rb | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index 4eb10fbd88..1a6565f221 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -44,16 +44,6 @@ class Impediment < Task @blocks_ids_list ||= relations_from.select{ |rel| rel.relation_type == IssueRelation::TYPE_BLOCKS }.collect(&:issue_to_id) end - def update_with_relationships(params) - attribs = params.reject { |k, v| !safe_attribute_names.include?(k.to_s) } - - result = journalized_update_attributes(attribs) - - move_after params[:prev] if result - - result - end - def move_after(prev_id) #our super's, move after is using awesome_nested_set which is inapproriate for impediments. #Impediments always have a parent_id of nil, it is their defining criteria. diff --git a/app/models/task.rb b/app/models/task.rb index ddbd7896c5..6e31de4772 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -54,7 +54,7 @@ class Task < Issue def update_with_relationships(params, is_impediment = false) attribs = params.reject { |k, v| !safe_attribute_names.include?(k.to_s) } - result = journalized_update_attributes!(attribs) + result = journalized_update_attributes(attribs) move_after params[:prev] if result From e619bfb20b7e741cc1c77c214ac7b38f5b115ac4 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Wed, 30 Mar 2011 09:14:54 +0200 Subject: [PATCH 38/46] #3178: using blocks_ids instead of blocks in impediment management, hence removing overhead --- app/helpers/rb_common_helper.rb | 4 ++-- app/models/impediment.rb | 6 +----- app/views/rb_impediments/_impediment.html.erb | 2 +- app/views/rb_taskboards/show.html.erb | 2 +- spec/models/impediment_spec.rb | 12 ++++++------ 5 files changed, 11 insertions(+), 15 deletions(-) diff --git a/app/helpers/rb_common_helper.rb b/app/helpers/rb_common_helper.rb index 7c110b7240..f9d125a92f 100644 --- a/app/helpers/rb_common_helper.rb +++ b/app/helpers/rb_common_helper.rb @@ -9,8 +9,8 @@ module RbCommonHelper story.blank? || story.assigned_to.blank? ? "" : "#{story.assigned_to.firstname} #{story.assigned_to.lastname}" end - def blocked_ids(blocked) - blocked.map{|b| b.id }.join(',') + def blocks_ids(ids) + ids.sort.join(',') end def build_inline_style(task) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index 1a6565f221..2cac71f7d3 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -5,7 +5,7 @@ class Impediment < Task after_save :update_blocks_list - safe_attributes "blocks", #change to blocks_ids once ui can be manipulated + safe_attributes "blocks_ids", :if => lambda {|impediment, user| (impediment.new_record? && user.allowed_to?(:create_impediments, impediment.project)) || user.allowed_to?(:update_impediments, impediment.project) @@ -30,10 +30,6 @@ class Impediment < Task super(since, project_id, true) end - def blocks=(ids) - self.blocks_ids = ids - end - def blocks_ids=(ids) @blocks_ids_list = [ids] if ids.is_a?(Integer) @blocks_ids_list = ids.split(/\D+/).map{|id| id.to_i} if ids.is_a?(String) diff --git a/app/views/rb_impediments/_impediment.html.erb b/app/views/rb_impediments/_impediment.html.erb index 440b262d72..7cad6ff927 100644 --- a/app/views/rb_impediments/_impediment.html.erb +++ b/app/views/rb_impediments/_impediment.html.erb @@ -4,7 +4,7 @@
<%= id_or_empty(impediment) %>
<%= impediment.subject %>
-
<%= blocked_ids(impediment.blocks) %>
+
<%= blocks_ids(impediment.blocks_ids) %>
<%= assignee_name_or_empty(impediment) %>
<%= assignee_id_or_empty(impediment) %>
diff --git a/app/views/rb_taskboards/show.html.erb b/app/views/rb_taskboards/show.html.erb index d460d065c8..dc0b1c8497 100644 --- a/app/views/rb_taskboards/show.html.erb +++ b/app/views/rb_taskboards/show.html.erb @@ -98,7 +98,7 @@ <%= render :partial => "rb_tasks/task", :object => Task.new %>
- <%= render :partial => "rb_impediments/impediment", :object => Task.new %> + <%= render :partial => "rb_impediments/impediment", :object => Impediment.new %>
diff --git a/spec/models/impediment_spec.rb b/spec/models/impediment_spec.rb index e2b5c9c480..6fdc7d29ce 100644 --- a/spec/models/impediment_spec.rb +++ b/spec/models/impediment_spec.rb @@ -94,7 +94,7 @@ describe Impediment do feature.save @impediment = Impediment.create_with_relationships({:subject => @impediment_subject, :assigned_to_id => user.id, - :blocks => feature.id.to_s, + :blocks_ids => feature.id.to_s, :status_id => issue_status1.id, :fixed_version_id => version.id}, project.id) @@ -112,7 +112,7 @@ describe Impediment do feature.save @impediment = Impediment.create_with_relationships({:subject => @impediment_subject, :assigned_to_id => user.id, - :blocks => feature.id.to_s, + :blocks_ids => feature.id.to_s, :status_id => issue_status1.id, :fixed_version_id => version.id}, project.id) @@ -128,7 +128,7 @@ describe Impediment do before(:each) do @impediment = Impediment.create_with_relationships({:subject => @impediment_subject, :assigned_to_id => user.id, - :blocks => "", + :blocks_ids => "", :status_id => issue_status1.id, :fixed_version_id => version.id}, project.id) @@ -196,7 +196,7 @@ describe Impediment do @story.fixed_version = version @story.save @blocks = @story.id.to_s - @impediment.update_with_relationships({:blocks => @blocks, + @impediment.update_with_relationships({:blocks_ids => @blocks, :status_id => issue_status1.id.to_s}) end @@ -209,7 +209,7 @@ describe Impediment do @story.fixed_version = Factory.create(:version, :project => project, :name => "another version") @story.save @blocks = @story.id.to_s - @impediment.update_with_relationships({:blocks => @blocks, + @impediment.update_with_relationships({:blocks_ids => @blocks, :status_id => issue_status1.id.to_s}) end @@ -222,7 +222,7 @@ describe Impediment do describe "WITHOUT a blocking relationship defined" do before(:each) do @blocks = "" - @impediment.update_with_relationships({:blocks => @blocks, + @impediment.update_with_relationships({:blocks_ids => @blocks, :status_id => issue_status1.id.to_s}) end From 1586bd89e13ad459b2229525d730cfcddeb1b2b6 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Thu, 31 Mar 2011 12:16:12 +0200 Subject: [PATCH 39/46] #3178: remove patching of ancestor_of and descendant_of because the issue_relations are now created after the impediment has been saved --- lib/backlogs_issue_patch.rb | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/lib/backlogs_issue_patch.rb b/lib/backlogs_issue_patch.rb index acbe9064bd..74f2cbb151 100644 --- a/lib/backlogs_issue_patch.rb +++ b/lib/backlogs_issue_patch.rb @@ -11,8 +11,6 @@ module Backlogs alias_method_chain :move_to_project_without_transaction, :autolink alias_method_chain :recalculate_attributes_for, :remaining_hours - alias_method_chain :is_descendant_of?, :new_record - alias_method_chain :is_ancestor_of?, :new_record before_validation :backlogs_before_validation after_save :backlogs_after_save end @@ -58,22 +56,6 @@ module Backlogs return (self.parent_id && self.tracker_id == Task.tracker) end - def is_descendant_of_with_new_record?(other) - if self.new_record? - self.parent && (self.parent == other || self.parent.is_decendant_of?(other)) - else - is_descendant_of_without_new_record?(other) - end - end - - def is_ancestor_of_with_new_record?(other) - if self.new_record? - false - else - is_ancestor_of_without_new_record?(other) - end - end - def story if self.is_story? return self From b3f9cd0d65bd894a52b63129676d2baf73ac0b3f Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Thu, 31 Mar 2011 12:17:20 +0200 Subject: [PATCH 40/46] #3178: using id instead of object to create new IssueRelations for an Impediment --- app/models/impediment.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index 2cac71f7d3..68858c5c57 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -88,7 +88,9 @@ class Impediment < Task currently_blocking = relations_from.select{|rel| rel.relation_type == IssueRelation::TYPE_BLOCKS}.collect(&:issue_to_id) (self.blocks_ids - currently_blocking).each{ |id| - self.relations_from.create(:relation_type => IssueRelation::TYPE_BLOCKS, :issue_to => Issue.find(id), :issue_from => self) + rel = IssueRelation.new(:relation_type => IssueRelation::TYPE_BLOCKS, :issue_from => self) + rel.issue_to_id = id #attr_protected + self.relations_from << rel } end From e086d08a7474b5d1f9fd5b8fdd31f51b55c75dd0 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Thu, 31 Mar 2011 12:18:26 +0200 Subject: [PATCH 41/46] #3178: Using Impediment class to find_all_updated_since in the updated_items_controller --- app/controllers/rb_updated_items_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/rb_updated_items_controller.rb b/app/controllers/rb_updated_items_controller.rb index 6650603452..cf0a369fbe 100644 --- a/app/controllers/rb_updated_items_controller.rb +++ b/app/controllers/rb_updated_items_controller.rb @@ -26,7 +26,7 @@ class RbUpdatedItemsController < RbApplicationController end if only.include? :impediments - @items[:impediments] = Task.find_all_updated_since(params[:since], @project.id, true) + @items[:impediments] = Impediment.find_all_updated_since(params[:since], @project.id) if @items[:impediments].length > 0 latest_updates << @items[:impediments].sort{ |a,b| a.updated_on <=> b.updated_on }.last end From 54c74499ce2cf94f11b003fb8f5285277082b08e Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Thu, 31 Mar 2011 12:19:30 +0200 Subject: [PATCH 42/46] #3178: cucumber tests for creating impediments, also contains step definitions needed for testing --- features/scrum_master.feature | 60 +++++++++++++++++++---- features/step_definitions/_given_steps.rb | 11 +++-- features/step_definitions/_then_steps.rb | 20 ++++++++ features/step_definitions/_when_steps.rb | 7 +++ 4 files changed, 86 insertions(+), 12 deletions(-) diff --git a/features/scrum_master.feature b/features/scrum_master.feature index badd803e28..5bca70a2af 100644 --- a/features/scrum_master.feature +++ b/features/scrum_master.feature @@ -1,7 +1,7 @@ Feature: Scrum Master As a scrum master I want to manage sprints and their stories - So that they get done according the product owner's requirements + So that they get done according the product owner´s requirements Background: Given there is 1 project with: @@ -26,6 +26,8 @@ Feature: Scrum Master | manage_subtasks | And there is 1 user with: | login | markus | + | firstname | Markus | + | Lastname | Master | And the user "markus" is a "scrum master" And the project has the following sprints: | name | sprint_start_date | effective_date | @@ -46,19 +48,59 @@ Feature: Scrum Master | position | subject | sprint | | 5 | Story A | Sprint 001 | | 6 | Story B | Sprint 001 | + | 7 | Story C | Sprint 002 | + And there are the following trackers: + | name | + | Task | + And the tracker "Task" is configured to track tasks + And there are the following issue status: + | name | is_closed | is_default | + | New | false | true | + | In Progress | false | false | + | Resolved | false | false | + | Closed | true | false | + | Rejected | true | false | + And the tracker "Task" has the default workflow for the role "scrum master" + And the project has the following tasks: + | subject | sprint | parent | + | Task 1 | Sprint 001 | Story A | And the project has the following impediments: - | subject | sprint | blocks | - | Impediment 1 | Sprint 001 | Story A | + | subject | sprint | blocks | + | Impediment 1 | Sprint 001 | Story A | And I am logged in as "markus" + @javascript + Scenario: Create an impediment blocking a non existent issue + Given I am on the taskboard for "Sprint 001" + When I press "td.add_new" within "#impediments" + And I fill in "Bad Company" for "subject" + And I fill in "1918817726612" for "blocks_ids" + And I select "Markus Master" from "assigned_to_id" + And I press "OK" + Then I should see "Bad Company" within "#impediments" + And the impediment "Bad Company" should signal unsuccessful saving + + @javascript Scenario: Create an impediment Given I am on the taskboard for "Sprint 001" - And I want to create an impediment for Sprint 001 - And I want to set the subject of the impediment to Bad Impediment - And I want to indicate that the impediment blocks Story B - When I create the impediment - Then the request should complete successfully - And the sprint named Sprint 001 should have 2 impediments named Bad Impediment + When I press "td.add_new" within "#impediments" + And I fill in "Bad Company" for "subject" + And I fill in the ids of the tasks "Task 1" for "blocks_ids" + And I select "Markus Master" from "assigned_to_id" + And I press "OK" + Then I should see "Bad Company" within "#impediments" + And the impediment "Bad Company" should signal successful saving + + @javascript + Scenario: Create an impediment blocking an issue of another sprint + Given I am on the taskboard for "Sprint 001" + When I press "td.add_new" within "#impediments" + And I fill in "Bad Company" for "subject" + And I fill in the ids of the stories "Story C" for "blocks_ids" + And I select "Markus Master" from "assigned_to_id" + And I press "OK" + Then I should see "Bad Company" within "#impediments" + And the impediment "Bad Company" should signal unsuccessful saving Scenario: Update an impediment Given I am on the taskboard for "Sprint 001" diff --git a/features/step_definitions/_given_steps.rb b/features/step_definitions/_given_steps.rb index 42225331fa..f86482d38e 100644 --- a/features/step_definitions/_given_steps.rb +++ b/features/step_definitions/_given_steps.rb @@ -154,7 +154,7 @@ Given /^the [pP]roject(?: "([^\"]*)")? has the following tasks:$/ do |project_na table.hashes.each do |task| story = Story.find(:first, :conditions => { :subject => task['parent'] }) - params = initialize_task_params(project, story, author) + params = initialize_task_params(project, story) params['subject'] = task['subject'] # NOTE: We're bypassing the controller here because we're just @@ -172,9 +172,9 @@ Given /^the [pP]roject(?: "([^\"]*)")? has the following impediments:$/ do |proj table.hashes.each do |impediment| sprint = Sprint.find(:first, :conditions => { :name => impediment['sprint'] }) blocks = Story.find(:all, :conditions => { :subject => impediment['blocks'].split(', ') }).map{ |s| s.id } - params = initialize_impediment_params(project, sprint, author) + params = initialize_impediment_params(project, sprint) params['subject'] = impediment['subject'] - params['blocks'] = blocks.join(',') + params['blocks_ids'] = blocks.join(',') # NOTE: We're bypassing the controller here because we're just # setting up the database for the actual tests. The actual tests, @@ -249,3 +249,8 @@ end Given /^the scrum statistics are enabled$/ do Setting.plugin_redmine_backlogs = Setting.plugin_redmine_backlogs.merge(:show_statistics => true) end + +Given /^the tracker "(.+?)" is configured to track tasks$/ do |tracker_name| + tracker = Tracker.find_by_name(tracker_name) + Setting.plugin_redmine_backlogs = Setting.plugin_redmine_backlogs.merge(:task_tracker => tracker.id) +end diff --git a/features/step_definitions/_then_steps.rb b/features/step_definitions/_then_steps.rb index 92aa55f082..795f32be61 100644 --- a/features/step_definitions/_then_steps.rb +++ b/features/step_definitions/_then_steps.rb @@ -114,6 +114,26 @@ Then /^the sprint named (.+) should have (\d+) impediments? named (.+)$/ do |spr sprints.first.impediments.map{ |i| i.subject==impediment_subject}.length.should == count.to_i end +Then /^the impediment "(.+)" should signal( | un)successful saving$/ do |impediment_subject, negative| + negative = !negative.blank? + + element = {} + begin + wait_until(5) do + element = page.find(:xpath, "//div[contains(concat(' ',normalize-space(@class),' '),' impediment ') and contains(., '#{impediment_subject}')]") + !element[:class].include?('saving') || element[:class].include?('error') + end + rescue Capybara::TimeoutError + fail "The impediment '#{impediment_subject}' did not finish saving within within 5 sec" + end + + if negative + element[:class].should be_include('error') + else + element[:class].should_not be_include('error') + end +end + Then /^the sprint should be updated accordingly$/ do sprint = Sprint.find(@sprint_params['id']) diff --git a/features/step_definitions/_when_steps.rb b/features/step_definitions/_when_steps.rb index 6bb838b8ef..8f13c44d3e 100644 --- a/features/step_definitions/_when_steps.rb +++ b/features/step_definitions/_when_steps.rb @@ -173,3 +173,10 @@ When /^I confirm the story form$/ do sleep 1.5 steps 'Then I should not see ".saving"' end + +When /^I fill in the ids of the (tasks|issues|stories) "(.+?)" for "(.+?)"$/ do |model_name, subjects, field| + model = Kernel.const_get(model_name.classify) + ids = subjects.split(/,/).collect { |subject| model.find_by_subject(subject).id } + + When %{I fill in "#{ids.join(", ")}" for "#{field}"} +end From b0107443f99d4b984427c5310207c47b2c8d23a7 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Thu, 31 Mar 2011 12:45:13 +0200 Subject: [PATCH 43/46] #3178: cukes for updating impediments --- features/scrum_master.feature | 33 +++++++++++++++++++----- features/step_definitions/_when_steps.rb | 4 +++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/features/scrum_master.feature b/features/scrum_master.feature index 5bca70a2af..950283c33c 100644 --- a/features/scrum_master.feature +++ b/features/scrum_master.feature @@ -102,14 +102,35 @@ Feature: Scrum Master Then I should see "Bad Company" within "#impediments" And the impediment "Bad Company" should signal unsuccessful saving + @javascript Scenario: Update an impediment Given I am on the taskboard for "Sprint 001" - And I want to edit the impediment named Impediment 1 - And I want to set the subject of the impediment to Good Impediment - And I want to indicate that the impediment blocks Story B - When I update the impediment - Then the request should complete successfully - And the sprint named Sprint 001 should have 1 impediment named Good Impediment + When I click on the impediment called "Impediment 1" + And I fill in "Bad Company" for "subject" + And I fill in the ids of the tasks "Task 1" for "blocks_ids" + And I press "OK" + Then I should see "Bad Company" within "#impediments" + And the impediment "Bad Company" should signal successful saving + + @javascript + Scenario: Update an impediment to block an issue of another sprint + Given I am on the taskboard for "Sprint 001" + When I click on the impediment called "Impediment 1" + And I fill in "Bad Company" for "subject" + And I fill in the ids of the stories "Story C" for "blocks_ids" + And I press "OK" + Then I should see "Bad Company" within "#impediments" + And the impediment "Bad Company" should signal unsuccessful saving + + @javascript + Scenario: Update an impediment to block a non existent issue + Given I am on the taskboard for "Sprint 001" + When I click on the impediment called "Impediment 1" + And I fill in "Bad Company" for "subject" + And I fill in "0" for "blocks_ids" + And I press "OK" + Then I should see "Bad Company" within "#impediments" + And the impediment "Bad Company" should signal unsuccessful saving Scenario: Update sprint details Given I am on the master backlog diff --git a/features/step_definitions/_when_steps.rb b/features/step_definitions/_when_steps.rb index 8f13c44d3e..f675cac670 100644 --- a/features/step_definitions/_when_steps.rb +++ b/features/step_definitions/_when_steps.rb @@ -180,3 +180,7 @@ When /^I fill in the ids of the (tasks|issues|stories) "(.+?)" for "(.+?)"$/ do When %{I fill in "#{ids.join(", ")}" for "#{field}"} end + +When /^I click on the impediment called "(.+?)"$/ do |impediment_name| + When %Q{I click on the text "#{impediment_name}"} +end From 867873e7a7758bceeb9dd7419f240509c4cb4485 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Thu, 31 Mar 2011 14:07:08 +0200 Subject: [PATCH 44/46] #3178: providing a non existent issue id as blocked by impediment does fail smoothly --- app/models/impediment.rb | 8 ++++++-- spec/models/impediment_spec.rb | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/app/models/impediment.rb b/app/models/impediment.rb index 68858c5c57..c2b862cb59 100644 --- a/app/models/impediment.rb +++ b/app/models/impediment.rb @@ -99,7 +99,11 @@ class Impediment < Task end def validate_blocks_list - errors.add :blocks_ids, :must_block_at_least_one_issue if blocks_ids.size == 0 - errors.add :blocks_ids, :can_only_contain_issues_of_current_sprint if Issue.find(blocks_ids).any?{|i| i.fixed_version != self.fixed_version } + if blocks_ids.size == 0 + errors.add :blocks_ids, :must_block_at_least_one_issue + else + issues = Issue.find_all_by_id(blocks_ids) + errors.add :blocks_ids, :can_only_contain_issues_of_current_sprint if issues.size == 0 || issues.any?{|i| i.fixed_version != self.fixed_version } + end end end \ No newline at end of file diff --git a/spec/models/impediment_spec.rb b/spec/models/impediment_spec.rb index 6fdc7d29ce..18272c6601 100644 --- a/spec/models/impediment_spec.rb +++ b/spec/models/impediment_spec.rb @@ -122,6 +122,21 @@ describe Impediment do it { @impediment.should be_new_record } it { @impediment.errors[:blocks_ids].should eql I18n.t(:can_only_contain_issues_of_current_sprint, :scope => [:activerecord, :errors, :models, :impediment, :attributes, :blocks_ids]) } end + + describe "WITH the story being non existent" do + before(:each) do + @impediment = Impediment.create_with_relationships({:subject => @impediment_subject, + :assigned_to_id => user.id, + :blocks_ids => "0", + :status_id => issue_status1.id, + :fixed_version_id => version.id}, + project.id) + end + + it_should_behave_like "impediment creation with no blocking relationship" + it { @impediment.should be_new_record } + it { @impediment.errors[:blocks_ids].should eql I18n.t(:can_only_contain_issues_of_current_sprint, :scope => [:activerecord, :errors, :models, :impediment, :attributes, :blocks_ids]) } + end end describe "WITHOUT a blocking relationship defined" do @@ -217,6 +232,18 @@ describe Impediment do it { @impediment.should be_changed } it { @impediment.errors[:blocks_ids].should eql I18n.t(:can_only_contain_issues_of_current_sprint, :scope => [:activerecord, :errors, :models, :impediment, :attributes, :blocks_ids]) } end + + describe "WITH the story beeing non existent" do + before(:each) do + @blocks = "0" + @impediment.update_with_relationships({:blocks_ids => @blocks, + :status_id => issue_status1.id.to_s}) + end + + it_should_behave_like "impediment update with unchanged blocking relationship" + it { @impediment.should be_changed } + it { @impediment.errors[:blocks_ids].should eql I18n.t(:can_only_contain_issues_of_current_sprint, :scope => [:activerecord, :errors, :models, :impediment, :attributes, :blocks_ids]) } + end end describe "WITHOUT a blocking relationship defined" do From db924abb43cc68eef2b3fa93e9bf2e76f8594c22 Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Thu, 31 Mar 2011 15:01:26 +0200 Subject: [PATCH 45/46] #3178: using fieldlabel attribute as label on the task edit/create form if specified, using this on blocks_ids --- app/views/rb_impediments/_impediment.html.erb | 2 +- assets/javascripts/app/model.js | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/views/rb_impediments/_impediment.html.erb b/app/views/rb_impediments/_impediment.html.erb index 7cad6ff927..b130f30331 100644 --- a/app/views/rb_impediments/_impediment.html.erb +++ b/app/views/rb_impediments/_impediment.html.erb @@ -4,7 +4,7 @@
<%= id_or_empty(impediment) %>
<%= impediment.subject %>
-
<%= blocks_ids(impediment.blocks_ids) %>
+
<%= blocks_ids(impediment.blocks_ids) %>
<%= assignee_name_or_empty(impediment) %>
<%= assignee_id_or_empty(impediment) %>
diff --git a/assets/javascripts/app/model.js b/assets/javascripts/app/model.js index d0289b7058..5d85f87771 100644 --- a/assets/javascripts/app/model.js +++ b/assets/javascripts/app/model.js @@ -105,14 +105,18 @@ RB.Model = (function ($) { this.$.find('.editable').each(function (index) { - var field, fieldType, fieldName, input; + var field, fieldType, fieldLabel, fieldName, input; field = $(this); fieldName = field.attr('fieldname'); + fieldLabel = field.attr('fieldlabel'); fieldType = field.attr('fieldtype') || 'input'; - $("").text(fieldName.replace(/_/ig, " ").replace(/ id$/ig, "")). - appendTo(editor); + if (!fieldLabel) { + fieldLabel = fieldName.replace(/_/ig, " ").replace(/ id$/ig, ""); + } + + $("").text(fieldLabel).appendTo(editor); if (fieldType === 'select') { input = $('#' + fieldName + '_options').clone(true); From 75768371d2b0a786a2a42b6d7594d9f981df0e4a Mon Sep 17 00:00:00 2001 From: Jens Ulferts Date: Thu, 31 Mar 2011 15:02:04 +0200 Subject: [PATCH 46/46] #3178: i18n for impediment blocks_ids, cukes for that --- config/locales/de.yml | 4 +++ config/locales/en-GB.yml | 5 +++ config/locales/en.yml | 6 ++++ features/scrum_master.feature | 41 ++++++++++++++++++++---- features/step_definitions/_then_steps.rb | 4 +++ 5 files changed, 53 insertions(+), 7 deletions(-) diff --git a/config/locales/de.yml b/config/locales/de.yml index 5c8c7ba7ba..550f3b73ce 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -97,3 +97,7 @@ de: version_settings_display_option_right: rechts version_settings_display_label: Spalte im Backlog field_display: Spalte im Backlog + + field_blocks_ids: Blockiert (IDs) + error_can_only_contain_issues_of_current_sprint: kann nur IDs von Tickets des aktuellen Sprints enthalten + error_must_block_at_least_one_issue: muss die ID wenigstens eines Tickets enthalten \ No newline at end of file diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index 306088173a..7b9f6b6c79 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -90,3 +90,8 @@ en-GB: version_settings_display_label: Column in backlog field_display: Column in backlog + field_blocks_ids: Blocks (IDs) + + error_can_only_contain_issues_of_current_sprint: can only contain the IDs of current sprint's tickets + error_must_block_at_least_one_issue: must contain the ID of at least one ticket + diff --git a/config/locales/en.yml b/config/locales/en.yml index 60c4bbd007..c95211c5a4 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -115,3 +115,9 @@ en: version_settings_display_option_right: right version_settings_display_label: Column in backlog field_display: Column in backlog + + field_blocks_ids: Blocks (IDs) + + error_can_only_contain_issues_of_current_sprint: can only contain the IDs of current sprint's tickets + error_must_block_at_least_one_issue: must contain the ID of at least one ticket + diff --git a/features/scrum_master.feature b/features/scrum_master.feature index 950283c33c..25b2e2c648 100644 --- a/features/scrum_master.feature +++ b/features/scrum_master.feature @@ -70,37 +70,51 @@ Feature: Scrum Master And I am logged in as "markus" @javascript - Scenario: Create an impediment blocking a non existent issue + Scenario: Create an impediment Given I am on the taskboard for "Sprint 001" When I press "td.add_new" within "#impediments" And I fill in "Bad Company" for "subject" - And I fill in "1918817726612" for "blocks_ids" + And I fill in the ids of the tasks "Task 1" for "blocks_ids" + And I select "Markus Master" from "assigned_to_id" + And I press "OK" + Then I should see "Bad Company" within "#impediments" + And the impediment "Bad Company" should signal successful saving + + @javascript + Scenario: Create an impediment blocking an issue of another sprint + Given I am on the taskboard for "Sprint 001" + When I press "td.add_new" within "#impediments" + And I fill in "Bad Company" for "subject" + And I fill in the ids of the stories "Story C" for "blocks_ids" And I select "Markus Master" from "assigned_to_id" And I press "OK" Then I should see "Bad Company" within "#impediments" And the impediment "Bad Company" should signal unsuccessful saving + And the error alert should show "Blocks (IDs) can only contain the IDs of current sprint's tickets" @javascript - Scenario: Create an impediment + Scenario: Create an impediment blocking a non existent issue Given I am on the taskboard for "Sprint 001" When I press "td.add_new" within "#impediments" And I fill in "Bad Company" for "subject" - And I fill in the ids of the tasks "Task 1" for "blocks_ids" + And I fill in "0" for "blocks_ids" And I select "Markus Master" from "assigned_to_id" And I press "OK" Then I should see "Bad Company" within "#impediments" - And the impediment "Bad Company" should signal successful saving + And the impediment "Bad Company" should signal unsuccessful saving + And the error alert should show "Blocks (IDs) can only contain the IDs of current sprint's tickets" @javascript - Scenario: Create an impediment blocking an issue of another sprint + Scenario: Create an impediment without specifying what it blocks Given I am on the taskboard for "Sprint 001" When I press "td.add_new" within "#impediments" And I fill in "Bad Company" for "subject" - And I fill in the ids of the stories "Story C" for "blocks_ids" + And I fill in "" for "blocks_ids" And I select "Markus Master" from "assigned_to_id" And I press "OK" Then I should see "Bad Company" within "#impediments" And the impediment "Bad Company" should signal unsuccessful saving + And the error alert should show "Blocks (IDs) must contain the ID of at least one ticket" @javascript Scenario: Update an impediment @@ -121,6 +135,7 @@ Feature: Scrum Master And I press "OK" Then I should see "Bad Company" within "#impediments" And the impediment "Bad Company" should signal unsuccessful saving + And the error alert should show "Blocks (IDs) can only contain the IDs of current sprint's tickets" @javascript Scenario: Update an impediment to block a non existent issue @@ -131,6 +146,18 @@ Feature: Scrum Master And I press "OK" Then I should see "Bad Company" within "#impediments" And the impediment "Bad Company" should signal unsuccessful saving + And the error alert should show "Blocks (IDs) can only contain the IDs of current sprint's tickets" + + @javascript + Scenario: Update an impediment to not block anything + Given I am on the taskboard for "Sprint 001" + When I click on the impediment called "Impediment 1" + And I fill in "Bad Company" for "subject" + And I fill in "" for "blocks_ids" + And I press "OK" + Then I should see "Bad Company" within "#impediments" + And the impediment "Bad Company" should signal unsuccessful saving + And the error alert should show "Blocks (IDs) must contain the ID of at least one ticket" Scenario: Update sprint details Given I am on the master backlog diff --git a/features/step_definitions/_then_steps.rb b/features/step_definitions/_then_steps.rb index 795f32be61..d14da9f6cc 100644 --- a/features/step_definitions/_then_steps.rb +++ b/features/step_definitions/_then_steps.rb @@ -192,3 +192,7 @@ Then /^(issue|task|story) (.+) should have (.+) set to (.+)$/ do |type, subject, issue = Issue.find_by_subject(subject) issue[attribute].should == value.to_i end + +Then /^the error alert should show "(.+?)"$/ do |msg| + Then %Q{I should see "#{msg}" within "#msgBox"} +end