From: Jean-Philippe Lang Date: Sat, 5 May 2007 13:22:27 +0000 (+0000) Subject: Issue relations first commit (not thoroughly tested). 4 kinds of relation are available: X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=92b02014d21f0e60230fc7a5c3c5ad71dac6e472;p=redminele%2Fredmine.git Issue relations first commit (not thoroughly tested). 4 kinds of relation are available: * relates to: do nothing special. Just to know that the 2 issues are related... * duplicates: will close the related issue with the same status when closing the issue (not implemented yet) * blocks: will require to close the blocking issue before closing the blocked issue (not implemented yet) * precedes (end to start relation): start date of the related issue depends on the due date of the preceding issue (implemented). A delay can be set so that the related issue can only start n days after the end of the preceding issue. When setting dates for an issue, dates of all downstream issues are set according to these relations. To set a relation, the 2 issues have to belong to the same project (may change in the future). So if an issue is moved to another project, all its relations are removed. Circular dependencies are checked when creating a relation. git-svn-id: http://redmine.rubyforge.org/svn/trunk@506 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- diff --git a/app/controllers/issue_relations_controller.rb b/app/controllers/issue_relations_controller.rb new file mode 100644 index 00000000..cb0ad552 --- /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 be1b8c00..99dc687f 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 6d8c3863..d3a71478 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 00000000..377059d5 --- /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 72a953f6..6dc812ce 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 00000000..05ea5205 --- /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 00000000..8b514dc1 --- /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 %> + +<%= 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 00000000..f817d385 --- /dev/null +++ b/app/views/issues/_relations.rhtml @@ -0,0 +1,22 @@ +

<%=l(:label_related_issues)%>

+ + +<% @issue.relations.each do |relation| %> + + + + + + + + +<% end %> +
<%= 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) %>
+ +<% 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 2eb01f09..d7d9bcf6 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 dfa2a5df..8e2670a9 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 00000000..802c1243 --- /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 00000000..3f1da8f2 --- /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 41b6c6d8..6041f71b 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 efd5e38b..35e4328c 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 7fcb2b14..fadcaad3 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 806c8d46..e6c9002e 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 8423ba93..394417ac 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 0c48ee20..2deb0911 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 274171d6..f746faf9 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 4719e417..0d8bfc67 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 79f998c1..344d8152 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 81708d1d..7ca0cc4d 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(){