diff --git a/app/controllers/issue_relations_controller.rb b/app/controllers/issue_relations_controller.rb
new file mode 100644
index 000000000..cb0ad552a
--- /dev/null
+++ b/app/controllers/issue_relations_controller.rb
@@ -0,0 +1,59 @@
+# redMine - project management software
+# Copyright (C) 2006-2007 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.
+
+class IssueRelationsController < ApplicationController
+ layout 'base'
+ before_filter :find_project, :authorize
+
+ def new
+ @relation = IssueRelation.new(params[:relation])
+ @relation.issue_from = @issue
+ @relation.save if request.post?
+ respond_to do |format|
+ format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
+ format.js do
+ render :update do |page|
+ page.replace_html "relations", :partial => 'issues/relations'
+ if @relation.errors.empty?
+ page << "$('relation_delay').value = ''"
+ page << "$('relation_issue_to_id').value = ''"
+ end
+ end
+ end
+ end
+ end
+
+ def destroy
+ relation = IssueRelation.find(params[:id])
+ if request.post? && @issue.relations.include?(relation)
+ relation.destroy
+ @issue.reload
+ end
+ respond_to do |format|
+ format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
+ format.js { render(:update) {|page| page.replace_html "relations", :partial => 'issues/relations'} }
+ end
+ end
+
+private
+ def find_project
+ @issue = Issue.find(params[:issue_id])
+ @project = @issue.project
+ rescue ActiveRecord::RecordNotFound
+ render_404
+ end
+end
diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb
index be1b8c003..99dc687f8 100644
--- a/app/controllers/issues_controller.rb
+++ b/app/controllers/issues_controller.rb
@@ -23,6 +23,8 @@ class IssuesController < ApplicationController
include CustomFieldsHelper
helper :ifpdf
include IfpdfHelper
+ helper :issue_relations
+ include IssueRelationsHelper
def show
@status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 6d8c3863e..d3a71478b 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -364,6 +364,9 @@ class ProjectsController < ApplicationController
unless i.project_id == new_project.id
i.category = nil
i.fixed_version = nil
+ # delete issue relations
+ i.relations_from.clear
+ i.relations_to.clear
end
# move the issue
i.project = new_project
diff --git a/app/helpers/issue_relations_helper.rb b/app/helpers/issue_relations_helper.rb
new file mode 100644
index 000000000..377059d5f
--- /dev/null
+++ b/app/helpers/issue_relations_helper.rb
@@ -0,0 +1,23 @@
+# redMine - project management software
+# Copyright (C) 2006-2007 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.
+
+module IssueRelationsHelper
+ def collection_for_relation_type_select
+ values = IssueRelation::TYPES
+ values.keys.sort{|x,y| values[x][:order] <=> values[y][:order]}.collect{|k| [l(values[k][:name]), k]}
+ end
+end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 72a953f62..6dc812ce4 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -1,5 +1,5 @@
# redMine - project management software
-# Copyright (C) 2006 Jean-Philippe Lang
+# Copyright (C) 2006-2007 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
@@ -16,7 +16,6 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Issue < ActiveRecord::Base
-
belongs_to :project
belongs_to :tracker
belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id'
@@ -33,6 +32,9 @@ class Issue < ActiveRecord::Base
has_many :custom_fields, :through => :custom_values
has_and_belongs_to_many :changesets, :order => "revision ASC"
+ has_many :relations_from, :class_name => 'IssueRelation', :foreign_key => 'issue_from_id', :dependent => :delete_all
+ has_many :relations_to, :class_name => 'IssueRelation', :foreign_key => 'issue_to_id', :dependent => :delete_all
+
acts_as_watchable
validates_presence_of :subject, :description, :priority, :tracker, :author, :status
@@ -52,13 +54,13 @@ class Issue < ActiveRecord::Base
if self.due_date and self.start_date and self.due_date < self.start_date
errors.add :due_date, :activerecord_error_greater_than_start_date
end
+
+ if start_date && soonest_start && start_date < soonest_start
+ errors.add :start_date, :activerecord_error_invalid
+ end
end
-
- #def before_create
- # build_history
- #end
- def before_save
+ def before_save
if @current_journal
# attributes changes
(Issue.column_names - %w(id description)).each {|c|
@@ -78,6 +80,10 @@ class Issue < ActiveRecord::Base
end
end
+ def after_save
+ relations_from.each(&:set_issue_to_dates)
+ end
+
def long_id
"%05d" % self.id
end
@@ -98,12 +104,25 @@ class Issue < ActiveRecord::Base
def spent_hours
@spent_hours ||= time_entries.sum(:hours) || 0
end
-
-private
- # Creates an history for the issue
- #def build_history
- # @history = self.histories.build
- # @history.status = self.status
- # @history.author = self.author
- #end
+
+ def relations
+ (relations_from + relations_to).sort
+ end
+
+ def all_dependent_issues
+ dependencies = []
+ relations_from.each do |relation|
+ dependencies << relation.issue_to
+ dependencies += relation.issue_to.all_dependent_issues
+ end
+ dependencies
+ end
+
+ def duration
+ (start_date && due_date) ? due_date - start_date : 0
+ end
+
+ def soonest_start
+ @soonest_start ||= relations_to.collect{|relation| relation.successor_soonest_start}.compact.min
+ end
end
diff --git a/app/models/issue_relation.rb b/app/models/issue_relation.rb
new file mode 100644
index 000000000..05ea52057
--- /dev/null
+++ b/app/models/issue_relation.rb
@@ -0,0 +1,79 @@
+# redMine - project management software
+# Copyright (C) 2006-2007 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.
+
+class IssueRelation < ActiveRecord::Base
+ belongs_to :issue_from, :class_name => 'Issue', :foreign_key => 'issue_from_id'
+ belongs_to :issue_to, :class_name => 'Issue', :foreign_key => 'issue_to_id'
+
+ TYPE_RELATES = "relates"
+ TYPE_DUPLICATES = "duplicates"
+ TYPE_BLOCKS = "blocks"
+ TYPE_PRECEDES = "precedes"
+
+ TYPES = { TYPE_RELATES => { :name => :label_relates_to, :sym_name => :label_relates_to, :order => 1 },
+ TYPE_DUPLICATES => { :name => :label_duplicates, :sym_name => :label_duplicates, :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 },
+ }.freeze
+
+ validates_presence_of :issue_from, :issue_to, :relation_type
+ validates_inclusion_of :relation_type, :in => TYPES.keys
+ validates_numericality_of :delay, :allow_nil => true
+ validates_uniqueness_of :issue_to_id, :scope => :issue_from_id
+
+ def validate
+ if issue_from && issue_to
+ errors.add :issue_to_id, :activerecord_error_invalid if issue_from_id == issue_to_id
+ errors.add :issue_to_id, :activerecord_error_not_same_project unless issue_from.project_id == issue_to.project_id
+ errors.add_to_base :activerecord_error_circular_dependency if issue_to.all_dependent_issues.include? issue_from
+ end
+ end
+
+ def other_issue(issue)
+ (self.issue_from_id == issue.id) ? issue_to : issue_from
+ end
+
+ def label_for(issue)
+ TYPES[relation_type] ? TYPES[relation_type][(self.issue_from_id == issue.id) ? :name : :sym_name] : :unknow
+ end
+
+ def before_save
+ if TYPE_PRECEDES == relation_type
+ self.delay ||= 0
+ else
+ self.delay = nil
+ end
+ set_issue_to_dates
+ end
+
+ def set_issue_to_dates
+ soonest_start = self.successor_soonest_start
+ if soonest_start && (!issue_to.start_date || issue_to.start_date < soonest_start)
+ issue_to.start_date, issue_to.due_date = successor_soonest_start, successor_soonest_start + issue_to.duration
+ issue_to.save
+ end
+ end
+
+ def successor_soonest_start
+ return nil unless (TYPE_PRECEDES == self.relation_type) && (issue_from.start_date || issue_from.due_date)
+ (issue_from.due_date || issue_from.start_date) + 1 + delay
+ end
+
+ def <=>(relation)
+ TYPES[self.relation_type][:order] <=> TYPES[relation.relation_type][:order]
+ end
+end
diff --git a/app/views/issue_relations/_form.rhtml b/app/views/issue_relations/_form.rhtml
new file mode 100644
index 000000000..8b514dc1a
--- /dev/null
+++ b/app/views/issue_relations/_form.rhtml
@@ -0,0 +1,10 @@
+<%= error_messages_for 'relation' %>
+
+
<%= f.select :relation_type, collection_for_relation_type_select, {}, :onchange => "setPredecessorFieldsVisibility();" %>
+<%= l(:label_issue) %> #<%= f.text_field :issue_to_id, :size => 6 %>
+
+<%= l(:field_delay) %>: <%= f.text_field :delay, :size => 3 %> <%= l(:label_day_plural) %>
+
+<%= submit_tag l(:button_add) %>
+
+<%= javascript_tag "setPredecessorFieldsVisibility();" %>
diff --git a/app/views/issues/_relations.rhtml b/app/views/issues/_relations.rhtml
new file mode 100644
index 000000000..f817d3851
--- /dev/null
+++ b/app/views/issues/_relations.rhtml
@@ -0,0 +1,22 @@
+<%=l(:label_related_issues)%>
+
+
+<% @issue.relations.each do |relation| %>
+
+<%= l(relation.label_for(@issue)) %> <%= "(#{lwr(:actionview_datehelper_time_in_words_day, relation.delay)})" if relation.delay && relation.delay != 0 %> <%= link_to_issue relation.other_issue(@issue) %> |
+<%=h relation.other_issue(@issue).subject %> |
+ <%= relation.other_issue(@issue).status.name %> |
+<%= format_date(relation.other_issue(@issue).start_date) %> |
+<%= format_date(relation.other_issue(@issue).due_date) %> |
+<%= link_to_remote image_tag('delete.png'), { :url => {:controller => 'issue_relations', :action => 'destroy', :issue_id => @issue, :id => relation},
+ :method => :post
+ }, :title => l(:label_relation_delete) %> |
+
+<% end %>
+
+
+<% if authorize_for('issue_relations', 'new') %>
+ <% remote_form_for(:relation, @relation, :url => {:controller => 'issue_relations', :action => 'new', :issue_id => @issue}, :method => :post) do |f| %>
+ <%= render :partial => 'issue_relations/form', :locals => {:f => f}%>
+ <% end %>
+<% end %>
diff --git a/app/views/issues/show.rhtml b/app/views/issues/show.rhtml
index 2eb01f094..d7d9bcf6d 100644
--- a/app/views/issues/show.rhtml
+++ b/app/views/issues/show.rhtml
@@ -81,6 +81,12 @@ end %>
+<% if authorize_for('issue_relations', 'new') || @issue.relations.any? %>
+
+<%= render :partial => 'relations' %>
+
+<% end %>
+
<%=l(:label_history)%>
<% if @journals_count > @journals.length %>(<%= l(:label_last_changes, @journals.length) %>)<% end %>
diff --git a/config/routes.rb b/config/routes.rb
index dfa2a5df2..8e2670a99 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -15,6 +15,8 @@ ActionController::Routing::Routes.draw do |map|
map.connect 'help/:ctrl/:page', :controller => 'help'
#map.connect ':controller/:action/:id/:sort_key/:sort_order'
+ map.connect 'issues/:issue_id/relations/:action/:id', :controller => 'issue_relations'
+
# Allow downloading Web Service WSDL as a file with an extension
# instead of a file named 'wsdl'
map.connect ':controller/service.wsdl', :action => 'wsdl'
diff --git a/db/migrate/042_create_issue_relations.rb b/db/migrate/042_create_issue_relations.rb
new file mode 100644
index 000000000..802c12437
--- /dev/null
+++ b/db/migrate/042_create_issue_relations.rb
@@ -0,0 +1,14 @@
+class CreateIssueRelations < ActiveRecord::Migration
+ def self.up
+ create_table :issue_relations do |t|
+ t.column :issue_from_id, :integer, :null => false
+ t.column :issue_to_id, :integer, :null => false
+ t.column :relation_type, :string, :default => "", :null => false
+ t.column :delay, :integer
+ end
+ end
+
+ def self.down
+ drop_table :issue_relations
+ end
+end
diff --git a/db/migrate/043_add_relations_permissions.rb b/db/migrate/043_add_relations_permissions.rb
new file mode 100644
index 000000000..3f1da8f27
--- /dev/null
+++ b/db/migrate/043_add_relations_permissions.rb
@@ -0,0 +1,11 @@
+class AddRelationsPermissions < ActiveRecord::Migration
+ def self.up
+ Permission.create :controller => "issue_relations", :action => "new", :description => "label_relation_new", :sort => 1080, :is_public => false, :mail_option => 0, :mail_enabled => 0
+ Permission.create :controller => "issue_relations", :action => "destroy", :description => "label_relation_delete", :sort => 1085, :is_public => false, :mail_option => 0, :mail_enabled => 0
+ end
+
+ def self.down
+ Permission.find_by_controller_and_action("issue_relations", "new").destroy
+ Permission.find_by_controller_and_action("issue_relations", "destroy").destroy
+ end
+end
diff --git a/lang/bg.yml b/lang/bg.yml
index 41b6c6d88..6041f71b3 100644
--- a/lang/bg.yml
+++ b/lang/bg.yml
@@ -33,6 +33,8 @@ activerecord_error_taken: вече съществува
activerecord_error_not_a_number: не е число
activerecord_error_not_a_date: е невалидна дата
activerecord_error_greater_than_start_date: трябва да е след началната дата
+activerecord_error_not_same_project: doesn't belong to the same project
+activerecord_error_circular_dependency: This relation would create a circular dependency
general_fmt_age: %d yr
general_fmt_age_plural: %d yrs
@@ -149,6 +151,8 @@ field_activity: Дейност
field_spent_on: Дата
field_identifier: Идентификатор
field_is_filter: Използва се за филтър
+field_issue_to_id: Related issue
+field_delay: Delay
setting_app_title: Заглавие
setting_app_subtitle: Описание
@@ -364,6 +368,18 @@ label_watched_issues: Наблюдавани задачи
label_related_issues: Свързани задачи
label_applied_status: Промени статуса на
label_loading: Зареждане...
+label_relation_new: New relation
+label_relation_delete: Delete relation
+label_relates_to: related tp
+label_duplicates: duplicates
+label_blocks: blocks
+label_blocked_by: blocked by
+label_precedes: precedes
+label_follows: follows
+label_end_to_start: start to end
+label_end_to_end: end to end
+label_start_to_start: start to start
+label_start_to_end: start to end
button_login: Вход
button_submit: Изпращане
diff --git a/lang/de.yml b/lang/de.yml
index efd5e38b6..35e4328cc 100644
--- a/lang/de.yml
+++ b/lang/de.yml
@@ -33,6 +33,8 @@ activerecord_error_taken: ist bereits vergeben
activerecord_error_not_a_number: ist keine Zahl
activerecord_error_not_a_date: ist kein gültiges Datum
activerecord_error_greater_than_start_date: muss größer als Anfangsdatum sein
+activerecord_error_not_same_project: doesn't belong to the same project
+activerecord_error_circular_dependency: This relation would create a circular dependency
general_fmt_age: %d Jahr
general_fmt_age_plural: %d Jahre
@@ -149,6 +151,8 @@ field_activity: Aktivität
field_spent_on: Datum
field_identifier: Identifier
field_is_filter: Used as a filter
+field_issue_to_id: Related issue
+field_delay: Delay
setting_app_title: Applikation Titel
setting_app_subtitle: Applikation Untertitel
@@ -364,6 +368,18 @@ label_watched_issues: Watched issues
label_related_issues: Related issues
label_applied_status: Applied status
label_loading: Loading...
+label_relation_new: New relation
+label_relation_delete: Delete relation
+label_relates_to: related tp
+label_duplicates: duplicates
+label_blocks: blocks
+label_blocked_by: blocked by
+label_precedes: precedes
+label_follows: follows
+label_end_to_start: start to end
+label_end_to_end: end to end
+label_start_to_start: start to start
+label_start_to_end: start to end
button_login: Einloggen
button_submit: OK
diff --git a/lang/en.yml b/lang/en.yml
index 7fcb2b14b..fadcaad3f 100644
--- a/lang/en.yml
+++ b/lang/en.yml
@@ -33,6 +33,8 @@ activerecord_error_taken: has already been taken
activerecord_error_not_a_number: is not a number
activerecord_error_not_a_date: is not a valid date
activerecord_error_greater_than_start_date: must be greater than start date
+activerecord_error_not_same_project: doesn't belong to the same project
+activerecord_error_circular_dependency: This relation would create a circular dependency
general_fmt_age: %d yr
general_fmt_age_plural: %d yrs
@@ -149,6 +151,8 @@ field_activity: Activity
field_spent_on: Date
field_identifier: Identifier
field_is_filter: Used as a filter
+field_issue_to_id: Related issue
+field_delay: Delay
setting_app_title: Application title
setting_app_subtitle: Application subtitle
@@ -364,6 +368,18 @@ label_watched_issues: Watched issues
label_related_issues: Related issues
label_applied_status: Applied status
label_loading: Loading...
+label_relation_new: New relation
+label_relation_delete: Delete relation
+label_relates_to: related tp
+label_duplicates: duplicates
+label_blocks: blocks
+label_blocked_by: blocked by
+label_precedes: precedes
+label_follows: follows
+label_end_to_start: start to end
+label_end_to_end: end to end
+label_start_to_start: start to start
+label_start_to_end: start to end
button_login: Login
button_submit: Submit
diff --git a/lang/es.yml b/lang/es.yml
index 806c8d462..e6c9002e7 100644
--- a/lang/es.yml
+++ b/lang/es.yml
@@ -33,6 +33,8 @@ activerecord_error_taken: has already been taken
activerecord_error_not_a_number: is not a number
activerecord_error_not_a_date: no es una fecha válida
activerecord_error_greater_than_start_date: debe ser la fecha mayor que del comienzo
+activerecord_error_not_same_project: doesn't belong to the same project
+activerecord_error_circular_dependency: This relation would create a circular dependency
general_fmt_age: %d año
general_fmt_age_plural: %d años
@@ -149,6 +151,8 @@ field_activity: Activity
field_spent_on: Fecha
field_identifier: Identifier
field_is_filter: Used as a filter
+field_issue_to_id: Related issue
+field_delay: Delay
setting_app_title: Título del aplicación
setting_app_subtitle: Subtítulo del aplicación
@@ -364,6 +368,18 @@ label_watched_issues: Watched issues
label_related_issues: Related issues
label_applied_status: Applied status
label_loading: Loading...
+label_relation_new: New relation
+label_relation_delete: Delete relation
+label_relates_to: related tp
+label_duplicates: duplicates
+label_blocks: blocks
+label_blocked_by: blocked by
+label_precedes: precedes
+label_follows: follows
+label_end_to_start: start to end
+label_end_to_end: end to end
+label_start_to_start: start to start
+label_start_to_end: start to end
button_login: Conexión
button_submit: Someter
diff --git a/lang/fr.yml b/lang/fr.yml
index 8423ba93b..394417ac9 100644
--- a/lang/fr.yml
+++ b/lang/fr.yml
@@ -1,4 +1,4 @@
-_gloc_rule_default: '|n| n<=1 ? "" : "_plural" '
+_gloc_rule_default: '|n| n==1 ? "" : "_plural" '
actionview_datehelper_select_day_prefix:
actionview_datehelper_select_month_names: Janvier,Février,Mars,Avril,Mai,Juin,Juillet,Août,Septembre,Octobre,Novembre,Décembre
@@ -33,6 +33,8 @@ activerecord_error_taken: est déjà utilisé
activerecord_error_not_a_number: n'est pas un nombre
activerecord_error_not_a_date: n'est pas une date valide
activerecord_error_greater_than_start_date: doit être postérieur à la date de début
+activerecord_error_not_same_project: n'appartient pas au même projet
+activerecord_error_circular_dependency: Cette relation créerait une dépendance circulaire
general_fmt_age: %d an
general_fmt_age_plural: %d ans
@@ -149,6 +151,8 @@ field_activity: Activité
field_spent_on: Date
field_identifier: Identifiant
field_is_filter: Utilisé comme filtre
+field_issue_to_id: Demande liée
+field_delay: Retard
setting_app_title: Titre de l'application
setting_app_subtitle: Sous-titre de l'application
@@ -364,6 +368,18 @@ label_watched_issues: Demandes surveillées
label_related_issues: Demandes liées
label_applied_status: Statut appliqué
label_loading: Chargement...
+label_relation_new: Nouvelle relation
+label_relation_delete: Supprimer la relation
+label_relates_to: lié à
+label_duplicates: doublon de
+label_blocks: bloque
+label_blocked_by: bloqué par
+label_precedes: précède
+label_follows: suit
+label_end_to_start: début à fin
+label_end_to_end: fin à fin
+label_start_to_start: début à début
+label_start_to_end: début à fin
button_login: Connexion
button_submit: Soumettre
diff --git a/lang/it.yml b/lang/it.yml
index 0c48ee20e..2deb09115 100644
--- a/lang/it.yml
+++ b/lang/it.yml
@@ -33,6 +33,8 @@ activerecord_error_taken: e' gia' stato/a preso/a
activerecord_error_not_a_number: non e' un numero
activerecord_error_not_a_date: non e' una data valida
activerecord_error_greater_than_start_date: deve essere maggiore della data di partenza
+activerecord_error_not_same_project: doesn't belong to the same project
+activerecord_error_circular_dependency: This relation would create a circular dependency
general_fmt_age: %d yr
general_fmt_age_plural: %d yrs
@@ -149,6 +151,8 @@ field_activity: Activity
field_spent_on: Data
field_identifier: Identifier
field_is_filter: Used as a filter
+field_issue_to_id: Related issue
+field_delay: Delay
setting_app_title: Titolo applicazione
setting_app_subtitle: Sottotitolo applicazione
@@ -364,6 +368,18 @@ label_watched_issues: Watched issues
label_related_issues: Related issues
label_applied_status: Applied status
label_loading: Loading...
+label_relation_new: New relation
+label_relation_delete: Delete relation
+label_relates_to: related tp
+label_duplicates: duplicates
+label_blocks: blocks
+label_blocked_by: blocked by
+label_precedes: precedes
+label_follows: follows
+label_end_to_start: start to end
+label_end_to_end: end to end
+label_start_to_start: start to start
+label_start_to_end: start to end
button_login: Login
button_submit: Invia
diff --git a/lang/ja.yml b/lang/ja.yml
index 274171d6d..f746faf97 100644
--- a/lang/ja.yml
+++ b/lang/ja.yml
@@ -34,6 +34,8 @@ activerecord_error_taken: はすでに登録されています
activerecord_error_not_a_number: が数字ではありません
activerecord_error_not_a_date: の日付が間違っています
activerecord_error_greater_than_start_date: を開始日より後にしてください
+activerecord_error_not_same_project: doesn't belong to the same project
+activerecord_error_circular_dependency: This relation would create a circular dependency
general_fmt_age: %d歳
general_fmt_age_plural: %d歳
@@ -150,6 +152,8 @@ field_activity: 活動
field_spent_on: 日付
field_identifier: 識別子
field_is_filter: Used as a filter
+field_issue_to_id: Related issue
+field_delay: Delay
setting_app_title: アプリケーションのタイトル
setting_app_subtitle: アプリケーションのサブタイトル
@@ -365,6 +369,18 @@ label_watched_issues: Watched issues
label_related_issues: Related issues
label_applied_status: Applied status
label_loading: Loading...
+label_relation_new: New relation
+label_relation_delete: Delete relation
+label_relates_to: related tp
+label_duplicates: duplicates
+label_blocks: blocks
+label_blocked_by: blocked by
+label_precedes: precedes
+label_follows: follows
+label_end_to_start: start to end
+label_end_to_end: end to end
+label_start_to_start: start to start
+label_start_to_end: start to end
button_login: ログイン
button_submit: 変更
diff --git a/lang/pt.yml b/lang/pt.yml
index 4719e4174..0d8bfc67c 100644
--- a/lang/pt.yml
+++ b/lang/pt.yml
@@ -33,6 +33,8 @@ activerecord_error_taken: ja esta examinado
activerecord_error_not_a_number: nao e um numero
activerecord_error_not_a_date: nao e uma data valida
activerecord_error_greater_than_start_date: deve ser maior que a data inicial
+activerecord_error_not_same_project: doesn't belong to the same project
+activerecord_error_circular_dependency: This relation would create a circular dependency
general_fmt_age: %d yr
general_fmt_age_plural: %d yrs
@@ -149,6 +151,8 @@ field_activity: Atividade
field_spent_on: Data
field_identifier: Identificador
field_is_filter: Used as a filter
+field_issue_to_id: Related issue
+field_delay: Delay
setting_app_title: Titulo da aplicacao
setting_app_subtitle: Sub-titulo da aplicacao
@@ -364,6 +368,18 @@ label_watched_issues: Watched issues
label_related_issues: Related issues
label_applied_status: Applied status
label_loading: Loading...
+label_relation_new: New relation
+label_relation_delete: Delete relation
+label_relates_to: related tp
+label_duplicates: duplicates
+label_blocks: blocks
+label_blocked_by: blocked by
+label_precedes: precedes
+label_follows: follows
+label_end_to_start: start to end
+label_end_to_end: end to end
+label_start_to_start: start to start
+label_start_to_end: start to end
button_login: Login
button_submit: Enviar
diff --git a/lang/zh.yml b/lang/zh.yml
index 79f998c1c..344d8152b 100644
--- a/lang/zh.yml
+++ b/lang/zh.yml
@@ -36,6 +36,8 @@ activerecord_error_taken: has already been taken
activerecord_error_not_a_number: 不是数字
activerecord_error_not_a_date: 不是有效的日期
activerecord_error_greater_than_start_date: 必需大于开始日期
+activerecord_error_not_same_project: doesn't belong to the same project
+activerecord_error_circular_dependency: This relation would create a circular dependency
general_fmt_age: %d yr
general_fmt_age_plural: %d yrs
@@ -152,6 +154,8 @@ field_activity: 活动
field_spent_on: 日期
field_identifier: Identifier
field_is_filter: Used as a filter
+field_issue_to_id: Related issue
+field_delay: Delay
setting_app_title: 应用程序标题
setting_app_subtitle: 应用程序子标题
@@ -367,6 +371,18 @@ label_watched_issues: Watched issues
label_related_issues: Related issues
label_applied_status: Applied status
label_loading: Loading...
+label_relation_new: New relation
+label_relation_delete: Delete relation
+label_relates_to: related tp
+label_duplicates: duplicates
+label_blocks: blocks
+label_blocked_by: blocked by
+label_precedes: precedes
+label_follows: follows
+label_end_to_start: start to end
+label_end_to_end: end to end
+label_start_to_start: start to start
+label_start_to_end: start to end
button_login: 登录
button_submit: 提交
diff --git a/public/javascripts/application.js b/public/javascripts/application.js
index 81708d1d9..7ca0cc4d8 100644
--- a/public/javascripts/application.js
+++ b/public/javascripts/application.js
@@ -32,6 +32,15 @@ function showTab(name) {
return false;
}
+function setPredecessorFieldsVisibility() {
+ relationType = $('relation_relation_type');
+ if (relationType && relationType.value == "precedes") {
+ Element.show('predecessor_fields');
+ } else {
+ Element.hide('predecessor_fields');
+ }
+}
+
/* shows and hides ajax indicator */
Ajax.Responders.register({
onCreate: function(){