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 %> + +<%= 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| %> + + + + + + + + +<% 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 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(){