From beb20e7c6e906b1b5c892841c1948cb50df86e3e Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Fri, 18 Dec 2009 20:35:16 +0000 Subject: [PATCH] Adds 'follows' relation (#1432). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@3190 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/issue_relation.rb | 17 +++++++++++- public/javascripts/application.js | 2 +- test/unit/issue_relation_test.rb | 46 +++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 test/unit/issue_relation_test.rb diff --git a/app/models/issue_relation.rb b/app/models/issue_relation.rb index d26292c3..2728d77a 100644 --- a/app/models/issue_relation.rb +++ b/app/models/issue_relation.rb @@ -23,20 +23,24 @@ class IssueRelation < ActiveRecord::Base TYPE_DUPLICATES = "duplicates" TYPE_BLOCKS = "blocks" TYPE_PRECEDES = "precedes" + TYPE_FOLLOWS = "follows" TYPES = { TYPE_RELATES => { :name => :label_relates_to, :sym_name => :label_relates_to, :order => 1 }, TYPE_DUPLICATES => { :name => :label_duplicates, :sym_name => :label_duplicated_by, :order => 2 }, TYPE_BLOCKS => { :name => :label_blocks, :sym_name => :label_blocked_by, :order => 3 }, TYPE_PRECEDES => { :name => :label_precedes, :sym_name => :label_follows, :order => 4 }, + TYPE_FOLLOWS => { :name => :label_follows, :sym_name => :label_precedes, :order => 5 } }.freeze validates_presence_of :issue_from, :issue_to, :relation_type - validates_inclusion_of :relation_type, :in => TYPES.keys + validates_inclusion_of :relation_type, :in => [TYPE_RELATES, TYPE_DUPLICATES, TYPE_BLOCKS, TYPE_PRECEDES] validates_numericality_of :delay, :allow_nil => true validates_uniqueness_of :issue_to_id, :scope => :issue_from_id attr_protected :issue_from_id, :issue_to_id + before_validation :reverse_if_needed + def validate if issue_from && issue_to errors.add :issue_to_id, :invalid if issue_from_id == issue_to_id @@ -78,4 +82,15 @@ class IssueRelation < ActiveRecord::Base def <=>(relation) TYPES[self.relation_type][:order] <=> TYPES[relation.relation_type][:order] end + + private + + def reverse_if_needed + if (TYPE_FOLLOWS == relation_type) + issue_tmp = issue_to + self.issue_to = issue_from + self.issue_from = issue_tmp + self.relation_type = TYPE_PRECEDES + end + end end diff --git a/public/javascripts/application.js b/public/javascripts/application.js index 5221bf4c..57419d0b 100644 --- a/public/javascripts/application.js +++ b/public/javascripts/application.js @@ -124,7 +124,7 @@ function displayTabsButtons() { function setPredecessorFieldsVisibility() { relationType = $('relation_relation_type'); - if (relationType && relationType.value == "precedes") { + if (relationType && (relationType.value == "precedes" || relationType.value == "follows")) { Element.show('predecessor_fields'); } else { Element.hide('predecessor_fields'); diff --git a/test/unit/issue_relation_test.rb b/test/unit/issue_relation_test.rb new file mode 100644 index 00000000..cba105e7 --- /dev/null +++ b/test/unit/issue_relation_test.rb @@ -0,0 +1,46 @@ +# Redmine - project management software +# Copyright (C) 2006-2009 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require File.dirname(__FILE__) + '/../test_helper' + +class IssueRelationTest < ActiveSupport::TestCase + fixtures :issue_relations, :issues + + def test_create + from = Issue.find(1) + to = Issue.find(2) + + relation = IssueRelation.new :issue_from => from, :issue_to => to, :relation_type => IssueRelation::TYPE_PRECEDES + assert relation.save + relation.reload + assert_equal IssueRelation::TYPE_PRECEDES, relation.relation_type + assert_equal from, relation.issue_from + assert_equal to, relation.issue_to + end + + def test_follows_relation_should_be_reversed + from = Issue.find(1) + to = Issue.find(2) + + relation = IssueRelation.new :issue_from => from, :issue_to => to, :relation_type => IssueRelation::TYPE_FOLLOWS + assert relation.save + relation.reload + assert_equal IssueRelation::TYPE_PRECEDES, relation.relation_type + assert_equal to, relation.issue_from + assert_equal from, relation.issue_to + end +end