Compare commits

..
51 Commits
Author SHA1 Message Date
Jean-Philippe Lang c393f1e92c tagged version 2.3.2
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/tags/2.3.2@12025 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-07-14 14:51:29 +00:00
Jean-Philippe Lang 8efcf60319 Updates for 2.3.2 release.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@12023 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-07-14 14:50:07 +00:00
Jean-Philippe Lang e07bc81c5e Add more info about the ruby version (#14419).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@12002 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-07-11 18:43:48 +00:00
Jean-Philippe Lang 5c6349a7ca Merged r11905 from trunk (#14103).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@12001 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-07-11 18:37:47 +00:00
Jean-Philippe Lang 37fbdb1457 Merged r11906 from trunk (#14101).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@12000 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-07-11 18:37:00 +00:00
Jean-Philippe Lang a13acb7851 Merged r11869 from trunk (#12888).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11999 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-07-11 18:36:02 +00:00
Jean-Philippe Lang 01887f1e67 Merged r11915 from trunk (#14186).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11998 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-07-11 18:33:54 +00:00
Jean-Philippe Lang 3d9f274140 Merged r11839 from trunk (#14020).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11997 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-07-11 18:33:07 +00:00
Jean-Philippe Lang 7375dff6d6 Merged r11827 to r11833 from trunk (#14015).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11996 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-07-11 18:28:54 +00:00
Jean-Philippe Lang 9874a61ec3 Merged r11854 from trunk (#13783).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11995 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-07-11 17:51:19 +00:00
Toshi MARUYAMA b5998b59ab Merged r11982 from trunk to 2.3-stable (#14346)
fix Latvian "button_log_time" translation by Arnis Juraga.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11984 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-06-26 11:49:38 +00:00
Toshi MARUYAMA c590cded4b Merged r11980 from trunk to 2.3-stable (#9996)
replace "email.yml" to "configuration.yml" in pl.yml.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11981 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-06-15 12:55:48 +00:00
Toshi MARUYAMA 5b8af329e2 2.3-stable: pin nokogiri version < 1.6.0 (#14245)
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11953 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-06-10 08:24:46 +00:00
Toshi MARUYAMA 0badc79162 Merged r11942 from trunk to 2.3-stable (#14242)
fix that project auto generation fails when projects created in the same time.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11945 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-06-08 11:39:56 +00:00
Toshi MARUYAMA 5e57cbfdc4 Merged r11932 from trunk to 2.3-stable (#14221)
translate x_hours in many languages.

Contributed by Filou Centrinov.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11935 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-06-06 06:13:53 +00:00
Toshi MARUYAMA 489527ada7 Merged r11925 from trunk to 2.3-stable (#13692)
prevent coderay "warning: already initialized constant" on Ruby 1.8.7.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11929 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-06-05 04:06:47 +00:00
Toshi MARUYAMA 6ce685a63c Merged r11920 and r11921 from trunk to 2.3-stable (#14178)
pdf: restore "col_id_width" parameter of issues_to_pdf_draw_borders.

Contributed by Massimo Rossello.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11924 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-06-04 12:42:29 +00:00
Toshi MARUYAMA 8045385990 Merged r11919 from trunk to 2.3-stable (#14196)
Italian translation for 2.3-stable by Riccardo Rocca.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11922 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-06-04 11:40:41 +00:00
Toshi MARUYAMA 3a4c46089f Merged r11911 from trunk to 2.3-stable (#14182, #14180)
pt-BR translation for 2.3-stable updated by Marcela Oliveira.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11914 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-31 11:05:39 +00:00
Toshi MARUYAMA 53d45273a9 Merged r11901 from trunk to 2.3-stable (#14145)
German translation of x_hours updated by Filou Centrinov.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11903 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-25 06:04:36 +00:00
Jean-Philippe Lang cc23ab9652 Merged r11850 from trunk (#14051).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11872 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-18 19:35:26 +00:00
Jean-Philippe Lang ea33a66c6b Merged r11851 from trunk (#14023).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11871 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-18 19:34:19 +00:00
Jean-Philippe Lang a8c27df9fe Merged r11843 from trunk (#13910).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11870 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-18 19:33:27 +00:00
Jean-Philippe Lang af632568e3 Merged r11760 from trunk (#13850).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11837 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-12 09:45:52 +00:00
Jean-Philippe Lang 2c408ca6a5 Merged r11761 from trunk (#13821).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11836 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-12 09:44:52 +00:00
Jean-Philippe Lang 2a6dadf787 Merged r11762 and r11763 from trunk (#13783).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11835 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-12 09:43:59 +00:00
Toshi MARUYAMA 958f1accec Merged r11798 from trunk to 2.3-stable (#14003, #14005)
Swedish Translation for 2.3-stable updated by Nicklas Holm.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11801 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-08 01:36:46 +00:00
Toshi MARUYAMA 77a2cbfa6a Merged r11791 from trunk to 2.3-stable (#13950)
remove duplicate Lithuanian "error_attachment_too_big" translation keys.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11792 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-05 10:38:05 +00:00
Toshi MARUYAMA 73b4b614ee Merged r11724 from trunk to 2.3-stable.
Add TODO comment about gantt issues sort (#7335).

Sorting by date was dropped by r4581 (#7128).

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11769 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-02 22:44:54 +00:00
Jean-Philippe Lang 1a71316b37 Merged r11757 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11758 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-01 15:14:28 +00:00
Jean-Philippe Lang 5fa087a792 Merged r11592 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11756 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-01 15:12:24 +00:00
Jean-Philippe Lang 425a0fe988 Merged r11754 from trunk (#12684).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11755 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-01 13:14:21 +00:00
Jean-Philippe Lang 606762dcad Merged r11750 from trunk (#12650).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11751 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-01 12:53:10 +00:00
Jean-Philippe Lang 07dc1e34ff Merged r11748 from trunk (#13712).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11749 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-01 12:36:48 +00:00
Jean-Philippe Lang 1afe67bf74 Merged r11698 from trunk (#13541).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11747 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-01 12:17:31 +00:00
Jean-Philippe Lang f9f4591cff Merged r11680 from trunk (#13541).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11746 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-01 12:16:56 +00:00
Jean-Philippe Lang aa4fc1b58a Merged r11696 from trunk (#13618).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11745 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-05-01 12:15:49 +00:00
Toshi MARUYAMA 8c17237638 Merged r11737 and r11738 from trunk to 2.3-stable (#13823)
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11739 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-04-21 09:00:27 +00:00
Toshi MARUYAMA 06ab582e5d Merged r11728, r11729, r11730, r11731, r11732 and r11733 from trunk to 2.3-stable (#13811)
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11734 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-04-20 11:26:12 +00:00
Toshi MARUYAMA af66c42d9e 2.3-stable: svn propset svn:eol-style native test fixtures (#13644)
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11710 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-04-05 09:59:21 +00:00
Toshi MARUYAMA 655c50849d Merged r11706 and r11707 from trunk to 2.3-stable (#13644)
fix diff error in case of line_left out of range.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11709 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-04-05 09:56:14 +00:00
Toshi MARUYAMA bd5b7428d8 Merged r11700 from trunk to 2.3-stable (#13678, #13674)
Lithuanian translation for 2.3-stable updated by Vasaris Vėjas.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11703 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-04-04 12:52:40 +00:00
Toshi MARUYAMA 4ed30a4495 Merged r11699 from trunk to 2.3-stable (#13678)
remove duplicate "text_repository_usernames_mapping" from Lithuanian translation.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11702 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-04-04 12:52:29 +00:00
Jean-Philippe Lang ca39b05420 Merged r11692 from trunk (#13586).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11697 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-04-03 17:04:40 +00:00
Etienne Massip e189641e8c Merged r11693 from trunk (#13630).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11695 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-04-02 17:50:39 +00:00
Toshi MARUYAMA 102dd4c11b 2.3-stable: svn:eol-style native jquery.ui.datepicker-pt.js (#13584)
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11691 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-03-25 14:56:22 +00:00
Toshi MARUYAMA c1d853d957 Merged r11686 from trunk to 2.3-stable (#13584)
add missing Portuguese jQuery UI date picker.

jquery.ui.datepicker-pt.js is from
https://raw.github.com/jquery/jquery-ui/49f9b849b9c5023f13/ui/i18n/jquery.ui.datepicker-pt.js

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11690 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-03-25 14:51:06 +00:00
Toshi MARUYAMA 225f99377a Merged r11682 and r11685 from trunk to 2.3-stable (#13579)
fix that datepicker uses Simplified Chinese in Traditional Chinese locale.

Contributed by Chage Juan.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11689 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-03-25 14:50:55 +00:00
Toshi MARUYAMA d8cf4c57d3 Merged r11675 from trunk to 2.3-stable (#13552, #13551)
Dutch translations for 2.3-stable updated by Pieter Nicolai.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11679 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-03-22 01:04:33 +00:00
Toshi MARUYAMA 4b5fa08f66 Merged r11671, r11672 and r11674 from trunk to 2.3-stable (#13405)
Fixed commit link title escaping.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11678 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-03-22 01:04:22 +00:00
Toshi MARUYAMA 4380c0af73 Merged r11664 from trunk to 2.3-stable (#13531 ,#13528)
Traditional Chinese translation for 2.3-stable updated by ChunChang Lo.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/2.3-stable@11669 e93f8b46-1217-0410-a6f0-8f06a7374b81
2013-03-20 07:01:37 +00:00
95 changed files with 984 additions and 320 deletions
+2 -1
View File
@@ -3,7 +3,7 @@ source 'https://rubygems.org'
gem "rails", "3.2.13" gem "rails", "3.2.13"
gem "jquery-rails", "~> 2.0.2" gem "jquery-rails", "~> 2.0.2"
gem "i18n", "~> 0.6.0" gem "i18n", "~> 0.6.0"
gem "coderay", "~> 1.0.6" gem "coderay", "~> 1.0.9"
gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby] gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby]
gem "builder", "3.0.0" gem "builder", "3.0.0"
@@ -80,6 +80,7 @@ group :test do
gem "shoulda", "~> 3.3.2" gem "shoulda", "~> 3.3.2"
gem "mocha", "~> 0.13.3" gem "mocha", "~> 0.13.3"
gem 'capybara', '~> 2.0.0' gem 'capybara', '~> 2.0.0'
gem 'nokogiri', '< 1.6.0'
end end
local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local") local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local")
+5 -7
View File
@@ -70,14 +70,12 @@ class EnumerationsController < ApplicationController
@enumeration.destroy @enumeration.destroy
redirect_to enumerations_path redirect_to enumerations_path
return return
elsif params[:reassign_to_id] elsif params[:reassign_to_id].present? && (reassign_to = @enumeration.class.find_by_id(params[:reassign_to_id].to_i))
if reassign_to = @enumeration.class.find_by_id(params[:reassign_to_id]) @enumeration.destroy(reassign_to)
@enumeration.destroy(reassign_to) redirect_to enumerations_path
redirect_to enumerations_path return
return
end
end end
@enumerations = @enumeration.class.all - [@enumeration] @enumerations = @enumeration.class.system.all - [@enumeration]
end end
private private
-1
View File
@@ -53,7 +53,6 @@ class MyController < ApplicationController
if request.post? if request.post?
@user.safe_attributes = params[:user] @user.safe_attributes = params[:user]
@user.pref.attributes = params[:pref] @user.pref.attributes = params[:pref]
@user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
if @user.save if @user.save
@user.pref.save @user.pref.save
@user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : []) @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
-2
View File
@@ -92,7 +92,6 @@ class UsersController < ApplicationController
if @user.save if @user.save
@user.pref.attributes = params[:pref] @user.pref.attributes = params[:pref]
@user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
@user.pref.save @user.pref.save
@user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : []) @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
@@ -137,7 +136,6 @@ class UsersController < ApplicationController
was_activated = (@user.status_change == [User::STATUS_REGISTERED, User::STATUS_ACTIVE]) was_activated = (@user.status_change == [User::STATUS_REGISTERED, User::STATUS_ACTIVE])
# TODO: Similar to My#account # TODO: Similar to My#account
@user.pref.attributes = params[:pref] @user.pref.attributes = params[:pref]
@user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
if @user.save if @user.save
@user.pref.save @user.pref.save
+6 -2
View File
@@ -471,7 +471,11 @@ module ApplicationHelper
end end
def accesskey(s) def accesskey(s)
Redmine::AccessKeys.key_for s @used_accesskeys ||= []
key = Redmine::AccessKeys.key_for(s)
return nil if @used_accesskeys.include?(key)
@used_accesskeys << key
key
end end
# Formats text according to system settings. # Formats text according to system settings.
@@ -758,7 +762,7 @@ module ApplicationHelper
if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first) if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first)
link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier}, link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier},
:class => 'changeset', :class => 'changeset',
:title => truncate_single_line(h(changeset.comments), :length => 100) :title => truncate_single_line(changeset.comments, :length => 100)
end end
else else
if repository && User.current.allowed_to?(:browse_repository, project) if repository && User.current.allowed_to?(:browse_repository, project)
+24
View File
@@ -29,6 +29,30 @@ module QueriesHelper
end end
end end
def query_filters_hidden_tags(query)
tags = ''.html_safe
query.filters.each do |field, options|
tags << hidden_field_tag("f[]", field, :id => nil)
tags << hidden_field_tag("op[#{field}]", options[:operator], :id => nil)
options[:values].each do |value|
tags << hidden_field_tag("v[#{field}][]", value, :id => nil)
end
end
tags
end
def query_columns_hidden_tags(query)
tags = ''.html_safe
query.columns.each do |column|
tags << hidden_field_tag("c[]", column.name, :id => nil)
end
tags
end
def query_hidden_tags(query)
query_filters_hidden_tags(query) + query_columns_hidden_tags(query)
end
def available_block_columns_tags(query) def available_block_columns_tags(query)
tags = ''.html_safe tags = ''.html_safe
query.available_block_columns.each do |column| query.available_block_columns.each do |column|
+1
View File
@@ -38,6 +38,7 @@ class Enumeration < ActiveRecord::Base
scope :shared, lambda { where(:project_id => nil) } scope :shared, lambda { where(:project_id => nil) }
scope :sorted, lambda { order("#{table_name}.position ASC") } scope :sorted, lambda { order("#{table_name}.position ASC") }
scope :active, lambda { where(:active => true) } scope :active, lambda { where(:active => true) }
scope :system, lambda { where(:project_id => nil) }
scope :named, lambda {|arg| where("LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip)} scope :named, lambda {|arg| where("LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip)}
def self.default def self.default
+91 -6
View File
@@ -854,15 +854,100 @@ class Issue < ActiveRecord::Base
end end
# Returns all the other issues that depend on the issue # Returns all the other issues that depend on the issue
# The algorithm is a modified breadth first search (bfs)
def all_dependent_issues(except=[]) def all_dependent_issues(except=[])
except << self # The found dependencies
dependencies = [] dependencies = []
dependencies += relations_from.map(&:issue_to)
dependencies += children unless leaf? # The visited flag for every node (issue) used by the breadth first search
dependencies << parent eNOT_DISCOVERED = 0 # The issue is "new" to the algorithm, it has not seen it before.
dependencies.compact!
ePROCESS_ALL = 1 # The issue is added to the queue. Process both children and relations of
# the issue when it is processed.
ePROCESS_RELATIONS_ONLY = 2 # The issue was added to the queue and will be output as dependent issue,
# but its children will not be added to the queue when it is processed.
eRELATIONS_PROCESSED = 3 # The related issues, the parent issue and the issue itself have been added to
# the queue, but its children have not been added.
ePROCESS_CHILDREN_ONLY = 4 # The relations and the parent of the issue have been added to the queue, but
# the children still need to be processed.
eALL_PROCESSED = 5 # The issue and all its children, its parent and its related issues have been
# added as dependent issues. It needs no further processing.
issue_status = Hash.new(eNOT_DISCOVERED)
# The queue
queue = []
# Initialize the bfs, add start node (self) to the queue
queue << self
issue_status[self] = ePROCESS_ALL
while (!queue.empty?) do
current_issue = queue.shift
current_issue_status = issue_status[current_issue]
dependencies << current_issue
# Add parent to queue, if not already in it.
parent = current_issue.parent
parent_status = issue_status[parent]
if parent && (parent_status == eNOT_DISCOVERED) && !except.include?(parent)
queue << parent
issue_status[parent] = ePROCESS_RELATIONS_ONLY
end
# Add children to queue, but only if they are not already in it and
# the children of the current node need to be processed.
if (current_issue_status == ePROCESS_CHILDREN_ONLY || current_issue_status == ePROCESS_ALL)
current_issue.children.each do |child|
next if except.include?(child)
if (issue_status[child] == eNOT_DISCOVERED)
queue << child
issue_status[child] = ePROCESS_ALL
elsif (issue_status[child] == eRELATIONS_PROCESSED)
queue << child
issue_status[child] = ePROCESS_CHILDREN_ONLY
elsif (issue_status[child] == ePROCESS_RELATIONS_ONLY)
queue << child
issue_status[child] = ePROCESS_ALL
end
end
end
# Add related issues to the queue, if they are not already in it.
current_issue.relations_from.map(&:issue_to).each do |related_issue|
next if except.include?(related_issue)
if (issue_status[related_issue] == eNOT_DISCOVERED)
queue << related_issue
issue_status[related_issue] = ePROCESS_ALL
elsif (issue_status[related_issue] == eRELATIONS_PROCESSED)
queue << related_issue
issue_status[related_issue] = ePROCESS_CHILDREN_ONLY
elsif (issue_status[related_issue] == ePROCESS_RELATIONS_ONLY)
queue << related_issue
issue_status[related_issue] = ePROCESS_ALL
end
end
# Set new status for current issue
if (current_issue_status == ePROCESS_ALL) || (current_issue_status == ePROCESS_CHILDREN_ONLY)
issue_status[current_issue] = eALL_PROCESSED
elsif (current_issue_status == ePROCESS_RELATIONS_ONLY)
issue_status[current_issue] = eRELATIONS_PROCESSED
end
end # while
# Remove the issues from the "except" parameter from the result array
dependencies -= except dependencies -= except
dependencies + dependencies.map {|issue| issue.all_dependent_issues(except)}.flatten dependencies.delete(self)
dependencies
end end
# Returns an array of issues that duplicate this one # Returns an array of issues that duplicate this one
+1 -1
View File
@@ -390,7 +390,7 @@ class Mailer < ActionMailer::Base
# Removes the author from the recipients and cc # Removes the author from the recipients and cc
# if he doesn't want to receive notifications about what he does # if he doesn't want to receive notifications about what he does
if @author && @author.logged? && @author.pref[:no_self_notified] if @author && @author.logged? && @author.pref.no_self_notified
headers[:to].delete(@author.mail) if headers[:to].is_a?(Array) headers[:to].delete(@author.mail) if headers[:to].is_a?(Array)
headers[:cc].delete(@author.mail) if headers[:cc].is_a?(Array) headers[:cc].delete(@author.mail) if headers[:cc].is_a?(Array)
end end
+4 -1
View File
@@ -673,7 +673,7 @@ class Project < ActiveRecord::Base
# Returns an auto-generated project identifier based on the last identifier used # Returns an auto-generated project identifier based on the last identifier used
def self.next_identifier def self.next_identifier
p = Project.order('created_on DESC').first p = Project.order('id DESC').first
p.nil? ? nil : p.identifier.to_s.succ p.nil? ? nil : p.identifier.to_s.succ
end end
@@ -840,6 +840,9 @@ class Project < ActiveRecord::Base
new_issue = Issue.new new_issue = Issue.new
new_issue.copy_from(issue, :subtasks => false, :link => false) new_issue.copy_from(issue, :subtasks => false, :link => false)
new_issue.project = self new_issue.project = self
# Changing project resets the custom field values
# TODO: handle this in Issue#project=
new_issue.custom_field_values = issue.custom_field_values.inject({}) {|h,v| h[v.custom_field_id] = v.value; h}
# Reassign fixed_versions by name, since names are unique per project # Reassign fixed_versions by name, since names are unique per project
if issue.fixed_version && issue.fixed_version.project == project if issue.fixed_version && issue.fixed_version.project == project
new_issue.fixed_version = self.versions.detect {|v| v.name == issue.fixed_version.name} new_issue.fixed_version = self.versions.detect {|v| v.name == issue.fixed_version.name}
+5 -2
View File
@@ -577,8 +577,11 @@ class Query < ActiveRecord::Base
customized_class = queried_class.reflect_on_association(assoc.to_sym).klass.base_class rescue nil customized_class = queried_class.reflect_on_association(assoc.to_sym).klass.base_class rescue nil
raise "Unknown #{queried_class.name} association #{assoc}" unless customized_class raise "Unknown #{queried_class.name} association #{assoc}" unless customized_class
end end
"#{queried_table_name}.#{customized_key} #{not_in} IN (SELECT #{customized_class.table_name}.id FROM #{customized_class.table_name} LEFT OUTER JOIN #{db_table} ON #{db_table}.customized_type='#{customized_class}' AND #{db_table}.customized_id=#{customized_class.table_name}.id AND #{db_table}.custom_field_id=#{custom_field_id} WHERE " + where = sql_for_field(field, operator, value, db_table, db_field, true)
sql_for_field(field, operator, value, db_table, db_field, true) + ')' if operator =~ /[<>]/
where = "(#{where}) AND #{db_table}.#{db_field} <> ''"
end
"#{queried_table_name}.#{customized_key} #{not_in} IN (SELECT #{customized_class.table_name}.id FROM #{customized_class.table_name} LEFT OUTER JOIN #{db_table} ON #{db_table}.customized_type='#{customized_class}' AND #{db_table}.customized_id=#{customized_class.table_name}.id AND #{db_table}.custom_field_id=#{custom_field_id} WHERE #{where})"
end end
# Helper method to generate the WHERE sql for a +field+, +operator+ and a +value+ # Helper method to generate the WHERE sql for a +field+, +operator+ and a +value+
+6 -2
View File
@@ -24,11 +24,15 @@ class TimeEntryActivity < Enumeration
OptionName OptionName
end end
def objects
TimeEntry.where(:activity_id => self_and_descendants(1).map(&:id))
end
def objects_count def objects_count
time_entries.count objects.count
end end
def transfer_relations(to) def transfer_relations(to)
time_entries.update_all("activity_id = #{to.id}") objects.update_all(:activity_id => to.id)
end end
end end
+3
View File
@@ -56,4 +56,7 @@ class UserPreference < ActiveRecord::Base
def warn_on_leaving_unsaved; self[:warn_on_leaving_unsaved] || '1'; end def warn_on_leaving_unsaved; self[:warn_on_leaving_unsaved] || '1'; end
def warn_on_leaving_unsaved=(value); self[:warn_on_leaving_unsaved]=value; end def warn_on_leaving_unsaved=(value); self[:warn_on_leaving_unsaved]=value; end
def no_self_notified; (self[:no_self_notified] == true || self[:no_self_notified] == '1'); end
def no_self_notified=(value); self[:no_self_notified]=value; end
end end
+2 -1
View File
@@ -47,7 +47,8 @@ class Version < ActiveRecord::Base
'wiki_page_title', 'wiki_page_title',
'status', 'status',
'sharing', 'sharing',
'custom_field_values' 'custom_field_values',
'custom_fields'
# Returns true if +user+ or current user is allowed to view the version # Returns true if +user+ or current user is allowed to view the version
def visible?(user=User.current) def visible?(user=User.current)
+1 -1
View File
@@ -12,7 +12,7 @@
<p><em><%=h @document.category.name %><br /> <p><em><%=h @document.category.name %><br />
<%= format_date @document.created_on %></em></p> <%= format_date @document.created_on %></em></p>
<div class="wiki"> <div class="wiki">
<%= textilizable @document.description, :attachments => @document.attachments %> <%= textilizable @document, :description, :attachments => @document.attachments %>
</div> </div>
<h3><%= l(:label_attachment_plural) %></h3> <h3><%= l(:label_attachment_plural) %></h3>
+1 -1
View File
@@ -4,7 +4,7 @@
<div class="box"> <div class="box">
<p><strong><%= l(:text_enumeration_destroy_question, @enumeration.objects_count) %></strong></p> <p><strong><%= l(:text_enumeration_destroy_question, @enumeration.objects_count) %></strong></p>
<p><label for='reassign_to_id'><%= l(:text_enumeration_category_reassign_to) %></label> <p><label for='reassign_to_id'><%= l(:text_enumeration_category_reassign_to) %></label>
<%= select_tag 'reassign_to_id', (content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---") + options_from_collection_for_select(@enumerations, 'id', 'name')) %></p> <%= select_tag 'reassign_to_id', (content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---", :value => '') + options_from_collection_for_select(@enumerations, 'id', 'name')) %></p>
</div> </div>
<%= submit_tag l(:button_apply) %> <%= submit_tag l(:button_apply) %>
+3
View File
@@ -1,3 +1,6 @@
<% if @journal.private_notes? %>
(<%= l(:field_private_notes) %>)
<% end %>
<%= l(:text_issue_updated, :id => "##{@issue.id}", :author => h(@journal.user)) %> <%= l(:text_issue_updated, :id => "##{@issue.id}", :author => h(@journal.user)) %>
<ul> <ul>
+1 -1
View File
@@ -1,4 +1,4 @@
<%= l(:text_issue_updated, :id => "##{@issue.id}", :author => @journal.user) %> <%= "(#{l(:field_private_notes)}) " if @journal.private_notes? -%><%= l(:text_issue_updated, :id => "##{@issue.id}", :author => @journal.user) %>
<% details_to_strings(@journal.details, true).each do |string| -%> <% details_to_strings(@journal.details, true).each do |string| -%>
<%= string %> <%= string %>
+1 -1
View File
@@ -3,7 +3,7 @@ var operatorLabels = <%= raw_json Query.operators_labels %>;
var operatorByType = <%= raw_json Query.operators_by_filter_type %>; var operatorByType = <%= raw_json Query.operators_by_filter_type %>;
var availableFilters = <%= raw_json query.available_filters_as_json %>; var availableFilters = <%= raw_json query.available_filters_as_json %>;
var labelDayPlural = <%= raw_json l(:label_day_plural) %>; var labelDayPlural = <%= raw_json l(:label_day_plural) %>;
var allProjects = <%= raw query.all_projects_values.to_json %>; var allProjects = <%= raw_json query.all_projects_values %>;
$(document).ready(function(){ $(document).ready(function(){
initFilters(); initFilters();
<% query.filters.each do |field, options| %> <% query.filters.each do |field, options| %>
+2 -1
View File
@@ -27,7 +27,8 @@
<div id="csv-export-options" style="display:none;"> <div id="csv-export-options" style="display:none;">
<h3 class="title"><%= l(:label_export_options, :export_format => 'CSV') %></h3> <h3 class="title"><%= l(:label_export_options, :export_format => 'CSV') %></h3>
<%= form_tag(params.merge({:format => 'csv',:page=>nil}), :method => :get, :id => 'csv-export-form') do %> <%= form_tag(params.slice(:project_id, :issue_id).merge(:format => 'csv', :page=>nil), :method => :get, :id => 'csv-export-form') do %>
<%= query_hidden_tags @query %>
<p> <p>
<label><%= radio_button_tag 'columns', '', true %> <%= l(:description_selected_columns) %></label><br /> <label><%= radio_button_tag 'columns', '', true %> <%= l(:description_selected_columns) %></label><br />
<label><%= radio_button_tag 'columns', 'all' %> <%= l(:description_all_columns) %></label> <label><%= radio_button_tag 'columns', 'all' %> <%= l(:description_all_columns) %></label>
+5 -4
View File
@@ -19,9 +19,10 @@
end %> end %>
<p><em class="info"><%= l(:text_user_mail_option) %></em></p> <p><em class="info"><%= l(:text_user_mail_option) %></em></p>
<% end %> <% end %>
<%= fields_for :pref, @user.pref do |pref_fields| %>
<p> <p>
<label> <%= pref_fields.check_box :no_self_notified %>
<%= l(:label_user_mail_no_self_notified) %> <label for="pref_no_self_notified"><%= l(:label_user_mail_no_self_notified) %></label>
<%= check_box_tag 'no_self_notified', 1, @user.pref[:no_self_notified] %>
</label>
</p> </p>
<% end %>
+2 -2
View File
@@ -50,8 +50,8 @@ ar:
one: "حوالي ساعة" one: "حوالي ساعة"
other: "ساعات %{count}حوالي " other: "ساعات %{count}حوالي "
x_hours: x_hours:
one: "1 hour" one: "%{count} ساعة"
other: "%{count} hours" other: "%{count} ساعات"
x_days: x_days:
one: "يوم" one: "يوم"
other: "%{count} أيام" other: "%{count} أيام"
+2 -2
View File
@@ -109,8 +109,8 @@ az:
many: "təxminən %{count} saat" many: "təxminən %{count} saat"
other: "təxminən %{count} saat" other: "təxminən %{count} saat"
x_hours: x_hours:
one: "1 hour" one: "1 saat"
other: "%{count} hours" other: "%{count} saat"
x_days: x_days:
one: "%{count} gün" one: "%{count} gün"
few: "%{count} gün" few: "%{count} gün"
+2 -2
View File
@@ -51,8 +51,8 @@ bg:
one: "около 1 час" one: "около 1 час"
other: "около %{count} часа" other: "около %{count} часа"
x_hours: x_hours:
one: "1 hour" one: "1 час"
other: "%{count} hours" other: "%{count} часа"
x_days: x_days:
one: "1 ден" one: "1 ден"
other: "%{count} дена" other: "%{count} дена"
+2 -2
View File
@@ -49,8 +49,8 @@ bs:
one: "oko 1 sahat" one: "oko 1 sahat"
other: "oko %{count} sahata" other: "oko %{count} sahata"
x_hours: x_hours:
one: "1 hour" one: "1 sahat"
other: "%{count} hours" other: "%{count} sahata"
x_days: x_days:
one: "1 dan" one: "1 dan"
other: "%{count} dana" other: "%{count} dana"
+2 -2
View File
@@ -53,8 +53,8 @@ ca:
one: "aproximadament 1 hora" one: "aproximadament 1 hora"
other: "aproximadament %{count} hores" other: "aproximadament %{count} hores"
x_hours: x_hours:
one: "1 hour" one: "1 hora"
other: "%{count} hours" other: "%{count} hores"
x_days: x_days:
one: "1 dia" one: "1 dia"
other: "%{count} dies" other: "%{count} dies"
+2 -2
View File
@@ -55,8 +55,8 @@ cs:
one: "asi 1 hodina" one: "asi 1 hodina"
other: "asi %{count} hodin" other: "asi %{count} hodin"
x_hours: x_hours:
one: "1 hour" one: "1 hodina"
other: "%{count} hours" other: "%{count} hodin"
x_days: x_days:
one: "1 den" one: "1 den"
other: "%{count} dnů" other: "%{count} dnů"
+2 -2
View File
@@ -52,8 +52,8 @@ da:
one: "cirka en time" one: "cirka en time"
other: "cirka %{count} timer" other: "cirka %{count} timer"
x_hours: x_hours:
one: "1 hour" one: "1 time"
other: "%{count} hours" other: "%{count} timer"
x_days: x_days:
one: "en dag" one: "en dag"
other: "%{count} dage" other: "%{count} dage"
+2 -2
View File
@@ -53,8 +53,8 @@ de:
one: 'etwa 1 Stunde' one: 'etwa 1 Stunde'
other: 'etwa %{count} Stunden' other: 'etwa %{count} Stunden'
x_hours: x_hours:
one: "1 hour" one: "1 Stunde"
other: "%{count} hours" other: "%{count} Stunden"
x_days: x_days:
one: '1 Tag' one: '1 Tag'
other: '%{count} Tagen' other: '%{count} Tagen'
+2 -2
View File
@@ -52,8 +52,8 @@ el:
one: "περίπου 1 ώρα" one: "περίπου 1 ώρα"
other: "περίπου %{count} ώρες" other: "περίπου %{count} ώρες"
x_hours: x_hours:
one: "1 hour" one: "1 ώρα"
other: "%{count} hours" other: "%{count} ώρες"
x_days: x_days:
one: "1 ημέρα" one: "1 ημέρα"
other: "%{count} ημέρες" other: "%{count} ημέρες"
+2 -2
View File
@@ -80,8 +80,8 @@ es:
one: "alrededor de 1 hora" one: "alrededor de 1 hora"
other: "alrededor de %{count} horas" other: "alrededor de %{count} horas"
x_hours: x_hours:
one: "1 hour" one: "1 hora"
other: "%{count} hours" other: "%{count} horas"
x_days: x_days:
one: "1 día" one: "1 día"
other: "%{count} días" other: "%{count} días"
+2 -2
View File
@@ -67,8 +67,8 @@ et:
one: "umbes tund" one: "umbes tund"
other: "umbes %{count} tundi" other: "umbes %{count} tundi"
x_hours: x_hours:
one: "1 hour" one: "1 tund"
other: "%{count} hours" other: "%{count} tundi"
x_days: x_days:
one: "1 päev" one: "1 päev"
other: "%{count} päeva" other: "%{count} päeva"
+2 -2
View File
@@ -53,8 +53,8 @@ eu:
one: "ordu 1 inguru" one: "ordu 1 inguru"
other: "%{count} ordu inguru" other: "%{count} ordu inguru"
x_hours: x_hours:
one: "1 hour" one: "ordu 1"
other: "%{count} hours" other: "%{count} ordu"
x_days: x_days:
one: "egun 1" one: "egun 1"
other: "%{count} egun" other: "%{count} egun"
+2 -2
View File
@@ -50,8 +50,8 @@ fa:
one: "نزدیک 1 ساعت" one: "نزدیک 1 ساعت"
other: "نزدیک %{count} ساعت" other: "نزدیک %{count} ساعت"
x_hours: x_hours:
one: "1 hour" one: "1 ساعت"
other: "%{count} hours" other: "%{count} ساعت"
x_days: x_days:
one: "1 روز" one: "1 روز"
other: "%{count} روز" other: "%{count} روز"
+2 -2
View File
@@ -95,8 +95,8 @@ fi:
one: "noin tunti" one: "noin tunti"
other: "noin %{count} tuntia" other: "noin %{count} tuntia"
x_hours: x_hours:
one: "1 hour" one: "1 tunti"
other: "%{count} hours" other: "%{count} tuntia"
x_days: x_days:
one: "päivä" one: "päivä"
other: "%{count} päivää" other: "%{count} päivää"
+2 -2
View File
@@ -91,8 +91,8 @@ gl:
one: 'aproximadamente unha hora' one: 'aproximadamente unha hora'
other: '%{count} horas' other: '%{count} horas'
x_hours: x_hours:
one: "1 hour" one: "1 hora"
other: "%{count} hours" other: "%{count} horas"
x_days: x_days:
one: '1 día' one: '1 día'
other: '%{count} días' other: '%{count} días'
+2 -2
View File
@@ -56,8 +56,8 @@ he:
one: 'בערך שעה אחת' one: 'בערך שעה אחת'
other: 'בערך %{count} שעות' other: 'בערך %{count} שעות'
x_hours: x_hours:
one: "1 hour" one: "1 שעה"
other: "%{count} hours" other: "%{count} שעות"
x_days: x_days:
one: 'יום אחד' one: 'יום אחד'
other: '%{count} ימים' other: '%{count} ימים'
+2 -2
View File
@@ -49,8 +49,8 @@ hr:
one: "oko sat vremena" one: "oko sat vremena"
other: "oko %{count} sati" other: "oko %{count} sati"
x_hours: x_hours:
one: "1 hour" one: "1 sata"
other: "%{count} hours" other: "%{count} sati"
x_days: x_days:
one: "1 dan" one: "1 dan"
other: "%{count} dana" other: "%{count} dana"
+2 -2
View File
@@ -51,8 +51,8 @@
one: 'csaknem 1 órája' one: 'csaknem 1 órája'
other: 'csaknem %{count} órája' other: 'csaknem %{count} órája'
x_hours: x_hours:
one: "1 hour" one: "1 óra"
other: "%{count} hours" other: "%{count} óra"
x_days: x_days:
one: '1 napja' one: '1 napja'
other: '%{count} napja' other: '%{count} napja'
+2 -2
View File
@@ -47,8 +47,8 @@ id:
one: "sekitar sejam" one: "sekitar sejam"
other: "sekitar %{count} jam" other: "sekitar %{count} jam"
x_hours: x_hours:
one: "1 hour" one: "1 jam"
other: "%{count} hours" other: "%{count} jam"
x_days: x_days:
one: "sehari" one: "sehari"
other: "%{count} hari" other: "%{count} hari"
+68 -71
View File
@@ -55,8 +55,8 @@ it:
one: "circa un'ora" one: "circa un'ora"
other: "circa %{count} ore" other: "circa %{count} ore"
x_hours: x_hours:
one: "1 hour" one: "1 ora"
other: "%{count} hours" other: "%{count} ore"
x_days: x_days:
one: "1 giorno" one: "1 giorno"
other: "%{count} giorni" other: "%{count} giorni"
@@ -1001,90 +1001,87 @@ it:
button_export: Esporta button_export: Esporta
label_export_options: "%{export_format} opzioni per l'export" label_export_options: "%{export_format} opzioni per l'export"
error_attachment_too_big: Questo file non può essere caricato in quanto la sua dimensione supera la massima consentita (%{max_size}) error_attachment_too_big: Questo file non può essere caricato in quanto la sua dimensione supera la massima consentita (%{max_size})
notice_failed_to_save_time_entries: "Failed to save %{count} time entrie(s) on %{total} selected: %{ids}." notice_failed_to_save_time_entries: "Non ho potuto salvare %{count} registrazioni di tempo impiegato su %{total} selezionate: %{ids}."
label_x_issues: label_x_issues:
zero: 0 segnalazione zero: 0 segnalazione
one: 1 segnalazione one: 1 segnalazione
other: "%{count} segnalazioni" other: "%{count} segnalazioni"
label_repository_new: New repository label_repository_new: Nuovo repository
field_repository_is_default: Main repository field_repository_is_default: Repository principale
label_copy_attachments: Copy attachments label_copy_attachments: Copia allegati
label_item_position: "%{position}/%{count}" label_item_position: "%{position}/%{count}"
label_completed_versions: Completed versions label_completed_versions: Completed versions
text_project_identifier_info: Only lower case letters (a-z), numbers, dashes and underscores are allowed.<br />Once saved, the identifier cannot be changed. text_project_identifier_info: Consentiti solo lettere minuscole (a-z), numeri, trattini e trattini bassi.<br />Una volta salvato, l'identificatore non può essere modificato.
field_multiple: Multiple values field_multiple: Valori multipli
setting_commit_cross_project_ref: Allow issues of all the other projects to be referenced and fixed setting_commit_cross_project_ref: Allow issues of all the other projects to be referenced and fixed
text_issue_conflict_resolution_add_notes: Add my notes and discard my other changes text_issue_conflict_resolution_add_notes: Aggiunge le mie note e non salvare le mie ulteriori modifiche
text_issue_conflict_resolution_overwrite: Apply my changes anyway (previous notes will be kept but some changes may be overwritten) text_issue_conflict_resolution_overwrite: Applica comunque le mie modifiche (le note precedenti verranno mantenute ma alcuni cambiamenti potrebbero essere sovrascritti)
notice_issue_update_conflict: The issue has been updated by an other user while you were editing it. notice_issue_update_conflict: La segnalazione è stata aggiornata da un altro utente mentre la stavi editando.
text_issue_conflict_resolution_cancel: Discard all my changes and redisplay %{link} text_issue_conflict_resolution_cancel: Cancella ogni modifica e rivisualizza %{link}
permission_manage_related_issues: Manage related issues permission_manage_related_issues: Gestisci relative segnalazioni
field_auth_source_ldap_filter: LDAP filter field_auth_source_ldap_filter: Filtro LDAP
label_search_for_watchers: Search for watchers to add label_search_for_watchers: Cerca osservatori da aggiungere
notice_account_deleted: Your account has been permanently deleted. notice_account_deleted: Il tuo account sarà definitivamente rimosso.
setting_unsubscribe: Allow users to delete their own account setting_unsubscribe: Consentire agli utenti di cancellare il proprio account
button_delete_my_account: Delete my account button_delete_my_account: Cancella il mio account
text_account_destroy_confirmation: |- text_account_destroy_confirmation: "Sei sicuro di voler procedere?\nIl tuo account sarà definitivamente cancellato, senza alcuna possibilità di ripristino."
Are you sure you want to proceed? error_session_expired: "La tua sessione è scaduta. Effettua nuovamente il login."
Your account will be permanently deleted, with no way to reactivate it. text_session_expiration_settings: "Attenzione: la modifica di queste impostazioni può far scadere le sessioni correnti, compresa la tua."
error_session_expired: Your session has expired. Please login again. setting_session_lifetime: Massima durata di una sessione
text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours." setting_session_timeout: Timeout di inattività di una sessione
setting_session_lifetime: Session maximum lifetime label_session_expiration: Scadenza sessione
setting_session_timeout: Session inactivity timeout permission_close_project: Chiusura / riapertura progetto
label_session_expiration: Session expiration label_show_closed_projects: Vedi progetti chiusi
permission_close_project: Close / reopen the project button_close: Chiudi
label_show_closed_projects: View closed projects button_reopen: Riapri
button_close: Close project_status_active: attivo
button_reopen: Reopen project_status_closed: chiuso
project_status_active: active project_status_archived: archiviato
project_status_closed: closed text_project_closed: Questo progetto è chiuso e in sola lettura.
project_status_archived: archived notice_user_successful_create: Creato utente %{id}.
text_project_closed: This project is closed and read-only. field_core_fields: Campi standard
notice_user_successful_create: User %{id} created. field_timeout: Timeout (in secondi)
field_core_fields: Standard fields setting_thumbnails_enabled: Mostra miniature degli allegati
field_timeout: Timeout (in seconds) setting_thumbnails_size: Dimensioni delle miniature (in pixels)
setting_thumbnails_enabled: Display attachment thumbnails label_status_transitions: Transizioni di stato
setting_thumbnails_size: Thumbnails size (in pixels) label_fields_permissions: Permessi sui campi
label_status_transitions: Status transitions label_readonly: Sola lettura
label_fields_permissions: Fields permissions label_required: Richiesto
label_readonly: Read-only text_repository_identifier_info: Consentiti solo lettere minuscole (a-z), numeri, trattini e trattini bassi.<br />Una volta salvato, ll'identificatore non può essere modificato.
label_required: Required
text_repository_identifier_info: Only lower case letters (a-z), numbers, dashes and underscores are allowed.<br />Once saved, the identifier cannot be changed.
field_board_parent: Parent forum field_board_parent: Parent forum
label_attribute_of_project: Project's %{name} label_attribute_of_project: Project's %{name}
label_attribute_of_author: Author's %{name} label_attribute_of_author: Author's %{name}
label_attribute_of_assigned_to: Assignee's %{name} label_attribute_of_assigned_to: Assegnatari %{name}
label_attribute_of_fixed_version: Target version's %{name} label_attribute_of_fixed_version: Target version's %{name}
label_copy_subtasks: Copy subtasks label_copy_subtasks: Copia sottoattività
label_copied_to: copied to label_copied_to: copia a
label_copied_from: copied from label_copied_from: copia da
label_any_issues_in_project: any issues in project label_any_issues_in_project: ogni segnalazione del progetto
label_any_issues_not_in_project: any issues not in project label_any_issues_not_in_project: ogni segnalazione non nel progetto
field_private_notes: Private notes field_private_notes: Note private
permission_view_private_notes: View private notes permission_view_private_notes: Visualizza note private
permission_set_notes_private: Set notes as private permission_set_notes_private: Imposta note come private
label_no_issues_in_project: no issues in project label_no_issues_in_project: progetto privo di segnalazioni
label_any: tutti label_any: tutti
label_last_n_weeks: last %{count} weeks label_last_n_weeks: ultime %{count} settimane
setting_cross_project_subtasks: Allow cross-project subtasks setting_cross_project_subtasks: Consenti sottoattività cross-project
label_cross_project_descendants: Con sottoprogetti label_cross_project_descendants: Con sottoprogetti
label_cross_project_tree: Con progetto padre label_cross_project_tree: Con progetto padre
label_cross_project_hierarchy: Con gerarchia progetto label_cross_project_hierarchy: Con gerarchia progetto
label_cross_project_system: Con tutti i progetti label_cross_project_system: Con tutti i progetti
button_hide: Hide button_hide: Nascondi
setting_non_working_week_days: Non-working days setting_non_working_week_days: Giorni non lavorativi
label_in_the_next_days: in the next label_in_the_next_days: nei prossimi
label_in_the_past_days: in the past label_in_the_past_days: nei passati
label_attribute_of_user: User's %{name} label_attribute_of_user: Utente %{name}
text_turning_multiple_off: If you disable multiple values, multiple values will be text_turning_multiple_off: Disabilitando valori multipli, i valori multipli verranno rimossi, in modo da mantenere un solo valore per item.
removed in order to preserve only one value per item. label_attribute_of_issue: Segnalazione %{name}
label_attribute_of_issue: Issue's %{name} permission_add_documents: Aggiungi documenti
permission_add_documents: Add documents permission_edit_documents: Edita documenti
permission_edit_documents: Edit documents permission_delete_documents: Cancella documenti
permission_delete_documents: Delete documents
label_gantt_progress_line: Progress line label_gantt_progress_line: Progress line
setting_jsonp_enabled: Enable JSONP support setting_jsonp_enabled: Abilita supporto a JSONP
field_inherit_members: Inherit members field_inherit_members: Eredita membri
field_closed_on: Closed field_closed_on: Chiuso
setting_default_projects_tracker_ids: Default trackers for new projects setting_default_projects_tracker_ids: Trackers di default per nuovi progetti
label_total_time: Totale label_total_time: Totale
+2 -2
View File
@@ -50,8 +50,8 @@ ko:
one: "약 한시간" one: "약 한시간"
other: "약 %{count}시간" other: "약 %{count}시간"
x_hours: x_hours:
one: "1 hour" one: "1 시간"
other: "%{count} hours" other: "%{count} 시간"
x_days: x_days:
one: "하루" one: "하루"
other: "%{count}일" other: "%{count}일"
+32 -32
View File
@@ -1,8 +1,10 @@
# Lithuanian translations for Ruby on Rails # Lithuanian translations for Ruby on Rails
# by Laurynas Butkus (laurynas.butkus@gmail.com) # by Laurynas Butkus (laurynas.butkus@gmail.com)
# Redmine translation by Gediminas Muižis gediminas.muizis@gmail.com # Redmine translation by Gediminas Muižis gediminas.muizis@gmail.com
# and Sergej Jegorov sergej.jegorov@gmail.com # and Sergej Jegorov sergej.jegorov@gmail.com
# and Gytis Gurklys gytis.gurklys@gmail.com # and Gytis Gurklys gytis.gurklys@gmail.com
# and Andrius Kriučkovas andrius.kriuckovas@gmail.com
lt: lt:
direction: ltr direction: ltr
date: date:
@@ -228,8 +230,8 @@ lt:
notice_default_data_loaded: Numatytoji konfiguracija sėkmingai užkrauta. notice_default_data_loaded: Numatytoji konfiguracija sėkmingai užkrauta.
notice_unable_delete_version: Neįmanoma panaikinti versiją. notice_unable_delete_version: Neįmanoma panaikinti versiją.
notice_unable_delete_time_entry: Neįmano ištrinti laiko žurnalo įrašą. notice_unable_delete_time_entry: Neįmano ištrinti laiko žurnalo įrašą.
notice_issue_done_ratios_updated: Issue done ratios updated. notice_issue_done_ratios_updated: Problemos baigtumo rodikliai atnaujinti.
notice_gantt_chart_truncated: The chart was truncated because it exceeds the maximum number of items that can be displayed (%{max}) notice_gantt_chart_truncated: Grafikas buvo sutrumpintas, kadangi jis viršija maksimalų (%{max}) leistinų atvaizduoti elementų kiekį
notice_issue_successful_create: Darbas %{id} sukurtas. notice_issue_successful_create: Darbas %{id} sukurtas.
error_can_t_load_default_data: "Numatytoji konfiguracija negali būti užkrauta: %{value}" error_can_t_load_default_data: "Numatytoji konfiguracija negali būti užkrauta: %{value}"
@@ -241,16 +243,16 @@ lt:
error_no_tracker_in_project: 'Joks pėdsekys nesusietas su šiuo projektu. Prašom patikrinti Projekto nustatymus.' error_no_tracker_in_project: 'Joks pėdsekys nesusietas su šiuo projektu. Prašom patikrinti Projekto nustatymus.'
error_no_default_issue_status: Nenustatyta numatytoji darbų būsena. Prašome patikrinti konfigūravimą ("Administravimas -> Darbų būsenos"). error_no_default_issue_status: Nenustatyta numatytoji darbų būsena. Prašome patikrinti konfigūravimą ("Administravimas -> Darbų būsenos").
error_can_not_delete_custom_field: Negalima ištrinti kliento lauko error_can_not_delete_custom_field: Negalima ištrinti kliento lauko
error_can_not_delete_tracker: "This tracker contains issues and cannot be deleted." error_can_not_delete_tracker: "Šis pėdsekys turi įrašus ir todėl negali būti ištrintas."
error_can_not_remove_role: "This role is in use and cannot be deleted." error_can_not_remove_role: "Ši rolė yra naudojama ir negali būti ištrinta."
error_can_not_reopen_issue_on_closed_version: Uždarytai versijai priskirtas darbas negali būti atnaujintas. error_can_not_reopen_issue_on_closed_version: Uždarytai versijai priskirtas darbas negali būti atnaujintas.
error_can_not_archive_project: Šio projekto negalima suarchyvuoti error_can_not_archive_project: Šio projekto negalima suarchyvuoti
error_issue_done_ratios_not_updated: "Issue done ratios not updated." error_issue_done_ratios_not_updated: "Įrašo baigtumo rodikliai nebuvo atnaujinti. "
error_workflow_copy_source: 'Please select a source tracker or role' error_workflow_copy_source: 'Prašome pasirinkti pirminį šaltinio seklį arba rolę'
error_workflow_copy_target: 'Please select target tracker(s) and role(s)' error_workflow_copy_target: 'Prašome pasirinkti galutinį paskirties seklį(-ius) arba rolę(-s)'
error_unable_delete_issue_status: 'Negalima ištrinti darbo statuso' error_unable_delete_issue_status: 'Negalima ištrinti darbo statuso'
error_unable_to_connect: Negalima prisijungti (%{value}) error_unable_to_connect: Negalima prisijungti (%{value})
error_attachment_too_big: "This file cannot be uploaded because it exceeds the maximum allowed file size (%{max_size})" error_attachment_too_big: "Ši byla negali būti įkelta, nes viršija maksimalią (%{max_size}) leistiną bylos apimtį"
warning_attachments_not_saved: "%{count} byla(ų) negali būti išsaugota." warning_attachments_not_saved: "%{count} byla(ų) negali būti išsaugota."
mail_subject_lost_password: "Jūsų %{value} slaptažodis" mail_subject_lost_password: "Jūsų %{value} slaptažodis"
@@ -431,7 +433,7 @@ lt:
setting_cache_formatted_text: Paslėpti formatuotą tekstą setting_cache_formatted_text: Paslėpti formatuotą tekstą
setting_default_notification_option: Numatytosios pranešimų nuostatos setting_default_notification_option: Numatytosios pranešimų nuostatos
setting_commit_logtime_enabled: Įjungti laiko registravimą setting_commit_logtime_enabled: Įjungti laiko registravimą
setting_commit_logtime_activity_id: Activity for logged time setting_commit_logtime_activity_id: Laiko įrašų veikla
setting_gantt_items_limit: Maksimalus rodmenų skaičius rodomas Gantt'o grafike setting_gantt_items_limit: Maksimalus rodmenų skaičius rodomas Gantt'o grafike
setting_issue_group_assignment: Leisti darbo priskirimą grupėms setting_issue_group_assignment: Leisti darbo priskirimą grupėms
setting_default_issue_start_date_to_creation_date: Naudoti dabartinę datą kaip naujų darbų pradžios datą setting_default_issue_start_date_to_creation_date: Naudoti dabartinę datą kaip naujų darbų pradžios datą
@@ -877,8 +879,8 @@ lt:
label_issues_visibility_public: Visi vieši darbai label_issues_visibility_public: Visi vieši darbai
label_issues_visibility_own: Darbai, sukurti vartotojo arba jam priskirti label_issues_visibility_own: Darbai, sukurti vartotojo arba jam priskirti
label_git_report_last_commit: Nurodyti paskutinį failų ir katalogų pakeitimą label_git_report_last_commit: Nurodyti paskutinį failų ir katalogų pakeitimą
label_parent_revision: Parent label_parent_revision: Pirminė revizija
label_child_revision: Child label_child_revision: Sekanti revizija
label_export_options: "%{export_format} eksportavimo nustatymai" label_export_options: "%{export_format} eksportavimo nustatymai"
button_login: Registruotis button_login: Registruotis
@@ -991,20 +993,19 @@ lt:
text_enumeration_destroy_question: "%{count} objektai(ų) priskirti šiai reikšmei." text_enumeration_destroy_question: "%{count} objektai(ų) priskirti šiai reikšmei."
text_enumeration_category_reassign_to: 'Priskirti juos šiai reikšmei:' text_enumeration_category_reassign_to: 'Priskirti juos šiai reikšmei:'
text_email_delivery_not_configured: "El.pašto siuntimas nesukonfigūruotas, ir perspėjimai neaktyvus.\nSukonfigūruokite savo SMTP serverį byloje config/configuration.yml ir perleiskite programą norėdami pritaikyti pakeitimus." text_email_delivery_not_configured: "El.pašto siuntimas nesukonfigūruotas, ir perspėjimai neaktyvus.\nSukonfigūruokite savo SMTP serverį byloje config/configuration.yml ir perleiskite programą norėdami pritaikyti pakeitimus."
text_repository_usernames_mapping: "Select or update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped."
text_repository_usernames_mapping: "Parinkite ar atnaujinkite Redmine vartotoją, kuris paminėtas saugyklos log'e.\nVartotojai, turintys tą patį Redmine ir saugyklos vardą ar el.paštą yra automatiškai surišti." text_repository_usernames_mapping: "Parinkite ar atnaujinkite Redmine vartotoją, kuris paminėtas saugyklos log'e.\nVartotojai, turintys tą patį Redmine ir saugyklos vardą ar el.paštą yra automatiškai surišti."
text_diff_truncated: "... Šis diff'as nukarpytas, nes jis viršijo maksimalų rodomų eilučių skaičių." text_diff_truncated: "... Šis diff'as nukarpytas, nes jis viršijo maksimalų rodomų eilučių skaičių."
text_custom_field_possible_values_info: 'Po vieną eilutę kiekvienai reikšmei' text_custom_field_possible_values_info: 'Po vieną eilutę kiekvienai reikšmei'
text_wiki_page_destroy_question: "This page has %{descendants} child page(s) and descendant(s). What do you want to do?" text_wiki_page_destroy_question: "Šis puslapis turi %{descendants} susijusių arba išvestinių puslapių. Ką norėtumėte daryti?"
text_wiki_page_nullify_children: Laikyti child puslapius kaip pagrindinius puslapius text_wiki_page_nullify_children: Laikyti child puslapius kaip pagrindinius puslapius
text_wiki_page_destroy_children: "Pašalinti child puslapius ir jų palikuonis" text_wiki_page_destroy_children: "Pašalinti child puslapius ir jų palikuonis"
text_wiki_page_reassign_children: "Priskirkite iš naujo 'child' puslapius šiam pagrindiniam puslapiui" text_wiki_page_reassign_children: "Priskirkite iš naujo 'child' puslapius šiam pagrindiniam puslapiui"
text_own_membership_delete_confirmation: "You are about to remove some or all of your permissions and may no longer be able to edit this project after that.\nAre you sure you want to continue?" text_own_membership_delete_confirmation: "Jūs esate pasiruošęs panaikinti dalį arba visus leidimus ir po šio pakeitimo galite prarasti šio projekto redagavimo galimybę. \n Ar jūs esate įsitikinęs ir tęsti?"
text_zoom_in: Priartinti text_zoom_in: Priartinti
text_zoom_out: Nutolinti text_zoom_out: Nutolinti
text_warn_on_leaving_unsaved: "Dabartinis puslapis turi neišsaugoto teksto, kuris bus prarastas, jeigu paliksite šį puslapį." text_warn_on_leaving_unsaved: "Dabartinis puslapis turi neišsaugoto teksto, kuris bus prarastas, jeigu paliksite šį puslapį."
text_scm_path_encoding_note: "Numatytasis: UTF-8" text_scm_path_encoding_note: "Numatytasis: UTF-8"
text_git_repository_note: Repository is bare and local (e.g. /gitrepo, c:\gitrepo) text_git_repository_note: Saugykla (repository) yra plika ir vietinė (pvz. /gitrepo, c:\gitrepo)
text_mercurial_repository_note: Vietinė saugykla (e.g. /hgrepo, c:\hgrepo) text_mercurial_repository_note: Vietinė saugykla (e.g. /hgrepo, c:\hgrepo)
text_scm_command: Komanda text_scm_command: Komanda
text_scm_command_version: Versija text_scm_command_version: Versija
@@ -1069,7 +1070,7 @@ lt:
label_completed_versions: Užbaigtos versijos label_completed_versions: Užbaigtos versijos
text_project_identifier_info: Leidžiamos tik mažosios raidės (a-z), skaitmenys, brūkšneliai ir pabraukimo simboliai.<br />Kartą išsaugojus pakeitimai negalimi text_project_identifier_info: Leidžiamos tik mažosios raidės (a-z), skaitmenys, brūkšneliai ir pabraukimo simboliai.<br />Kartą išsaugojus pakeitimai negalimi
field_multiple: Keletas reikšmių field_multiple: Keletas reikšmių
setting_commit_cross_project_ref: Allow issues of all the other projects to be referenced and fixed setting_commit_cross_project_ref: Leisti visų kitų projektų įrašus susieti nuorodomis ir sutaisyti
text_issue_conflict_resolution_add_notes: Išsaugoti mano žinutę ir atmesti likusius mano pataisymus text_issue_conflict_resolution_add_notes: Išsaugoti mano žinutę ir atmesti likusius mano pataisymus
text_issue_conflict_resolution_overwrite: Išsaugoti mano pakeitimus (ankstesnių pakeitimų žinutės bus išsaugotos, tačiau kai kurie pakeitimai bus perrašyti) text_issue_conflict_resolution_overwrite: Išsaugoti mano pakeitimus (ankstesnių pakeitimų žinutės bus išsaugotos, tačiau kai kurie pakeitimai bus perrašyti)
notice_issue_update_conflict: Darbas buvo pakoreguotas kito vartotojo kol jūs atlikote pakeitimus. notice_issue_update_conflict: Darbas buvo pakoreguotas kito vartotojo kol jūs atlikote pakeitimus.
@@ -1131,18 +1132,17 @@ lt:
setting_non_working_week_days: Nedarbo dienos setting_non_working_week_days: Nedarbo dienos
label_in_the_next_days: per ateinančias label_in_the_next_days: per ateinančias
label_in_the_past_days: per paskutines label_in_the_past_days: per paskutines
label_attribute_of_user: User's %{name} label_attribute_of_user: Vartotojo %{name}
text_turning_multiple_off: If you disable multiple values, multiple values will be text_turning_multiple_off: Jei jūs išjungsite kelių reikšmių pasirinkimą, visos išvardintos reikšmės bus pašalintos ir palikta tik viena reikšmė kiekvienam laukui.
removed in order to preserve only one value per item. label_attribute_of_issue: Įrašai %{name}
label_attribute_of_issue: Issue's %{name} permission_add_documents: Pridėti dokumentus
permission_add_documents: Add documents permission_edit_documents: Redaguoti dokumentus
permission_edit_documents: Edit documents permission_delete_documents: Trinti dokumentus
permission_delete_documents: Delete documents label_gantt_progress_line: Progreso linija
label_gantt_progress_line: Progress line setting_jsonp_enabled: Įgalinti JSONP palaikymą
setting_jsonp_enabled: Enable JSONP support field_inherit_members: Paveldėti narius
field_inherit_members: Inherit members field_closed_on: Uždarytas
field_closed_on: Closed setting_default_projects_tracker_ids: Sekliai pagal nutylėjimą naujiems projektams
setting_default_projects_tracker_ids: Default trackers for new projects
label_total_time: Iš viso label_total_time: Iš viso
text_scm_config: You can configure your SCM commands in config/configuration.yml. Please restart the application after editing it. text_scm_config: Jūs galite pakeisti SCM komandas byloje config/configuration.yml. Prašome perkrauti programą po redagavimo, idant įgalinti pakeitimus.
text_scm_command_not_available: SCM command is not available. Please check settings on the administration panel. text_scm_command_not_available: SCM komanda nepasiekiama. Patikrinkite administravimo skydelio nustatymus.
+3 -3
View File
@@ -46,8 +46,8 @@ lv:
one: "aptuveni 1 stunda" one: "aptuveni 1 stunda"
other: "aptuveni %{count} stundas" other: "aptuveni %{count} stundas"
x_hours: x_hours:
one: "1 hour" one: "1 stunda"
other: "%{count} hours" other: "%{count} stundas"
x_days: x_days:
one: "1 diena" one: "1 diena"
other: "%{count} dienas" other: "%{count} dienas"
@@ -775,7 +775,7 @@ lv:
button_cancel: Atcelt button_cancel: Atcelt
button_activate: Aktivizēt button_activate: Aktivizēt
button_sort: Kārtot button_sort: Kārtot
button_log_time: Ilgs laiks button_log_time: Reģistrēt laiku
button_rollback: Atjaunot uz šo versiju button_rollback: Atjaunot uz šo versiju
button_watch: Vērot button_watch: Vērot
button_unwatch: Nevērot button_unwatch: Nevērot
+2 -2
View File
@@ -50,8 +50,8 @@ mk:
one: "околу 1 час" one: "околу 1 час"
other: "околу %{count} часа" other: "околу %{count} часа"
x_hours: x_hours:
one: "1 hour" one: "1 час"
other: "%{count} hours" other: "%{count} часа"
x_days: x_days:
one: "1 ден" one: "1 ден"
other: "%{count} дена" other: "%{count} дена"
+2 -2
View File
@@ -51,8 +51,8 @@ mn:
one: "1 цаг орчим" one: "1 цаг орчим"
other: "ойролцоогоор %{count} цаг" other: "ойролцоогоор %{count} цаг"
x_hours: x_hours:
one: "1 hour" one: "1 цаг"
other: "%{count} hours" other: "%{count} цаг"
x_days: x_days:
one: "1 өдөр" one: "1 өдөр"
other: "%{count} өдөр" other: "%{count} өдөр"
+26 -27
View File
@@ -50,7 +50,7 @@ nl:
other: "ongeveer %{count} uren" other: "ongeveer %{count} uren"
x_hours: x_hours:
one: "1 uur" one: "1 uur"
other: "%{count} hours" other: "%{count} uren"
x_days: x_days:
one: "1 dag" one: "1 dag"
other: "%{count} dagen" other: "%{count} dagen"
@@ -343,9 +343,9 @@ nl:
one: 1 open one: 1 open
other: "%{count} open" other: "%{count} open"
label_x_closed_issues_abbr: label_x_closed_issues_abbr:
zero: 0 closed zero: 0 gesloten
one: 1 closed one: 1 gesloten
other: "%{count} closed" other: "%{count} gesloten"
label_comment: Commentaar label_comment: Commentaar
label_comment_add: Voeg commentaar toe label_comment_add: Voeg commentaar toe
label_comment_added: Commentaar toegevoegd label_comment_added: Commentaar toegevoegd
@@ -1022,7 +1022,7 @@ nl:
text_project_closed: Dit project is gesloten en op alleen-lezen text_project_closed: Dit project is gesloten en op alleen-lezen
notice_user_successful_create: Gebruiker %{id} aangemaakt. notice_user_successful_create: Gebruiker %{id} aangemaakt.
field_core_fields: Standaard verleden field_core_fields: Standaard verleden
field_timeout: Timeout (in seconds) field_timeout: Timeout (in seconden)
setting_thumbnails_enabled: Geef bijlage miniaturen weer setting_thumbnails_enabled: Geef bijlage miniaturen weer
setting_thumbnails_size: Grootte miniaturen (in pixels) setting_thumbnails_size: Grootte miniaturen (in pixels)
label_status_transitions: Status transitie label_status_transitions: Status transitie
@@ -1036,36 +1036,35 @@ nl:
label_attribute_of_assigned_to: Toegewezen %{name} label_attribute_of_assigned_to: Toegewezen %{name}
label_attribute_of_fixed_version: Target versions %{name} label_attribute_of_fixed_version: Target versions %{name}
label_copy_subtasks: Kopieer subtaken label_copy_subtasks: Kopieer subtaken
label_copied_to: copied to label_copied_to: gekopieerd naar
label_copied_from: copied from label_copied_from: gekopieerd van
label_any_issues_in_project: any issues in project label_any_issues_in_project: any issues in project
label_any_issues_not_in_project: any issues not in project label_any_issues_not_in_project: any issues not in project
field_private_notes: Private notes field_private_notes: Privé notities
permission_view_private_notes: View private notes permission_view_private_notes: Bekijk privé notities
permission_set_notes_private: Set notes as private permission_set_notes_private: Maak notities privé
label_no_issues_in_project: no issues in project label_no_issues_in_project: geen issues in project
label_any: alle label_any: alle
label_last_n_weeks: last %{count} weeks label_last_n_weeks: afgelopen %{count} weken
setting_cross_project_subtasks: Allow cross-project subtasks setting_cross_project_subtasks: Sta subtaken in andere projecten toe
label_cross_project_descendants: Met subprojecten label_cross_project_descendants: Met subprojecten
label_cross_project_tree: Met project boom label_cross_project_tree: Met project boom
label_cross_project_hierarchy: Met project hiërarchie label_cross_project_hierarchy: Met project hiërarchie
label_cross_project_system: Met alle projecten label_cross_project_system: Met alle projecten
button_hide: Hide button_hide: Verberg
setting_non_working_week_days: Non-working days setting_non_working_week_days: Niet-werkdagen
label_in_the_next_days: in the next label_in_the_next_days: in de volgende
label_in_the_past_days: in the past label_in_the_past_days: in de afgelopen
label_attribute_of_user: User's %{name} label_attribute_of_user: User's %{name}
text_turning_multiple_off: If you disable multiple values, multiple values will be text_turning_multiple_off: Bij het uitschakelen van meerdere waardes zal er maar een waarde bewaard blijven.
removed in order to preserve only one value per item.
label_attribute_of_issue: Issue's %{name} label_attribute_of_issue: Issue's %{name}
permission_add_documents: Add documents permission_add_documents: Voeg documenten toe
permission_edit_documents: Edit documents permission_edit_documents: Bewerk documenten
permission_delete_documents: Delete documents permission_delete_documents: Verwijder documenten
label_gantt_progress_line: Progress line label_gantt_progress_line: Voortgangslijn
setting_jsonp_enabled: Enable JSONP support setting_jsonp_enabled: Schakel JSONP support in
field_inherit_members: Inherit members field_inherit_members: Neem leden over
field_closed_on: Closed field_closed_on: Gesloten
setting_default_projects_tracker_ids: Default trackers for new projects setting_default_projects_tracker_ids: Standaard trackers voor nieuwe projecten
label_total_time: Totaal label_total_time: Totaal
setting_emails_header: Email header setting_emails_header: Email header
+2 -2
View File
@@ -44,8 +44,8 @@
one: "rundt 1 time" one: "rundt 1 time"
other: "rundt %{count} timer" other: "rundt %{count} timer"
x_hours: x_hours:
one: "1 hour" one: "1 time"
other: "%{count} hours" other: "%{count} timer"
x_days: x_days:
one: "1 dag" one: "1 dag"
other: "%{count} dager" other: "%{count} dager"
+3 -3
View File
@@ -82,8 +82,8 @@ pl:
one: "około godziny" one: "około godziny"
other: "około %{count} godzin" other: "około %{count} godzin"
x_hours: x_hours:
one: "1 hour" one: "1 godzina"
other: "%{count} hours" other: "%{count} godzin"
x_days: x_days:
one: "1 dzień" one: "1 dzień"
other: "%{count} dni" other: "%{count} dni"
@@ -772,7 +772,7 @@ pl:
text_default_administrator_account_changed: Zmieniono domyślne hasło administratora text_default_administrator_account_changed: Zmieniono domyślne hasło administratora
text_destroy_time_entries: Usuń wpisy dziennika text_destroy_time_entries: Usuń wpisy dziennika
text_destroy_time_entries_question: Przepracowano %{hours} godzin przy zagadnieniu, które chcesz usunąć. Co chcesz zrobić? text_destroy_time_entries_question: Przepracowano %{hours} godzin przy zagadnieniu, które chcesz usunąć. Co chcesz zrobić?
text_email_delivery_not_configured: "Dostarczanie poczty elektronicznej nie zostało skonfigurowane, więc powiadamianie jest nieaktywne.\nSkonfiguruj serwer SMTP w config/email.yml a następnie zrestartuj aplikację i uaktywnij to." text_email_delivery_not_configured: "Dostarczanie poczty elektronicznej nie zostało skonfigurowane, więc powiadamianie jest nieaktywne.\nSkonfiguruj serwer SMTP w config/configuration.yml a następnie zrestartuj aplikację i uaktywnij to."
text_enumeration_category_reassign_to: 'Zmień przypisanie na tą wartość:' text_enumeration_category_reassign_to: 'Zmień przypisanie na tą wartość:'
text_enumeration_destroy_question: "%{count} obiektów jest przypisanych do tej wartości." text_enumeration_destroy_question: "%{count} obiektów jest przypisanych do tej wartości."
text_file_repository_writable: Zapisywalne repozytorium plików text_file_repository_writable: Zapisywalne repozytorium plików
+1 -1
View File
@@ -1105,5 +1105,5 @@ pt-BR:
setting_jsonp_enabled: Ativar suporte JSONP setting_jsonp_enabled: Ativar suporte JSONP
field_inherit_members: Herdar membros field_inherit_members: Herdar membros
field_closed_on: Fechado field_closed_on: Fechado
setting_default_projects_tracker_ids: Default trackers for new projects setting_default_projects_tracker_ids: Tipos padrões para novos projeto
label_total_time: Total label_total_time: Total
+2 -2
View File
@@ -45,8 +45,8 @@ ro:
one: "aproximativ o oră" one: "aproximativ o oră"
other: "aproximativ %{count} ore" other: "aproximativ %{count} ore"
x_hours: x_hours:
one: "1 hour" one: "1 oră"
other: "%{count} hours" other: "%{count} ore"
x_days: x_days:
one: "o zi" one: "o zi"
other: "%{count} zile" other: "%{count} zile"
+2 -2
View File
@@ -46,8 +46,8 @@ sk:
one: "okolo 1 hodiny" one: "okolo 1 hodiny"
other: "okolo %{count} hodín" other: "okolo %{count} hodín"
x_hours: x_hours:
one: "1 hour" one: "1 hodina"
other: "%{count} hours" other: "%{count} hodín"
x_days: x_days:
one: "1 deň" one: "1 deň"
other: "%{count} dní" other: "%{count} dní"
+2 -2
View File
@@ -50,8 +50,8 @@ sl:
one: "okrog 1. ure" one: "okrog 1. ure"
other: "okrog %{count} ur" other: "okrog %{count} ur"
x_hours: x_hours:
one: "1 hour" one: "1 ura"
other: "%{count} hours" other: "%{count} ur"
x_days: x_days:
one: "1 dan" one: "1 dan"
other: "%{count} dni" other: "%{count} dni"
+2 -2
View File
@@ -50,8 +50,8 @@ sq:
one: "about 1 hour" one: "about 1 hour"
other: "about %{count} hours" other: "about %{count} hours"
x_hours: x_hours:
one: "1 hour" one: "1 ore"
other: "%{count} hours" other: "%{count} ore"
x_days: x_days:
one: "1 day" one: "1 day"
other: "%{count} days" other: "%{count} days"
+2 -2
View File
@@ -53,8 +53,8 @@ sr-YU:
one: "približno jedan sat" one: "približno jedan sat"
other: "približno %{count} sati" other: "približno %{count} sati"
x_hours: x_hours:
one: "1 hour" one: "1 sat"
other: "%{count} hours" other: "%{count} sati"
x_days: x_days:
one: "jedan dan" one: "jedan dan"
other: "%{count} dana" other: "%{count} dana"
+2 -2
View File
@@ -51,8 +51,8 @@ sr:
one: "приближно један сат" one: "приближно један сат"
other: "приближно %{count} сати" other: "приближно %{count} сати"
x_hours: x_hours:
one: "1 hour" one: "1 сат"
other: "%{count} hours" other: "%{count} сати"
x_days: x_days:
one: "један дан" one: "један дан"
other: "%{count} дана" other: "%{count} дана"
+5 -5
View File
@@ -272,6 +272,7 @@ sv:
field_author: Författare field_author: Författare
field_created_on: Skapad field_created_on: Skapad
field_updated_on: Uppdaterad field_updated_on: Uppdaterad
field_closed_on: Stängd
field_field_format: Format field_field_format: Format
field_is_for_all: För alla projekt field_is_for_all: För alla projekt
field_possible_values: Möjliga värden field_possible_values: Möjliga värden
@@ -372,6 +373,7 @@ sv:
field_timeout: "Timeout (i sekunder)" field_timeout: "Timeout (i sekunder)"
field_board_parent: Förälderforum field_board_parent: Förälderforum
field_private_notes: Privata anteckningar field_private_notes: Privata anteckningar
field_inherit_members: Ärv medlemmar
setting_app_title: Applikationsrubrik setting_app_title: Applikationsrubrik
setting_app_subtitle: Applikationsunderrubrik setting_app_subtitle: Applikationsunderrubrik
@@ -440,6 +442,8 @@ sv:
setting_thumbnails_enabled: Visa miniatyrbilder av bilagor setting_thumbnails_enabled: Visa miniatyrbilder av bilagor
setting_thumbnails_size: Storlek på miniatyrbilder (i pixlar) setting_thumbnails_size: Storlek på miniatyrbilder (i pixlar)
setting_non_working_week_days: Lediga dagar setting_non_working_week_days: Lediga dagar
setting_jsonp_enabled: Aktivera JSONP-stöd
setting_default_projects_tracker_ids: Standardärendetyper för nya projekt
permission_add_project: Skapa projekt permission_add_project: Skapa projekt
permission_add_subprojects: Skapa underprojekt permission_add_subprojects: Skapa underprojekt
@@ -657,6 +661,7 @@ sv:
one: 1 ärende one: 1 ärende
other: "%{count} ärenden" other: "%{count} ärenden"
label_total: Total label_total: Total
label_total_time: Total tid
label_permissions: Behörigheter label_permissions: Behörigheter
label_current_status: Nuvarande status label_current_status: Nuvarande status
label_new_statuses_allowed: Nya tillåtna statusvärden label_new_statuses_allowed: Nya tillåtna statusvärden
@@ -1120,8 +1125,3 @@ sv:
description_date_from: Ange startdatum description_date_from: Ange startdatum
description_date_to: Ange slutdatum description_date_to: Ange slutdatum
text_repository_identifier_info: 'Endast gemener (a-z), siffror, streck och understreck är tillåtna.<br />När identifieraren sparats kan den inte ändras.' text_repository_identifier_info: 'Endast gemener (a-z), siffror, streck och understreck är tillåtna.<br />När identifieraren sparats kan den inte ändras.'
setting_jsonp_enabled: Enable JSONP support
field_inherit_members: Inherit members
field_closed_on: Closed
setting_default_projects_tracker_ids: Default trackers for new projects
label_total_time: Total
+2 -2
View File
@@ -56,8 +56,8 @@ tr:
one: 'yaklaşık 1 saat' one: 'yaklaşık 1 saat'
other: 'yaklaşık %{count} saat' other: 'yaklaşık %{count} saat'
x_hours: x_hours:
one: "1 hour" one: "1 saat"
other: "%{count} hours" other: "%{count} saat"
x_days: x_days:
one: '1 gün' one: '1 gün'
other: '%{count} gün' other: '%{count} gün'
+5 -3
View File
@@ -4,6 +4,8 @@
"zh-TW": "zh-TW":
direction: ltr direction: ltr
jquery:
locale: "zh-TW"
date: date:
formats: formats:
# Use the strftime parameters for formats. # Use the strftime parameters for formats.
@@ -121,8 +123,8 @@
one: "約 1 小時" one: "約 1 小時"
other: "約 %{count} 小時" other: "約 %{count} 小時"
x_hours: x_hours:
one: "1 hour" one: "1 小時"
other: "%{count} hours" other: "%{count} 小時"
x_days: x_days:
one: "1 天" one: "1 天"
other: "%{count} 天" other: "%{count} 天"
@@ -483,6 +485,7 @@
setting_thumbnails_size: "縮圖大小 (單位: 像素 pixels)" setting_thumbnails_size: "縮圖大小 (單位: 像素 pixels)"
setting_non_working_week_days: 非工作日 setting_non_working_week_days: 非工作日
setting_jsonp_enabled: 啟用 JSONP 支援 setting_jsonp_enabled: 啟用 JSONP 支援
setting_default_projects_tracker_ids: 新專案預設使用的追蹤標籤
permission_add_project: 建立專案 permission_add_project: 建立專案
permission_add_subprojects: 建立子專案 permission_add_subprojects: 建立子專案
@@ -1165,5 +1168,4 @@
description_date_from: 輸入起始日期 description_date_from: 輸入起始日期
description_date_to: 輸入結束日期 description_date_to: 輸入結束日期
text_repository_identifier_info: '僅允許使用小寫英文字母 (a-z), 阿拉伯數字, 虛線與底線。<br />一旦儲存之後, 代碼便無法再次被更改。' text_repository_identifier_info: '僅允許使用小寫英文字母 (a-z), 阿拉伯數字, 虛線與底線。<br />一旦儲存之後, 代碼便無法再次被更改。'
setting_default_projects_tracker_ids: Default trackers for new projects
label_total_time: 總計 label_total_time: 總計
+17 -9
View File
@@ -99,9 +99,11 @@ RedmineApp::Application.routes.draw do
match 'copy', :via => [:get, :post] match 'copy', :via => [:get, :post]
end end
resources :memberships, :shallow => true, :controller => 'members', :only => [:index, :show, :new, :create, :update, :destroy] do shallow do
collection do resources :memberships, :controller => 'members', :only => [:index, :show, :new, :create, :update, :destroy] do
get 'autocomplete' collection do
get 'autocomplete'
end
end end
end end
@@ -134,15 +136,19 @@ RedmineApp::Application.routes.draw do
get 'report', :on => :collection get 'report', :on => :collection
end end
resources :queries, :only => [:new, :create] resources :queries, :only => [:new, :create]
resources :issue_categories, :shallow => true shallow do
resources :issue_categories
end
resources :documents, :except => [:show, :edit, :update, :destroy] resources :documents, :except => [:show, :edit, :update, :destroy]
resources :boards resources :boards
resources :repositories, :shallow => true, :except => [:index, :show] do shallow do
member do resources :repositories, :except => [:index, :show] do
match 'committers', :via => [:get, :post] member do
match 'committers', :via => [:get, :post]
end
end end
end end
match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get
resources :wiki, :except => [:index, :new, :create], :as => 'wiki_page' do resources :wiki, :except => [:index, :new, :create], :as => 'wiki_page' do
member do member do
@@ -176,7 +182,9 @@ RedmineApp::Application.routes.draw do
get 'report' get 'report'
end end
end end
resources :relations, :shallow => true, :controller => 'issue_relations', :only => [:index, :show, :create, :destroy] shallow do
resources :relations, :controller => 'issue_relations', :only => [:index, :show, :create, :destroy]
end
end end
match '/issues', :controller => 'issues', :action => 'destroy', :via => :delete match '/issues', :controller => 'issues', :action => 'destroy', :via => :delete
+47
View File
@@ -4,6 +4,53 @@ Redmine - project management software
Copyright (C) 2006-2013 Jean-Philippe Lang Copyright (C) 2006-2013 Jean-Philippe Lang
http://www.redmine.org/ http://www.redmine.org/
== 2013-07-14 v2.3.2
* Defect #9996: configuration.yml in documentation , but redmine ask me to create email.yml
* Defect #13692: warning: already initialized constant on Ruby 1.8.7
* Defect #13783: Internal error on time tracking activity enumeration deletion
* Defect #13821: "obj" parameter is not defined for macros used in description of documents
* Defect #13850: Unable to set custom fields for versions using the REST API
* Defect #13910: Values of custom fields are not kept in issues when copying a project
* Defect #13950: Duplicate Lithuanian "error_attachment_too_big" translation keys
* Defect #14015: Ruby hangs when adding a subtask
* Defect #14020: Locking and unlocking a user resets the email notification checkbox
* Defect #14023: Can't delete relation when Redmine runs in a subpath
* Defect #14051: Filtering issues with custom field in date format with NULL(empty) value
* Defect #14178: PDF API broken in version 2.3.1
* Defect #14186: Project name is not properly escaped in issue filters JSON
* Defect #14242: Project auto generation fails when projects created in the same time
* Defect #14245: Gem::InstallError: nokogiri requires Ruby version >= 1.9.2.
* Defect #14346: Latvian translation for "Log time"
* Feature #12888: Adding markings to emails generated by Private comments
* Feature #14419: Include RUBY_PATCHLEVEL and RUBY_RELEASE_DATE in info.rb
* Patch #14005: Swedish Translation for 2.3-stable
* Patch #14101: Receive IMAP by uid's
* Patch #14103: Disconnect and logout from IMAP after mail receive
* Patch #14145: German translation of x_hours
* Patch #14182: pt-BR translation for 2.3-stable
* Patch #14196: Italian translation for 2.3-stable
* Patch #14221: Translation of x_hours for many languages
== 2013-05-01 v2.3.1
* Defect #12650: Lost text after selection in issue list with IE
* Defect #12684: Hotkey for Issue-Edit doesn't work as expected
* Defect #13405: Commit link title is escaped twice when using "commit:" prefix
* Defect #13541: Can't access SCM when log/production.scm.stderr.log is not writable
* Defect #13579: Datepicker uses Simplified Chinese in Traditional Chinese locale
* Defect #13584: Missing Portuguese jQuery UI date picker
* Defect #13586: Circular loop testing prevents precedes/follows relation between subtasks
* Defect #13618: CSV export of spent time ignores filters and columns selection
* Defect #13630: PDF export generates the issue id twice
* Defect #13644: Diff - Internal Error
* Defect #13712: Fix email rake tasks to also support no_account_notice and default_group options
* Defect #13811: Broken javascript in IE7 ; recurrence of #12195
* Defect #13823: Trailing comma in javascript files
* Patch #13531: Traditional Chinese translation for 2.3-stable
* Patch #13552: Dutch translations for 2.3-stable
* Patch #13678: Lithuanian translation for 2.3-stable
== 2013-03-19 v2.3.0 == 2013-03-19 v2.3.0
* Defect #3107: Issue with two digit year on Logtime * Defect #3107: Issue with two digit year on Logtime
+8 -1
View File
@@ -7,7 +7,7 @@ http://www.redmine.org/
== Requirements == Requirements
* Ruby 1.8.7, 1.9.2 or 1.9.3 * Ruby 1.8.7, 1.9.2, 1.9.3 or 2.0.0
* RubyGems * RubyGems
* Bundler >= 1.0.21 * Bundler >= 1.0.21
@@ -15,6 +15,7 @@ http://www.redmine.org/
* MySQL (tested with MySQL 5.1) * MySQL (tested with MySQL 5.1)
* PostgreSQL (tested with PostgreSQL 9.1) * PostgreSQL (tested with PostgreSQL 9.1)
* SQLite3 (tested with SQLite 3.7) * SQLite3 (tested with SQLite 3.7)
* SQLServer (tested with SQLServer 2012)
Optional: Optional:
* SCM binaries (e.g. svn, git...), for repository browsing (must be available in PATH) * SCM binaries (e.g. svn, git...), for repository browsing (must be available in PATH)
@@ -39,6 +40,12 @@ Optional:
of the rmagick gem using: of the rmagick gem using:
bundle install --without development test rmagick bundle install --without development test rmagick
Only the gems that are needed by the adapters you've specified in your database
configuration file are actually installed (eg. if your config/database.yml
uses the 'mysql2' adapter, then only the mysql2 gem will be installed). Don't
forget to re-run `bundle install` when you change config/database.yml for using
other database adapters.
If you need to load some gems that are not required by Redmine core (eg. fcgi), If you need to load some gems that are not required by Redmine core (eg. fcgi),
you can create a file named Gemfile.local at the root of your redmine directory. you can create a file named Gemfile.local at the root of your redmine directory.
It will be loaded automatically when running `bundle install`. It will be loaded automatically when running `bundle install`.
+16 -16
View File
@@ -380,7 +380,7 @@ module Redmine
col_width col_width
end end
def render_table_header(pdf, query, col_width, row_height, col_id_width, table_width) def render_table_header(pdf, query, col_width, row_height, table_width)
# headers # headers
pdf.SetFontStyle('B',8) pdf.SetFontStyle('B',8)
pdf.SetFillColor(230, 230, 230) pdf.SetFillColor(230, 230, 230)
@@ -389,13 +389,12 @@ module Redmine
base_x = pdf.GetX base_x = pdf.GetX
base_y = pdf.GetY base_y = pdf.GetY
max_height = issues_to_pdf_write_cells(pdf, query.inline_columns, col_width, row_height, true) max_height = issues_to_pdf_write_cells(pdf, query.inline_columns, col_width, row_height, true)
pdf.Rect(base_x, base_y, table_width + col_id_width, max_height, 'FD'); pdf.Rect(base_x, base_y, table_width, max_height, 'FD');
pdf.SetXY(base_x, base_y); pdf.SetXY(base_x, base_y);
# write the cells on page # write the cells on page
pdf.RDMCell(col_id_width, row_height, "#", "T", 0, 'C', 1)
issues_to_pdf_write_cells(pdf, query.inline_columns, col_width, row_height, true) issues_to_pdf_write_cells(pdf, query.inline_columns, col_width, row_height, true)
issues_to_pdf_draw_borders(pdf, base_x, base_y, base_y + max_height, col_id_width, col_width) issues_to_pdf_draw_borders(pdf, base_x, base_y, base_y + max_height, 0, col_width)
pdf.SetY(base_y + max_height); pdf.SetY(base_y + max_height);
# rows # rows
@@ -417,22 +416,22 @@ module Redmine
# Landscape A4 = 210 x 297 mm # Landscape A4 = 210 x 297 mm
page_height = 210 page_height = 210
page_width = 297 page_width = 297
left_margin = 10
right_margin = 10 right_margin = 10
bottom_margin = 20 bottom_margin = 20
col_id_width = 10
row_height = 4 row_height = 4
# column widths # column widths
table_width = page_width - right_margin - 10 # fixed left margin table_width = page_width - right_margin - left_margin
col_width = [] col_width = []
unless query.inline_columns.empty? unless query.inline_columns.empty?
col_width = calc_col_width(issues, query, table_width - col_id_width, pdf) col_width = calc_col_width(issues, query, table_width, pdf)
table_width = col_width.inject(0) {|s,v| s += v} table_width = col_width.inject(0) {|s,v| s += v}
end end
# use full width if the description is displayed # use full width if the description is displayed
if table_width > 0 && query.has_column?(:description) if table_width > 0 && query.has_column?(:description)
col_width = col_width.map {|w| w = w * (page_width - right_margin - 10 - col_id_width) / table_width} col_width = col_width.map {|w| w * (page_width - right_margin - left_margin) / table_width}
table_width = col_width.inject(0) {|s,v| s += v} table_width = col_width.inject(0) {|s,v| s += v}
end end
@@ -440,7 +439,7 @@ module Redmine
pdf.SetFontStyle('B',11) pdf.SetFontStyle('B',11)
pdf.RDMCell(190,10, title) pdf.RDMCell(190,10, title)
pdf.Ln pdf.Ln
render_table_header(pdf, query, col_width, row_height, col_id_width, table_width) render_table_header(pdf, query, col_width, row_height, table_width)
previous_group = false previous_group = false
issue_list(issues) do |issue, level| issue_list(issues) do |issue, level|
if query.grouped? && if query.grouped? &&
@@ -449,7 +448,7 @@ module Redmine
group_label = group.blank? ? 'None' : group.to_s.dup group_label = group.blank? ? 'None' : group.to_s.dup
group_label << " (#{query.issue_count_by_group[group]})" group_label << " (#{query.issue_count_by_group[group]})"
pdf.Bookmark group_label, 0, -1 pdf.Bookmark group_label, 0, -1
pdf.RDMCell(table_width + col_id_width, row_height * 2, group_label, 1, 1, 'L') pdf.RDMCell(table_width, row_height * 2, group_label, 1, 1, 'L')
pdf.SetFontStyle('',8) pdf.SetFontStyle('',8)
previous_group = group previous_group = group
end end
@@ -468,15 +467,14 @@ module Redmine
space_left = page_height - base_y - bottom_margin space_left = page_height - base_y - bottom_margin
if max_height > space_left if max_height > space_left
pdf.AddPage("L") pdf.AddPage("L")
render_table_header(pdf, query, col_width, row_height, col_id_width, table_width) render_table_header(pdf, query, col_width, row_height, table_width)
base_x = pdf.GetX base_x = pdf.GetX
base_y = pdf.GetY base_y = pdf.GetY
end end
# write the cells on page # write the cells on page
pdf.RDMCell(col_id_width, row_height, issue.id.to_s, "T", 0, 'C', 1)
issues_to_pdf_write_cells(pdf, col_values, col_width, row_height) issues_to_pdf_write_cells(pdf, col_values, col_width, row_height)
issues_to_pdf_draw_borders(pdf, base_x, base_y, base_y + max_height, col_id_width, col_width) issues_to_pdf_draw_borders(pdf, base_x, base_y, base_y + max_height, 0, col_width)
pdf.SetY(base_y + max_height); pdf.SetY(base_y + max_height);
if query.has_column?(:description) && issue.description? if query.has_column?(:description) && issue.description?
@@ -513,9 +511,11 @@ module Redmine
end end
# Draw lines to close the row (MultiCell border drawing in not uniform) # Draw lines to close the row (MultiCell border drawing in not uniform)
#
# parameter "col_id_width" is not used. it is kept for compatibility.
def issues_to_pdf_draw_borders(pdf, top_x, top_y, lower_y, def issues_to_pdf_draw_borders(pdf, top_x, top_y, lower_y,
id_width, col_widths) col_id_width, col_widths)
col_x = top_x + id_width col_x = top_x
pdf.Line(col_x, top_y, col_x, lower_y) # id right border pdf.Line(col_x, top_y, col_x, lower_y) # id right border
col_widths.each do |width| col_widths.each do |width|
col_x += width col_x += width
+1 -1
View File
@@ -675,7 +675,7 @@ module Redmine
start_date + (end_date - start_date + 1) * (progress / 100.0) start_date + (end_date - start_date + 1) * (progress / 100.0)
end end
# Sorts a collection of issues by start_date, due_date, id for gantt rendering # TODO: Sorts a collection of issues by start_date, due_date, id for gantt rendering
def sort_issues!(issues) def sort_issues!(issues)
issues.sort! { |a, b| gantt_issue_compare(a, b) } issues.sort! { |a, b| gantt_issue_compare(a, b) }
end end
+12 -10
View File
@@ -29,25 +29,27 @@ module Redmine
imap = Net::IMAP.new(host, port, ssl) imap = Net::IMAP.new(host, port, ssl)
imap.login(imap_options[:username], imap_options[:password]) unless imap_options[:username].nil? imap.login(imap_options[:username], imap_options[:password]) unless imap_options[:username].nil?
imap.select(folder) imap.select(folder)
imap.search(['NOT', 'SEEN']).each do |message_id| imap.uid_search(['NOT', 'SEEN']).each do |uid|
msg = imap.fetch(message_id,'RFC822')[0].attr['RFC822'] msg = imap.uid_fetch(uid,'RFC822')[0].attr['RFC822']
logger.debug "Receiving message #{message_id}" if logger && logger.debug? logger.debug "Receiving message #{uid}" if logger && logger.debug?
if MailHandler.receive(msg, options) if MailHandler.receive(msg, options)
logger.debug "Message #{message_id} successfully received" if logger && logger.debug? logger.debug "Message #{uid} successfully received" if logger && logger.debug?
if imap_options[:move_on_success] if imap_options[:move_on_success]
imap.copy(message_id, imap_options[:move_on_success]) imap.uid_copy(uid, imap_options[:move_on_success])
end end
imap.store(message_id, "+FLAGS", [:Seen, :Deleted]) imap.uid_store(uid, "+FLAGS", [:Seen, :Deleted])
else else
logger.debug "Message #{message_id} can not be processed" if logger && logger.debug? logger.debug "Message #{uid} can not be processed" if logger && logger.debug?
imap.store(message_id, "+FLAGS", [:Seen]) imap.uid_store(uid, "+FLAGS", [:Seen])
if imap_options[:move_on_failure] if imap_options[:move_on_failure]
imap.copy(message_id, imap_options[:move_on_failure]) imap.uid_copy(uid, imap_options[:move_on_failure])
imap.store(message_id, "+FLAGS", [:Deleted]) imap.uid_store(uid, "+FLAGS", [:Deleted])
end end
end end
end end
imap.expunge imap.expunge
imap.logout
imap.disconnect
end end
private private
+3 -3
View File
@@ -10,16 +10,16 @@ module Redmine
s = "Environment:\n" s = "Environment:\n"
s << [ s << [
["Redmine version", Redmine::VERSION], ["Redmine version", Redmine::VERSION],
["Ruby version", "#{RUBY_VERSION} (#{RUBY_PLATFORM})"], ["Ruby version", "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"],
["Rails version", Rails::VERSION::STRING], ["Rails version", Rails::VERSION::STRING],
["Environment", Rails.env], ["Environment", Rails.env],
["Database adapter", ActiveRecord::Base.connection.adapter_name] ["Database adapter", ActiveRecord::Base.connection.adapter_name]
].map {|info| " %-40s %s" % info}.join("\n") ].map {|info| " %-30s %s" % info}.join("\n")
s << "\nRedmine plugins:\n" s << "\nRedmine plugins:\n"
plugins = Redmine::Plugin.all plugins = Redmine::Plugin.all
if plugins.any? if plugins.any?
s << plugins.map {|plugin| " %-40s %s" % [plugin.id.to_s, plugin.version.to_s]}.join("\n") s << plugins.map {|plugin| " %-30s %s" % [plugin.id.to_s, plugin.version.to_s]}.join("\n")
else else
s << " no plugin installed" s << " no plugin installed"
end end
+26 -5
View File
@@ -219,18 +219,39 @@ module Redmine
end end
# Path to the file where scm stderr output is logged # Path to the file where scm stderr output is logged
# Returns nil if the log file is not writable
def self.stderr_log_file def self.stderr_log_file
@stderr_log_path ||= if @stderr_log_file.nil?
Redmine::Configuration['scm_stderr_log_file'].presence || writable = false
Rails.root.join("log/#{Rails.env}.scm.stderr.log").to_s path = Redmine::Configuration['scm_stderr_log_file'].presence
path ||= Rails.root.join("log/#{Rails.env}.scm.stderr.log").to_s
if File.exists?(path)
if File.file?(path) && File.writable?(path)
writable = true
else
logger.warn("SCM log file (#{path}) is not writable")
end
else
begin
File.open(path, "w") {}
writable = true
rescue => e
logger.warn("SCM log file (#{path}) cannot be created: #{e.message}")
end
end
@stderr_log_file = writable ? path : false
end
@stderr_log_file || nil
end end
def self.shellout(cmd, options = {}, &block) def self.shellout(cmd, options = {}, &block)
if logger && logger.debug? if logger && logger.debug?
logger.debug "Shelling out: #{strip_credential(cmd)}" logger.debug "Shelling out: #{strip_credential(cmd)}"
# Capture stderr in a log file
if stderr_log_file
cmd = "#{cmd} 2>>#{shell_quote(stderr_log_file)}"
end
end end
# Capture stderr in a log file
cmd = "#{cmd} 2>>#{shell_quote(stderr_log_file)}"
begin begin
mode = "r+" mode = "r+"
IO.popen(cmd, mode) do |io| IO.popen(cmd, mode) do |io|
-1
View File
@@ -33,7 +33,6 @@ module Redmine
module CodeRay module CodeRay
require 'coderay' require 'coderay'
require 'coderay/helpers/file_type'
class << self class << self
# Highlights +text+ as the content of +filename+ # Highlights +text+ as the content of +filename+
+8 -4
View File
@@ -199,15 +199,19 @@ module Redmine
while starting < max && line_left[starting] == line_right[starting] while starting < max && line_left[starting] == line_right[starting]
starting += 1 starting += 1
end end
while line_left[starting].ord.between?(128, 191) && starting > 0 if (! "".respond_to?(:force_encoding)) && starting < line_left.size
starting -= 1 while line_left[starting].ord.between?(128, 191) && starting > 0
starting -= 1
end
end end
ending = -1 ending = -1
while ending >= -(max - starting) && line_left[ending] == line_right[ending] while ending >= -(max - starting) && line_left[ending] == line_right[ending]
ending -= 1 ending -= 1
end end
while line_left[ending].ord.between?(128, 191) && ending > -1 if (! "".respond_to?(:force_encoding)) && ending > (-1 * line_left.size)
ending -= 1 while line_left[ending].ord.between?(128, 191) && ending > -1
ending -= 1
end
end end
unless starting == 0 && ending == -1 unless starting == 0 && ending == -1
[starting, ending] [starting, ending]
+1 -1
View File
@@ -4,7 +4,7 @@ module Redmine
module VERSION #:nodoc: module VERSION #:nodoc:
MAJOR = 2 MAJOR = 2
MINOR = 3 MINOR = 3
TINY = 0 TINY = 2
# Branch values: # Branch values:
# * official release: nil # * official release: nil
+10
View File
@@ -29,6 +29,8 @@ General options:
create: create a user account create: create a user account
no_permission_check=1 disable permission checking when receiving no_permission_check=1 disable permission checking when receiving
the email the email
no_account_notice=1 disable new user account notification
default_group=foo,bar adds created user to foo and bar groups
Issue attributes control options: Issue attributes control options:
project=PROJECT identifier of the target project project=PROJECT identifier of the target project
@@ -58,6 +60,8 @@ END_DESC
options[:allow_override] = ENV['allow_override'] if ENV['allow_override'] options[:allow_override] = ENV['allow_override'] if ENV['allow_override']
options[:unknown_user] = ENV['unknown_user'] if ENV['unknown_user'] options[:unknown_user] = ENV['unknown_user'] if ENV['unknown_user']
options[:no_permission_check] = ENV['no_permission_check'] if ENV['no_permission_check'] options[:no_permission_check] = ENV['no_permission_check'] if ENV['no_permission_check']
options[:no_account_notice] = ENV['no_account_notice'] if ENV['no_account_notice']
options[:default_group] = ENV['default_group'] if ENV['default_group']
MailHandler.receive(STDIN.read, options) MailHandler.receive(STDIN.read, options)
end end
@@ -73,6 +77,8 @@ General options:
create: create a user account create: create a user account
no_permission_check=1 disable permission checking when receiving no_permission_check=1 disable permission checking when receiving
the email the email
no_account_notice=1 disable new user account notification
default_group=foo,bar adds created user to foo and bar groups
Available IMAP options: Available IMAP options:
host=HOST IMAP server host (default: 127.0.0.1) host=HOST IMAP server host (default: 127.0.0.1)
@@ -129,6 +135,8 @@ END_DESC
options[:allow_override] = ENV['allow_override'] if ENV['allow_override'] options[:allow_override] = ENV['allow_override'] if ENV['allow_override']
options[:unknown_user] = ENV['unknown_user'] if ENV['unknown_user'] options[:unknown_user] = ENV['unknown_user'] if ENV['unknown_user']
options[:no_permission_check] = ENV['no_permission_check'] if ENV['no_permission_check'] options[:no_permission_check] = ENV['no_permission_check'] if ENV['no_permission_check']
options[:no_account_notice] = ENV['no_account_notice'] if ENV['no_account_notice']
options[:default_group] = ENV['default_group'] if ENV['default_group']
Redmine::IMAP.check(imap_options, options) Redmine::IMAP.check(imap_options, options)
end end
@@ -162,6 +170,8 @@ END_DESC
options[:allow_override] = ENV['allow_override'] if ENV['allow_override'] options[:allow_override] = ENV['allow_override'] if ENV['allow_override']
options[:unknown_user] = ENV['unknown_user'] if ENV['unknown_user'] options[:unknown_user] = ENV['unknown_user'] if ENV['unknown_user']
options[:no_permission_check] = ENV['no_permission_check'] if ENV['no_permission_check'] options[:no_permission_check] = ENV['no_permission_check'] if ENV['no_permission_check']
options[:no_account_notice] = ENV['no_account_notice'] if ENV['no_account_notice']
options[:default_group] = ENV['default_group'] if ENV['default_group']
Redmine::POP3.check(pop_options, options) Redmine::POP3.check(pop_options, options)
end end
+10 -10
View File
@@ -14,12 +14,12 @@ function toggleCheckboxesBySelector(selector) {
$(selector).each(function(index) { $(selector).each(function(index) {
if (!$(this).is(':checked')) { all_checked = false; } if (!$(this).is(':checked')) { all_checked = false; }
}); });
$(selector).attr('checked', !all_checked) $(selector).attr('checked', !all_checked);
} }
function showAndScrollTo(id, focus) { function showAndScrollTo(id, focus) {
$('#'+id).show(); $('#'+id).show();
if (focus!=null) { if (focus !== null) {
$('#'+focus).focus(); $('#'+focus).focus();
} }
$('html, body').animate({scrollTop: $('#'+id).offset().top}, 100); $('html, body').animate({scrollTop: $('#'+id).offset().top}, 100);
@@ -131,10 +131,10 @@ function buildFilterRow(field, operator, values) {
select = tr.find('td.operator select'); select = tr.find('td.operator select');
for (i=0;i<operators.length;i++){ for (i=0;i<operators.length;i++){
var option = $('<option>').val(operators[i]).text(operatorLabels[operators[i]]); var option = $('<option>').val(operators[i]).text(operatorLabels[operators[i]]);
if (operators[i] == operator) {option.attr('selected', true)}; if (operators[i] == operator) { option.attr('selected', true); }
select.append(option); select.append(option);
} }
select.change(function(){toggleOperator(field)}); select.change(function(){ toggleOperator(field); });
switch (filterOptions['type']){ switch (filterOptions['type']){
case "list": case "list":
@@ -146,7 +146,7 @@ function buildFilterRow(field, operator, values) {
' <span class="toggle-multiselect">&nbsp;</span></span>' ' <span class="toggle-multiselect">&nbsp;</span></span>'
); );
select = tr.find('td.values select'); select = tr.find('td.values select');
if (values.length > 1) {select.attr('multiple', true)}; if (values.length > 1) { select.attr('multiple', true); }
for (i=0;i<filterValues.length;i++){ for (i=0;i<filterValues.length;i++){
var filterValue = filterValues[i]; var filterValue = filterValues[i];
var option = $('<option>'); var option = $('<option>');
@@ -189,7 +189,7 @@ function buildFilterRow(field, operator, values) {
var filterValue = allProjects[i]; var filterValue = allProjects[i];
var option = $('<option>'); var option = $('<option>');
option.val(filterValue[1]).text(filterValue[0]); option.val(filterValue[1]).text(filterValue[0]);
if (values[0] == filterValue[1]) {option.attr('selected', true)}; if (values[0] == filterValue[1]) { option.attr('selected', true); }
select.append(option); select.append(option);
} }
case "integer": case "integer":
@@ -352,7 +352,7 @@ function setPredecessorFieldsVisibility() {
function showModal(id, width) { function showModal(id, width) {
var el = $('#'+id).first(); var el = $('#'+id).first();
if (el.length == 0 || el.is(':visible')) {return;} if (el.length === 0 || el.is(':visible')) {return;}
var title = el.find('h3.title').text(); var title = el.find('h3.title').text();
el.dialog({ el.dialog({
width: width, width: width,
@@ -462,7 +462,7 @@ function observeAutocompleteField(fieldId, url, options) {
source: url, source: url,
minLength: 2, minLength: 2,
search: function(){$('#'+fieldId).addClass('ajax-loading');}, search: function(){$('#'+fieldId).addClass('ajax-loading');},
response: function(){$('#'+fieldId).removeClass('ajax-loading');}, response: function(){$('#'+fieldId).removeClass('ajax-loading');}
}, options)); }, options));
$('#'+fieldId).addClass('autocomplete'); $('#'+fieldId).addClass('autocomplete');
}); });
@@ -546,13 +546,13 @@ function warnLeavingUnsaved(message) {
}); });
if (warn) {return warnLeavingUnsavedMessage;} if (warn) {return warnLeavingUnsavedMessage;}
}; };
}; }
function setupAjaxIndicator() { function setupAjaxIndicator() {
$('#ajax-indicator').bind('ajaxSend', function(event, xhr, settings) { $('#ajax-indicator').bind('ajaxSend', function(event, xhr, settings) {
if ($('.ajax-loading').length == 0 && settings.contentType != 'application/octet-stream') { if ($('.ajax-loading').length === 0 && settings.contentType != 'application/octet-stream') {
$('#ajax-indicator').show(); $('#ajax-indicator').show();
} }
}); });
+1 -1
View File
@@ -186,7 +186,7 @@ function contextMenuCheckSelectionBox(tr, checked) {
function contextMenuClearDocumentSelection() { function contextMenuClearDocumentSelection() {
// TODO // TODO
if (document.selection) { if (document.selection) {
document.selection.clear(); // IE document.selection.empty(); // IE
} else { } else {
window.getSelection().removeAllRanges(); window.getSelection().removeAllRanges();
} }
+1 -1
View File
@@ -93,7 +93,7 @@ function drawRelations() {
.attr({stroke: "none", .attr({stroke: "none",
fill: color, fill: color,
"stroke-linecap": "butt", "stroke-linecap": "butt",
"stroke-linejoin": "miter", "stroke-linejoin": "miter"
}); });
}); });
} }
+22
View File
@@ -0,0 +1,22 @@
/* Portuguese initialisation for the jQuery UI date picker plugin. */
jQuery(function($){
$.datepicker.regional['pt'] = {
closeText: 'Fechar',
prevText: '&#x3C;Anterior',
nextText: 'Seguinte',
currentText: 'Hoje',
monthNames: ['Janeiro','Fevereiro','Março','Abril','Maio','Junho',
'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],
monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun',
'Jul','Ago','Set','Out','Nov','Dez'],
dayNames: ['Domingo','Segunda-feira','Terça-feira','Quarta-feira','Quinta-feira','Sexta-feira','Sábado'],
dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'],
dayNamesMin: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'],
weekHeader: 'Sem',
dateFormat: 'dd/mm/yy',
firstDay: 0,
isRTL: false,
showMonthAfterYear: false,
yearSuffix: ''};
$.datepicker.setDefaults($.datepicker.regional['pt']);
});
@@ -9,8 +9,8 @@ jsToolBar.strings['Heading 2'] = 'Heading 2';
jsToolBar.strings['Heading 3'] = 'Heading 3'; jsToolBar.strings['Heading 3'] = 'Heading 3';
jsToolBar.strings['Unordered list'] = 'Nenumeruotas sąrašas'; jsToolBar.strings['Unordered list'] = 'Nenumeruotas sąrašas';
jsToolBar.strings['Ordered list'] = 'Numeruotas sąrašas'; jsToolBar.strings['Ordered list'] = 'Numeruotas sąrašas';
jsToolBar.strings['Quote'] = 'Quote'; jsToolBar.strings['Quote'] = 'Cituoti';
jsToolBar.strings['Unquote'] = 'Remove Quote'; jsToolBar.strings['Unquote'] = 'Pašalinti citavimą';
jsToolBar.strings['Preformatted text'] = 'Preformatuotas tekstas'; jsToolBar.strings['Preformatted text'] = 'Preformatuotas tekstas';
jsToolBar.strings['Wiki link'] = 'Nuoroda į Wiki puslapį'; jsToolBar.strings['Wiki link'] = 'Nuoroda į Wiki puslapį';
jsToolBar.strings['Image'] = 'Paveikslas'; jsToolBar.strings['Image'] = 'Paveikslas';
+1 -1
View File
@@ -43,7 +43,7 @@ function drawRevisionGraph(holder, commits_hash, graph_space) {
revisionGraph.circle(x, y, 3) revisionGraph.circle(x, y, 3)
.attr({ .attr({
fill: colors[commit.space], fill: colors[commit.space],
stroke: 'none', stroke: 'none'
}).toFront(); }).toFront();
// paths to parents // paths to parents
$.each(commit.parent_scmids, function(index, parent_scmid) { $.each(commit.parent_scmids, function(index, parent_scmid) {
+2 -1
View File
@@ -3,8 +3,9 @@ changesets_001:
commit_date: 2007-04-11 commit_date: 2007-04-11
committed_on: 2007-04-11 15:14:44 +02:00 committed_on: 2007-04-11 15:14:44 +02:00
revision: 1 revision: 1
scmid: 691322a8eb01e11fd7
id: 100 id: 100
comments: My very first commit comments: 'My very first commit do not escaping #<>&'
repository_id: 10 repository_id: 10
committer: dlopper committer: dlopper
user_id: 3 user_id: 3
+7
View File
@@ -0,0 +1,7 @@
--- a.txt 2013-04-05 14:19:39.000000000 +0900
+++ b.txt 2013-04-05 14:19:51.000000000 +0900
@@ -1,3 +1,3 @@
aaaa
-日本
+日本語
bbbb
+7
View File
@@ -0,0 +1,7 @@
--- a.txt 2013-04-05 14:19:39.000000000 +0900
+++ b.txt 2013-04-05 14:19:51.000000000 +0900
@@ -1,3 +1,3 @@
aaaa
-日本
+にっぽん日本
bbbb
+1 -1
View File
@@ -83,7 +83,7 @@ class AdminControllerTest < ActionController::TestCase
def test_test_email def test_test_email
user = User.find(1) user = User.find(1)
user.pref[:no_self_notified] = '1' user.pref.no_self_notified = '1'
user.pref.save! user.pref.save!
ActionMailer::Base.deliveries.clear ActionMailer::Base.deliveries.clear
@@ -126,4 +126,11 @@ class EnumerationsControllerTest < ActionController::TestCase
# check that the issue was reassign # check that the issue was reassign
assert_equal 6, issue.reload.priority_id assert_equal 6, issue.reload.priority_id
end end
def test_destroy_enumeration_in_use_with_blank_reassignment
assert_no_difference 'IssuePriority.count' do
delete :destroy, :id => 4, :reassign_to_id => ''
end
assert_response :success
end
end end
@@ -548,6 +548,46 @@ class TimelogControllerTest < ActionController::TestCase
assert assigns(:items).first.is_a?(TimeEntry) assert assigns(:items).first.is_a?(TimeEntry)
end end
def test_index_at_project_level_should_include_csv_export_dialog
get :index, :project_id => 'ecookbook',
:f => ['spent_on'],
:op => {'spent_on' => '>='},
:v => {'spent_on' => ['2007-04-01']},
:c => ['spent_on', 'user']
assert_response :success
assert_select '#csv-export-options' do
assert_select 'form[action=?][method=get]', '/projects/ecookbook/time_entries.csv' do
# filter
assert_select 'input[name=?][value=?]', 'f[]', 'spent_on'
assert_select 'input[name=?][value=?]', 'op[spent_on]', '&gt;='
assert_select 'input[name=?][value=?]', 'v[spent_on][]', '2007-04-01'
# columns
assert_select 'input[name=?][value=?]', 'c[]', 'spent_on'
assert_select 'input[name=?][value=?]', 'c[]', 'user'
assert_select 'input[name=?]', 'c[]', 2
end
end
end
def test_index_cross_project_should_include_csv_export_dialog
get :index
assert_response :success
assert_select '#csv-export-options' do
assert_select 'form[action=?][method=get]', '/time_entries.csv'
end
end
def test_index_at_issue_level_should_include_csv_export_dialog
get :index, :project_id => 'ecookbook', :issue_id => 3
assert_response :success
assert_select '#csv-export-options' do
assert_select 'form[action=?][method=get]', '/projects/ecookbook/issues/3/time_entries.csv'
end
end
def test_index_csv_all_projects def test_index_csv_all_projects
Setting.date_format = '%m/%d/%Y' Setting.date_format = '%m/%d/%Y'
get :index, :format => 'csv' get :index, :format => 'csv'
+12
View File
@@ -325,6 +325,18 @@ class UsersControllerTest < ActionController::TestCase
assert_equal [1, 2], u.notified_projects_ids.sort assert_equal [1, 2], u.notified_projects_ids.sort
end end
def test_update_status_should_not_update_attributes
user = User.find(2)
user.pref[:no_self_notified] = '1'
user.pref.save
put :update, :id => 2, :user => {:status => 3}
assert_response 302
user = User.find(2)
assert_equal 3, user.status
assert_equal '1', user.pref[:no_self_notified]
end
def test_destroy def test_destroy
assert_difference 'User.count', -1 do assert_difference 'User.count', -1 do
delete :destroy, :id => 2 delete :destroy, :id => 2
@@ -82,6 +82,29 @@ class Redmine::ApiTest::VersionsTest < Redmine::ApiTest::Base
assert_tag 'version', :child => {:tag => 'id', :content => version.id.to_s} assert_tag 'version', :child => {:tag => 'id', :content => version.id.to_s}
end end
should "create the version with custom fields" do
field = VersionCustomField.generate!
assert_difference 'Version.count' do
post '/projects/1/versions.xml', {
:version => {
:name => 'API test',
:custom_fields => [
{'id' => field.id.to_s, 'value' => 'Some value'}
]
}
}, credentials('jsmith')
end
version = Version.first(:order => 'id DESC')
assert_equal 'API test', version.name
assert_equal 'Some value', version.custom_field_value(field)
assert_response :created
assert_equal 'application/xml', @response.content_type
assert_select 'version>custom_fields>custom_field[id=?]>value', field.id.to_s, 'Some value'
end
context "with failure" do context "with failure" do
should "return the errors" do should "return the errors" do
assert_no_difference('Version.count') do assert_no_difference('Version.count') do
+20
View File
@@ -85,6 +85,26 @@ class LayoutTest < ActionController::IntegrationTest
get '/issues' get '/issues'
assert_not_include "/javascripts/i18n/jquery.ui.datepicker", response.body assert_not_include "/javascripts/i18n/jquery.ui.datepicker", response.body
end end
with_settings :default_language => 'zh' do
get '/issues'
assert_include "/javascripts/i18n/jquery.ui.datepicker-zh-CN.js", response.body
end
with_settings :default_language => 'zh-TW' do
get '/issues'
assert_include "/javascripts/i18n/jquery.ui.datepicker-zh-TW.js", response.body
end
with_settings :default_language => 'pt' do
get '/issues'
assert_include "/javascripts/i18n/jquery.ui.datepicker-pt.js", response.body
end
with_settings :default_language => 'pt-BR' do
get '/issues'
assert_include "/javascripts/i18n/jquery.ui.datepicker-pt-BR.js", response.body
end
end end
def test_search_field_outside_project_should_link_to_global_search def test_search_field_outside_project_should_link_to_global_search
+13 -1
View File
@@ -107,10 +107,11 @@ module ObjectHelpers
def TimeEntry.generate!(attributes={}) def TimeEntry.generate!(attributes={})
entry = TimeEntry.new(attributes) entry = TimeEntry.new(attributes)
entry.user ||= User.find(2) entry.user ||= User.find(2)
entry.issue ||= Issue.find(1) entry.issue ||= Issue.find(1) unless entry.project
entry.project ||= entry.issue.project entry.project ||= entry.issue.project
entry.activity ||= TimeEntryActivity.first entry.activity ||= TimeEntryActivity.first
entry.spent_on ||= Date.today entry.spent_on ||= Date.today
entry.hours ||= 1.0
entry.save! entry.save!
entry entry
end end
@@ -147,4 +148,15 @@ module ObjectHelpers
attachment.save! attachment.save!
attachment attachment
end end
def CustomField.generate!(attributes={})
@generated_custom_field_name ||= 'Custom field 0'
@generated_custom_field_name.succ!
field = new(attributes)
field.name = @generated_custom_field_name.dup if field.name.blank?
field.field_format = 'string' if field.field_format.blank?
yield field if block_given?
field.save!
field
end
end end
+22 -7
View File
@@ -264,11 +264,15 @@ RAW
note_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'}, note_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'},
:class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)') :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
changeset_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1}, revision_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
:class => 'changeset', :title => 'My very first commit') :class => 'changeset', :title => 'My very first commit do not escaping #<>&')
changeset_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2}, revision_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
:class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3') :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
changeset_link2 = link_to('691322a8eb01e11fd7',
{:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
:class => 'changeset', :title => 'My very first commit do not escaping #<>&')
document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1}, document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1},
:class => 'document') :class => 'document')
@@ -304,10 +308,11 @@ RAW
# should not ignore leading zero # should not ignore leading zero
'#03' => '#03', '#03' => '#03',
# changesets # changesets
'r1' => changeset_link, 'r1' => revision_link,
'r1.' => "#{changeset_link}.", 'r1.' => "#{revision_link}.",
'r1, r2' => "#{changeset_link}, #{changeset_link2}", 'r1, r2' => "#{revision_link}, #{revision_link2}",
'r1,r2' => "#{changeset_link},#{changeset_link2}", 'r1,r2' => "#{revision_link},#{revision_link2}",
'commit:691322a8eb01e11fd7' => changeset_link2,
# documents # documents
'document#1' => document_link, 'document#1' => document_link,
'document:"Test document"' => document_link, 'document:"Test document"' => document_link,
@@ -1205,4 +1210,14 @@ RAW
def test_javascript_include_tag_for_plugin_should_pick_the_plugin_javascript def test_javascript_include_tag_for_plugin_should_pick_the_plugin_javascript
assert_match 'src="/plugin_assets/foo/javascripts/scripts.js"', javascript_include_tag("scripts", :plugin => :foo) assert_match 'src="/plugin_assets/foo/javascripts/scripts.js"', javascript_include_tag("scripts", :plugin => :foo)
end end
def test_raw_json_should_escape_closing_tags
s = raw_json(["<foo>bar</foo>"])
assert_equal '["<foo>bar<\/foo>"]', s
end
def test_raw_json_should_be_html_safe
s = raw_json(["foo"])
assert s.html_safe?
end
end end
+13
View File
@@ -137,6 +137,19 @@ class IssueRelationTest < ActiveSupport::TestCase
assert_include 'This relation would create a circular dependency', r.errors.full_messages assert_include 'This relation would create a circular dependency', r.errors.full_messages
end end
def test_subtasks_should_allow_precedes_relation
parent = Issue.generate!
child1 = Issue.generate!(:parent_issue_id => parent.id)
child2 = Issue.generate!(:parent_issue_id => parent.id)
r = IssueRelation.new(
:issue_from => child1, :issue_to => child2,
:relation_type => IssueRelation::TYPE_PRECEDES
)
assert r.valid?
assert r.save
end
def test_validates_circular_dependency_on_reverse_relations def test_validates_circular_dependency_on_reverse_relations
IssueRelation.delete_all IssueRelation.delete_all
assert IssueRelation.create!( assert IssueRelation.create!(
+130
View File
@@ -1792,6 +1792,136 @@ class IssueTest < ActiveSupport::TestCase
assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
end end
def test_all_dependent_issues_with_subtask
IssueRelation.delete_all
project = Project.generate!(:name => "testproject")
parentIssue = Issue.generate!(:project => project)
childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
assert_equal [childIssue1.id, childIssue2.id].sort, parentIssue.all_dependent_issues.collect(&:id).uniq.sort
end
def test_all_dependent_issues_does_not_include_self
IssueRelation.delete_all
project = Project.generate!(:name => "testproject")
parentIssue = Issue.generate!(:project => project)
childIssue = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
assert_equal [childIssue.id], parentIssue.all_dependent_issues.collect(&:id)
end
def test_all_dependent_issues_with_parenttask_and_sibling
IssueRelation.delete_all
project = Project.generate!(:name => "testproject")
parentIssue = Issue.generate!(:project => project)
childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
assert_equal [parentIssue.id].sort, childIssue1.all_dependent_issues.collect(&:id)
end
def test_all_dependent_issues_with_relation_to_leaf_in_other_tree
IssueRelation.delete_all
project = Project.generate!(:name => "testproject")
parentIssue1 = Issue.generate!(:project => project)
childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
parentIssue2 = Issue.generate!(:project => project)
childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
assert IssueRelation.create(:issue_from => parentIssue1,
:issue_to => childIssue2_2,
:relation_type => IssueRelation::TYPE_BLOCKS)
assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_2.id].sort,
parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
end
def test_all_dependent_issues_with_relation_to_parent_in_other_tree
IssueRelation.delete_all
project = Project.generate!(:name => "testproject")
parentIssue1 = Issue.generate!(:project => project)
childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
parentIssue2 = Issue.generate!(:project => project)
childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
assert IssueRelation.create(:issue_from => parentIssue1,
:issue_to => parentIssue2,
:relation_type => IssueRelation::TYPE_BLOCKS)
assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_1.id, childIssue2_2.id].sort,
parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
end
def test_all_dependent_issues_with_transitive_relation
IssueRelation.delete_all
project = Project.generate!(:name => "testproject")
parentIssue1 = Issue.generate!(:project => project)
childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
parentIssue2 = Issue.generate!(:project => project)
childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
independentIssue = Issue.generate!(:project => project)
assert IssueRelation.create(:issue_from => parentIssue1,
:issue_to => childIssue2_1,
:relation_type => IssueRelation::TYPE_RELATES)
assert IssueRelation.create(:issue_from => childIssue2_1,
:issue_to => independentIssue,
:relation_type => IssueRelation::TYPE_RELATES)
assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
end
def test_all_dependent_issues_with_transitive_relation2
IssueRelation.delete_all
project = Project.generate!(:name => "testproject")
parentIssue1 = Issue.generate!(:project => project)
childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
parentIssue2 = Issue.generate!(:project => project)
childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
independentIssue = Issue.generate!(:project => project)
assert IssueRelation.create(:issue_from => parentIssue1,
:issue_to => independentIssue,
:relation_type => IssueRelation::TYPE_RELATES)
assert IssueRelation.create(:issue_from => independentIssue,
:issue_to => childIssue2_1,
:relation_type => IssueRelation::TYPE_RELATES)
assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
end
def test_all_dependent_issues_with_persistent_circular_dependency def test_all_dependent_issues_with_persistent_circular_dependency
IssueRelation.delete_all IssueRelation.delete_all
assert IssueRelation.create!(:issue_from => Issue.find(1), assert IssueRelation.create!(:issue_from => Issue.find(1),
@@ -244,6 +244,70 @@ DIFF
end end
end end
def test_offset_range_ascii_1
raw = <<-DIFF
--- a.txt 2013-04-05 14:19:39.000000000 +0900
+++ b.txt 2013-04-05 14:19:51.000000000 +0900
@@ -1,3 +1,3 @@
aaaa
-abc
+abcd
bbbb
DIFF
diff = Redmine::UnifiedDiff.new(raw, :type => 'sbs')
assert_equal 1, diff.size
assert_equal 3, diff.first.size
assert_equal "abc<span></span>", diff.first[1].html_line_left
assert_equal "abc<span>d</span>", diff.first[1].html_line_right
end
def test_offset_range_ascii_2
raw = <<-DIFF
--- a.txt 2013-04-05 14:19:39.000000000 +0900
+++ b.txt 2013-04-05 14:19:51.000000000 +0900
@@ -1,3 +1,3 @@
aaaa
-abc
+zabc
bbbb
DIFF
diff = Redmine::UnifiedDiff.new(raw, :type => 'sbs')
assert_equal 1, diff.size
assert_equal 3, diff.first.size
assert_equal "<span></span>abc", diff.first[1].html_line_left
assert_equal "<span>z</span>abc", diff.first[1].html_line_right
end
def test_offset_range_japanese_1
ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span></span>"
ja1.force_encoding('UTF-8') if ja1.respond_to?(:force_encoding)
ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xaa\x9e</span>"
ja2.force_encoding('UTF-8') if ja2.respond_to?(:force_encoding)
with_settings :repositories_encodings => '' do
diff = Redmine::UnifiedDiff.new(
read_diff_fixture('issue-13644-1.diff'), :type => 'sbs')
assert_equal 1, diff.size
assert_equal 3, diff.first.size
assert_equal ja1, diff.first[1].html_line_left
assert_equal ja2, diff.first[1].html_line_right
end
end
def test_offset_range_japanese_2
ja1 = "<span></span>\xe6\x97\xa5\xe6\x9c\xac"
ja1.force_encoding('UTF-8') if ja1.respond_to?(:force_encoding)
ja2 = "<span>\xe3\x81\xab\xe3\x81\xa3\xe3\x81\xbd\xe3\x82\x93</span>\xe6\x97\xa5\xe6\x9c\xac"
ja2.force_encoding('UTF-8') if ja2.respond_to?(:force_encoding)
with_settings :repositories_encodings => '' do
diff = Redmine::UnifiedDiff.new(
read_diff_fixture('issue-13644-2.diff'), :type => 'sbs')
assert_equal 1, diff.size
assert_equal 3, diff.first.size
assert_equal ja1, diff.first[1].html_line_left
assert_equal ja2, diff.first[1].html_line_right
end
end
private private
def read_diff_fixture(filename) def read_diff_fixture(filename)
+14 -3
View File
@@ -215,14 +215,14 @@ class MailerTest < ActiveSupport::TestCase
# Remove members except news author # Remove members except news author
news.project.memberships.each {|m| m.destroy unless m.user == user} news.project.memberships.each {|m| m.destroy unless m.user == user}
user.pref[:no_self_notified] = false user.pref.no_self_notified = false
user.pref.save user.pref.save
User.current = user User.current = user
Mailer.news_added(news.reload).deliver Mailer.news_added(news.reload).deliver
assert_equal 1, last_email.bcc.size assert_equal 1, last_email.bcc.size
# nobody to notify # nobody to notify
user.pref[:no_self_notified] = true user.pref.no_self_notified = true
user.pref.save user.pref.save
User.current = user User.current = user
ActionMailer::Base.deliveries.clear ActionMailer::Base.deliveries.clear
@@ -296,7 +296,7 @@ class MailerTest < ActiveSupport::TestCase
issue = Issue.find(1) issue = Issue.find(1)
user = User.find(9) user = User.find(9)
# minimal email notification options # minimal email notification options
user.pref[:no_self_notified] = '1' user.pref.no_self_notified = '1'
user.pref.save user.pref.save
user.mail_notification = false user.mail_notification = false
user.save user.save
@@ -361,6 +361,17 @@ class MailerTest < ActiveSupport::TestCase
assert_not_include 'someone@foo.bar', ActionMailer::Base.deliveries.last.bcc.sort assert_not_include 'someone@foo.bar', ActionMailer::Base.deliveries.last.bcc.sort
end end
def test_issue_edit_should_mark_private_notes
journal = Journal.find(2)
journal.private_notes = true
journal.save!
with_settings :default_language => 'en' do
Mailer.issue_edit(journal).deliver
end
assert_mail_body_match '(Private notes)', last_email
end
def test_document_added def test_document_added
document = Document.find(1) document = Document.find(1)
valid_languages.each do |lang| valid_languages.each do |lang|
+13
View File
@@ -69,6 +69,19 @@ class ProjectCopyTest < ActiveSupport::TestCase
assert_equal "Closed", copied_issue.status.name assert_equal "Closed", copied_issue.status.name
end end
test "#copy should copy issues custom values" do
field = IssueCustomField.generate!(:is_for_all => true, :trackers => Tracker.all)
issue = Issue.generate!(:project => @source_project, :subject => 'Custom field copy')
issue.custom_field_values = {field.id => 'custom'}
issue.save!
assert_equal 'custom', issue.reload.custom_field_value(field)
assert @project.copy(@source_project)
copy = @project.issues.find_by_subject('Custom field copy')
assert copy
assert_equal 'custom', copy.reload.custom_field_value(field)
end
test "#copy should copy issues assigned to a locked version" do test "#copy should copy issues assigned to a locked version" do
User.current = User.find(1) User.current = User.find(1)
assigned_version = Version.generate!(:name => "Assigned Issues") assigned_version = Version.generate!(:name => "Assigned Issues")
+14
View File
@@ -337,6 +337,20 @@ class QueryTest < ActiveSupport::TestCase
find_issues_with_query(query) find_issues_with_query(query)
end end
def test_operator_lesser_than_on_date_custom_field
f = IssueCustomField.create!(:name => 'filter', :field_format => 'date', :is_filter => true, :is_for_all => true)
CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '2013-04-11')
CustomValue.create!(:custom_field => f, :customized => Issue.find(2), :value => '2013-05-14')
CustomValue.create!(:custom_field => f, :customized => Issue.find(3), :value => '')
query = IssueQuery.new(:project => Project.find(1), :name => '_')
query.add_filter("cf_#{f.id}", '<=', ['2013-05-01'])
issue_ids = find_issues_with_query(query).map(&:id)
assert_include 1, issue_ids
assert_not_include 2, issue_ids
assert_not_include 3, issue_ids
end
def test_operator_between def test_operator_between
query = IssueQuery.new(:project => Project.find(1), :name => '_') query = IssueQuery.new(:project => Project.find(1), :name => '_')
query.add_filter('done_ratio', '><', ['30', '40']) query.add_filter('done_ratio', '><', ['30', '40'])
+29 -1
View File
@@ -84,5 +84,33 @@ class TimeEntryActivityTest < ActiveSupport::TestCase
e.reload e.reload
assert_equal "0", e.custom_value_for(field).value assert_equal "0", e.custom_value_for(field).value
end end
end
def test_system_activity_with_child_in_use_should_be_in_use
project = Project.generate!
system_activity = TimeEntryActivity.create!(:name => 'Activity')
project_activity = TimeEntryActivity.create!(:name => 'Activity', :project => project, :parent_id => system_activity.id)
TimeEntry.generate!(:project => project, :activity => project_activity)
assert project_activity.in_use?
assert system_activity.in_use?
end
def test_destroying_a_system_activity_should_reassign_children_activities
project = Project.generate!
system_activity = TimeEntryActivity.create!(:name => 'Activity')
project_activity = TimeEntryActivity.create!(:name => 'Activity', :project => project, :parent_id => system_activity.id)
entries = [
TimeEntry.generate!(:project => project, :activity => system_activity),
TimeEntry.generate!(:project => project, :activity => project_activity)
]
assert_difference 'TimeEntryActivity.count', -2 do
assert_nothing_raised do
assert system_activity.destroy(TimeEntryActivity.find_by_name('Development'))
end
end
assert entries.all? {|entry| entry.reload.activity.name == 'Development'}
end
end