From 80256cf298e669e5b63b86594f6d9607e830cc80 Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Tue, 24 Aug 2010 15:27:12 +0000 Subject: [PATCH 01/25] Refactor: extract #bulk_update method from IssuesController#bulk_edit. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4037 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/issues_controller.rb | 45 ++++++++++++----------- app/views/issues/bulk_edit.rhtml | 2 +- config/routes.rb | 1 + lib/redmine.rb | 2 +- test/functional/issues_controller_test.rb | 32 ++++++++-------- test/integration/routing_test.rb | 3 ++ 6 files changed, 46 insertions(+), 39 deletions(-) diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index dc1cef492dd..29b13136050 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -20,7 +20,7 @@ class IssuesController < ApplicationController default_search_scope :issues before_filter :find_issue, :only => [:show, :edit, :update] - before_filter :find_issues, :only => [:bulk_edit, :move, :perform_move, :destroy] + before_filter :find_issues, :only => [:bulk_edit, :bulk_update, :move, :perform_move, :destroy] before_filter :find_project, :only => [:new, :create] before_filter :authorize, :except => [:index] before_filter :find_optional_project, :only => [:index] @@ -54,6 +54,7 @@ class IssuesController < ApplicationController :render => { :nothing => true, :status => :method_not_allowed } verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed } + verify :method => :post, :only => :bulk_update, :render => {:nothing => true, :status => :method_not_allowed } verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed } def index @@ -191,29 +192,31 @@ def update # Bulk edit a set of issues def bulk_edit @issues.sort! - if request.post? - attributes = (params[:issue] || {}).reject {|k,v| v.blank?} - attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'} - attributes[:custom_field_values].reject! {|k,v| v.blank?} if attributes[:custom_field_values] - - unsaved_issue_ids = [] - @issues.each do |issue| - issue.reload - journal = issue.init_journal(User.current, params[:notes]) - issue.safe_attributes = attributes - call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue }) - unless issue.save - # Keep unsaved issue ids to display them in flash error - unsaved_issue_ids << issue.id - end - end - set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids) - redirect_back_or_default({:controller => 'issues', :action => 'index', :project_id => @project}) - return - end @available_statuses = Workflow.available_statuses(@project) @custom_fields = @project.all_issue_custom_fields end + + def bulk_update + @issues.sort! + + attributes = (params[:issue] || {}).reject {|k,v| v.blank?} + attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'} + attributes[:custom_field_values].reject! {|k,v| v.blank?} if attributes[:custom_field_values] + + unsaved_issue_ids = [] + @issues.each do |issue| + issue.reload + journal = issue.init_journal(User.current, params[:notes]) + issue.safe_attributes = attributes + call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue }) + unless issue.save + # Keep unsaved issue ids to display them in flash error + unsaved_issue_ids << issue.id + end + end + set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids) + redirect_back_or_default({:controller => 'issues', :action => 'index', :project_id => @project}) + end def destroy @hours = TimeEntry.sum(:hours, :conditions => ['issue_id IN (?)', @issues]).to_f diff --git a/app/views/issues/bulk_edit.rhtml b/app/views/issues/bulk_edit.rhtml index b01128840ba..5fdfd58a66b 100644 --- a/app/views/issues/bulk_edit.rhtml +++ b/app/views/issues/bulk_edit.rhtml @@ -2,7 +2,7 @@ -<% form_tag() do %> +<% form_tag(:action => 'bulk_update') do %> <%= @issues.collect {|i| hidden_field_tag('ids[]', i.id)}.join %>
diff --git a/config/routes.rb b/config/routes.rb index b480a490000..4e1f9d7d509 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -132,6 +132,7 @@ issues_actions.connect 'issues/:id/quoted', :controller => 'journals', :action => 'new', :id => /\d+/ issues_actions.connect 'issues/:id/:action', :action => /edit|destroy/, :id => /\d+/ issues_actions.connect 'issues.:format', :action => 'create', :format => /xml/ + issues_actions.connect 'issues/bulk_edit', :action => 'bulk_update' end issues_routes.with_options :conditions => {:method => :put} do |issues_actions| issues_actions.connect 'issues/:id/edit', :action => 'update', :id => /\d+/ diff --git a/lib/redmine.rb b/lib/redmine.rb index b0a5a9f09e4..e1f1e2e16d2 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -66,7 +66,7 @@ :queries => :index, :reports => [:issue_report, :issue_report_details]} map.permission :add_issues, {:issues => [:new, :create, :update_form]} - map.permission :edit_issues, {:issues => [:edit, :update, :bulk_edit, :update_form], :journals => [:new]} + map.permission :edit_issues, {:issues => [:edit, :update, :bulk_edit, :bulk_update, :update_form], :journals => [:new]} map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]} map.permission :manage_subtasks, {} map.permission :add_issue_notes, {:issues => [:edit, :update], :journals => [:new]} diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb index 7c00db70849..7d69db8ea5a 100644 --- a/test/functional/issues_controller_test.rb +++ b/test/functional/issues_controller_test.rb @@ -910,10 +910,10 @@ def test_get_bulk_edit assert_tag :select, :attributes => {:name => 'issue[custom_field_values][1]'} end - def test_bulk_edit + def test_bulk_update @request.session[:user_id] = 2 # update issues priority - post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing', + post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing', :issue => {:priority_id => 7, :assigned_to_id => '', :custom_field_values => {'2' => ''}} @@ -929,10 +929,10 @@ def test_bulk_edit assert_equal 1, journal.details.size end - def test_bullk_edit_should_send_a_notification + def test_bullk_update_should_send_a_notification @request.session[:user_id] = 2 ActionMailer::Base.deliveries.clear - post(:bulk_edit, + post(:bulk_update, { :ids => [1, 2], :notes => 'Bulk editing', @@ -947,10 +947,10 @@ def test_bullk_edit_should_send_a_notification assert_equal 2, ActionMailer::Base.deliveries.size end - def test_bulk_edit_status + def test_bulk_update_status @request.session[:user_id] = 2 # update issues priority - post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing status', + post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing status', :issue => {:priority_id => '', :assigned_to_id => '', :status_id => '5'} @@ -960,10 +960,10 @@ def test_bulk_edit_status assert issue.closed? end - def test_bulk_edit_custom_field + def test_bulk_update_custom_field @request.session[:user_id] = 2 # update issues priority - post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing custom field', + post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing custom field', :issue => {:priority_id => '', :assigned_to_id => '', :custom_field_values => {'2' => '777'}} @@ -978,20 +978,20 @@ def test_bulk_edit_custom_field assert_equal '777', journal.details.first.value end - def test_bulk_unassign + def test_bulk_update_unassign assert_not_nil Issue.find(2).assigned_to @request.session[:user_id] = 2 # unassign issues - post :bulk_edit, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'} + post :bulk_update, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'} assert_response 302 # check that the issues were updated assert_nil Issue.find(2).assigned_to end - def test_post_bulk_edit_should_allow_fixed_version_to_be_set_to_a_subproject + def test_post_bulk_update_should_allow_fixed_version_to_be_set_to_a_subproject @request.session[:user_id] = 2 - post :bulk_edit, :ids => [1,2], :issue => {:fixed_version_id => 4} + post :bulk_update, :ids => [1,2], :issue => {:fixed_version_id => 4} assert_response :redirect issues = Issue.find([1,2]) @@ -1001,17 +1001,17 @@ def test_post_bulk_edit_should_allow_fixed_version_to_be_set_to_a_subproject end end - def test_post_bulk_edit_should_redirect_back_using_the_back_url_parameter + def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter @request.session[:user_id] = 2 - post :bulk_edit, :ids => [1,2], :back_url => '/issues' + post :bulk_update, :ids => [1,2], :back_url => '/issues' assert_response :redirect assert_redirected_to '/issues' end - def test_post_bulk_edit_should_not_redirect_back_using_the_back_url_parameter_off_the_host + def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host @request.session[:user_id] = 2 - post :bulk_edit, :ids => [1,2], :back_url => 'http://google.com' + post :bulk_update, :ids => [1,2], :back_url => 'http://google.com' assert_response :redirect assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier diff --git a/test/integration/routing_test.rb b/test/integration/routing_test.rb index b05a1285d1f..119b506ae68 100644 --- a/test/integration/routing_test.rb +++ b/test/integration/routing_test.rb @@ -108,6 +108,9 @@ class RoutingTest < ActionController::IntegrationTest should_route :post, "/issues/context_menu", :controller => 'context_menus', :action => 'issues' should_route :get, "/issues/changes", :controller => 'journals', :action => 'index' + + should_route :get, "/issues/bulk_edit", :controller => 'issues', :action => 'bulk_edit' + should_route :post, "/issues/bulk_edit", :controller => 'issues', :action => 'bulk_update' end context "issue categories" do From 2e2241cf8455db4ececccd3dc647ead4bb75cb24 Mon Sep 17 00:00:00 2001 From: Azamat Hackimov Date: Tue, 24 Aug 2010 15:32:11 +0000 Subject: [PATCH 02/25] Translation updates * de (#6198) * ja (#6189) * zh-TW (#6197) git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4038 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/locales/de.yml | 18 ++++++++++-------- config/locales/ja.yml | 6 +++--- config/locales/zh-TW.yml | 11 +++++------ 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/config/locales/de.yml b/config/locales/de.yml index e4d1de93d47..78cc99d4a59 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -68,10 +68,11 @@ de: other: "fast {{count}} Jahren" number: + # Default format for numbers format: - precision: 2 separator: ',' delimiter: '.' + precision: 2 currency: format: unit: '€' @@ -214,6 +215,7 @@ de: mail_body_wiki_content_added: "Die Wiki-Seite '{{page}}' wurde von {{author}} hinzugefügt." mail_subject_wiki_content_updated: "Wiki-Seite '{{page}}' erfolgreich aktualisiert" mail_body_wiki_content_updated: "Die Wiki-Seite '{{page}}' wurde von {{author}} aktualisiert." + gui_validation_error: 1 Fehler gui_validation_error_plural: "{{count}} Fehler" @@ -252,7 +254,7 @@ de: field_priority: Priorität field_fixed_version: Zielversion field_user: Benutzer - field_principal: Principal + field_principal: Auftraggeber field_role: Rolle field_homepage: Projekt-Homepage field_is_public: Öffentlich @@ -297,6 +299,7 @@ de: field_redirect_existing_links: Existierende Links umleiten field_estimated_hours: Geschätzter Aufwand field_column_names: Spalten + field_time_entries: Logzeit field_time_zone: Zeitzone field_searchable: Durchsuchbar field_default_value: Standardwert @@ -428,6 +431,8 @@ de: project_module_wiki: Wiki project_module_repository: Projektarchiv project_module_boards: Foren + project_module_calendar: Kalender + project_module_gantt: Gantt label_user: Benutzer label_user_plural: Benutzer @@ -485,7 +490,7 @@ de: label_my_page: Meine Seite label_my_account: Mein Konto label_my_projects: Meine Projekte - label_my_page_block: My page block + label_my_page_block: Bereich "Meine Seite" label_administration: Administration label_login: Anmelden label_logout: Abmelden @@ -499,7 +504,7 @@ de: label_user_activity: "Aktivität von {{value}}" label_new: Neu label_logged_as: Angemeldet als - label_environment: Environment + label_environment: Umgebung label_authentication: Authentifizierung label_auth_source: Authentifizierungs-Modus label_auth_source_new: Neuer Authentifizierungs-Modus @@ -831,7 +836,7 @@ de: button_quote: Zitieren button_duplicate: Duplizieren button_show: Anzeigen - + status_active: aktiv status_registered: angemeldet status_locked: gesperrt @@ -927,6 +932,3 @@ de: enumeration_activities: Aktivitäten (Zeiterfassung) enumeration_system_activity: System-Aktivität - field_time_entries: Log time - project_module_gantt: Gantt - project_module_calendar: Calendar diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 75d29df28be..50ccc872946 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -305,6 +305,7 @@ ja: field_redirect_existing_links: 既存のリンクをリダイレクトする field_estimated_hours: 予定工数 field_column_names: 項目 + field_time_entries: 時間を記録 field_time_zone: タイムゾーン field_searchable: 検索条件に設定可能とする field_default_value: デフォルト値 @@ -436,6 +437,8 @@ ja: project_module_wiki: Wiki project_module_repository: リポジトリ project_module_boards: フォーラム + project_module_gantt: ガントチャート + project_module_calendar: カレンダー label_user: ユーザ label_user_plural: ユーザ @@ -934,6 +937,3 @@ ja: enumeration_doc_categories: 文書カテゴリ enumeration_activities: 作業分類 (時間トラッキング) enumeration_system_activity: システム作業分類 - field_time_entries: Log time - project_module_gantt: Gantt - project_module_calendar: Calendar diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 7d40c2ece09..9a6d83b3825 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -1,4 +1,4 @@ -# Chinese (Taiwan) translations for Ruby on Rails +# Chinese (Taiwan) translations for Ruby on Rails # by tsechingho (http://github.com/tsechingho) # See http://github.com/svenfuchs/rails-i18n/ for details. @@ -497,6 +497,8 @@ project_module_wiki: Wiki project_module_repository: 版本控管 project_module_boards: 討論區 + project_module_calendar: 日曆 + project_module_gantt: 甘特圖 label_user: 用戶 label_user_plural: 用戶清單 @@ -514,7 +516,7 @@ label_issue: 項目 label_issue_new: 建立新項目 label_issue_plural: 項目清單 - label_issue_view_all: 檢視全部的項目 + label_issue_view_all: 檢視所有項目 label_issues_by: "項目按 {{value}} 分組顯示" label_issue_added: 項目已新增 label_issue_updated: 項目已更新 @@ -564,7 +566,7 @@ label_last_login: 最近一次連線 label_registered_on: 註冊於 label_activity: 活動 - label_overall_activity: 檢視整體活動 + label_overall_activity: 整體活動 label_user_activity: "{{value}} 的活動" label_new: 建立新的... label_logged_as: 目前登入 @@ -995,6 +997,3 @@ enumeration_doc_categories: 文件分類 enumeration_activities: 活動 (時間追蹤) enumeration_system_activity: 系統活動 - - project_module_gantt: Gantt - project_module_calendar: Calendar From bc951a9d4f849099f907c5a01b066b75f9d7bf4c Mon Sep 17 00:00:00 2001 From: Azamat Hackimov Date: Tue, 24 Aug 2010 16:15:14 +0000 Subject: [PATCH 03/25] remove BOM from zh-TW git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4039 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/locales/zh-TW.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 9a6d83b3825..0216525b0cb 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -1,4 +1,4 @@ -# Chinese (Taiwan) translations for Ruby on Rails +# Chinese (Taiwan) translations for Ruby on Rails # by tsechingho (http://github.com/tsechingho) # See http://github.com/svenfuchs/rails-i18n/ for details. From daa4272c0e7f657a0070424224cabccbbeca6197 Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Wed, 25 Aug 2010 14:59:16 +0000 Subject: [PATCH 04/25] Refactor: extract method in bulk_update. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4040 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/issues_controller.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 29b13136050..f10ba03bfaf 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -198,11 +198,8 @@ def bulk_edit def bulk_update @issues.sort! + attributes = parse_params_for_bulk_issue_attributes(params) - attributes = (params[:issue] || {}).reject {|k,v| v.blank?} - attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'} - attributes[:custom_field_values].reject! {|k,v| v.blank?} if attributes[:custom_field_values] - unsaved_issue_ids = [] @issues.each do |issue| issue.reload @@ -318,4 +315,11 @@ def check_for_default_issue_status return false end end + + def parse_params_for_bulk_issue_attributes(params) + attributes = (params[:issue] || {}).reject {|k,v| v.blank?} + attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'} + attributes[:custom_field_values].reject! {|k,v| v.blank?} if attributes[:custom_field_values] + attributes + end end From 56e984b5e740398d0659432ecdee770de1943e84 Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Thu, 26 Aug 2010 16:36:59 +0000 Subject: [PATCH 05/25] Refactor: convert many of the custom Issue routes to REST resources. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4041 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/calendars_controller.rb | 5 +- app/controllers/gantts_controller.rb | 4 ++ app/views/calendars/show.html.erb | 3 +- app/views/gantts/show.html.erb | 3 +- config/routes.rb | 66 +++++++------------ lib/redmine.rb | 4 +- .../context_menus_controller_test.rb | 2 +- test/integration/issues_test.rb | 2 +- test/integration/routing_test.rb | 8 +-- 9 files changed, 44 insertions(+), 53 deletions(-) diff --git a/app/controllers/calendars_controller.rb b/app/controllers/calendars_controller.rb index 1115691a158..febacd0757d 100644 --- a/app/controllers/calendars_controller.rb +++ b/app/controllers/calendars_controller.rb @@ -32,8 +32,11 @@ def show @calendar.events = events end - render :layout => false if request.xhr? + render :action => 'show', :layout => false if request.xhr? end + def update + show + end end diff --git a/app/controllers/gantts_controller.rb b/app/controllers/gantts_controller.rb index cdfef5238a5..6a6071e8650 100644 --- a/app/controllers/gantts_controller.rb +++ b/app/controllers/gantts_controller.rb @@ -43,4 +43,8 @@ def show end end + def update + show + end + end diff --git a/app/views/calendars/show.html.erb b/app/views/calendars/show.html.erb index 4541cc0c8a0..afbceb9cd10 100644 --- a/app/views/calendars/show.html.erb +++ b/app/views/calendars/show.html.erb @@ -1,6 +1,7 @@

<%= l(:label_calendar) %>

-<% form_tag({}, :id => 'query_form') do %> +<% form_tag(calendar_path, :method => :put, :id => 'query_form') do %> + <%= hidden_field_tag('project_id', @project.to_param) if @project%>
<%= l(:label_filter_plural) %>
diff --git a/app/views/gantts/show.html.erb b/app/views/gantts/show.html.erb index 653a41d41ba..5d4ef0dbf9e 100644 --- a/app/views/gantts/show.html.erb +++ b/app/views/gantts/show.html.erb @@ -1,6 +1,7 @@

<%= l(:label_gantt) %>

-<% form_tag(params.merge(:month => nil, :year => nil, :months => nil), :id => 'query_form') do %> +<% form_tag(gantt_path(:month => params[:month], :year => params[:year], :months => params[:months]), :method => :put, :id => 'query_form') do %> + <%= hidden_field_tag('project_id', @project.to_param) if @project%>
<%= l(:label_filter_plural) %>
diff --git a/config/routes.rb b/config/routes.rb index 4e1f9d7d509..ea511221697 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -104,58 +104,39 @@ end map.resources :issue_moves, :only => [:new, :create], :path_prefix => '/issues', :as => 'move' + + # Misc issue routes. TODO: move into resources map.auto_complete_issues '/issues/auto_complete', :controller => 'auto_completes', :action => 'issues' - # TODO: would look nicer as /issues/:id/preview - map.preview_issue '/issues/preview/:id', :controller => 'previews', :action => 'issue' + map.preview_issue '/issues/preview/:id', :controller => 'previews', :action => 'issue' # TODO: would look nicer as /issues/:id/preview map.issues_context_menu '/issues/context_menu', :controller => 'context_menus', :action => 'issues' map.issue_changes '/issues/changes', :controller => 'journals', :action => 'index' - - map.with_options :controller => 'issues' do |issues_routes| - issues_routes.with_options :conditions => {:method => :get} do |issues_views| - issues_views.connect 'issues', :action => 'index' - issues_views.connect 'issues.:format', :action => 'index' - issues_views.connect 'projects/:project_id/issues', :action => 'index' - issues_views.connect 'projects/:project_id/issues.:format', :action => 'index' - issues_views.connect 'projects/:project_id/issues/new', :action => 'new' - issues_views.connect 'projects/:project_id/issues/gantt', :controller => 'gantts', :action => 'show' - issues_views.connect 'projects/:project_id/issues/calendar', :controller => 'calendars', :action => 'show' - issues_views.connect 'projects/:project_id/issues/:copy_from/copy', :action => 'new' - issues_views.connect 'issues/:id', :action => 'show', :id => /\d+/ - issues_views.connect 'issues/:id.:format', :action => 'show', :id => /\d+/ - issues_views.connect 'issues/:id/edit', :action => 'edit', :id => /\d+/ - end - issues_routes.with_options :conditions => {:method => :post} do |issues_actions| - issues_actions.connect 'issues', :action => 'index' - issues_actions.connect 'projects/:project_id/issues', :action => 'create' - issues_actions.connect 'projects/:project_id/issues/gantt', :controller => 'gantts', :action => 'show' - issues_actions.connect 'projects/:project_id/issues/calendar', :controller => 'calendars', :action => 'show' - issues_actions.connect 'issues/:id/quoted', :controller => 'journals', :action => 'new', :id => /\d+/ - issues_actions.connect 'issues/:id/:action', :action => /edit|destroy/, :id => /\d+/ - issues_actions.connect 'issues.:format', :action => 'create', :format => /xml/ - issues_actions.connect 'issues/bulk_edit', :action => 'bulk_update' - end - issues_routes.with_options :conditions => {:method => :put} do |issues_actions| - issues_actions.connect 'issues/:id/edit', :action => 'update', :id => /\d+/ - issues_actions.connect 'issues/:id.:format', :action => 'update', :id => /\d+/, :format => /xml/ - end - issues_routes.with_options :conditions => {:method => :delete} do |issues_actions| - issues_actions.connect 'issues/:id.:format', :action => 'destroy', :id => /\d+/, :format => /xml/ - end - issues_routes.connect 'issues/gantt', :controller => 'gantts', :action => 'show' - issues_routes.connect 'issues/calendar', :controller => 'calendars', :action => 'show' - issues_routes.connect 'issues/:action' + map.bulk_edit_issue 'issues/bulk_edit', :controller => 'issues', :action => 'bulk_edit', :conditions => { :method => :get } + map.bulk_update_issue 'issues/bulk_edit', :controller => 'issues', :action => 'bulk_update', :conditions => { :method => :post } + map.quoted_issue '/issues/:id/quoted', :controller => 'journals', :action => 'new', :id => /\d+/, :conditions => { :method => :post } + map.connect '/issues/:id/destroy', :controller => 'issues', :action => 'destroy', :conditions => { :method => :post } # legacy + + map.resource :gantt, :path_prefix => '/issues', :controller => 'gantts', :only => [:show, :update] + map.resource :gantt, :path_prefix => '/projects/:project_id/issues', :controller => 'gantts', :only => [:show, :update] + map.resource :calendar, :path_prefix => '/issues', :controller => 'calendars', :only => [:show, :update] + map.resource :calendar, :path_prefix => '/projects/:project_id/issues', :controller => 'calendars', :only => [:show, :update] + + map.with_options :controller => 'reports', :conditions => {:method => :get} do |reports| + reports.connect 'projects/:id/issues/report', :action => 'issue_report' + reports.connect 'projects/:id/issues/report/:detail', :action => 'issue_report_details' end + # Following two routes conflict with the resources because #index allows POST + map.connect '/issues', :controller => 'issues', :action => 'index', :conditions => { :method => :post } + map.connect '/issues/create', :controller => 'issues', :action => 'index', :conditions => { :method => :post } + + map.resources :issues, :member => { :edit => :post }, :collection => {} + map.resources :issues, :path_prefix => '/projects/:project_id', :collection => { :create => :post } + map.with_options :controller => 'issue_relations', :conditions => {:method => :post} do |relations| relations.connect 'issues/:issue_id/relations/:id', :action => 'new' relations.connect 'issues/:issue_id/relations/:id/destroy', :action => 'destroy' end - map.with_options :controller => 'reports', :conditions => {:method => :get} do |reports| - reports.connect 'projects/:id/issues/report', :action => 'issue_report' - reports.connect 'projects/:id/issues/report/:detail', :action => 'issue_report_details' - end - map.with_options :controller => 'news' do |news_routes| news_routes.with_options :conditions => {:method => :get} do |news_views| news_views.connect 'news', :action => 'index' @@ -203,6 +184,7 @@ project_views.connect 'projects/:id/files', :action => 'list_files' project_views.connect 'projects/:id/files/new', :action => 'add_file' project_views.connect 'projects/:id/settings/:tab', :action => 'settings' + project_views.connect 'projects/:project_id/issues/:copy_from/copy', :controller => 'issues', :action => 'new' end projects.with_options :action => 'activity', :conditions => {:method => :get} do |activity| diff --git a/lib/redmine.rb b/lib/redmine.rb index e1f1e2e16d2..69b7b7a94fb 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -137,11 +137,11 @@ end map.project_module :calendar do |map| - map.permission :view_calendar, :calendars => :show + map.permission :view_calendar, :calendars => [:show, :update] end map.project_module :gantt do |map| - map.permission :view_gantt, :gantts => :show + map.permission :view_gantt, :gantts => [:show, :update] end end diff --git a/test/functional/context_menus_controller_test.rb b/test/functional/context_menus_controller_test.rb index eee9dc60828..764350879c1 100644 --- a/test/functional/context_menus_controller_test.rb +++ b/test/functional/context_menus_controller_test.rb @@ -12,7 +12,7 @@ def test_context_menu_one_issue :attributes => { :href => '/issues/1/edit', :class => 'icon-edit' } assert_tag :tag => 'a', :content => 'Closed', - :attributes => { :href => '/issues/1/edit?issue%5Bstatus_id%5D=5', + :attributes => { :href => '/issues/1?issue%5Bstatus_id%5D=5', :class => '' } assert_tag :tag => 'a', :content => 'Immediate', :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&issue%5Bpriority_id%5D=8', diff --git a/test/integration/issues_test.rb b/test/integration/issues_test.rb index 0c1a36d3482..c8a151cfd76 100644 --- a/test/integration/issues_test.rb +++ b/test/integration/issues_test.rb @@ -69,7 +69,7 @@ def test_issue_attachements log_user('jsmith', 'jsmith') set_tmp_attachments_directory - put 'issues/1/edit', + put 'issues/1', :notes => 'Some notes', :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'This is an attachment'}} assert_redirected_to "issues/1" diff --git a/test/integration/routing_test.rb b/test/integration/routing_test.rb index 119b506ae68..9b5f3939974 100644 --- a/test/integration/routing_test.rb +++ b/test/integration/routing_test.rb @@ -91,14 +91,14 @@ class RoutingTest < ActionController::IntegrationTest should_route :post, "/issues/1/quoted", :controller => 'journals', :action => 'new', :id => '1' should_route :get, "/issues/calendar", :controller => 'calendars', :action => 'show' - should_route :post, "/issues/calendar", :controller => 'calendars', :action => 'show' + should_route :put, "/issues/calendar", :controller => 'calendars', :action => 'update' should_route :get, "/projects/project-name/issues/calendar", :controller => 'calendars', :action => 'show', :project_id => 'project-name' - should_route :post, "/projects/project-name/issues/calendar", :controller => 'calendars', :action => 'show', :project_id => 'project-name' + should_route :put, "/projects/project-name/issues/calendar", :controller => 'calendars', :action => 'update', :project_id => 'project-name' should_route :get, "/issues/gantt", :controller => 'gantts', :action => 'show' - should_route :post, "/issues/gantt", :controller => 'gantts', :action => 'show' + should_route :put, "/issues/gantt", :controller => 'gantts', :action => 'update' should_route :get, "/projects/project-name/issues/gantt", :controller => 'gantts', :action => 'show', :project_id => 'project-name' - should_route :post, "/projects/project-name/issues/gantt", :controller => 'gantts', :action => 'show', :project_id => 'project-name' + should_route :put, "/projects/project-name/issues/gantt", :controller => 'gantts', :action => 'update', :project_id => 'project-name' should_route :get, "/issues/auto_complete", :controller => 'auto_completes', :action => 'issues' From 3eea03d70efd4e894a5020e8bae62a6af6e59803 Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Thu, 26 Aug 2010 16:37:05 +0000 Subject: [PATCH 06/25] Refactor: extract link to previous and next month into helpers. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4042 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/calendars_helper.rb | 14 ++++++++++++++ app/views/calendars/show.html.erb | 9 +-------- 2 files changed, 15 insertions(+), 8 deletions(-) create mode 100644 app/helpers/calendars_helper.rb diff --git a/app/helpers/calendars_helper.rb b/app/helpers/calendars_helper.rb new file mode 100644 index 00000000000..d3544f2678e --- /dev/null +++ b/app/helpers/calendars_helper.rb @@ -0,0 +1,14 @@ +module CalendarsHelper + def link_to_previous_month(year, month) + link_to_remote ('« ' + (month==1 ? "#{month_name(12)} #{year-1}" : "#{month_name(month-1)}")), + {:update => "content", :url => { :year => (month==1 ? year-1 : year), :month =>(month==1 ? 12 : month-1) }}, + {:href => url_for(:action => 'show', :year => (month==1 ? year-1 : year), :month =>(month==1 ? 12 : month-1))} + end + + def link_to_next_month(year, month) + link_to_remote ((month==12 ? "#{month_name(1)} #{year+1}" : "#{month_name(month+1)}") + ' »'), + {:update => "content", :url => { :year => (month==12 ? year+1 : year), :month =>(month==12 ? 1 : month+1) }}, + {:href => url_for(:action => 'show', :year => (month==12 ? year+1 : year), :month =>(month==12 ? 1 : month+1))} + + end +end diff --git a/app/views/calendars/show.html.erb b/app/views/calendars/show.html.erb index afbceb9cd10..09bf7ddf2a1 100644 --- a/app/views/calendars/show.html.erb +++ b/app/views/calendars/show.html.erb @@ -10,14 +10,7 @@

-<%= link_to_remote ('« ' + (@month==1 ? "#{month_name(12)} #{@year-1}" : "#{month_name(@month-1)}")), - {:update => "content", :url => { :year => (@month==1 ? @year-1 : @year), :month =>(@month==1 ? 12 : @month-1) }}, - {:href => url_for(:action => 'show', :year => (@month==1 ? @year-1 : @year), :month =>(@month==1 ? 12 : @month-1))} - %> | -<%= link_to_remote ((@month==12 ? "#{month_name(1)} #{@year+1}" : "#{month_name(@month+1)}") + ' »'), - {:update => "content", :url => { :year => (@month==12 ? @year+1 : @year), :month =>(@month==12 ? 1 : @month+1) }}, - {:href => url_for(:action => 'show', :year => (@month==12 ? @year+1 : @year), :month =>(@month==12 ? 1 : @month+1))} - %> + <%= link_to_previous_month(@year, @month) %> | <%= link_to_next_month(@year, @month) %>

From 91380eeaab3028aac9a33559fe3932a86b066b6e Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Thu, 26 Aug 2010 16:37:11 +0000 Subject: [PATCH 07/25] Refactor: extract ternary operators to temps. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4043 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/calendars_helper.rb | 36 +++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/app/helpers/calendars_helper.rb b/app/helpers/calendars_helper.rb index d3544f2678e..52cc425122e 100644 --- a/app/helpers/calendars_helper.rb +++ b/app/helpers/calendars_helper.rb @@ -1,14 +1,38 @@ module CalendarsHelper def link_to_previous_month(year, month) - link_to_remote ('« ' + (month==1 ? "#{month_name(12)} #{year-1}" : "#{month_name(month-1)}")), - {:update => "content", :url => { :year => (month==1 ? year-1 : year), :month =>(month==1 ? 12 : month-1) }}, - {:href => url_for(:action => 'show', :year => (month==1 ? year-1 : year), :month =>(month==1 ? 12 : month-1))} + target_year, target_month = if month == 1 + [year - 1, 12] + else + [year, month - 1] + end + + name = if target_month == 12 + "#{month_name(target_month)} #{target_year}" + else + "#{month_name(target_month)}" + end + + link_to_remote ('« ' + name), + {:update => "content", :url => { :year => target_year, :month => target_month }}, + {:href => url_for(:action => 'show', :year => target_year, :month => target_month)} end def link_to_next_month(year, month) - link_to_remote ((month==12 ? "#{month_name(1)} #{year+1}" : "#{month_name(month+1)}") + ' »'), - {:update => "content", :url => { :year => (month==12 ? year+1 : year), :month =>(month==12 ? 1 : month+1) }}, - {:href => url_for(:action => 'show', :year => (month==12 ? year+1 : year), :month =>(month==12 ? 1 : month+1))} + target_year, target_month = if month == 12 + [year + 1, 1] + else + [year, month + 1] + end + + name = if target_month == 1 + "#{month_name(target_month)} #{target_year}" + else + "#{month_name(target_month)}" + end + + link_to_remote (name + ' »'), + {:update => "content", :url => { :year => target_year, :month => target_month }}, + {:href => url_for(:action => 'show', :year => target_year, :month =>target_month)} end end From ab1e74d16cb21ee1f7410c94538c2b6e2bdd3b5b Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Thu, 26 Aug 2010 16:37:16 +0000 Subject: [PATCH 08/25] Refactor: extract target link generation. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4044 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/calendars_helper.rb | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/app/helpers/calendars_helper.rb b/app/helpers/calendars_helper.rb index 52cc425122e..2bc028d6559 100644 --- a/app/helpers/calendars_helper.rb +++ b/app/helpers/calendars_helper.rb @@ -12,9 +12,11 @@ def link_to_previous_month(year, month) "#{month_name(target_month)}" end - link_to_remote ('« ' + name), - {:update => "content", :url => { :year => target_year, :month => target_month }}, - {:href => url_for(:action => 'show', :year => target_year, :month => target_month)} + link_target = calendar_path(:year => target_year, :month => target_month) + + link_to_remote(('« ' + name), + {:update => "content", :url => link_target, :method => :put}, + {:href => link_target}) end def link_to_next_month(year, month) @@ -30,9 +32,11 @@ def link_to_next_month(year, month) "#{month_name(target_month)}" end - link_to_remote (name + ' »'), - {:update => "content", :url => { :year => target_year, :month => target_month }}, - {:href => url_for(:action => 'show', :year => target_year, :month =>target_month)} + link_target = calendar_path(:year => target_year, :month => target_month) + + link_to_remote((name + ' »'), + {:update => "content", :url => link_target, :method => :put}, + {:href => link_target}) end end From 30821586cb31dd2af9b634477c026a817e294986 Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Thu, 26 Aug 2010 16:37:21 +0000 Subject: [PATCH 09/25] Add the project_id to the Calendar link to month. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4045 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/calendars_helper.rb | 12 +++++++----- app/views/calendars/show.html.erb | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/helpers/calendars_helper.rb b/app/helpers/calendars_helper.rb index 2bc028d6559..88327f51c76 100644 --- a/app/helpers/calendars_helper.rb +++ b/app/helpers/calendars_helper.rb @@ -1,5 +1,5 @@ module CalendarsHelper - def link_to_previous_month(year, month) + def link_to_previous_month(year, month, options={}) target_year, target_month = if month == 1 [year - 1, 12] else @@ -11,15 +11,16 @@ def link_to_previous_month(year, month) else "#{month_name(target_month)}" end - - link_target = calendar_path(:year => target_year, :month => target_month) + + project_id = options[:project].present? ? options[:project].to_param : nil + link_target = calendar_path(:year => target_year, :month => target_month, :project_id => project_id) link_to_remote(('« ' + name), {:update => "content", :url => link_target, :method => :put}, {:href => link_target}) end - def link_to_next_month(year, month) + def link_to_next_month(year, month, options={}) target_year, target_month = if month == 12 [year + 1, 1] else @@ -32,7 +33,8 @@ def link_to_next_month(year, month) "#{month_name(target_month)}" end - link_target = calendar_path(:year => target_year, :month => target_month) + project_id = options[:project].present? ? options[:project].to_param : nil + link_target = calendar_path(:year => target_year, :month => target_month, :project_id => project_id) link_to_remote((name + ' »'), {:update => "content", :url => link_target, :method => :put}, diff --git a/app/views/calendars/show.html.erb b/app/views/calendars/show.html.erb index 09bf7ddf2a1..5304166614f 100644 --- a/app/views/calendars/show.html.erb +++ b/app/views/calendars/show.html.erb @@ -10,7 +10,7 @@

- <%= link_to_previous_month(@year, @month) %> | <%= link_to_next_month(@year, @month) %> + <%= link_to_previous_month(@year, @month, :project => @project) %> | <%= link_to_next_month(@year, @month, :project => @project) %>

From 5b08b2f33d4072e2a41545637ef40365c3ef7ea4 Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Thu, 26 Aug 2010 16:37:26 +0000 Subject: [PATCH 10/25] Refactor: extract common code to link_to_month. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4046 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/calendars_helper.rb | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/app/helpers/calendars_helper.rb b/app/helpers/calendars_helper.rb index 88327f51c76..08e665dcd4e 100644 --- a/app/helpers/calendars_helper.rb +++ b/app/helpers/calendars_helper.rb @@ -12,12 +12,7 @@ def link_to_previous_month(year, month, options={}) "#{month_name(target_month)}" end - project_id = options[:project].present? ? options[:project].to_param : nil - link_target = calendar_path(:year => target_year, :month => target_month, :project_id => project_id) - - link_to_remote(('« ' + name), - {:update => "content", :url => link_target, :method => :put}, - {:href => link_target}) + link_to_month(('« ' + name), target_year, target_month, options) end def link_to_next_month(year, month, options={}) @@ -33,12 +28,18 @@ def link_to_next_month(year, month, options={}) "#{month_name(target_month)}" end + link_to_month((name + ' »'), target_year, target_month, options) + end + + def link_to_month(link_name, year, month, options={}) project_id = options[:project].present? ? options[:project].to_param : nil - link_target = calendar_path(:year => target_year, :month => target_month, :project_id => project_id) - link_to_remote((name + ' »'), + link_target = calendar_path(:year => year, :month => month, :project_id => project_id) + + link_to_remote(link_name, {:update => "content", :url => link_target, :method => :put}, {:href => link_target}) end + end From b925325ddbd5fb594f20221dd724f7822ed4c3d3 Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Fri, 27 Aug 2010 14:05:54 +0000 Subject: [PATCH 11/25] Refactor: extract ProjectsController#activity to a new Activities controller. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4047 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/activities_controller.rb | 59 +++++++++++++ app/controllers/projects_controller.rb | 50 +---------- .../index.html.erb} | 0 app/views/boards/index.rhtml | 4 +- app/views/projects/index.rhtml | 2 +- app/views/projects/show.rhtml | 2 +- app/views/users/show.rhtml | 6 +- app/views/welcome/index.rhtml | 2 +- app/views/wiki/special_date_index.rhtml | 4 +- config/routes.rb | 2 +- lib/redmine.rb | 4 +- test/functional/activities_controller_test.rb | 87 +++++++++++++++++++ test/functional/projects_controller_test.rb | 81 ----------------- test/integration/routing_test.rb | 8 +- 14 files changed, 166 insertions(+), 145 deletions(-) create mode 100644 app/controllers/activities_controller.rb rename app/views/{projects/activity.rhtml => activities/index.html.erb} (100%) create mode 100644 test/functional/activities_controller_test.rb diff --git a/app/controllers/activities_controller.rb b/app/controllers/activities_controller.rb new file mode 100644 index 00000000000..ae6a6736966 --- /dev/null +++ b/app/controllers/activities_controller.rb @@ -0,0 +1,59 @@ +class ActivitiesController < ApplicationController + menu_item :activity + before_filter :find_optional_project + accept_key_auth :index + + def index + @days = Setting.activity_days_default.to_i + + if params[:from] + begin; @date_to = params[:from].to_date + 1; rescue; end + end + + @date_to ||= Date.today + 1 + @date_from = @date_to - @days + @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1') + @author = (params[:user_id].blank? ? nil : User.active.find(params[:user_id])) + + @activity = Redmine::Activity::Fetcher.new(User.current, :project => @project, + :with_subprojects => @with_subprojects, + :author => @author) + @activity.scope_select {|t| !params["show_#{t}"].nil?} + @activity.scope = (@author.nil? ? :default : :all) if @activity.scope.empty? + + events = @activity.events(@date_from, @date_to) + + if events.empty? || stale?(:etag => [events.first, User.current]) + respond_to do |format| + format.html { + @events_by_day = events.group_by(&:event_date) + render :layout => false if request.xhr? + } + format.atom { + title = l(:label_activity) + if @author + title = @author.name + elsif @activity.scope.size == 1 + title = l("label_#{@activity.scope.first.singularize}_plural") + end + render_feed(events, :title => "#{@project || Setting.app_title}: #{title}") + } + end + end + + rescue ActiveRecord::RecordNotFound + render_404 + end + + private + + # TODO: refactor, duplicated in projects_controller + def find_optional_project + return true unless params[:id] + @project = Project.find(params[:id]) + authorize + rescue ActiveRecord::RecordNotFound + render_404 + end + +end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 44071d214ef..6bb7663869a 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -17,17 +17,15 @@ class ProjectsController < ApplicationController menu_item :overview - menu_item :activity, :only => :activity menu_item :roadmap, :only => :roadmap menu_item :files, :only => [:list_files, :add_file] menu_item :settings, :only => :settings - before_filter :find_project, :except => [ :index, :list, :add, :copy, :activity ] - before_filter :find_optional_project, :only => :activity - before_filter :authorize, :except => [ :index, :list, :add, :copy, :archive, :unarchive, :destroy, :activity ] + before_filter :find_project, :except => [ :index, :list, :add, :copy ] + before_filter :authorize, :except => [ :index, :list, :add, :copy, :archive, :unarchive, :destroy] before_filter :authorize_global, :only => :add before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy ] - accept_key_auth :activity, :index + accept_key_auth :index after_filter :only => [:add, :edit, :archive, :unarchive, :destroy] do |controller| if controller.request.post? @@ -313,48 +311,6 @@ def roadmap @versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?} end - def activity - @days = Setting.activity_days_default.to_i - - if params[:from] - begin; @date_to = params[:from].to_date + 1; rescue; end - end - - @date_to ||= Date.today + 1 - @date_from = @date_to - @days - @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1') - @author = (params[:user_id].blank? ? nil : User.active.find(params[:user_id])) - - @activity = Redmine::Activity::Fetcher.new(User.current, :project => @project, - :with_subprojects => @with_subprojects, - :author => @author) - @activity.scope_select {|t| !params["show_#{t}"].nil?} - @activity.scope = (@author.nil? ? :default : :all) if @activity.scope.empty? - - events = @activity.events(@date_from, @date_to) - - if events.empty? || stale?(:etag => [events.first, User.current]) - respond_to do |format| - format.html { - @events_by_day = events.group_by(&:event_date) - render :layout => false if request.xhr? - } - format.atom { - title = l(:label_activity) - if @author - title = @author.name - elsif @activity.scope.size == 1 - title = l("label_#{@activity.scope.first.singularize}_plural") - end - render_feed(events, :title => "#{@project || Setting.app_title}: #{title}") - } - end - end - - rescue ActiveRecord::RecordNotFound - render_404 - end - private def find_optional_project return true unless params[:id] diff --git a/app/views/projects/activity.rhtml b/app/views/activities/index.html.erb similarity index 100% rename from app/views/projects/activity.rhtml rename to app/views/activities/index.html.erb diff --git a/app/views/boards/index.rhtml b/app/views/boards/index.rhtml index 7cc6a0e2f5d..6310f942efc 100644 --- a/app/views/boards/index.rhtml +++ b/app/views/boards/index.rhtml @@ -30,11 +30,11 @@ <% other_formats_links do |f| %> - <%= f.link_to 'Atom', :url => {:controller => 'projects', :action => 'activity', :id => @project, :show_messages => 1, :key => User.current.rss_key} %> + <%= f.link_to 'Atom', :url => {:controller => 'activities', :action => 'index', :id => @project, :show_messages => 1, :key => User.current.rss_key} %> <% end %> <% content_for :header_tags do %> - <%= auto_discovery_link_tag(:atom, {:controller => 'projects', :action => 'activity', :id => @project, :format => 'atom', :show_messages => 1, :key => User.current.rss_key}) %> + <%= auto_discovery_link_tag(:atom, {:controller => 'activities', :action => 'index', :id => @project, :format => 'atom', :show_messages => 1, :key => User.current.rss_key}) %> <% end %> <% html_title l(:label_board_plural) %> diff --git a/app/views/projects/index.rhtml b/app/views/projects/index.rhtml index b4952e90563..a2ba1c38972 100644 --- a/app/views/projects/index.rhtml +++ b/app/views/projects/index.rhtml @@ -6,7 +6,7 @@ <%= link_to(l(:label_project_new), {:controller => 'projects', :action => 'add'}, :class => 'icon icon-add') + ' |' if User.current.allowed_to?(:add_project, nil, :global => true) %> <%= link_to(l(:label_issue_view_all), { :controller => 'issues' }) + ' |' if User.current.allowed_to?(:view_issues, nil, :global => true) %> <%= link_to(l(:label_overall_spent_time), { :controller => 'time_entries' }) + ' |' if User.current.allowed_to?(:view_time_entries, nil, :global => true) %> - <%= link_to l(:label_overall_activity), { :controller => 'projects', :action => 'activity' }%> + <%= link_to l(:label_overall_activity), { :controller => 'activities', :action => 'index' }%>

<%=l(:label_project_plural)%>

diff --git a/app/views/projects/show.rhtml b/app/views/projects/show.rhtml index 62ea27848e5..0ad9a11daf6 100644 --- a/app/views/projects/show.rhtml +++ b/app/views/projects/show.rhtml @@ -74,7 +74,7 @@ <% end %> <% content_for :header_tags do %> -<%= auto_discovery_link_tag(:atom, {:action => 'activity', :id => @project, :format => 'atom', :key => User.current.rss_key}) %> +<%= auto_discovery_link_tag(:atom, {:controller => 'activities', :action => 'index', :id => @project, :format => 'atom', :key => User.current.rss_key}) %> <% end %> <% html_title(l(:label_overview)) -%> diff --git a/app/views/users/show.rhtml b/app/views/users/show.rhtml index df5aec82513..a2f90226c32 100644 --- a/app/views/users/show.rhtml +++ b/app/views/users/show.rhtml @@ -35,7 +35,7 @@
<% unless @events_by_day.empty? %> -

<%= link_to l(:label_activity), :controller => 'projects', :action => 'activity', :id => nil, :user_id => @user, :from => @events_by_day.keys.first %>

+

<%= link_to l(:label_activity), :controller => 'activities', :action => 'index', :id => nil, :user_id => @user, :from => @events_by_day.keys.first %>

<%=l(:label_reported_issues)%>: <%= Issue.count(:conditions => ["author_id=?", @user.id]) %> @@ -57,11 +57,11 @@

<% other_formats_links do |f| %> - <%= f.link_to 'Atom', :url => {:controller => 'projects', :action => 'activity', :id => nil, :user_id => @user, :key => User.current.rss_key} %> + <%= f.link_to 'Atom', :url => {:controller => 'activities', :action => 'index', :id => nil, :user_id => @user, :key => User.current.rss_key} %> <% end %> <% content_for :header_tags do %> - <%= auto_discovery_link_tag(:atom, :controller => 'projects', :action => 'activity', :user_id => @user, :format => :atom, :key => User.current.rss_key) %> + <%= auto_discovery_link_tag(:atom, :controller => 'activities', :action => 'index', :user_id => @user, :format => :atom, :key => User.current.rss_key) %> <% end %> <% end %> <%= call_hook :view_account_right_bottom, :user => @user %> diff --git a/app/views/welcome/index.rhtml b/app/views/welcome/index.rhtml index 6ac09c15393..982d6da525a 100644 --- a/app/views/welcome/index.rhtml +++ b/app/views/welcome/index.rhtml @@ -34,6 +34,6 @@ <% content_for :header_tags do %> <%= auto_discovery_link_tag(:atom, {:controller => 'news', :action => 'index', :key => User.current.rss_key, :format => 'atom'}, :title => "#{Setting.app_title}: #{l(:label_news_latest)}") %> -<%= auto_discovery_link_tag(:atom, {:controller => 'projects', :action => 'activity', :key => User.current.rss_key, :format => 'atom'}, +<%= auto_discovery_link_tag(:atom, {:controller => 'activities', :action => 'index', :key => User.current.rss_key, :format => 'atom'}, :title => "#{Setting.app_title}: #{l(:label_activity)}") %> <% end %> diff --git a/app/views/wiki/special_date_index.rhtml b/app/views/wiki/special_date_index.rhtml index 228737a5e8f..b34fb84645a 100644 --- a/app/views/wiki/special_date_index.rhtml +++ b/app/views/wiki/special_date_index.rhtml @@ -23,11 +23,11 @@ <% unless @pages.empty? %> <% other_formats_links do |f| %> - <%= f.link_to 'Atom', :url => {:controller => 'projects', :action => 'activity', :id => @project, :show_wiki_edits => 1, :key => User.current.rss_key} %> + <%= f.link_to 'Atom', :url => {:controller => 'activities', :action => 'index', :id => @project, :show_wiki_edits => 1, :key => User.current.rss_key} %> <%= f.link_to('HTML', :url => {:action => 'special', :page => 'export'}) if User.current.allowed_to?(:export_wiki_pages, @project) %> <% end %> <% end %> <% content_for :header_tags do %> -<%= auto_discovery_link_tag(:atom, :controller => 'projects', :action => 'activity', :id => @project, :show_wiki_edits => 1, :format => 'atom', :key => User.current.rss_key) %> +<%= auto_discovery_link_tag(:atom, :controller => 'activities', :action => 'index', :id => @project, :show_wiki_edits => 1, :format => 'atom', :key => User.current.rss_key) %> <% end %> diff --git a/config/routes.rb b/config/routes.rb index ea511221697..1465e1ffeaf 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -187,7 +187,7 @@ project_views.connect 'projects/:project_id/issues/:copy_from/copy', :controller => 'issues', :action => 'new' end - projects.with_options :action => 'activity', :conditions => {:method => :get} do |activity| + projects.with_options :controller => 'activities', :action => 'index', :conditions => {:method => :get} do |activity| activity.connect 'projects/:id/activity' activity.connect 'projects/:id/activity.:format' activity.connect 'activity', :id => nil diff --git a/lib/redmine.rb b/lib/redmine.rb index 69b7b7a94fb..7040a1f99a5 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -44,7 +44,7 @@ # Permissions Redmine::AccessControl.map do |map| - map.permission :view_project, {:projects => [:show, :activity]}, :public => true + map.permission :view_project, {:projects => [:show], :activities => [:index]}, :public => true map.permission :search_project, {:search => :index}, :public => true map.permission :add_project, {:projects => :add}, :require => :loggedin map.permission :edit_project, {:projects => [:settings, :edit]}, :require => :member @@ -185,7 +185,7 @@ Redmine::MenuManager.map :project_menu do |menu| menu.push :overview, { :controller => 'projects', :action => 'show' } - menu.push :activity, { :controller => 'projects', :action => 'activity' } + menu.push :activity, { :controller => 'activities', :action => 'index' } menu.push :roadmap, { :controller => 'projects', :action => 'roadmap' }, :if => Proc.new { |p| p.shared_versions.any? } menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural diff --git a/test/functional/activities_controller_test.rb b/test/functional/activities_controller_test.rb new file mode 100644 index 00000000000..ba9c3398516 --- /dev/null +++ b/test/functional/activities_controller_test.rb @@ -0,0 +1,87 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class ActivitiesControllerTest < ActionController::TestCase + fixtures :all + + def test_project_index + get :index, :id => 1, :with_subprojects => 0 + assert_response :success + assert_template 'index' + assert_not_nil assigns(:events_by_day) + + assert_tag :tag => "h3", + :content => /#{2.days.ago.to_date.day}/, + :sibling => { :tag => "dl", + :child => { :tag => "dt", + :attributes => { :class => /issue-edit/ }, + :child => { :tag => "a", + :content => /(#{IssueStatus.find(2).name})/, + } + } + } + end + + def test_previous_project_index + get :index, :id => 1, :from => 3.days.ago.to_date + assert_response :success + assert_template 'index' + assert_not_nil assigns(:events_by_day) + + assert_tag :tag => "h3", + :content => /#{3.day.ago.to_date.day}/, + :sibling => { :tag => "dl", + :child => { :tag => "dt", + :attributes => { :class => /issue/ }, + :child => { :tag => "a", + :content => /#{Issue.find(1).subject}/, + } + } + } + end + + def test_global_index + get :index + assert_response :success + assert_template 'index' + assert_not_nil assigns(:events_by_day) + + assert_tag :tag => "h3", + :content => /#{5.day.ago.to_date.day}/, + :sibling => { :tag => "dl", + :child => { :tag => "dt", + :attributes => { :class => /issue/ }, + :child => { :tag => "a", + :content => /#{Issue.find(5).subject}/, + } + } + } + end + + def test_user_index + get :index, :user_id => 2 + assert_response :success + assert_template 'index' + assert_not_nil assigns(:events_by_day) + + assert_tag :tag => "h3", + :content => /#{3.day.ago.to_date.day}/, + :sibling => { :tag => "dl", + :child => { :tag => "dt", + :attributes => { :class => /issue/ }, + :child => { :tag => "a", + :content => /#{Issue.find(1).subject}/, + } + } + } + end + + def test_index_atom_feed + get :index, :format => 'atom' + assert_response :success + assert_template 'common/feed.atom.rxml' + assert_tag :tag => 'entry', :child => { + :tag => 'link', + :attributes => {:href => 'http://test.host/issues/11'}} + end + +end diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index 988496cec32..f9c8ce0227b 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -400,87 +400,6 @@ def test_roadmap_showing_subprojects_versions assert assigns(:versions).include?(Version.find(4)), "Shared version not found" assert assigns(:versions).include?(@subproject_version), "Subproject version not found" end - def test_project_activity - get :activity, :id => 1, :with_subprojects => 0 - assert_response :success - assert_template 'activity' - assert_not_nil assigns(:events_by_day) - - assert_tag :tag => "h3", - :content => /#{2.days.ago.to_date.day}/, - :sibling => { :tag => "dl", - :child => { :tag => "dt", - :attributes => { :class => /issue-edit/ }, - :child => { :tag => "a", - :content => /(#{IssueStatus.find(2).name})/, - } - } - } - end - - def test_previous_project_activity - get :activity, :id => 1, :from => 3.days.ago.to_date - assert_response :success - assert_template 'activity' - assert_not_nil assigns(:events_by_day) - - assert_tag :tag => "h3", - :content => /#{3.day.ago.to_date.day}/, - :sibling => { :tag => "dl", - :child => { :tag => "dt", - :attributes => { :class => /issue/ }, - :child => { :tag => "a", - :content => /#{Issue.find(1).subject}/, - } - } - } - end - - def test_global_activity - get :activity - assert_response :success - assert_template 'activity' - assert_not_nil assigns(:events_by_day) - - assert_tag :tag => "h3", - :content => /#{5.day.ago.to_date.day}/, - :sibling => { :tag => "dl", - :child => { :tag => "dt", - :attributes => { :class => /issue/ }, - :child => { :tag => "a", - :content => /#{Issue.find(5).subject}/, - } - } - } - end - - def test_user_activity - get :activity, :user_id => 2 - assert_response :success - assert_template 'activity' - assert_not_nil assigns(:events_by_day) - - assert_tag :tag => "h3", - :content => /#{3.day.ago.to_date.day}/, - :sibling => { :tag => "dl", - :child => { :tag => "dt", - :attributes => { :class => /issue/ }, - :child => { :tag => "a", - :content => /#{Issue.find(1).subject}/, - } - } - } - end - - def test_activity_atom_feed - get :activity, :format => 'atom' - assert_response :success - assert_template 'common/feed.atom.rxml' - assert_tag :tag => 'entry', :child => { - :tag => 'link', - :attributes => {:href => 'http://test.host/issues/11'}} - end - def test_archive @request.session[:user_id] = 1 # admin post :archive, :id => 1 diff --git a/test/integration/routing_test.rb b/test/integration/routing_test.rb index 9b5f3939974..62fdaf47a7b 100644 --- a/test/integration/routing_test.rb +++ b/test/integration/routing_test.rb @@ -19,8 +19,8 @@ class RoutingTest < ActionController::IntegrationTest context "activities" do - should_route :get, "/activity", :controller => 'projects', :action => 'activity', :id => nil - should_route :get, "/activity.atom", :controller => 'projects', :action => 'activity', :id => nil, :format => 'atom' + should_route :get, "/activity", :controller => 'activities', :action => 'index', :id => nil + should_route :get, "/activity.atom", :controller => 'activities', :action => 'index', :id => nil, :format => 'atom' end context "attachments" do @@ -175,8 +175,8 @@ class RoutingTest < ActionController::IntegrationTest should_route :get, "/projects/33/files", :controller => 'projects', :action => 'list_files', :id => '33' should_route :get, "/projects/33/files/new", :controller => 'projects', :action => 'add_file', :id => '33' should_route :get, "/projects/33/roadmap", :controller => 'projects', :action => 'roadmap', :id => '33' - should_route :get, "/projects/33/activity", :controller => 'projects', :action => 'activity', :id => '33' - should_route :get, "/projects/33/activity.atom", :controller => 'projects', :action => 'activity', :id => '33', :format => 'atom' + should_route :get, "/projects/33/activity", :controller => 'activities', :action => 'index', :id => '33' + should_route :get, "/projects/33/activity.atom", :controller => 'activities', :action => 'index', :id => '33', :format => 'atom' should_route :post, "/projects/new", :controller => 'projects', :action => 'add' should_route :post, "/projects.xml", :controller => 'projects', :action => 'add', :format => 'xml' From f92dcdf50a4ca854aabbf2b85e67dfcd71800ed4 Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Fri, 27 Aug 2010 20:08:59 +0000 Subject: [PATCH 12/25] Allow setting an issue's notes via params[:issue][:notes]. (XML API) git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4048 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/issues_controller.rb | 2 +- test/integration/issues_api_test.rb | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index f10ba03bfaf..0364e307c31 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -270,7 +270,7 @@ def update_issue_from_params @edit_allowed = User.current.allowed_to?(:edit_issues, @project) @time_entry = TimeEntry.new - @notes = params[:notes] + @notes = params[:notes] || (params[:issue].present? ? params[:issue][:notes] : nil) @issue.init_journal(User.current, @notes) # User can change issue attributes only if he has :edit permission or if a workflow transition is allowed if (@edit_allowed || !@allowed_statuses.empty?) && params[:issue] diff --git a/test/integration/issues_api_test.rb b/test/integration/issues_api_test.rb index a1e2cb7037b..e26cf643b57 100644 --- a/test/integration/issues_api_test.rb +++ b/test/integration/issues_api_test.rb @@ -198,7 +198,7 @@ def setup setup do @issue_count = Issue.count @journal_count = Journal.count - @attributes = {:subject => 'API update'} + @attributes = {:subject => 'API update', :notes => 'A new note'} put '/issues/1.xml', {:issue => @attributes}, :authorization => credentials('jsmith') end @@ -214,10 +214,15 @@ def setup assert_equal Journal.count, @journal_count + 1 end + should "add the note to the journal" do + journal = Journal.last + assert_equal "A new note", journal.notes + end + should "update the issue" do issue = Issue.find(1) @attributes.each do |attribute, value| - assert_equal value, issue.send(attribute) + assert_equal value, issue.send(attribute) unless attribute == :notes end end @@ -252,7 +257,7 @@ def setup setup do @issue_count = Issue.count @journal_count = Journal.count - @attributes = {:subject => 'API update'} + @attributes = {:subject => 'API update', :notes => 'A new note'} put '/issues/1.json', {:issue => @attributes}, :authorization => credentials('jsmith') end @@ -268,13 +273,18 @@ def setup assert_equal Journal.count, @journal_count + 1 end + should "add the note to the journal" do + journal = Journal.last + assert_equal "A new note", journal.notes + end + should "update the issue" do issue = Issue.find(1) @attributes.each do |attribute, value| - assert_equal value, issue.send(attribute) + assert_equal value, issue.send(attribute) unless attribute == :notes end end - + end context "PUT /issues/1.json with failed update" do From 1ebb0d9caec7cdc8d07c53d4d2fff416e41408aa Mon Sep 17 00:00:00 2001 From: Azamat Hackimov Date: Sun, 29 Aug 2010 12:54:04 +0000 Subject: [PATCH 13/25] Translation updates * mk (#6208) * sv (#6210) git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4049 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/locales/mk.yml | 915 ++++++++++++++++++ config/locales/sv.yml | 8 +- .../javascripts/calendar/lang/calendar-mk.js | 37 +- .../jstoolbar/lang/jstoolbar-mk.js | 23 +- 4 files changed, 950 insertions(+), 33 deletions(-) create mode 100644 config/locales/mk.yml diff --git a/config/locales/mk.yml b/config/locales/mk.yml new file mode 100644 index 00000000000..c680f900cd7 --- /dev/null +++ b/config/locales/mk.yml @@ -0,0 +1,915 @@ +mk: + # Text direction: Left-to-Right (ltr) or Right-to-Left (rtl) + direction: ltr + date: + formats: + # Use the strftime parameters for formats. + # When no format has been given, it uses default. + # You can provide other formats here if you like! + default: "%d/%m/%Y" + short: "%d %b" + long: "%d %B, %Y" + + day_names: [недела, понеделник, вторник, среда, четврток, петок, сабота] + abbr_day_names: [нед, пон, вто, сре, чет, пет, саб] + + # Don't forget the nil at the beginning; there's no such thing as a 0th month + month_names: [~, јануари, февруари, март, април, мај, јуни, јули, август, септември, октомври, ноември, декември] + abbr_month_names: [~, јан, фев, мар, апр, мај, јун, јул, авг, сеп, окт, ное, дек] + # Used in date_select and datime_select. + order: [ :day, :month, :year ] + + time: + formats: + default: "%d/%m/%Y %H:%M" + time: "%H:%M" + short: "%d %b %H:%M" + long: "%d %B, %Y %H:%M" + am: "предпладне" + pm: "попладне" + + datetime: + distance_in_words: + half_a_minute: "пола минута" + less_than_x_seconds: + one: "помалку од 1 секунда" + other: "помалку од {{count}} секунди" + x_seconds: + one: "1 секунда" + other: "{{count}} секунди" + less_than_x_minutes: + one: "помалку од 1 минута" + other: "помалку од {{count}} минути" + x_minutes: + one: "1 минута" + other: "{{count}} минути" + about_x_hours: + one: "околу 1 час" + other: "околу {{count}} часа" + x_days: + one: "1 ден" + other: "{{count}} дена" + about_x_months: + one: "околу 1 месец" + other: "околу {{count}} месеци" + x_months: + one: "1 месец" + other: "{{count}} месеци" + about_x_years: + one: "околу 1 година" + other: "околу {{count}} години" + over_x_years: + one: "преку 1 година" + other: "преку {{count}} години" + almost_x_years: + one: "скоро 1 година" + other: "скоро {{count}} години" + + number: + # Default format for numbers + format: + separator: "." + delimiter: "" + precision: 3 + human: + format: + delimiter: "" + precision: 1 + storage_units: + format: "%n %u" + units: + byte: + one: "Byte" + other: "Bytes" + kb: "KB" + mb: "MB" + gb: "GB" + tb: "TB" + + +# Used in array.to_sentence. + support: + array: + sentence_connector: "и" + skip_last_comma: false + + activerecord: + errors: + messages: + inclusion: "не е вклучено во листата" + exclusion: "е резервирано" + invalid: "е невалидно" + confirmation: "не се совпаѓа со потврдата" + accepted: "мора да е прифатено" + empty: "неможе да е празно" + blank: "неможе да е празно" + too_long: "е предолго (макс. {{count}} знаци)" + too_short: "е прекратко (мин. {{count}} знаци)" + wrong_length: "е погрешна должина (треба да е {{count}} знаци)" + taken: "е веќе зафатено" + not_a_number: "не е број" + not_a_date: "не е валидна дата" + greater_than: "мора да е поголемо од {{count}}" + greater_than_or_equal_to: "мора да е поголемо или еднакво на {{count}}" + equal_to: "мора да е еднакво на {{count}}" + less_than: "мора да е помало од {{count}}" + less_than_or_equal_to: "мора да е помало или еднакво на {{count}}" + odd: "мора да е непарно" + even: "мора да е парно" + greater_than_start_date: "мора да е поголема од почетната дата" + not_same_project: "не припаѓа на истиот проект" + circular_dependency: "Оваа врска ќе креира кружна зависност" + cant_link_an_issue_with_a_descendant: "Задача неможе да се поврзе со една од нејзините подзадачи" + + actionview_instancetag_blank_option: Изберете + + general_text_No: 'Не' + general_text_Yes: 'Да' + general_text_no: 'не' + general_text_yes: 'да' + general_lang_name: 'Macedonian (Македонски)' + general_csv_separator: ',' + general_csv_decimal_separator: '.' + general_csv_encoding: UTF-8 + general_pdf_encoding: UTF-8 + general_first_day_of_week: '1' + + notice_account_updated: Профилот е успешно ажуриран. + notice_account_invalid_creditentials: Неточен корисник или лозинка + notice_account_password_updated: Лозинката е успешно ажурирана. + notice_account_wrong_password: Погрешна лозинка + notice_account_register_done: Профилот е успешно креиран. За активација, клкнете на врската што ви е пратена по е-пошта. + notice_account_unknown_email: Непознат корисник. + notice_can_t_change_password: This account uses an external authentication source. Impossible to change the password. + notice_account_lost_email_sent: An email with instructions to choose a new password has been sent to you. + notice_account_activated: Your account has been activated. You can now log in. + notice_successful_create: Успешно креирање. + notice_successful_update: Успешно ажурирање. + notice_successful_delete: Успешно бришење. + notice_successful_connection: Успешна конекција. + notice_file_not_found: The page you were trying to access doesn't exist or has been removed. + notice_locking_conflict: Data has been updated by another user. + notice_not_authorized: You are not authorized to access this page. + notice_email_sent: "Е-порака е пратена на {{value}}" + notice_email_error: "Се случи грешка при праќање на е-пораката ({{value}})" + notice_feeds_access_key_reseted: Вашиот RSS клуч за пристап е reset. + notice_api_access_key_reseted: Вашиот API клуч за пристап е reset. + notice_failed_to_save_issues: "Failed to save {{count}} issue(s) on {{total}} selected: {{ids}}." + notice_failed_to_save_members: "Failed to save member(s): {{errors}}." + notice_no_issue_selected: "No issue is selected! Please, check the issues you want to edit." + notice_account_pending: "Your account was created and is now pending administrator approval." + notice_default_data_loaded: Default configuration successfully loaded. + notice_unable_delete_version: Unable to delete version. + notice_unable_delete_time_entry: Unable to delete time log entry. + notice_issue_done_ratios_updated: Issue done ratios updated. + + error_can_t_load_default_data: "Default configuration could not be loaded: {{value}}" + error_scm_not_found: "The entry or revision was not found in the repository." + error_scm_command_failed: "An error occurred when trying to access the repository: {{value}}" + error_scm_annotate: "The entry does not exist or can not be annotated." + error_issue_not_found_in_project: 'The issue was not found or does not belong to this project' + error_no_tracker_in_project: 'No tracker is associated to this project. Please check the Project settings.' + error_no_default_issue_status: 'No default issue status is defined. Please check your configuration (Go to "Administration -> Issue statuses").' + error_can_not_delete_custom_field: Unable to delete custom field + error_can_not_delete_tracker: "This tracker contains issues and can't be deleted." + error_can_not_remove_role: "This role is in use and can not be deleted." + error_can_not_reopen_issue_on_closed_version: 'An issue assigned to a closed version can not be reopened' + error_can_not_archive_project: This project can not be archived + error_issue_done_ratios_not_updated: "Issue done ratios not updated." + error_workflow_copy_source: 'Please select a source tracker or role' + error_workflow_copy_target: 'Please select target tracker(s) and role(s)' + error_unable_delete_issue_status: 'Unable to delete issue status' + error_unable_to_connect: "Unable to connect ({{value}})" + warning_attachments_not_saved: "{{count}} file(s) could not be saved." + + mail_subject_lost_password: "Вашата {{value}} лозинка" + mail_body_lost_password: 'To change your password, click on the following link:' + mail_subject_register: "Your {{value}} account activation" + mail_body_register: 'To activate your account, click on the following link:' + mail_body_account_information_external: "You can use your {{value}} account to log in." + mail_body_account_information: Your account information + mail_subject_account_activation_request: "{{value}} account activation request" + mail_body_account_activation_request: "Нов корисник ({{value}}) е регистриран. The account is pending your approval:" + mail_subject_reminder: "{{count}} issue(s) due in the next {{days}} days" + mail_body_reminder: "{{count}} issue(s) that are assigned to you are due in the next {{days}} days:" + mail_subject_wiki_content_added: "'{{page}}' wiki page has been added" + mail_body_wiki_content_added: "The '{{page}}' wiki page has been added by {{author}}." + mail_subject_wiki_content_updated: "'{{page}}' wiki page has been updated" + mail_body_wiki_content_updated: "The '{{page}}' wiki page has been updated by {{author}}." + + gui_validation_error: 1 грешка + gui_validation_error_plural: "{{count}} грешки" + + field_name: Име + field_description: Опис + field_summary: Краток опис + field_is_required: Задолжително + field_firstname: Име + field_lastname: Презиме + field_mail: Е-пошта + field_filename: Датотека + field_filesize: Големина + field_downloads: Превземања + field_author: Автор + field_created_on: Креиран + field_updated_on: Ажурирано + field_field_format: Формат + field_is_for_all: За сите проекти + field_possible_values: Можни вредности + field_regexp: Regular expression + field_min_length: Минимална должина + field_max_length: Максимална должина + field_value: Вредност + field_category: Категорија + field_title: Наслов + field_project: Проект + field_issue: Задача + field_status: Статус + field_notes: Белешки + field_is_closed: Задачата е затворена + field_is_default: Default value + field_tracker: Tracker + field_subject: Наслов + field_due_date: Краен рок + field_assigned_to: Доделена на + field_priority: Приоритет + field_fixed_version: Target version + field_user: Корисник + field_principal: Principal + field_role: Улога + field_homepage: Веб страна + field_is_public: Јавен + field_parent: Подпроект на + field_is_in_roadmap: Issues displayed in roadmap + field_login: Корисник + field_mail_notification: Известувања по e-пошта + field_admin: Администратор + field_last_login_on: Последна најава + field_language: Јазик + field_effective_date: Дата + field_password: Лозинка + field_new_password: Нова лозинка + field_password_confirmation: Потврда + field_version: Верзија + field_type: Тип + field_host: Хост + field_port: Порт + field_account: Account + field_base_dn: Base DN + field_attr_login: Login attribute + field_attr_firstname: Firstname attribute + field_attr_lastname: Lastname attribute + field_attr_mail: Email attribute + field_onthefly: Моментално (On-the-fly) креирање на корисници + field_start_date: Почеток + field_done_ratio: % Завршено + field_auth_source: Режим на автентикација + field_hide_mail: Криј ја мојата адреса на е-пошта + field_comments: Коментар + field_url: URL + field_start_page: Почетна страна + field_subproject: Подпроект + field_hours: Часови + field_activity: Активност + field_spent_on: Дата + field_identifier: Идентификатор + field_is_filter: Користи како филтер + field_issue_to: Поврзана задача + field_delay: Доцнење + field_assignable: На оваа улога може да се доделуваат задачи + field_redirect_existing_links: Пренасочи ги постоечките врски + field_estimated_hours: Проценето време + field_column_names: Колони + field_time_entries: Бележи време + field_time_zone: Временска зона + field_searchable: Може да се пребарува + field_default_value: Default value + field_comments_sorting: Прикажувај коментари + field_parent_title: Parent page + field_editable: Може да се уредува + field_watcher: Watcher + field_identity_url: OpenID URL + field_content: Содржина + field_group_by: Групирај ги резултатите според + field_sharing: Споделување + field_parent_issue: Parent task + + setting_app_title: Наслов на апликацијата + setting_app_subtitle: Поднаслов на апликацијата + setting_welcome_text: Текст за добредојде + setting_default_language: Default јазик + setting_login_required: Задолжителна автентикација + setting_self_registration: Само-регистрација + setting_attachment_max_size: Макс. големина на прилог + setting_issues_export_limit: Issues export limit + setting_mail_from: Emission email address + setting_bcc_recipients: Blind carbon copy recipients (bcc) + setting_plain_text_mail: Текстуални е-пораки (без HTML) + setting_host_name: Име на хост и патека + setting_text_formatting: Форматирање на текст + setting_wiki_compression: Компресија на историјата на вики + setting_feeds_limit: Feed content limit + setting_default_projects_public: Новите проекти се иницијално јавни + setting_autofetch_changesets: Autofetch commits + setting_sys_api_enabled: Enable WS for repository management + setting_commit_ref_keywords: Referencing keywords + setting_commit_fix_keywords: Fixing keywords + setting_autologin: Автоматска најава + setting_date_format: Формат на дата + setting_time_format: Формат на време + setting_cross_project_issue_relations: Дозволи релации на задачи меѓу проекти + setting_issue_list_default_columns: Default columns displayed on the issue list + setting_repositories_encodings: Repositories encodings + setting_commit_logs_encoding: Commit messages encoding + setting_emails_footer: Emails footer + setting_protocol: Протокол + setting_per_page_options: Objects per page options + setting_user_format: Приказ на корисниците + setting_activity_days_default: Денови прикажана во активноста на проектот + setting_display_subprojects_issues: Прикажи ги задачите на подпроектите во главните проекти + setting_enabled_scm: Овозможи SCM + setting_mail_handler_body_delimiters: "Truncate emails after one of these lines" + setting_mail_handler_api_enabled: Enable WS for incoming emails + setting_mail_handler_api_key: API клуч + setting_sequential_project_identifiers: Генерирај последователни идентификатори на проекти + setting_gravatar_enabled: Користи Gravatar кориснички икони + setting_gravatar_default: Default Gravatar image + setting_diff_max_lines_displayed: Max number of diff lines displayed + setting_file_max_size_displayed: Max size of text files displayed inline + setting_repository_log_display_limit: Maximum number of revisions displayed on file log + setting_openid: Дозволи OpenID најава и регистрација + setting_password_min_length: Мин. должина на лозинка + setting_new_project_user_role_id: Улога доделена на неадминистраторски корисник кој креира проект + setting_default_projects_modules: Default enabled modules for new projects + setting_issue_done_ratio: Calculate the issue done ratio with + setting_issue_done_ratio_issue_field: Use the issue field + setting_issue_done_ratio_issue_status: Use the issue status + setting_start_of_week: Start calendars on + setting_rest_api_enabled: Enable REST web service + setting_cache_formatted_text: Cache formatted text + + permission_add_project: Креирај проекти + permission_add_subprojects: Креирај подпроекти + permission_edit_project: Уреди проект + permission_select_project_modules: Изберете модули за проект + permission_manage_members: Manage members + permission_manage_project_activities: Manage project activities + permission_manage_versions: Manage versions + permission_manage_categories: Manage issue categories + permission_view_issues: Прегледај задачи + permission_add_issues: Додавај задачи + permission_edit_issues: Уредувај задачи + permission_manage_issue_relations: Manage issue relations + permission_add_issue_notes: Додавај белешки + permission_edit_issue_notes: Уредувај белешки + permission_edit_own_issue_notes: Уредувај сопствени белешки + permission_move_issues: Преместувај задачи + permission_delete_issues: Бриши задачи + permission_manage_public_queries: Manage public queries + permission_save_queries: Save queries + permission_view_gantt: View gantt chart + permission_view_calendar: View calendar + permission_view_issue_watchers: View watchers list + permission_add_issue_watchers: Add watchers + permission_delete_issue_watchers: Delete watchers + permission_log_time: Бележи потрошено време + permission_view_time_entries: Прегледај потрошено време + permission_edit_time_entries: Уредувај белешки за потрошено време + permission_edit_own_time_entries: Уредувај сопствени белешки за потрошено време + permission_manage_news: Manage news + permission_comment_news: Коментирај на вести + permission_manage_documents: Manage documents + permission_view_documents: Прегледувај документи + permission_manage_files: Manage files + permission_view_files: Прегледувај датотеки + permission_manage_wiki: Manage wiki + permission_rename_wiki_pages: Преименувај вики страници + permission_delete_wiki_pages: Бриши вики страници + permission_view_wiki_pages: Прегледувај вики + permission_view_wiki_edits: Прегледувај вики историја + permission_edit_wiki_pages: Уредувај вики страници + permission_delete_wiki_pages_attachments: Бриши прилози + permission_protect_wiki_pages: Заштитувај вики страници + permission_manage_repository: Manage repository + permission_browse_repository: Browse repository + permission_view_changesets: View changesets + permission_commit_access: Commit access + permission_manage_boards: Manage boards + permission_view_messages: View messages + permission_add_messages: Post messages + permission_edit_messages: Уредувај пораки + permission_edit_own_messages: Уредувај сопствени пораки + permission_delete_messages: Бриши пораки + permission_delete_own_messages: Бриши сопствени пораки + permission_export_wiki_pages: Export wiki pages + permission_manage_subtasks: Manage subtasks + + project_module_issue_tracking: Следење на задачи + project_module_time_tracking: Следење на време + project_module_news: Вести + project_module_documents: Документи + project_module_files: Датотеки + project_module_wiki: Вики + project_module_repository: Repository + project_module_boards: Форуми + project_module_calendar: Календар + project_module_gantt: Gantt + + label_user: Корисник + label_user_plural: Корисници + label_user_new: Нов корисник + label_user_anonymous: Анонимен + label_project: Проект + label_project_new: Нов проект + label_project_plural: Проекти + label_x_projects: + zero: нема проекти + one: 1 проект + other: "{{count}} проекти" + label_project_all: Сите проекти + label_project_latest: Последните проекти + label_issue: Задача + label_issue_new: Нова задача + label_issue_plural: Задачи + label_issue_view_all: Прегледај ги сите задачи + label_issues_by: "Задачи по {{value}}" + label_issue_added: Задачата е додадена + label_issue_updated: Задачата е ажурирана + label_document: Документ + label_document_new: Нов документ + label_document_plural: Документи + label_document_added: Документот е додаден + label_role: Улога + label_role_plural: Улоги + label_role_new: Нова улога + label_role_and_permissions: Улоги и овластувања + label_member: Член + label_member_new: Нов член + label_member_plural: Членови + label_tracker: Tracker + label_tracker_plural: Trackers + label_tracker_new: New tracker + label_workflow: Workflow + label_issue_status: Статус на задача + label_issue_status_plural: Статуси на задачи + label_issue_status_new: Нов статус + label_issue_category: Категорија на задача + label_issue_category_plural: Категории на задачи + label_issue_category_new: Нова категорија + label_custom_field: Прилагодено поле + label_custom_field_plural: Прилагодени полиња + label_custom_field_new: Ново прилагодено поле + label_enumerations: Enumerations + label_enumeration_new: Нова вредност + label_information: Информација + label_information_plural: Информации + label_please_login: Најави се + label_register: Регистрирај се + label_login_with_open_id_option: или најави се со OpenID + label_password_lost: Изгубена лозинка + label_home: Почетна + label_my_page: Мојата страна + label_my_account: Мојот профил + label_my_projects: Мои проекти + label_my_page_block: Блок елемент + label_administration: Администрација + label_login: Најави се + label_logout: Одјави се + label_help: Помош + label_reported_issues: Пријавени задачи + label_assigned_to_me_issues: Задачи доделени на мене + label_last_login: Последна најава + label_registered_on: Регистриран на + label_activity: Активност + label_overall_activity: Севкупна активност + label_user_activity: "Активност на {{value}}" + label_new: Нова + label_logged_as: Најавени сте како + label_environment: Опкружување + label_authentication: Автентикација + label_auth_source: Режим на автентикација + label_auth_source_new: Нов режим на автентикација + label_auth_source_plural: Режими на автентикација + label_subproject_plural: Подпроекти + label_subproject_new: Нов подпроект + label_and_its_subprojects: "{{value}} и неговите подпроекти" + label_min_max_length: Мин. - Макс. должина + label_list: Листа + label_date: Дата + label_integer: Integer + label_float: Float + label_boolean: Boolean + label_string: Текст + label_text: Долг текст + label_attribute: Атрибут + label_attribute_plural: Атрибути + label_download: "{{count}} превземање" + label_download_plural: "{{count}} превземања" + label_no_data: Нема податоци за прикажување + label_change_status: Промени статус + label_history: Историја + label_attachment: Датотека + label_attachment_new: Нова датотека + label_attachment_delete: Избриши датотека + label_attachment_plural: Датотеки + label_file_added: Датотеката е додадена + label_report: Извештај + label_report_plural: Извештаи + label_news: Новост + label_news_new: Додади новост + label_news_plural: Новости + label_news_latest: Последни новости + label_news_view_all: Прегледај ги сите новости + label_news_added: Новостта е додадена + label_settings: Settings + label_overview: Преглед + label_version: Верзија + label_version_new: Нова верзија + label_version_plural: Верзии + label_close_versions: Затвори ги завршените врзии + label_confirmation: Потврда + label_export_to: 'Достапно и во:' + label_read: Прочитај... + label_public_projects: Јавни проекти + label_open_issues: отворена + label_open_issues_plural: отворени + label_closed_issues: затворена + label_closed_issues_plural: затворени + label_x_open_issues_abbr_on_total: + zero: 0 отворени / {{total}} + one: 1 отворена / {{total}} + other: "{{count}} отворени / {{total}}" + label_x_open_issues_abbr: + zero: 0 отворени + one: 1 отворена + other: "{{count}} отворени" + label_x_closed_issues_abbr: + zero: 0 затворени + one: 1 затворена + other: "{{count}} затворени" + label_total: Вкупно + label_permissions: Овластувања + label_current_status: Моментален статус + label_new_statuses_allowed: Дозволени нови статуси + label_all: сите + label_none: ниеден + label_nobody: никој + label_next: Следно + label_previous: Претходно + label_used_by: Користено од + label_details: Детали + label_add_note: Додади белешка + label_per_page: По страна + label_calendar: Календар + label_months_from: месеци од + label_gantt: Gantt + label_internal: Internal + label_last_changes: "последни {{count}} промени" + label_change_view_all: Прегледај ги сите промени + label_personalize_page: Прилагоди ја странава + label_comment: Коментар + label_comment_plural: Коментари + label_x_comments: + zero: нема коментари + one: 1 коментар + other: "{{count}} коментари" + label_comment_add: Додади коментар + label_comment_added: Коментарот е додаден + label_comment_delete: Избриши коментари + label_query: Custom query + label_query_plural: Custom queries + label_query_new: New query + label_filter_add: Додади филтер + label_filter_plural: Филтри + label_equals: е + label_not_equals: не е + label_in_less_than: за помалку од + label_in_more_than: за повеќе од + label_greater_or_equal: '>=' + label_less_or_equal: '<=' + label_in: во + label_today: денес + label_all_time: цело време + label_yesterday: вчера + label_this_week: оваа недела + label_last_week: минатата недела + label_last_n_days: "последните {{count}} дена" + label_this_month: овој месец + label_last_month: минатиот месец + label_this_year: оваа година + label_date_range: Date range + label_less_than_ago: пред помалку од денови + label_more_than_ago: пред повеќе од денови + label_ago: пред денови + label_contains: содржи + label_not_contains: не содржи + label_day_plural: денови + label_repository: Складиште + label_repository_plural: Складишта + label_browse: Прелистувај + label_modification: "{{count}} промени" + label_modification_plural: "{{count}} промени" + label_branch: Гранка + label_tag: Tag + label_revision: Ревизија + label_revision_plural: Ревизии + label_revision_id: "Ревизија {{value}}" + label_associated_revisions: Associated revisions + label_added: added + label_modified: modified + label_copied: copied + label_renamed: renamed + label_deleted: deleted + label_latest_revision: Последна ревизија + label_latest_revision_plural: Последни ревизии + label_view_revisions: Прегледај ги ревизиите + label_view_all_revisions: Прегледај ги сите ревизии + label_max_size: Макс. големина + label_sort_highest: Премести најгоре + label_sort_higher: Премести нагоре + label_sort_lower: Премести надоле + label_sort_lowest: Премести најдоле + label_roadmap: Roadmap + label_roadmap_due_in: "Due in {{value}}" + label_roadmap_overdue: "Касни {{value}}" + label_roadmap_no_issues: Нема задачи за оваа верзија + label_search: Барај + label_result_plural: Резултати + label_all_words: Сите зборови + label_wiki: Вики + label_wiki_edit: Вики уредување + label_wiki_edit_plural: Вики уредувања + label_wiki_page: Вики страница + label_wiki_page_plural: Вики страници + label_index_by_title: Индекс по наслов + label_index_by_date: Индекс по дата + label_current_version: Current version + label_preview: Preview + label_feed_plural: Feeds + label_changes_details: Детали за сите промени + label_issue_tracking: Следење на задачи + label_spent_time: Потрошено време + label_overall_spent_time: Вкупно потрошено време + label_f_hour: "{{value}} час" + label_f_hour_plural: "{{value}} часа" + label_time_tracking: Следење на време + label_change_plural: Промени + label_statistics: Статистики + label_commits_per_month: Commits per month + label_commits_per_author: Commits per author + label_view_diff: View differences + label_diff_inline: inline + label_diff_side_by_side: side by side + label_options: Опции + label_copy_workflow_from: Copy workflow from + label_permissions_report: Permissions report + label_watched_issues: Watched issues + label_related_issues: Поврзани задачи + label_applied_status: Applied status + label_loading: Loading... + label_relation_new: Нова релација + label_relation_delete: Избриши релација + label_relates_to: related to + label_duplicates: дупликати + label_duplicated_by: duplicated by + label_blocks: blocks + label_blocked_by: блокирано од + label_precedes: претходи + label_follows: следи + label_end_to_start: крај до почеток + label_end_to_end: крај до крај + label_start_to_start: почеток до почеток + label_start_to_end: почеток до крај + label_stay_logged_in: Останете најавени + label_disabled: disabled + label_show_completed_versions: Show completed versions + label_me: јас + label_board: Форум + label_board_new: Нов форум + label_board_plural: Форуми + label_board_locked: Заклучен + label_board_sticky: Sticky + label_topic_plural: Теми + label_message_plural: Пораки + label_message_last: Последна порака + label_message_new: Нова порака + label_message_posted: Поракате е додадена + label_reply_plural: Одговори + label_send_information: Испрати ги информациите за профилот на корисникот + label_year: Година + label_month: Месец + label_week: Недела + label_date_from: Од + label_date_to: До + label_language_based: Според јазикот на корисникот + label_sort_by: "Подреди според {{value}}" + label_send_test_email: Испрати тест е-порака + label_feeds_access_key: RSS клуч за пристап + label_missing_feeds_access_key: Недостика RSS клуч за пристап + label_feeds_access_key_created_on: "RSS клучот за пристап креиран пред {{value}}" + label_module_plural: Модули + label_added_time_by: "Додадено од {{author}} пред {{age}}" + label_updated_time_by: "Ажурирано од {{author}} пред {{age}}" + label_updated_time: "Ажурирано пред {{value}}" + label_jump_to_a_project: Префрли се на проект... + label_file_plural: Датотеки + label_changeset_plural: Changesets + label_default_columns: Основни колони + label_no_change_option: (Без промена) + label_bulk_edit_selected_issues: Групно уредување на задачи + label_theme: Тема + label_default: Default + label_search_titles_only: Пребарувај само наслови + label_user_mail_option_all: "За било кој настан во сите мои проекти" + label_user_mail_option_selected: "За било кој настан само во избраните проекти..." + label_user_mail_option_none: "Само за работите кои ги следам или од кои сум дел" + label_user_mail_no_self_notified: "Не ме известувај за промените што јас ги правам" + label_registration_activation_by_email: активација на профил преку е-пошта + label_registration_manual_activation: мануелна активација на профил + label_registration_automatic_activation: автоматска активација на профил + label_display_per_page: "По страна: {{value}}" + label_age: Age + label_change_properties: Change properties + label_general: Општо + label_more: Повеќе + label_scm: SCM + label_plugins: Додатоци + label_ldap_authentication: LDAP автентикација + label_downloads_abbr: Превземања + label_optional_description: Опис (незадолжително) + label_add_another_file: Додади уште една датотека + label_preferences: Preferences + label_chronological_order: Во хронолошки ред + label_reverse_chronological_order: In reverse chronological order + label_planning: Планирање + label_incoming_emails: Дојдовни е-пораки + label_generate_key: Генерирај клуч + label_issue_watchers: Watchers + label_example: Пример + label_display: Прикажи + label_sort: Подреди + label_ascending: Растечки + label_descending: Опаѓачки + label_date_from_to: Од {{start}} до {{end}} + label_wiki_content_added: Вики страница додадена + label_wiki_content_updated: Вики страница ажурирана + label_group: Група + label_group_plural: Групи + label_group_new: Нова група + label_time_entry_plural: Потрошено време + label_version_sharing_none: Не споделено + label_version_sharing_descendants: Со сите подпроекти + label_version_sharing_hierarchy: Со хиерархијата на проектот + label_version_sharing_tree: Со дрвото на проектот + label_version_sharing_system: Со сите проекти + label_update_issue_done_ratios: Update issue done ratios + label_copy_source: Извор + label_copy_target: Дестинација + label_copy_same_as_target: Исто како дестинацијата + label_display_used_statuses_only: Only display statuses that are used by this tracker + label_api_access_key: API клуч за пристап + label_missing_api_access_key: Недостига API клуч за пристап + label_api_access_key_created_on: "API клучот за пристап е креиран пред {{value}}" + label_profile: Профил + label_subtask_plural: Подзадачи + label_project_copy_notifications: Праќај известувања по е-пошта при копирање на проект + + button_login: Најави се + button_submit: Испрати + button_save: Зачувај + button_check_all: Штиклирај ги сите + button_uncheck_all: Одштиклирај ги сите + button_delete: Избриши + button_create: Креирај + button_create_and_continue: Креирај и продолжи + button_test: Тест + button_edit: Уреди + button_add: Додади + button_change: Промени + button_apply: Примени + button_clear: Избриши + button_lock: Заклучи + button_unlock: Отклучи + button_download: Превземи + button_list: List + button_view: Прегледај + button_move: Премести + button_move_and_follow: Премести и следи + button_back: Back + button_cancel: Откажи + button_activate: Активирај + button_sort: Подреди + button_log_time: Бележи време + button_rollback: Rollback to this version + button_watch: Следи + button_unwatch: Не следи + button_reply: Одговори + button_archive: Архивирај + button_unarchive: Одархивирај + button_reset: Reset + button_rename: Преименувај + button_change_password: Промени лозинка + button_copy: Копирај + button_copy_and_follow: Копирај и следи + button_annotate: Annotate + button_update: Ажурирај + button_configure: Конфигурирај + button_quote: Цитирај + button_duplicate: Копирај + button_show: Show + + status_active: активни + status_registered: регистрирани + status_locked: заклучени + + version_status_open: отворени + version_status_locked: заклучени + version_status_closed: затворени + + field_active: Active + + text_select_mail_notifications: Изберете за кои настани да се праќаат известувања по е-пошта да се праќаат. + text_regexp_info: eg. ^[A-Z0-9]+$ + text_min_max_length_info: 0 значи без ограничување + text_project_destroy_confirmation: Дали сте сигурни дека сакате да го избришете проектот и сите поврзани податоци? + text_subprojects_destroy_warning: "Неговите подпроекти: {{value}} исто така ќе бидат избришани." + text_workflow_edit: Select a role and a tracker to edit the workflow + text_are_you_sure: Дали сте сигурни? + text_journal_changed: "{{label}} променето од {{old}} во {{new}}" + text_journal_set_to: "{{label}} set to {{value}}" + text_journal_deleted: "{{label}} избришан ({{old}})" + text_journal_added: "{{label}} {{value}} додаден" + text_tip_task_begin_day: задачи што почнуваат овој ден + text_tip_task_end_day: задачи што завршуваат овој ден + text_tip_task_begin_end_day: задачи што почнуваат и завршуваат овој ден + text_project_identifier_info: 'Само мали букви (a-z), бројки и dashes се дозволени
По зачувувањето, идентификаторот неможе да се смени.' + text_caracters_maximum: "{{count}} знаци максимум." + text_caracters_minimum: "Мора да е најмалку {{count}} знаци долго." + text_length_between: "Должина помеѓу {{min}} и {{max}} знаци." + text_tracker_no_workflow: No workflow defined for this tracker + text_unallowed_characters: Недозволени знаци + text_comma_separated: Дозволени се повеќе вредности (разделени со запирка). + text_line_separated: Дозволени се повеќе вредности (една линија за секоја вредност). + text_issues_ref_in_commit_messages: Referencing and fixing issues in commit messages + text_issue_added: "Задачата {{id}} е пријавена од {{author}}." + text_issue_updated: "Зачата {{id}} е ажурирана од {{author}}." + text_wiki_destroy_confirmation: Дали сте сигурни дека сакате да го избришете ова вики и целата негова содржина? + text_issue_category_destroy_question: "Некои задачи ({{count}}) се доделени на оваа категорија. Што сакате да правите?" + text_issue_category_destroy_assignments: Remove category assignments + text_issue_category_reassign_to: Додели ги задачите на оваа категорија + text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)." + text_no_configuration_data: "Roles, trackers, issue statuses and workflow have not been configured yet.\nIt is highly recommended to load the default configuration. You will be able to modify it once loaded." + text_load_default_configuration: Load the default configuration + text_status_changed_by_changeset: "Applied in changeset {{value}}." + text_issues_destroy_confirmation: 'Дали сте сигурни дека сакате да ги избришете избраните задачи?' + text_select_project_modules: 'Изберете модули за овој проект:' + text_default_administrator_account_changed: Default administrator account changed + text_file_repository_writable: Во папката за прилози може да се запишува + text_plugin_assets_writable: Во папката за додатоци може да се запишува + text_rmagick_available: RMagick available (незадолжително) + text_destroy_time_entries_question: "{{hours}} hours were reported on the issues you are about to delete. What do you want to do ?" + text_destroy_time_entries: Delete reported hours + text_assign_time_entries_to_project: Додели ги пријавените часови на проектот + text_reassign_time_entries: 'Reassign reported hours to this issue:' + text_user_wrote: "{{value}} напиша:" + text_enumeration_destroy_question: "{{count}} objects are assigned to this value." + text_enumeration_category_reassign_to: 'Reassign them to this value:' + text_email_delivery_not_configured: "Доставата по е-пошта не е конфигурирана, и известувањата се оневозможени.\nКонфигурирајте го Вашиот SMTP сервер во config/email.yml и рестартирајте ја апликацијата." + 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_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.' + text_custom_field_possible_values_info: 'One line for each value' + text_wiki_page_destroy_question: "This page has {{descendants}} child page(s) and descendant(s). What do you want to do?" + text_wiki_page_nullify_children: "Keep child pages as root pages" + text_wiki_page_destroy_children: "Delete child pages and all their descendants" + text_wiki_page_reassign_children: "Reassign child pages to this parent page" + 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_zoom_in: Zoom in + text_zoom_out: Zoom out + + default_role_manager: Менаџер + default_role_developer: Developer + default_role_reporter: Reporter + default_tracker_bug: Грешка + default_tracker_feature: Функционалност + default_tracker_support: Поддршка + default_issue_status_new: Нова + default_issue_status_in_progress: Во прогрес + default_issue_status_resolved: Разрешена + default_issue_status_feedback: Feedback + default_issue_status_closed: Затворена + default_issue_status_rejected: Одбиена + default_doc_category_user: Корисничка документација + default_doc_category_tech: Техничка документација + default_priority_low: Низок + default_priority_normal: Нормален + default_priority_high: Висок + default_priority_urgent: Итно + default_priority_immediate: Веднаш + default_activity_design: Дизајн + default_activity_development: Развој + + enumeration_issue_priorities: Приоритети на задача + enumeration_doc_categories: Категории на документ + enumeration_activities: Активности (следење на време) + enumeration_system_activity: Системска активност + diff --git a/config/locales/sv.yml b/config/locales/sv.yml index d6a9454fb78..e02ee7867c9 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -325,6 +325,7 @@ sv: field_redirect_existing_links: Omdirigera existerande länkar field_estimated_hours: Estimerad tid field_column_names: Kolumner + field_time_entries: Spenderad tid field_time_zone: Tidszon field_searchable: Sökbar field_default_value: Standardvärde @@ -456,6 +457,8 @@ sv: project_module_wiki: Wiki project_module_repository: Versionsarkiv project_module_boards: Forum + project_module_calendar: Kalender + project_module_gantt: Gantt label_user: Användare label_user_plural: Användare @@ -857,7 +860,7 @@ sv: button_update: Uppdatera button_configure: Konfigurera button_quote: Citera - button_duplicate: Duplisera + button_duplicate: Duplicera button_show: Visa status_active: aktiv @@ -954,6 +957,3 @@ sv: enumeration_doc_categories: Dokumentkategorier enumeration_activities: Aktiviteter (tidsuppföljning) enumeration_system_activity: Systemaktivitet - field_time_entries: Log time - project_module_gantt: Gantt - project_module_calendar: Calendar diff --git a/public/javascripts/calendar/lang/calendar-mk.js b/public/javascripts/calendar/lang/calendar-mk.js index 34fcaaee775..863e3bf2b6f 100644 --- a/public/javascripts/calendar/lang/calendar-mk.js +++ b/public/javascripts/calendar/lang/calendar-mk.js @@ -1,7 +1,7 @@ // ** I18N // Calendar МК language -// Author: Илин Татабитовски, +// Author: Ilin Tatabitovski, // Encoding: UTF-8 // Distributed under the same terms as the calendar itself. @@ -84,26 +84,26 @@ Calendar._TT["INFO"] = "За календарот"; Calendar._TT["ABOUT"] = "DHTML Date/Time Selector\n" + "(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) -"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + -"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"За последна верзија посети: http://www.dynarch.com/projects/calendar/\n" + +"Дистрибуирано под GNU LGPL. Види http://gnu.org/licenses/lgpl.html за детали." + "\n\n" + -"Date selection:\n" + -"- Use the \xab, \xbb buttons to select year\n" + -"- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" + -"- Hold mouse button on any of the above buttons for faster selection."; +"Бирање на дата:\n" + +"- Користи ги \xab, \xbb копчињата за да избереш година\n" + +"- Користи ги " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " копчињата за да избере месеци\n" + +"- Држи го притиснато копчето на глувчето на било кое копче за побрзо бирање."; Calendar._TT["ABOUT_TIME"] = "\n\n" + -"Time selection:\n" + -"- Click on any of the time parts to increase it\n" + -"- or Shift-click to decrease it\n" + -"- or click and drag for faster selection."; +"Бирање на време:\n" + +"- Клик на временските делови за да го зголемиш\n" + +"- или Shift-клик да го намалиш\n" + +"- или клик и влечи за побрзо бирање."; -Calendar._TT["PREV_YEAR"] = "Претходна година (hold for menu)"; -Calendar._TT["PREV_MONTH"] = "Претходен месец (hold for menu)"; +Calendar._TT["PREV_YEAR"] = "Претходна година (држи за мени)"; +Calendar._TT["PREV_MONTH"] = "Претходен месец (држи за мени)"; Calendar._TT["GO_TODAY"] = "Go Today"; -Calendar._TT["NEXT_MONTH"] = "Следен месец (hold for menu)"; -Calendar._TT["NEXT_YEAR"] = "Следна година (hold for menu)"; -Calendar._TT["SEL_DATE"] = "Изберете дата"; -Calendar._TT["DRAG_TO_MOVE"] = "Drag to move"; +Calendar._TT["NEXT_MONTH"] = "Следен месец (држи за мени)"; +Calendar._TT["NEXT_YEAR"] = "Следна година (држи за мени)"; +Calendar._TT["SEL_DATE"] = "Избери дата"; +Calendar._TT["DRAG_TO_MOVE"] = "Влечи да поместиш"; Calendar._TT["PART_TODAY"] = " (денес)"; // the following is to inform that "%s" is to be the first day of week @@ -117,7 +117,7 @@ Calendar._TT["WEEKEND"] = "0,6"; Calendar._TT["CLOSE"] = "Затвори"; Calendar._TT["TODAY"] = "Денес"; -Calendar._TT["TIME_PART"] = "(Shift-)Click or drag to change value"; +Calendar._TT["TIME_PART"] = "(Shift-)Клик или влечи за да промениш вредност"; // date formats Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%Y"; @@ -125,3 +125,4 @@ Calendar._TT["TT_DATE_FORMAT"] = "%a, %e %b"; Calendar._TT["WK"] = "нед"; Calendar._TT["TIME"] = "Време:"; + diff --git a/public/javascripts/jstoolbar/lang/jstoolbar-mk.js b/public/javascripts/jstoolbar/lang/jstoolbar-mk.js index 3af63a1cc79..30c68ec6cce 100644 --- a/public/javascripts/jstoolbar/lang/jstoolbar-mk.js +++ b/public/javascripts/jstoolbar/lang/jstoolbar-mk.js @@ -1,16 +1,17 @@ jsToolBar.strings = {}; -jsToolBar.strings['Strong'] = 'Strong'; -jsToolBar.strings['Italic'] = 'Italic'; -jsToolBar.strings['Underline'] = 'Underline'; -jsToolBar.strings['Deleted'] = 'Deleted'; -jsToolBar.strings['Code'] = 'Inline Code'; -jsToolBar.strings['Heading 1'] = 'Heading 1'; -jsToolBar.strings['Heading 2'] = 'Heading 2'; -jsToolBar.strings['Heading 3'] = 'Heading 3'; -jsToolBar.strings['Unordered list'] = 'Unordered list'; +jsToolBar.strings['Strong'] = 'Задебелен'; +jsToolBar.strings['Italic'] = 'Закосен'; +jsToolBar.strings['Underline'] = 'Подвлечен'; +jsToolBar.strings['Deleted'] = 'Прецртан'; +jsToolBar.strings['Code'] = 'Код'; +jsToolBar.strings['Heading 1'] = 'Заглавје 1'; +jsToolBar.strings['Heading 2'] = 'Заглавје 2'; +jsToolBar.strings['Heading 3'] = 'Заглавје 3'; +jsToolBar.strings['Unordered list'] = 'Неподредена листа'; jsToolBar.strings['Ordered list'] = 'Подредена листа'; jsToolBar.strings['Quote'] = 'Цитат'; jsToolBar.strings['Unquote'] = 'Отстрани цитат'; -jsToolBar.strings['Preformatted text'] = 'Preformatted text'; -jsToolBar.strings['Wiki link'] = 'Линк до вики страна'; +jsToolBar.strings['Preformatted text'] = 'Форматиран текст'; +jsToolBar.strings['Wiki link'] = 'Врска до вики страна'; jsToolBar.strings['Image'] = 'Слика'; + From a188abbe2813372d426afd2ab05841f0503f00c1 Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Mon, 30 Aug 2010 15:30:28 +0000 Subject: [PATCH 14/25] Refactor: move method, ProjectsController#roadmap to VersionsController#index. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4050 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/projects_controller.rb | 32 --------------- app/controllers/versions_controller.rb | 39 +++++++++++++++++-- .../roadmap.rhtml => versions/index.html.erb} | 0 config/routes.rb | 3 +- lib/redmine.rb | 7 ++-- test/functional/projects_controller_test.rb | 32 --------------- test/functional/versions_controller_test.rb | 33 ++++++++++++++++ test/integration/routing_test.rb | 2 +- 8 files changed, 75 insertions(+), 73 deletions(-) rename app/views/{projects/roadmap.rhtml => versions/index.html.erb} (100%) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 6bb7663869a..845ab3c157f 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -287,30 +287,6 @@ def list_files render :layout => !request.xhr? end - def roadmap - @trackers = @project.trackers.find(:all, :order => 'position') - retrieve_selected_tracker_ids(@trackers, @trackers.select {|t| t.is_in_roadmap?}) - @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1') - project_ids = @with_subprojects ? @project.self_and_descendants.collect(&:id) : [@project.id] - - @versions = @project.shared_versions || [] - @versions += @project.rolled_up_versions.visible if @with_subprojects - @versions = @versions.uniq.sort - @versions.reject! {|version| version.closed? || version.completed? } unless params[:completed] - - @issues_by_version = {} - unless @selected_tracker_ids.empty? - @versions.each do |version| - issues = version.fixed_issues.visible.find(:all, - :include => [:project, :status, :tracker, :priority], - :conditions => {:tracker_id => @selected_tracker_ids, :project_id => project_ids}, - :order => "#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id") - @issues_by_version[version] = issues - end - end - @versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?} - end - private def find_optional_project return true unless params[:id] @@ -320,14 +296,6 @@ def find_optional_project render_404 end - def retrieve_selected_tracker_ids(selectable_trackers, default_trackers=nil) - if ids = params[:tracker_ids] - @selected_tracker_ids = (ids.is_a? Array) ? ids.collect { |id| id.to_i.to_s } : ids.split('/').collect { |id| id.to_i.to_s } - else - @selected_tracker_ids = (default_trackers || selectable_trackers).collect {|t| t.id.to_s } - end - end - # Validates parent_id param according to user's permissions # TODO: move it to Project model in a validation that depends on User.current def validate_parent_id diff --git a/app/controllers/versions_controller.rb b/app/controllers/versions_controller.rb index 46b4778d40c..dd01da95b3b 100644 --- a/app/controllers/versions_controller.rb +++ b/app/controllers/versions_controller.rb @@ -18,13 +18,37 @@ class VersionsController < ApplicationController menu_item :roadmap model_object Version - before_filter :find_model_object, :except => [:new, :close_completed] - before_filter :find_project_from_association, :except => [:new, :close_completed] - before_filter :find_project, :only => [:new, :close_completed] + before_filter :find_model_object, :except => [:index, :new, :close_completed] + before_filter :find_project_from_association, :except => [:index, :new, :close_completed] + before_filter :find_project, :only => [:index, :new, :close_completed] before_filter :authorize helper :custom_fields helper :projects + + def index + @trackers = @project.trackers.find(:all, :order => 'position') + retrieve_selected_tracker_ids(@trackers, @trackers.select {|t| t.is_in_roadmap?}) + @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1') + project_ids = @with_subprojects ? @project.self_and_descendants.collect(&:id) : [@project.id] + + @versions = @project.shared_versions || [] + @versions += @project.rolled_up_versions.visible if @with_subprojects + @versions = @versions.uniq.sort + @versions.reject! {|version| version.closed? || version.completed? } unless params[:completed] + + @issues_by_version = {} + unless @selected_tracker_ids.empty? + @versions.each do |version| + issues = version.fixed_issues.visible.find(:all, + :include => [:project, :status, :tracker, :priority], + :conditions => {:tracker_id => @selected_tracker_ids, :project_id => project_ids}, + :order => "#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id") + @issues_by_version[version] = issues + end + end + @versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?} + end def show @issues = @version.fixed_issues.visible.find(:all, @@ -105,4 +129,13 @@ def find_project rescue ActiveRecord::RecordNotFound render_404 end + + def retrieve_selected_tracker_ids(selectable_trackers, default_trackers=nil) + if ids = params[:tracker_ids] + @selected_tracker_ids = (ids.is_a? Array) ? ids.collect { |id| id.to_i.to_s } : ids.split('/').collect { |id| id.to_i.to_s } + else + @selected_tracker_ids = (default_trackers || selectable_trackers).collect {|t| t.id.to_s } + end + end + end diff --git a/app/views/projects/roadmap.rhtml b/app/views/versions/index.html.erb similarity index 100% rename from app/views/projects/roadmap.rhtml rename to app/views/versions/index.html.erb diff --git a/config/routes.rb b/config/routes.rb index 1465e1ffeaf..1414e1000ed 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -180,7 +180,7 @@ project_views.connect 'projects/new', :action => 'add' project_views.connect 'projects/:id', :action => 'show' project_views.connect 'projects/:id.:format', :action => 'show' - project_views.connect 'projects/:id/:action', :action => /roadmap|destroy|settings/ + project_views.connect 'projects/:id/:action', :action => /destroy|settings/ project_views.connect 'projects/:id/files', :action => 'list_files' project_views.connect 'projects/:id/files/new', :action => 'add_file' project_views.connect 'projects/:id/settings/:tab', :action => 'settings' @@ -215,6 +215,7 @@ map.with_options :controller => 'versions' do |versions| versions.connect 'projects/:project_id/versions/new', :action => 'new' + versions.connect 'projects/:project_id/roadmap', :action => 'index' versions.with_options :conditions => {:method => :post} do |version_actions| version_actions.connect 'projects/:project_id/versions/close_completed', :action => 'close_completed' end diff --git a/lib/redmine.rb b/lib/redmine.rb index 7040a1f99a5..ecfc4625287 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -57,11 +57,10 @@ # Issue categories map.permission :manage_categories, {:projects => :settings, :issue_categories => [:new, :edit, :destroy]}, :require => :member # Issues - map.permission :view_issues, {:projects => :roadmap, - :issues => [:index, :show], + map.permission :view_issues, {:issues => [:index, :show], :auto_complete => [:issues], :context_menus => [:issues], - :versions => [:show, :status_by], + :versions => [:index, :show, :status_by], :journals => :index, :queries => :index, :reports => [:issue_report, :issue_report_details]} @@ -186,7 +185,7 @@ Redmine::MenuManager.map :project_menu do |menu| menu.push :overview, { :controller => 'projects', :action => 'show' } menu.push :activity, { :controller => 'activities', :action => 'index' } - menu.push :roadmap, { :controller => 'projects', :action => 'roadmap' }, + menu.push :roadmap, { :controller => 'versions', :action => 'index' }, :param => :project_id, :if => Proc.new { |p| p.shared_versions.any? } menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural menu.push :new_issue, { :controller => 'issues', :action => 'new' }, :param => :project_id, :caption => :label_issue_new, diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index f9c8ce0227b..36d60c859e3 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -368,38 +368,6 @@ def test_list_files :attributes => { :href => '/attachments/download/9/version_file.zip' } end - def test_roadmap - get :roadmap, :id => 1 - assert_response :success - assert_template 'roadmap' - assert_not_nil assigns(:versions) - # Version with no date set appears - assert assigns(:versions).include?(Version.find(3)) - # Completed version doesn't appear - assert !assigns(:versions).include?(Version.find(1)) - end - - def test_roadmap_with_completed_versions - get :roadmap, :id => 1, :completed => 1 - assert_response :success - assert_template 'roadmap' - assert_not_nil assigns(:versions) - # Version with no date set appears - assert assigns(:versions).include?(Version.find(3)) - # Completed version appears - assert assigns(:versions).include?(Version.find(1)) - end - - def test_roadmap_showing_subprojects_versions - @subproject_version = Version.generate!(:project => Project.find(3)) - get :roadmap, :id => 1, :with_subprojects => 1 - assert_response :success - assert_template 'roadmap' - assert_not_nil assigns(:versions) - - assert assigns(:versions).include?(Version.find(4)), "Shared version not found" - assert assigns(:versions).include?(@subproject_version), "Subproject version not found" - end def test_archive @request.session[:user_id] = 1 # admin post :archive, :id => 1 diff --git a/test/functional/versions_controller_test.rb b/test/functional/versions_controller_test.rb index e4864c908ab..5fcb1d05a35 100644 --- a/test/functional/versions_controller_test.rb +++ b/test/functional/versions_controller_test.rb @@ -31,6 +31,39 @@ def setup User.current = nil end + def test_index + get :index, :project_id => 1 + assert_response :success + assert_template 'index' + assert_not_nil assigns(:versions) + # Version with no date set appears + assert assigns(:versions).include?(Version.find(3)) + # Completed version doesn't appear + assert !assigns(:versions).include?(Version.find(1)) + end + + def test_index_with_completed_versions + get :index, :project_id => 1, :completed => 1 + assert_response :success + assert_template 'index' + assert_not_nil assigns(:versions) + # Version with no date set appears + assert assigns(:versions).include?(Version.find(3)) + # Completed version appears + assert assigns(:versions).include?(Version.find(1)) + end + + def test_index_showing_subprojects_versions + @subproject_version = Version.generate!(:project => Project.find(3)) + get :index, :project_id => 1, :with_subprojects => 1 + assert_response :success + assert_template 'index' + assert_not_nil assigns(:versions) + + assert assigns(:versions).include?(Version.find(4)), "Shared version not found" + assert assigns(:versions).include?(@subproject_version), "Subproject version not found" + end + def test_show get :show, :id => 2 assert_response :success diff --git a/test/integration/routing_test.rb b/test/integration/routing_test.rb index 62fdaf47a7b..590bd911904 100644 --- a/test/integration/routing_test.rb +++ b/test/integration/routing_test.rb @@ -174,7 +174,7 @@ class RoutingTest < ActionController::IntegrationTest should_route :get, "/projects/567/destroy", :controller => 'projects', :action => 'destroy', :id => '567' should_route :get, "/projects/33/files", :controller => 'projects', :action => 'list_files', :id => '33' should_route :get, "/projects/33/files/new", :controller => 'projects', :action => 'add_file', :id => '33' - should_route :get, "/projects/33/roadmap", :controller => 'projects', :action => 'roadmap', :id => '33' + should_route :get, "/projects/33/roadmap", :controller => 'versions', :action => 'index', :project_id => '33' should_route :get, "/projects/33/activity", :controller => 'activities', :action => 'index', :id => '33' should_route :get, "/projects/33/activity.atom", :controller => 'activities', :action => 'index', :id => '33', :format => 'atom' From daa8eaa9aebcc284e2904d1258cbfdd78ea23876 Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Tue, 31 Aug 2010 15:12:58 +0000 Subject: [PATCH 15/25] Refactor: move method, ProjectsController#list_files to FilesController#index. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4051 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/files_controller.rb | 22 ++++++++++++++ app/controllers/projects_controller.rb | 16 ++-------- .../list_files.rhtml => files/index.html.erb} | 0 config/routes.rb | 2 +- lib/redmine.rb | 4 +-- test/functional/files_controller_test.rb | 29 +++++++++++++++++++ test/functional/projects_controller_test.rb | 15 ---------- test/integration/routing_test.rb | 2 +- 8 files changed, 57 insertions(+), 33 deletions(-) create mode 100644 app/controllers/files_controller.rb rename app/views/{projects/list_files.rhtml => files/index.html.erb} (100%) create mode 100644 test/functional/files_controller_test.rb diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb new file mode 100644 index 00000000000..c84ce5f51b1 --- /dev/null +++ b/app/controllers/files_controller.rb @@ -0,0 +1,22 @@ +class FilesController < ApplicationController + menu_item :files + + before_filter :find_project + before_filter :authorize + + helper :sort + include SortHelper + + def index + sort_init 'filename', 'asc' + sort_update 'filename' => "#{Attachment.table_name}.filename", + 'created_on' => "#{Attachment.table_name}.created_on", + 'size' => "#{Attachment.table_name}.filesize", + 'downloads' => "#{Attachment.table_name}.downloads" + + @containers = [ Project.find(@project.id, :include => :attachments, :order => sort_clause)] + @containers += @project.versions.find(:all, :include => :attachments, :order => sort_clause).sort.reverse + render :layout => !request.xhr? + end + +end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 845ab3c157f..05c8d969d6f 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -18,7 +18,7 @@ class ProjectsController < ApplicationController menu_item :overview menu_item :roadmap, :only => :roadmap - menu_item :files, :only => [:list_files, :add_file] + menu_item :files, :only => [:add_file] menu_item :settings, :only => :settings before_filter :find_project, :except => [ :index, :list, :add, :copy ] @@ -248,7 +248,7 @@ def add_file if !attachments.empty? && Setting.notified_events.include?('file_added') Mailer.deliver_attachments_added(attachments[:files]) end - redirect_to :controller => 'projects', :action => 'list_files', :id => @project + redirect_to :controller => 'files', :action => 'index', :id => @project return end @versions = @project.versions.sort @@ -275,18 +275,6 @@ def reset_activities redirect_to :controller => 'projects', :action => 'settings', :tab => 'activities', :id => @project end - def list_files - sort_init 'filename', 'asc' - sort_update 'filename' => "#{Attachment.table_name}.filename", - 'created_on' => "#{Attachment.table_name}.created_on", - 'size' => "#{Attachment.table_name}.filesize", - 'downloads' => "#{Attachment.table_name}.downloads" - - @containers = [ Project.find(@project.id, :include => :attachments, :order => sort_clause)] - @containers += @project.versions.find(:all, :include => :attachments, :order => sort_clause).sort.reverse - render :layout => !request.xhr? - end - private def find_optional_project return true unless params[:id] diff --git a/app/views/projects/list_files.rhtml b/app/views/files/index.html.erb similarity index 100% rename from app/views/projects/list_files.rhtml rename to app/views/files/index.html.erb diff --git a/config/routes.rb b/config/routes.rb index 1414e1000ed..270bab4a0b2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -181,7 +181,7 @@ project_views.connect 'projects/:id', :action => 'show' project_views.connect 'projects/:id.:format', :action => 'show' project_views.connect 'projects/:id/:action', :action => /destroy|settings/ - project_views.connect 'projects/:id/files', :action => 'list_files' + project_views.connect 'projects/:id/files', :controller => 'files', :action => 'index' project_views.connect 'projects/:id/files/new', :action => 'add_file' project_views.connect 'projects/:id/settings/:tab', :action => 'settings' project_views.connect 'projects/:project_id/issues/:copy_from/copy', :controller => 'issues', :action => 'new' diff --git a/lib/redmine.rb b/lib/redmine.rb index ecfc4625287..726a2ad92fe 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -103,7 +103,7 @@ map.project_module :files do |map| map.permission :manage_files, {:projects => :add_file}, :require => :loggedin - map.permission :view_files, :projects => :list_files, :versions => :download + map.permission :view_files, :files => :index, :versions => :download end map.project_module :wiki do |map| @@ -198,7 +198,7 @@ :if => Proc.new { |p| p.wiki && !p.wiki.new_record? } menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id, :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural - menu.push :files, { :controller => 'projects', :action => 'list_files' }, :caption => :label_file_plural + menu.push :files, { :controller => 'files', :action => 'index' }, :caption => :label_file_plural menu.push :repository, { :controller => 'repositories', :action => 'show' }, :if => Proc.new { |p| p.repository && !p.repository.new_record? } menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true diff --git a/test/functional/files_controller_test.rb b/test/functional/files_controller_test.rb new file mode 100644 index 00000000000..90850218335 --- /dev/null +++ b/test/functional/files_controller_test.rb @@ -0,0 +1,29 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class FilesControllerTest < ActionController::TestCase + fixtures :all + + def setup + @controller = FilesController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + @request.session[:user_id] = nil + Setting.default_language = 'en' + end + + def test_index + get :index, :id => 1 + assert_response :success + assert_template 'index' + assert_not_nil assigns(:containers) + + # file attached to the project + assert_tag :a, :content => 'project_file.zip', + :attributes => { :href => '/attachments/download/8/project_file.zip' } + + # file attached to a project's version + assert_tag :a, :content => 'version_file.zip', + :attributes => { :href => '/attachments/download/9/version_file.zip' } + end + +end diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index 36d60c859e3..b22efd6ab45 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -353,21 +353,6 @@ def test_add_version_file assert_equal Version.find(2), a.container end - def test_list_files - get :list_files, :id => 1 - assert_response :success - assert_template 'list_files' - assert_not_nil assigns(:containers) - - # file attached to the project - assert_tag :a, :content => 'project_file.zip', - :attributes => { :href => '/attachments/download/8/project_file.zip' } - - # file attached to a project's version - assert_tag :a, :content => 'version_file.zip', - :attributes => { :href => '/attachments/download/9/version_file.zip' } - end - def test_archive @request.session[:user_id] = 1 # admin post :archive, :id => 1 diff --git a/test/integration/routing_test.rb b/test/integration/routing_test.rb index 590bd911904..cc1f451cfdf 100644 --- a/test/integration/routing_test.rb +++ b/test/integration/routing_test.rb @@ -172,7 +172,7 @@ class RoutingTest < ActionController::IntegrationTest should_route :get, "/projects/4223/settings", :controller => 'projects', :action => 'settings', :id => '4223' should_route :get, "/projects/4223/settings/members", :controller => 'projects', :action => 'settings', :id => '4223', :tab => 'members' should_route :get, "/projects/567/destroy", :controller => 'projects', :action => 'destroy', :id => '567' - should_route :get, "/projects/33/files", :controller => 'projects', :action => 'list_files', :id => '33' + should_route :get, "/projects/33/files", :controller => 'files', :action => 'index', :id => '33' should_route :get, "/projects/33/files/new", :controller => 'projects', :action => 'add_file', :id => '33' should_route :get, "/projects/33/roadmap", :controller => 'versions', :action => 'index', :project_id => '33' should_route :get, "/projects/33/activity", :controller => 'activities', :action => 'index', :id => '33' From b5e90972d88c69a1ef2c9e90879e8926d192acff Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Wed, 1 Sep 2010 15:17:45 +0000 Subject: [PATCH 16/25] Refactor: move method, ProjectsController#add_file to FilesController#new. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4052 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/files_controller.rb | 15 ++++++++ app/controllers/projects_controller.rb | 16 -------- app/views/files/index.html.erb | 2 +- .../add_file.rhtml => files/new.html.erb} | 2 +- config/routes.rb | 4 +- lib/redmine.rb | 2 +- test/functional/files_controller_test.rb | 38 +++++++++++++++++++ test/functional/projects_controller_test.rb | 36 ------------------ test/integration/routing_test.rb | 4 +- 9 files changed, 60 insertions(+), 59 deletions(-) rename app/views/{projects/add_file.rhtml => files/new.html.erb} (82%) diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb index c84ce5f51b1..fe5eb48c8b4 100644 --- a/app/controllers/files_controller.rb +++ b/app/controllers/files_controller.rb @@ -19,4 +19,19 @@ def index render :layout => !request.xhr? end + # TODO: split method into new (GET) and create (POST) + def new + if request.post? + container = (params[:version_id].blank? ? @project : @project.versions.find_by_id(params[:version_id])) + attachments = Attachment.attach_files(container, params[:attachments]) + render_attachment_warning_if_needed(container) + + if !attachments.empty? && Setting.notified_events.include?('file_added') + Mailer.deliver_attachments_added(attachments[:files]) + end + redirect_to :controller => 'files', :action => 'index', :id => @project + return + end + @versions = @project.versions.sort + end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 05c8d969d6f..61c7a7c71c5 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -18,7 +18,6 @@ class ProjectsController < ApplicationController menu_item :overview menu_item :roadmap, :only => :roadmap - menu_item :files, :only => [:add_file] menu_item :settings, :only => :settings before_filter :find_project, :except => [ :index, :list, :add, :copy ] @@ -239,21 +238,6 @@ def destroy @project = nil end - def add_file - if request.post? - container = (params[:version_id].blank? ? @project : @project.versions.find_by_id(params[:version_id])) - attachments = Attachment.attach_files(container, params[:attachments]) - render_attachment_warning_if_needed(container) - - if !attachments.empty? && Setting.notified_events.include?('file_added') - Mailer.deliver_attachments_added(attachments[:files]) - end - redirect_to :controller => 'files', :action => 'index', :id => @project - return - end - @versions = @project.versions.sort - end - def save_activities if request.post? && params[:enumerations] Project.transaction do diff --git a/app/views/files/index.html.erb b/app/views/files/index.html.erb index 2b2e5e870cb..66f5d12b9ad 100644 --- a/app/views/files/index.html.erb +++ b/app/views/files/index.html.erb @@ -1,5 +1,5 @@
-<%= link_to_if_authorized l(:label_attachment_new), {:controller => 'projects', :action => 'add_file', :id => @project}, :class => 'icon icon-add' %> +<%= link_to_if_authorized l(:label_attachment_new), {:controller => 'files', :action => 'new', :id => @project}, :class => 'icon icon-add' %>

<%=l(:label_attachment_plural)%>

diff --git a/app/views/projects/add_file.rhtml b/app/views/files/new.html.erb similarity index 82% rename from app/views/projects/add_file.rhtml rename to app/views/files/new.html.erb index ab9c7352dbc..bbb3b17334c 100644 --- a/app/views/projects/add_file.rhtml +++ b/app/views/files/new.html.erb @@ -2,7 +2,7 @@ <%= error_messages_for 'attachment' %>
-<% form_tag({ :action => 'add_file', :id => @project }, :multipart => true, :class => "tabular") do %> +<% form_tag({ :action => 'new', :id => @project }, :multipart => true, :class => "tabular") do %> <% if @versions.any? %>

diff --git a/config/routes.rb b/config/routes.rb index 270bab4a0b2..9c8a2f6ae8d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -182,7 +182,7 @@ project_views.connect 'projects/:id.:format', :action => 'show' project_views.connect 'projects/:id/:action', :action => /destroy|settings/ project_views.connect 'projects/:id/files', :controller => 'files', :action => 'index' - project_views.connect 'projects/:id/files/new', :action => 'add_file' + project_views.connect 'projects/:id/files/new', :controller => 'files', :action => 'new' project_views.connect 'projects/:id/settings/:tab', :action => 'settings' project_views.connect 'projects/:project_id/issues/:copy_from/copy', :controller => 'issues', :action => 'new' end @@ -199,7 +199,7 @@ project_actions.connect 'projects', :action => 'add' project_actions.connect 'projects.:format', :action => 'add', :format => /xml/ project_actions.connect 'projects/:id/:action', :action => /edit|destroy|archive|unarchive/ - project_actions.connect 'projects/:id/files/new', :action => 'add_file' + project_actions.connect 'projects/:id/files/new', :controller => 'files', :action => 'new' project_actions.connect 'projects/:id/activities/save', :action => 'save_activities' end diff --git a/lib/redmine.rb b/lib/redmine.rb index 726a2ad92fe..745c6d750f8 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -102,7 +102,7 @@ end map.project_module :files do |map| - map.permission :manage_files, {:projects => :add_file}, :require => :loggedin + map.permission :manage_files, {:files => :new}, :require => :loggedin map.permission :view_files, :files => :index, :versions => :download end diff --git a/test/functional/files_controller_test.rb b/test/functional/files_controller_test.rb index 90850218335..838caee70e3 100644 --- a/test/functional/files_controller_test.rb +++ b/test/functional/files_controller_test.rb @@ -26,4 +26,42 @@ def test_index :attributes => { :href => '/attachments/download/9/version_file.zip' } end + def test_add_file + set_tmp_attachments_directory + @request.session[:user_id] = 2 + Setting.notified_events = ['file_added'] + ActionMailer::Base.deliveries.clear + + assert_difference 'Attachment.count' do + post :new, :id => 1, :version_id => '', + :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}} + assert_response :redirect + end + assert_redirected_to 'projects/ecookbook/files' + a = Attachment.find(:first, :order => 'created_on DESC') + assert_equal 'testfile.txt', a.filename + assert_equal Project.find(1), a.container + + mail = ActionMailer::Base.deliveries.last + assert_kind_of TMail::Mail, mail + assert_equal "[eCookbook] New file", mail.subject + assert mail.body.include?('testfile.txt') + end + + def test_add_version_file + set_tmp_attachments_directory + @request.session[:user_id] = 2 + Setting.notified_events = ['file_added'] + + assert_difference 'Attachment.count' do + post :new, :id => 1, :version_id => '2', + :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}} + assert_response :redirect + end + assert_redirected_to 'projects/ecookbook/files' + a = Attachment.find(:first, :order => 'created_on DESC') + assert_equal 'testfile.txt', a.filename + assert_equal Version.find(2), a.container + end + end diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index b22efd6ab45..9d1582af087 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -317,42 +317,6 @@ def test_post_destroy assert_nil Project.find_by_id(1) end - def test_add_file - set_tmp_attachments_directory - @request.session[:user_id] = 2 - Setting.notified_events = ['file_added'] - ActionMailer::Base.deliveries.clear - - assert_difference 'Attachment.count' do - post :add_file, :id => 1, :version_id => '', - :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}} - end - assert_redirected_to 'projects/ecookbook/files' - a = Attachment.find(:first, :order => 'created_on DESC') - assert_equal 'testfile.txt', a.filename - assert_equal Project.find(1), a.container - - mail = ActionMailer::Base.deliveries.last - assert_kind_of TMail::Mail, mail - assert_equal "[eCookbook] New file", mail.subject - assert mail.body.include?('testfile.txt') - end - - def test_add_version_file - set_tmp_attachments_directory - @request.session[:user_id] = 2 - Setting.notified_events = ['file_added'] - - assert_difference 'Attachment.count' do - post :add_file, :id => 1, :version_id => '2', - :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}} - end - assert_redirected_to 'projects/ecookbook/files' - a = Attachment.find(:first, :order => 'created_on DESC') - assert_equal 'testfile.txt', a.filename - assert_equal Version.find(2), a.container - end - def test_archive @request.session[:user_id] = 1 # admin post :archive, :id => 1 diff --git a/test/integration/routing_test.rb b/test/integration/routing_test.rb index cc1f451cfdf..66836c4f93c 100644 --- a/test/integration/routing_test.rb +++ b/test/integration/routing_test.rb @@ -173,7 +173,7 @@ class RoutingTest < ActionController::IntegrationTest should_route :get, "/projects/4223/settings/members", :controller => 'projects', :action => 'settings', :id => '4223', :tab => 'members' should_route :get, "/projects/567/destroy", :controller => 'projects', :action => 'destroy', :id => '567' should_route :get, "/projects/33/files", :controller => 'files', :action => 'index', :id => '33' - should_route :get, "/projects/33/files/new", :controller => 'projects', :action => 'add_file', :id => '33' + should_route :get, "/projects/33/files/new", :controller => 'files', :action => 'new', :id => '33' should_route :get, "/projects/33/roadmap", :controller => 'versions', :action => 'index', :project_id => '33' should_route :get, "/projects/33/activity", :controller => 'activities', :action => 'index', :id => '33' should_route :get, "/projects/33/activity.atom", :controller => 'activities', :action => 'index', :id => '33', :format => 'atom' @@ -182,7 +182,7 @@ class RoutingTest < ActionController::IntegrationTest should_route :post, "/projects.xml", :controller => 'projects', :action => 'add', :format => 'xml' should_route :post, "/projects/4223/edit", :controller => 'projects', :action => 'edit', :id => '4223' should_route :post, "/projects/64/destroy", :controller => 'projects', :action => 'destroy', :id => '64' - should_route :post, "/projects/33/files/new", :controller => 'projects', :action => 'add_file', :id => '33' + should_route :post, "/projects/33/files/new", :controller => 'files', :action => 'new', :id => '33' should_route :post, "/projects/64/archive", :controller => 'projects', :action => 'archive', :id => '64' should_route :post, "/projects/64/unarchive", :controller => 'projects', :action => 'unarchive', :id => '64' should_route :post, "/projects/64/activities/save", :controller => 'projects', :action => 'save_activities', :id => '64' From 83b4343d2d403a21de4614016e165091e4c5914f Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Thu, 2 Sep 2010 17:39:56 +0000 Subject: [PATCH 17/25] Refactor: move method, ProjectsController#save_activities to ProjectEnumerationsController#save git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4053 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../project_enumerations_controller.rb | 18 +++ app/controllers/projects_controller.rb | 13 -- app/views/projects/settings/_activities.rhtml | 2 +- config/routes.rb | 2 +- lib/redmine.rb | 2 +- .../project_enumerations_controller_test.rb | 142 ++++++++++++++++++ test/functional/projects_controller_test.rb | 132 ---------------- test/integration/routing_test.rb | 2 +- 8 files changed, 164 insertions(+), 149 deletions(-) create mode 100644 app/controllers/project_enumerations_controller.rb create mode 100644 test/functional/project_enumerations_controller_test.rb diff --git a/app/controllers/project_enumerations_controller.rb b/app/controllers/project_enumerations_controller.rb new file mode 100644 index 00000000000..c4b48e47686 --- /dev/null +++ b/app/controllers/project_enumerations_controller.rb @@ -0,0 +1,18 @@ +class ProjectEnumerationsController < ApplicationController + before_filter :find_project + before_filter :authorize + + def save + if request.post? && params[:enumerations] + Project.transaction do + params[:enumerations].each do |id, activity| + @project.update_or_create_time_entry_activity(id, activity) + end + end + flash[:notice] = l(:notice_successful_update) + end + + redirect_to :controller => 'projects', :action => 'settings', :tab => 'activities', :id => @project + end + +end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 61c7a7c71c5..0670cb1ec86 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -238,19 +238,6 @@ def destroy @project = nil end - def save_activities - if request.post? && params[:enumerations] - Project.transaction do - params[:enumerations].each do |id, activity| - @project.update_or_create_time_entry_activity(id, activity) - end - end - flash[:notice] = l(:notice_successful_update) - end - - redirect_to :controller => 'projects', :action => 'settings', :tab => 'activities', :id => @project - end - def reset_activities @project.time_entry_activities.each do |time_entry_activity| time_entry_activity.destroy(time_entry_activity.parent) diff --git a/app/views/projects/settings/_activities.rhtml b/app/views/projects/settings/_activities.rhtml index d82bd96fb69..e39bf9b914d 100644 --- a/app/views/projects/settings/_activities.rhtml +++ b/app/views/projects/settings/_activities.rhtml @@ -1,4 +1,4 @@ -<% form_tag({:controller => 'projects', :action => 'save_activities', :id => @project}, :class => "tabular") do %> +<% form_tag({:controller => 'project_enumerations', :action => 'save', :id => @project}, :class => "tabular") do %> diff --git a/config/routes.rb b/config/routes.rb index 9c8a2f6ae8d..12411599873 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -200,7 +200,7 @@ project_actions.connect 'projects.:format', :action => 'add', :format => /xml/ project_actions.connect 'projects/:id/:action', :action => /edit|destroy|archive|unarchive/ project_actions.connect 'projects/:id/files/new', :controller => 'files', :action => 'new' - project_actions.connect 'projects/:id/activities/save', :action => 'save_activities' + project_actions.connect 'projects/:id/activities/save', :controller => 'project_enumerations', :action => 'save' end projects.with_options :conditions => {:method => :put} do |project_actions| diff --git a/lib/redmine.rb b/lib/redmine.rb index 745c6d750f8..fdd61225e03 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -87,7 +87,7 @@ map.permission :view_time_entries, :timelog => [:details, :report] map.permission :edit_time_entries, {:timelog => [:edit, :destroy]}, :require => :member map.permission :edit_own_time_entries, {:timelog => [:edit, :destroy]}, :require => :loggedin - map.permission :manage_project_activities, {:projects => [:save_activities, :reset_activities]}, :require => :member + map.permission :manage_project_activities, {:projects => [:reset_activities], :project_enumerations => [:save]}, :require => :member end map.project_module :news do |map| diff --git a/test/functional/project_enumerations_controller_test.rb b/test/functional/project_enumerations_controller_test.rb new file mode 100644 index 00000000000..23da423782f --- /dev/null +++ b/test/functional/project_enumerations_controller_test.rb @@ -0,0 +1,142 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class ProjectEnumerationsControllerTest < ActionController::TestCase + fixtures :all + + def setup + @request.session[:user_id] = nil + Setting.default_language = 'en' + end + + def test_save_to_override_system_activities + @request.session[:user_id] = 2 # manager + billable_field = TimeEntryActivityCustomField.find_by_name("Billable") + + post :save, :id => 1, :enumerations => { + "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design, De-activate + "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"}, # Development, Change custom value + "14"=>{"parent_id"=>"14", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"}, # Inactive Activity, Activate with custom value + "11"=>{"parent_id"=>"11", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"} # QA, no changes + } + + assert_response :redirect + assert_redirected_to 'projects/ecookbook/settings/activities' + + # Created project specific activities... + project = Project.find('ecookbook') + + # ... Design + design = project.time_entry_activities.find_by_name("Design") + assert design, "Project activity not found" + + assert_equal 9, design.parent_id # Relate to the system activity + assert_not_equal design.parent.id, design.id # Different records + assert_equal design.parent.name, design.name # Same name + assert !design.active? + + # ... Development + development = project.time_entry_activities.find_by_name("Development") + assert development, "Project activity not found" + + assert_equal 10, development.parent_id # Relate to the system activity + assert_not_equal development.parent.id, development.id # Different records + assert_equal development.parent.name, development.name # Same name + assert development.active? + assert_equal "0", development.custom_value_for(billable_field).value + + # ... Inactive Activity + previously_inactive = project.time_entry_activities.find_by_name("Inactive Activity") + assert previously_inactive, "Project activity not found" + + assert_equal 14, previously_inactive.parent_id # Relate to the system activity + assert_not_equal previously_inactive.parent.id, previously_inactive.id # Different records + assert_equal previously_inactive.parent.name, previously_inactive.name # Same name + assert previously_inactive.active? + assert_equal "1", previously_inactive.custom_value_for(billable_field).value + + # ... QA + assert_equal nil, project.time_entry_activities.find_by_name("QA"), "Custom QA activity created when it wasn't modified" + end + + def test_save_will_update_project_specific_activities + @request.session[:user_id] = 2 # manager + + project_activity = TimeEntryActivity.new({ + :name => 'Project Specific', + :parent => TimeEntryActivity.find(:first), + :project => Project.find(1), + :active => true + }) + assert project_activity.save + project_activity_two = TimeEntryActivity.new({ + :name => 'Project Specific Two', + :parent => TimeEntryActivity.find(:last), + :project => Project.find(1), + :active => true + }) + assert project_activity_two.save + + + post :save, :id => 1, :enumerations => { + project_activity.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # De-activate + project_activity_two.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"} # De-activate + } + + assert_response :redirect + assert_redirected_to 'projects/ecookbook/settings/activities' + + # Created project specific activities... + project = Project.find('ecookbook') + assert_equal 2, project.time_entry_activities.count + + activity_one = project.time_entry_activities.find_by_name(project_activity.name) + assert activity_one, "Project activity not found" + assert_equal project_activity.id, activity_one.id + assert !activity_one.active? + + activity_two = project.time_entry_activities.find_by_name(project_activity_two.name) + assert activity_two, "Project activity not found" + assert_equal project_activity_two.id, activity_two.id + assert !activity_two.active? + end + + def test_save_when_creating_new_activities_will_convert_existing_data + assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size + + @request.session[:user_id] = 2 # manager + post :save, :id => 1, :enumerations => { + "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"} # Design, De-activate + } + assert_response :redirect + + # No more TimeEntries using the system activity + assert_equal 0, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries still assigned to system activities" + # All TimeEntries using project activity + project_specific_activity = TimeEntryActivity.find_by_parent_id_and_project_id(9, 1) + assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(project_specific_activity.id, 1).size, "No Time Entries assigned to the project activity" + end + + def test_save_when_creating_new_activities_will_not_convert_existing_data_if_an_exception_is_raised + # TODO: Need to cause an exception on create but these tests + # aren't setup for mocking. Just create a record now so the + # second one is a dupicate + parent = TimeEntryActivity.find(9) + TimeEntryActivity.create!({:name => parent.name, :project_id => 1, :position => parent.position, :active => true}) + TimeEntry.create!({:project_id => 1, :hours => 1.0, :user => User.find(1), :issue_id => 3, :activity_id => 10, :spent_on => '2009-01-01'}) + + assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size + assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size + + @request.session[:user_id] = 2 # manager + post :save, :id => 1, :enumerations => { + "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design + "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"} # Development, Change custom value + } + assert_response :redirect + + # TimeEntries shouldn't have been reassigned on the failed record + assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries are not assigned to system activities" + # TimeEntries shouldn't have been reassigned on the saved record either + assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size, "Time Entries are not assigned to system activities" + end +end diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index 9d1582af087..152d0837b1c 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -427,138 +427,6 @@ def test_reset_activities_should_reassign_time_entries_back_to_the_system_activi assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "TimeEntries still assigned to project specific activity" end - def test_save_activities_to_override_system_activities - @request.session[:user_id] = 2 # manager - billable_field = TimeEntryActivityCustomField.find_by_name("Billable") - - post :save_activities, :id => 1, :enumerations => { - "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design, De-activate - "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"}, # Development, Change custom value - "14"=>{"parent_id"=>"14", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"}, # Inactive Activity, Activate with custom value - "11"=>{"parent_id"=>"11", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"} # QA, no changes - } - - assert_response :redirect - assert_redirected_to 'projects/ecookbook/settings/activities' - - # Created project specific activities... - project = Project.find('ecookbook') - - # ... Design - design = project.time_entry_activities.find_by_name("Design") - assert design, "Project activity not found" - - assert_equal 9, design.parent_id # Relate to the system activity - assert_not_equal design.parent.id, design.id # Different records - assert_equal design.parent.name, design.name # Same name - assert !design.active? - - # ... Development - development = project.time_entry_activities.find_by_name("Development") - assert development, "Project activity not found" - - assert_equal 10, development.parent_id # Relate to the system activity - assert_not_equal development.parent.id, development.id # Different records - assert_equal development.parent.name, development.name # Same name - assert development.active? - assert_equal "0", development.custom_value_for(billable_field).value - - # ... Inactive Activity - previously_inactive = project.time_entry_activities.find_by_name("Inactive Activity") - assert previously_inactive, "Project activity not found" - - assert_equal 14, previously_inactive.parent_id # Relate to the system activity - assert_not_equal previously_inactive.parent.id, previously_inactive.id # Different records - assert_equal previously_inactive.parent.name, previously_inactive.name # Same name - assert previously_inactive.active? - assert_equal "1", previously_inactive.custom_value_for(billable_field).value - - # ... QA - assert_equal nil, project.time_entry_activities.find_by_name("QA"), "Custom QA activity created when it wasn't modified" - end - - def test_save_activities_will_update_project_specific_activities - @request.session[:user_id] = 2 # manager - - project_activity = TimeEntryActivity.new({ - :name => 'Project Specific', - :parent => TimeEntryActivity.find(:first), - :project => Project.find(1), - :active => true - }) - assert project_activity.save - project_activity_two = TimeEntryActivity.new({ - :name => 'Project Specific Two', - :parent => TimeEntryActivity.find(:last), - :project => Project.find(1), - :active => true - }) - assert project_activity_two.save - - - post :save_activities, :id => 1, :enumerations => { - project_activity.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # De-activate - project_activity_two.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"} # De-activate - } - - assert_response :redirect - assert_redirected_to 'projects/ecookbook/settings/activities' - - # Created project specific activities... - project = Project.find('ecookbook') - assert_equal 2, project.time_entry_activities.count - - activity_one = project.time_entry_activities.find_by_name(project_activity.name) - assert activity_one, "Project activity not found" - assert_equal project_activity.id, activity_one.id - assert !activity_one.active? - - activity_two = project.time_entry_activities.find_by_name(project_activity_two.name) - assert activity_two, "Project activity not found" - assert_equal project_activity_two.id, activity_two.id - assert !activity_two.active? - end - - def test_save_activities_when_creating_new_activities_will_convert_existing_data - assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size - - @request.session[:user_id] = 2 # manager - post :save_activities, :id => 1, :enumerations => { - "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"} # Design, De-activate - } - assert_response :redirect - - # No more TimeEntries using the system activity - assert_equal 0, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries still assigned to system activities" - # All TimeEntries using project activity - project_specific_activity = TimeEntryActivity.find_by_parent_id_and_project_id(9, 1) - assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(project_specific_activity.id, 1).size, "No Time Entries assigned to the project activity" - end - - def test_save_activities_when_creating_new_activities_will_not_convert_existing_data_if_an_exception_is_raised - # TODO: Need to cause an exception on create but these tests - # aren't setup for mocking. Just create a record now so the - # second one is a dupicate - parent = TimeEntryActivity.find(9) - TimeEntryActivity.create!({:name => parent.name, :project_id => 1, :position => parent.position, :active => true}) - TimeEntry.create!({:project_id => 1, :hours => 1.0, :user => User.find(1), :issue_id => 3, :activity_id => 10, :spent_on => '2009-01-01'}) - - assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size - assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size - - @request.session[:user_id] = 2 # manager - post :save_activities, :id => 1, :enumerations => { - "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design - "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"} # Development, Change custom value - } - assert_response :redirect - - # TimeEntries shouldn't have been reassigned on the failed record - assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries are not assigned to system activities" - # TimeEntries shouldn't have been reassigned on the saved record either - assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size, "Time Entries are not assigned to system activities" - end - # A hook that is manually registered later class ProjectBasedTemplate < Redmine::Hook::ViewListener def view_layouts_base_html_head(context) diff --git a/test/integration/routing_test.rb b/test/integration/routing_test.rb index 66836c4f93c..74a0f7a71d0 100644 --- a/test/integration/routing_test.rb +++ b/test/integration/routing_test.rb @@ -185,7 +185,7 @@ class RoutingTest < ActionController::IntegrationTest should_route :post, "/projects/33/files/new", :controller => 'files', :action => 'new', :id => '33' should_route :post, "/projects/64/archive", :controller => 'projects', :action => 'archive', :id => '64' should_route :post, "/projects/64/unarchive", :controller => 'projects', :action => 'unarchive', :id => '64' - should_route :post, "/projects/64/activities/save", :controller => 'projects', :action => 'save_activities', :id => '64' + should_route :post, "/projects/64/activities/save", :controller => 'project_enumerations', :action => 'save', :id => '64' should_route :put, "/projects/1.xml", :controller => 'projects', :action => 'edit', :id => '1', :format => 'xml' From c1068bf0cd32df1edf9b1b69e76e30af84692b7c Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Fri, 3 Sep 2010 15:04:03 +0000 Subject: [PATCH 18/25] Refactor: move method, ProjectsController#reset_activities to ProjectEnumerationsController#destroy. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4054 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../project_enumerations_controller.rb | 8 ++++ app/controllers/projects_controller.rb | 8 ---- app/views/projects/settings/_activities.rhtml | 2 +- config/routes.rb | 2 +- lib/redmine.rb | 2 +- .../project_enumerations_controller_test.rb | 47 +++++++++++++++++++ test/functional/projects_controller_test.rb | 46 ------------------ test/integration/routing_test.rb | 2 +- 8 files changed, 59 insertions(+), 58 deletions(-) diff --git a/app/controllers/project_enumerations_controller.rb b/app/controllers/project_enumerations_controller.rb index c4b48e47686..d63e2364168 100644 --- a/app/controllers/project_enumerations_controller.rb +++ b/app/controllers/project_enumerations_controller.rb @@ -15,4 +15,12 @@ def save redirect_to :controller => 'projects', :action => 'settings', :tab => 'activities', :id => @project end + def destroy + @project.time_entry_activities.each do |time_entry_activity| + time_entry_activity.destroy(time_entry_activity.parent) + end + flash[:notice] = l(:notice_successful_update) + redirect_to :controller => 'projects', :action => 'settings', :tab => 'activities', :id => @project + end + end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 0670cb1ec86..90eddd7b297 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -238,14 +238,6 @@ def destroy @project = nil end - def reset_activities - @project.time_entry_activities.each do |time_entry_activity| - time_entry_activity.destroy(time_entry_activity.parent) - end - flash[:notice] = l(:notice_successful_update) - redirect_to :controller => 'projects', :action => 'settings', :tab => 'activities', :id => @project - end - private def find_optional_project return true unless params[:id] diff --git a/app/views/projects/settings/_activities.rhtml b/app/views/projects/settings/_activities.rhtml index e39bf9b914d..5909ac64ccc 100644 --- a/app/views/projects/settings/_activities.rhtml +++ b/app/views/projects/settings/_activities.rhtml @@ -32,7 +32,7 @@

-<%= link_to(l(:button_reset), {:controller => 'projects', :action => 'reset_activities', :id => @project}, +<%= link_to(l(:button_reset), {:controller => 'project_enumerations', :action => 'destroy', :id => @project}, :method => :delete, :confirm => l(:text_are_you_sure), :class => 'icon icon-del') %> diff --git a/config/routes.rb b/config/routes.rb index 12411599873..5448b5f581d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -209,7 +209,7 @@ projects.with_options :conditions => {:method => :delete} do |project_actions| project_actions.conditions 'projects/:id.:format', :action => 'destroy', :format => /xml/ - project_actions.conditions 'projects/:id/reset_activities', :action => 'reset_activities' + project_actions.conditions 'projects/:id/reset_activities', :controller => 'project_enumerations', :action => 'destroy' end end diff --git a/lib/redmine.rb b/lib/redmine.rb index fdd61225e03..fc750d1106e 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -87,7 +87,7 @@ map.permission :view_time_entries, :timelog => [:details, :report] map.permission :edit_time_entries, {:timelog => [:edit, :destroy]}, :require => :member map.permission :edit_own_time_entries, {:timelog => [:edit, :destroy]}, :require => :loggedin - map.permission :manage_project_activities, {:projects => [:reset_activities], :project_enumerations => [:save]}, :require => :member + map.permission :manage_project_activities, {:project_enumerations => [:save, :destroy]}, :require => :member end map.project_module :news do |map| diff --git a/test/functional/project_enumerations_controller_test.rb b/test/functional/project_enumerations_controller_test.rb index 23da423782f..c03be04fb7d 100644 --- a/test/functional/project_enumerations_controller_test.rb +++ b/test/functional/project_enumerations_controller_test.rb @@ -139,4 +139,51 @@ def test_save_when_creating_new_activities_will_not_convert_existing_data_if_an_ # TimeEntries shouldn't have been reassigned on the saved record either assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size, "Time Entries are not assigned to system activities" end + + def test_destroy + @request.session[:user_id] = 2 # manager + project_activity = TimeEntryActivity.new({ + :name => 'Project Specific', + :parent => TimeEntryActivity.find(:first), + :project => Project.find(1), + :active => true + }) + assert project_activity.save + project_activity_two = TimeEntryActivity.new({ + :name => 'Project Specific Two', + :parent => TimeEntryActivity.find(:last), + :project => Project.find(1), + :active => true + }) + assert project_activity_two.save + + delete :destroy, :id => 1 + assert_response :redirect + assert_redirected_to 'projects/ecookbook/settings/activities' + + assert_nil TimeEntryActivity.find_by_id(project_activity.id) + assert_nil TimeEntryActivity.find_by_id(project_activity_two.id) + end + + def test_destroy_should_reassign_time_entries_back_to_the_system_activity + @request.session[:user_id] = 2 # manager + project_activity = TimeEntryActivity.new({ + :name => 'Project Specific Design', + :parent => TimeEntryActivity.find(9), + :project => Project.find(1), + :active => true + }) + assert project_activity.save + assert TimeEntry.update_all("activity_id = '#{project_activity.id}'", ["project_id = ? AND activity_id = ?", 1, 9]) + assert 3, TimeEntry.find_all_by_activity_id_and_project_id(project_activity.id, 1).size + + delete :destroy, :id => 1 + assert_response :redirect + assert_redirected_to 'projects/ecookbook/settings/activities' + + assert_nil TimeEntryActivity.find_by_id(project_activity.id) + assert_equal 0, TimeEntry.find_all_by_activity_id_and_project_id(project_activity.id, 1).size, "TimeEntries still assigned to project specific activity" + assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "TimeEntries still assigned to project specific activity" + end + end diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index 152d0837b1c..4decb060fe2 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -381,52 +381,6 @@ def test_jump_should_not_redirect_to_unknown_tab assert_template 'show' end - def test_reset_activities - @request.session[:user_id] = 2 # manager - project_activity = TimeEntryActivity.new({ - :name => 'Project Specific', - :parent => TimeEntryActivity.find(:first), - :project => Project.find(1), - :active => true - }) - assert project_activity.save - project_activity_two = TimeEntryActivity.new({ - :name => 'Project Specific Two', - :parent => TimeEntryActivity.find(:last), - :project => Project.find(1), - :active => true - }) - assert project_activity_two.save - - delete :reset_activities, :id => 1 - assert_response :redirect - assert_redirected_to 'projects/ecookbook/settings/activities' - - assert_nil TimeEntryActivity.find_by_id(project_activity.id) - assert_nil TimeEntryActivity.find_by_id(project_activity_two.id) - end - - def test_reset_activities_should_reassign_time_entries_back_to_the_system_activity - @request.session[:user_id] = 2 # manager - project_activity = TimeEntryActivity.new({ - :name => 'Project Specific Design', - :parent => TimeEntryActivity.find(9), - :project => Project.find(1), - :active => true - }) - assert project_activity.save - assert TimeEntry.update_all("activity_id = '#{project_activity.id}'", ["project_id = ? AND activity_id = ?", 1, 9]) - assert 3, TimeEntry.find_all_by_activity_id_and_project_id(project_activity.id, 1).size - - delete :reset_activities, :id => 1 - assert_response :redirect - assert_redirected_to 'projects/ecookbook/settings/activities' - - assert_nil TimeEntryActivity.find_by_id(project_activity.id) - assert_equal 0, TimeEntry.find_all_by_activity_id_and_project_id(project_activity.id, 1).size, "TimeEntries still assigned to project specific activity" - assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "TimeEntries still assigned to project specific activity" - end - # A hook that is manually registered later class ProjectBasedTemplate < Redmine::Hook::ViewListener def view_layouts_base_html_head(context) diff --git a/test/integration/routing_test.rb b/test/integration/routing_test.rb index 74a0f7a71d0..71be6c3c719 100644 --- a/test/integration/routing_test.rb +++ b/test/integration/routing_test.rb @@ -190,7 +190,7 @@ class RoutingTest < ActionController::IntegrationTest should_route :put, "/projects/1.xml", :controller => 'projects', :action => 'edit', :id => '1', :format => 'xml' should_route :delete, "/projects/1.xml", :controller => 'projects', :action => 'destroy', :id => '1', :format => 'xml' - should_route :delete, "/projects/64/reset_activities", :controller => 'projects', :action => 'reset_activities', :id => '64' + should_route :delete, "/projects/64/reset_activities", :controller => 'project_enumerations', :action => 'destroy', :id => '64' end context "repositories" do From a2ce6e236c397a527deb18cc2196371855d27c41 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Barth Date: Fri, 3 Sep 2010 19:54:24 +0000 Subject: [PATCH 19/25] Allow mass status update through context menu. #3411 NB: it cannot be done with issues from different projects, same as other fields. This will be addressed separately, see #5332. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4055 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/context_menus_controller.rb | 6 ++++++ app/views/context_menus/issues.html.erb | 15 +++++++++------ test/functional/context_menus_controller_test.rb | 5 ++++- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/app/controllers/context_menus_controller.rb b/app/controllers/context_menus_controller.rb index 442f85b3767..e437a18dc25 100644 --- a/app/controllers/context_menus_controller.rb +++ b/app/controllers/context_menus_controller.rb @@ -6,6 +6,12 @@ def issues if (@issues.size == 1) @issue = @issues.first @allowed_statuses = @issue.new_statuses_allowed_to(User.current) + else + @allowed_statuses = @issues.map do |i| + i.new_statuses_allowed_to(User.current) + end.inject do |memo,s| + memo & s + end end projects = @issues.collect(&:project).compact.uniq @project = projects.first if projects.size == 1 diff --git a/app/views/context_menus/issues.html.erb b/app/views/context_menus/issues.html.erb index dc11b5fdb46..efd8cde0ee4 100644 --- a/app/views/context_menus/issues.html.erb +++ b/app/views/context_menus/issues.html.erb @@ -4,19 +4,22 @@ <% if !@issue.nil? -%>
  • <%= context_menu_link l(:button_edit), {:controller => 'issues', :action => 'edit', :id => @issue}, :class => 'icon-edit', :disabled => !@can[:edit] %>
  • +<% else %> +
  • <%= context_menu_link l(:button_edit), {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id)}, + :class => 'icon-edit', :disabled => !@can[:edit] %>
  • +<% end %> + + <% unless @allowed_statuses.empty? %>
  • <%= l(:field_status) %>
      <% @statuses.each do |s| -%> -
    • <%= context_menu_link s.name, {:controller => 'issues', :action => 'update', :id => @issue, :issue => {:status_id => s}, :back_url => @back}, :method => :put, - :selected => (s == @issue.status), :disabled => !(@can[:update] && @allowed_statuses.include?(s)) %>
    • +
    • <%= context_menu_link s.name, {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), :issue => {:status_id => s}, :back_url => @back}, :method => :post, + :selected => (@issue && s == @issue.status), :disabled => !(@can[:update] && @allowed_statuses.include?(s)) %>
    • <% end -%>
  • -<% else %> -
  • <%= context_menu_link l(:button_edit), {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id)}, - :class => 'icon-edit', :disabled => !@can[:edit] %>
  • -<% end %> + <% end %> <% unless @trackers.nil? %>
  • diff --git a/test/functional/context_menus_controller_test.rb b/test/functional/context_menus_controller_test.rb index 764350879c1..0ebae695a9d 100644 --- a/test/functional/context_menus_controller_test.rb +++ b/test/functional/context_menus_controller_test.rb @@ -12,7 +12,7 @@ def test_context_menu_one_issue :attributes => { :href => '/issues/1/edit', :class => 'icon-edit' } assert_tag :tag => 'a', :content => 'Closed', - :attributes => { :href => '/issues/1?issue%5Bstatus_id%5D=5', + :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&issue%5Bstatus_id%5D=5', :class => '' } assert_tag :tag => 'a', :content => 'Immediate', :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&issue%5Bpriority_id%5D=8', @@ -59,6 +59,9 @@ def test_context_menu_multiple_issues_of_same_project assert_tag :tag => 'a', :content => 'Edit', :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&ids%5B%5D=2', :class => 'icon-edit' } + assert_tag :tag => 'a', :content => 'Closed', + :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&ids%5B%5D=2&issue%5Bstatus_id%5D=5', + :class => '' } assert_tag :tag => 'a', :content => 'Immediate', :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&ids%5B%5D=2&issue%5Bpriority_id%5D=8', :class => '' } From 4776a5a42716181aaa51edf3fc6fc4bc0d19231e Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Barth Date: Fri, 3 Sep 2010 19:59:49 +0000 Subject: [PATCH 20/25] Hide checkboxes in issues list when printing git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4056 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/views/issues/_list.rhtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/issues/_list.rhtml b/app/views/issues/_list.rhtml index 2722b9e7b2a..1a2953bf5d1 100644 --- a/app/views/issues/_list.rhtml +++ b/app/views/issues/_list.rhtml @@ -3,7 +3,7 @@
    - <%= sort_header_tag('id', :caption => '#', :default_order => 'desc') %> @@ -25,7 +25,7 @@ <% previous_group = group %> <% end %> "> - + <% query.columns.each do |column| %><%= content_tag 'td', column_content(column, issue), :class => column.name %><% end %> From b6d9f2bddf40eed35c4172342516542640304ac6 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Barth Date: Fri, 3 Sep 2010 20:05:51 +0000 Subject: [PATCH 21/25] Add css classes to journals display to facilitate theming git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4057 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/journals_helper.rb | 7 +++++++ app/views/issues/_history.rhtml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/helpers/journals_helper.rb b/app/helpers/journals_helper.rb index c8d53f253be..990bfb1e574 100644 --- a/app/helpers/journals_helper.rb +++ b/app/helpers/journals_helper.rb @@ -39,4 +39,11 @@ def link_to_in_place_notes_editor(text, field_id, url, options={}) onclick = "new Ajax.Request('#{url_for(url)}', {asynchronous:true, evalScripts:true, method:'get'}); return false;" link_to text, '#', options.merge(:onclick => onclick) end + + def css_journal_classes(journal) + s = 'journal' + s << ' has-notes' unless journal.notes.blank? + s << ' has-details' unless journal.details.blank? + s + end end diff --git a/app/views/issues/_history.rhtml b/app/views/issues/_history.rhtml index a95cbf81c0f..4ea2dd2ac39 100644 --- a/app/views/issues/_history.rhtml +++ b/app/views/issues/_history.rhtml @@ -1,6 +1,6 @@ <% reply_links = authorize_for('issues', 'edit') -%> <% for journal in journals %> -
    +

    <%= avatar(journal.user, :size => "24") %> <%= content_tag('a', '', :name => "note-#{journal.indice}")%> From c799d03eceab362bac7e99313a255f6569c9756a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Barth Date: Fri, 3 Sep 2010 20:16:00 +0000 Subject: [PATCH 22/25] Added missing tests for User#allowed_to? #6291 git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4058 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/user_test.rb | 43 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index ea40ccff61a..c263eafc098 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -355,6 +355,49 @@ def denied_auth_source.allow_password_changes?; false; end end + context "#allowed_to?" do + context "with a unique project" do + should "return false if project is archived" do + project = Project.find(1) + Project.any_instance.stubs(:status).returns(Project::STATUS_ARCHIVED) + assert ! @admin.allowed_to?(:view_issues, Project.find(1)) + end + + should "return false if related module is disabled" do + project = Project.find(1) + project.enabled_module_names = ["issue_tracking"] + assert @admin.allowed_to?(:add_issues, project) + assert ! @admin.allowed_to?(:view_wiki_pages, project) + end + + should "authorize nearly everything for admin users" do + project = Project.find(1) + assert ! @admin.member_of?(project) + %w(edit_issues delete_issues manage_news manage_documents manage_wiki).each do |p| + assert @admin.allowed_to?(p.to_sym, project) + end + end + + should "authorize normal users depending on their roles" do + project = Project.find(1) + assert @jsmith.allowed_to?(:delete_messages, project) #Manager + assert ! @dlopper.allowed_to?(:delete_messages, project) #Developper + end + end + + context "with options[:global]" do + should "authorize if user has at least one role that has this permission" do + @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere + @anonymous = User.find(6) + assert @jsmith.allowed_to?(:delete_issue_watchers, nil, :global => true) + assert ! @dlopper2.allowed_to?(:delete_issue_watchers, nil, :global => true) + assert @dlopper2.allowed_to?(:add_issues, nil, :global => true) + assert ! @anonymous.allowed_to?(:add_issues, nil, :global => true) + assert @anonymous.allowed_to?(:view_issues, nil, :global => true) + end + end + end + if Object.const_defined?(:OpenID) def test_setting_identity_url From a9f5a17c678d6ebc495d42d858db0ce5727a5381 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Barth Date: Fri, 3 Sep 2010 21:43:07 +0000 Subject: [PATCH 23/25] Do not display items without valid selection in context menu when on different projects. #4998 git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4059 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/context_menus_controller.rb | 4 ++-- app/views/context_menus/issues.html.erb | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/controllers/context_menus_controller.rb b/app/controllers/context_menus_controller.rb index e437a18dc25..5f4b02ca267 100644 --- a/app/controllers/context_menus_controller.rb +++ b/app/controllers/context_menus_controller.rb @@ -13,8 +13,8 @@ def issues memo & s end end - projects = @issues.collect(&:project).compact.uniq - @project = projects.first if projects.size == 1 + @projects = @issues.collect(&:project).compact.uniq + @project = @projects.first if @projects.size == 1 @can = {:edit => (@project && User.current.allowed_to?(:edit_issues, @project)), :log_time => (@project && User.current.allowed_to?(:log_time, @project)), diff --git a/app/views/context_menus/issues.html.erb b/app/views/context_menus/issues.html.erb index efd8cde0ee4..94d4e802f3f 100644 --- a/app/views/context_menus/issues.html.erb +++ b/app/views/context_menus/issues.html.erb @@ -32,6 +32,8 @@ <% end %> + + <% if @projects.size == 1 %>
  • <%= l(:field_priority) %>
      @@ -41,6 +43,8 @@ <% end -%>
  • + <% end %> + <% unless @project.nil? || @project.shared_versions.open.empty? -%>
  • <%= l(:field_fixed_version) %> @@ -80,7 +84,8 @@
  • <% end -%> - <% if Issue.use_field_for_done_ratio? %> + + <% if Issue.use_field_for_done_ratio? && @projects.size == 1 %>
  • <%= l(:field_done_ratio) %>
      @@ -91,6 +96,7 @@
  • <% end %> + <% if !@issue.nil? %> <% if @can[:log_time] -%>
  • <%= context_menu_link l(:button_log_time), {:controller => 'timelog', :action => 'edit', :issue_id => @issue}, From c5071cd091ae5eda0dea5e9ba23a42b58462a117 Mon Sep 17 00:00:00 2001 From: Azamat Hackimov Date: Sun, 5 Sep 2010 11:33:08 +0000 Subject: [PATCH 24/25] Translation updates: * ca (#6263) * nl (#6248) git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4060 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/locales/ca.yml | 235 +++++++++--------- config/locales/nl.yml | 36 +-- .../javascripts/calendar/lang/calendar-ca.js | 22 +- 3 files changed, 150 insertions(+), 143 deletions(-) diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 80d857e9eec..b5c28d98ec0 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -1,4 +1,8 @@ +# Redmine catalan translation: +# by Joan Duran + ca: + # Text direction: Left-to-Right (ltr) or Right-to-Left (rtl) direction: ltr date: formats: @@ -65,6 +69,7 @@ ca: other: "almost {{count}} years" number: + # Default format for numbers format: separator: "." delimiter: "" @@ -83,6 +88,7 @@ ca: mb: "MB" gb: "GB" tb: "TB" + # Used in array.to_sentence. support: @@ -116,6 +122,7 @@ ca: greater_than_start_date: "ha de ser superior que la data inicial" not_same_project: "no pertany al mateix projecte" circular_dependency: "Aquesta relació crearia una dependència circular" + cant_link_an_issue_with_a_descendant: "Un assumpte no es pot enllaçar a una de les seves subtasques" actionview_instancetag_blank_option: Seleccioneu @@ -149,18 +156,33 @@ ca: notice_email_sent: "S'ha enviat un correu electrònic a {{value}}" notice_email_error: "S'ha produït un error en enviar el correu ({{value}})" notice_feeds_access_key_reseted: "S'ha reiniciat la clau d'accés del RSS." + notice_api_access_key_reseted: "S'ha reiniciat la clau d'accés a l'API." notice_failed_to_save_issues: "No s'han pogut desar %s assumptes de {{count}} seleccionats: {{ids}}." + notice_failed_to_save_members: "No s'han pogut desar els membres: {{errors}}." notice_no_issue_selected: "No s'ha seleccionat cap assumpte. Activeu els assumptes que voleu editar." notice_account_pending: "S'ha creat el compte i ara està pendent de l'aprovació de l'administrador." notice_default_data_loaded: "S'ha carregat correctament la configuració predeterminada." notice_unable_delete_version: "No s'ha pogut suprimir la versió." + notice_unable_delete_time_entry: "No s'ha pogut suprimir l'entrada del registre de temps." + notice_issue_done_ratios_updated: "S'ha actualitzat el tant per cent dels assumptes." error_can_t_load_default_data: "No s'ha pogut carregar la configuració predeterminada: {{value}} " error_scm_not_found: "No s'ha trobat l'entrada o la revisió en el dipòsit." error_scm_command_failed: "S'ha produït un error en intentar accedir al dipòsit: {{value}}" error_scm_annotate: "L'entrada no existeix o no s'ha pogut anotar." error_issue_not_found_in_project: "No s'ha trobat l'assumpte o no pertany a aquest projecte" - + error_no_tracker_in_project: "Aquest projecte no té seguidor associat. Comproveu els paràmetres del projecte." + error_no_default_issue_status: "No s'ha definit cap estat d'assumpte predeterminat. Comproveu la configuració (aneu a «Administració -> Estats de l'assumpte»)." + error_can_not_delete_custom_field: "No s'ha pogut suprimir el camp personalitat" + error_can_not_delete_tracker: "Aquest seguidor conté assumptes i no es pot suprimir." + error_can_not_remove_role: "Aquest rol s'està utilitzant i no es pot suprimir." + error_can_not_reopen_issue_on_closed_version: "Un assumpte assignat a una versió tancada no es pot tornar a obrir" + error_can_not_archive_project: "Aquest projecte no es pot arxivar" + error_issue_done_ratios_not_updated: "No s'ha actualitza el tant per cent dels assumptes." + error_workflow_copy_source: "Seleccioneu un seguidor o rol font" + error_workflow_copy_target: "Seleccioneu seguidors i rols objectiu" + error_unable_delete_issue_status: "No s'ha pogut suprimir l'estat de l'assumpte" + error_unable_to_connect: "No s'ha pogut connectar ({{value}})" warning_attachments_not_saved: "No s'han pogut desar {{count}} fitxers." mail_subject_lost_password: "Contrasenya de {{value}}" @@ -173,6 +195,10 @@ ca: mail_body_account_activation_request: "S'ha registrat un usuari nou ({{value}}). El seu compte està pendent d'aprovació:" mail_subject_reminder: "{{count}} assumptes venceran els següents {{days}} dies" mail_body_reminder: "{{count}} assumptes que teniu assignades venceran els següents {{days}} dies:" + mail_subject_wiki_content_added: "S'ha afegit la pàgina wiki «{{page}}»" + mail_body_wiki_content_added: "En {{author}} ha afegit la pàgina wiki «{{page}}»." + mail_subject_wiki_content_updated: "S'ha actualitzat la pàgina wiki «{{page}}»" + mail_body_wiki_content_updated: "En {{author}} ha actualitzat la pàgina wiki «{{page}}»." gui_validation_error: 1 error gui_validation_error_plural: "{{count}} errors" @@ -212,6 +238,7 @@ ca: field_priority: Prioritat field_fixed_version: Versió objectiu field_user: Usuari + field_principal: Principal field_role: Rol field_homepage: Pàgina web field_is_public: Públic @@ -256,6 +283,7 @@ ca: field_redirect_existing_links: Redirigeix els enllaços existents field_estimated_hours: Temps previst field_column_names: Columnes + field_time_entries: "Registre de temps" field_time_zone: Zona horària field_searchable: Es pot cercar field_default_value: Valor predeterminat @@ -265,6 +293,9 @@ ca: field_watcher: Vigilància field_identity_url: URL OpenID field_content: Contingut + field_group_by: "Agrupa els resultats per" + field_sharing: Compartició + field_parent_issue: "Tasca pare" setting_app_title: "Títol de l'aplicació" setting_app_subtitle: "Subtítol de l'aplicació" @@ -300,20 +331,35 @@ ca: setting_activity_days_default: "Dies a mostrar l'activitat del projecte" setting_display_subprojects_issues: "Mostra els assumptes d'un subprojecte en el projecte pare per defecte" setting_enabled_scm: "Habilita l'SCM" + setting_mail_handler_body_delimiters: "Trunca els correus electrònics després d'una d'aquestes línies" setting_mail_handler_api_enabled: "Habilita el WS per correus electrònics d'entrada" setting_mail_handler_api_key: Clau API setting_sequential_project_identifiers: Genera identificadors de projecte seqüencials setting_gravatar_enabled: "Utilitza les icones d'usuari Gravatar" + setting_gravatar_default: "Imatge Gravatar predeterminada" setting_diff_max_lines_displayed: Número màxim de línies amb diferències mostrades setting_file_max_size_displayed: Mida màxima dels fitxers de text mostrats en línia setting_repository_log_display_limit: Número màxim de revisions que es mostren al registre de fitxers setting_openid: "Permet entrar i registrar-se amb l'OpenID" - + setting_password_min_length: "Longitud mínima de la contrasenya" + setting_new_project_user_role_id: "Aquest rol es dóna a un usuari no administrador per a crear projectes" + setting_default_projects_modules: "Mòduls activats per defecte en els projectes nous" + setting_issue_done_ratio: "Calcula tant per cent realitzat de l'assumpte amb" + setting_issue_done_ratio_issue_status: "Utilitza l'estat de l'assumpte" + setting_issue_done_ratio_issue_field: "Utilitza el camp de l'assumpte" + setting_start_of_week: "Inicia les setmanes en" + setting_rest_api_enabled: "Habilita el servei web REST" + setting_cache_formatted_text: Cache formatted text + + permission_add_project: "Crea projectes" + permission_add_subprojects: "Crea subprojectes" permission_edit_project: Edita el projecte permission_select_project_modules: Selecciona els mòduls del projecte permission_manage_members: Gestiona els membres + permission_manage_project_activities: "Gestiona les activitats del projecte" permission_manage_versions: Gestiona les versions permission_manage_categories: Gestiona les categories dels assumptes + permission_view_issues: "Visualitza els assumptes" permission_add_issues: Afegeix assumptes permission_edit_issues: Edita els assumptes permission_manage_issue_relations: Gestiona les relacions dels assumptes @@ -328,6 +374,7 @@ ca: permission_view_calendar: Visualitza el calendari permission_view_issue_watchers: Visualitza la llista de vigilàncies permission_add_issue_watchers: Afegeix vigilàncies + permission_delete_issue_watchers: Suprimeix els vigilants permission_log_time: Registra el temps invertit permission_view_time_entries: Visualitza el temps invertit permission_edit_time_entries: Edita els registres de temps @@ -357,6 +404,8 @@ ca: permission_edit_own_messages: Edita els missatges propis permission_delete_messages: Suprimeix els missatges permission_delete_own_messages: Suprimeix els missatges propis + permission_export_wiki_pages: "Exporta les pàgines wiki" + permission_manage_subtasks: "Gestiona subtasques" project_module_issue_tracking: "Seguidor d'assumptes" project_module_time_tracking: Seguidor de temps @@ -366,10 +415,13 @@ ca: project_module_wiki: Wiki project_module_repository: Dipòsit project_module_boards: Taulers + project_module_calendar: Calendari + project_module_gantt: Gantt label_user: Usuari label_user_plural: Usuaris label_user_new: Usuari nou + label_user_anonymous: Anònim label_project: Projecte label_project_new: Projecte nou label_project_plural: Projectes @@ -416,12 +468,13 @@ ca: label_information_plural: Informació label_please_login: Entreu label_register: Registre - label_login_with_open_id_option: o entra amb l'OpenID + label_login_with_open_id_option: "o entra amb l'OpenID" label_password_lost: Contrasenya perduda label_home: Inici label_my_page: La meva pàgina label_my_account: El meu compte label_my_projects: Els meus projectes + label_my_page_block: "Els meus blocs de pàgina" label_administration: Administració label_login: Entra label_logout: Surt @@ -441,6 +494,7 @@ ca: label_auth_source_new: "Mode d'autenticació nou" label_auth_source_plural: "Modes d'autenticació" label_subproject_plural: Subprojectes + label_subproject_new: "Subprojecte nou" label_and_its_subprojects: "{{value}} i els seus subprojectes" label_min_max_length: Longitud mín - max label_list: Llist @@ -475,8 +529,9 @@ ca: label_version: Versió label_version_new: Versió nova label_version_plural: Versions + label_close_versions: "Tanca les versions completades" label_confirmation: Confirmació - label_export_to: 'També disponible a:' + label_export_to: "També disponible a:" label_read: Llegeix... label_public_projects: Projectes públics label_open_issues: obert @@ -533,6 +588,8 @@ ca: label_not_equals: no és label_in_less_than: en menys de label_in_more_than: en més de + label_greater_or_equal: ">=" + label_less_or_equal: <= label_in: en label_today: avui label_all_time: tot el temps @@ -555,17 +612,21 @@ ca: label_browse: Navega label_modification: "{{count}} canvi" label_modification_plural: "{{count}} canvis" + label_branch: Branca + label_tag: Etiqueta label_revision: Revisió label_revision_plural: Revisions + label_revision_id: "Revisió {{value}}" label_associated_revisions: Revisions associades label_added: afegit label_modified: modificat - label_renamed: reanomenat label_copied: copiat + label_renamed: reanomenat label_deleted: suprimit label_latest_revision: Última revisió label_latest_revision_plural: Últimes revisions label_view_revisions: Visualitza les revisions + label_view_all_revisions: "Visualitza totes les revisions" label_max_size: Mida màxima label_sort_highest: Mou a la part superior label_sort_higher: Mou cap amunt @@ -591,6 +652,7 @@ ca: label_changes_details: Detalls de tots els canvis label_issue_tracking: "Seguiment d'assumptes" label_spent_time: Temps invertit + label_overall_spent_time: "Temps total invertit" label_f_hour: "{{value}} hora" label_f_hour_plural: "{{value}} hores" label_time_tracking: Temps de seguiment @@ -628,6 +690,8 @@ ca: label_board: Fòrum label_board_new: Fòrum nou label_board_plural: Fòrums + label_board_locked: Bloquejat + label_board_sticky: Sticky label_topic_plural: Temes label_message_plural: Missatges label_message_last: Últim missatge @@ -643,6 +707,8 @@ ca: label_language_based: "Basat en l'idioma de l'usuari" label_sort_by: "Ordena per {{value}}" label_send_test_email: Envia un correu electrònic de prova + label_feeds_access_key: "Clau d'accés del RSS" + label_missing_feeds_access_key: "Falta una clau d'accés del RSS" label_feeds_access_key_created_on: "Clau d'accés del RSS creada fa {{value}}" label_module_plural: Mòduls label_added_time_by: "Afegit per {{author}} fa {{age}}" @@ -688,6 +754,28 @@ ca: label_ascending: Ascendent label_descending: Descendent label_date_from_to: Des de {{start}} a {{end}} + label_wiki_content_added: "S'ha afegit la pàgina wiki" + label_wiki_content_updated: "S'ha actualitzat la pàgina wiki" + label_group: Grup + label_group_plural: Grups + label_group_new: Grup nou + label_time_entry_plural: Temps invertit + label_version_sharing_hierarchy: "Amb la jerarquia del projecte" + label_version_sharing_system: "Amb tots els projectes" + label_version_sharing_descendants: "Amb tots els subprojectes" + label_version_sharing_tree: "Amb l'arbre del projecte" + label_version_sharing_none: "Sense compartir" + label_update_issue_done_ratios: "Actualitza el tant per cent dels assumptes realitzats" + label_copy_source: Font + label_copy_target: Objectiu + label_copy_same_as_target: "El mateix que l'objectiu" + label_display_used_statuses_only: "Mostra només els estats que utilitza aquest seguidor" + label_api_access_key: "Clau d'accés a l'API" + label_missing_api_access_key: "Falta una clau d'accés de l'API" + label_api_access_key_created_on: "Clau d'accés de l'API creada fa {{value}}" + label_profile: Perfil + label_subtask_plural: Subtasques + label_project_copy_notifications: "Envia notificacions de correu electrònic durant la còpia del projecte" button_login: Entra button_submit: Tramet @@ -709,11 +797,12 @@ ca: button_list: Llista button_view: Visualitza button_move: Mou + button_move_and_follow: "Mou i segueix" button_back: Enrere button_cancel: Cancel·la button_activate: Activa button_sort: Ordena - button_log_time: "Hora d'entrada" + button_log_time: "Registre de temps" button_rollback: Torna a aquesta versió button_watch: Vigila button_unwatch: No vigilis @@ -724,15 +813,24 @@ ca: button_rename: Reanomena button_change_password: Canvia la contrasenya button_copy: Copia + button_copy_and_follow: "Copia i segueix" button_annotate: Anota button_update: Actualitza button_configure: Configura button_quote: Cita + button_duplicate: Duplica + button_show: Mostra status_active: actiu status_registered: informat status_locked: bloquejat + version_status_open: oberta + version_status_locked: bloquejada + version_status_closed: tancada + + field_active: Actiu + text_select_mail_notifications: "Seleccioneu les accions per les quals s'hauria d'enviar una notificació per correu electrònic." text_regexp_info: ex. ^[A-Z0-9]+$ text_min_max_length_info: 0 significa sense restricció @@ -740,6 +838,10 @@ ca: text_subprojects_destroy_warning: "També seran suprimits els seus subprojectes: {{value}}." text_workflow_edit: Seleccioneu un rol i un seguidor per a editar el flux de treball text_are_you_sure: Segur? + text_journal_changed: "{{label}} ha canviat de {{old}} a {{new}}" + text_journal_set_to: "{{label}} s'ha establert a {{value}}" + text_journal_deleted: "{{label}} s'ha suprimit ({{old}})" + text_journal_added: "S'ha afegit {{label}} {{value}}" text_tip_task_begin_day: "tasca que s'inicia aquest dia" text_tip_task_end_day: tasca que finalitza aquest dia text_tip_task_begin_end_day: "tasca que s'inicia i finalitza aquest dia" @@ -750,6 +852,7 @@ ca: text_tracker_no_workflow: "No s'ha definit cap flux de treball per a aquest seguidor" text_unallowed_characters: Caràcters no permesos text_comma_separated: Es permeten valors múltiples (separats per una coma). + text_line_separated: "Es permeten diversos valors (una línia per cada valor)." text_issues_ref_in_commit_messages: Referència i soluciona els assumptes en els missatges publicats text_issue_added: "L'assumpte {{id}} ha sigut informat per {{author}}." text_issue_updated: "L'assumpte {{id}} ha sigut actualitzat per {{author}}." @@ -770,14 +873,21 @@ ca: text_destroy_time_entries_question: "S'han informat {{hours}} hores en els assumptes que aneu a suprimir. Què voleu fer?" text_destroy_time_entries: Suprimeix les hores informades text_assign_time_entries_to_project: Assigna les hores informades al projecte - text_reassign_time_entries: 'Torna a assignar les hores informades a aquest assumpte:' + text_reassign_time_entries: "Torna a assignar les hores informades a aquest assumpte:" text_user_wrote: "{{value}} va escriure:" text_enumeration_destroy_question: "{{count}} objectes estan assignats a aquest valor." - text_enumeration_category_reassign_to: 'Torna a assignar-los a aquest valor:' + text_enumeration_category_reassign_to: "Torna a assignar-los a aquest valor:" text_email_delivery_not_configured: "El lliurament per correu electrònic no està configurat i les notificacions estan inhabilitades.\nConfigureu el servidor SMTP a config/email.yml i reinicieu l'aplicació per habilitar-lo." text_repository_usernames_mapping: "Seleccioneu l'assignació entre els usuaris del Redmine i cada nom d'usuari trobat al dipòsit.\nEls usuaris amb el mateix nom d'usuari o correu del Redmine i del dipòsit s'assignaran automàticament." text_diff_truncated: "... Aquestes diferències s'han trucat perquè excedeixen la mida màxima que es pot mostrar." - text_custom_field_possible_values_info: 'Una línia per a cada valor' + text_custom_field_possible_values_info: "Una línia per a cada valor" + text_wiki_page_destroy_question: "Aquesta pàgina té {{descendants}} pàgines fill i descendents. Què voleu fer?" + text_wiki_page_nullify_children: "Deixa les pàgines fill com a pàgines arrel" + text_wiki_page_destroy_children: "Suprimeix les pàgines fill i tots els seus descendents" + text_wiki_page_reassign_children: "Reasigna les pàgines fill a aquesta pàgina pare" + text_own_membership_delete_confirmation: "Esteu a punt de suprimir algun o tots els vostres permisos i potser no podreu editar més aquest projecte.\nSegur que voleu continuar?" + text_zoom_in: Redueix + text_zoom_out: Amplia default_role_manager: Gestor default_role_developer: Desenvolupador @@ -804,108 +914,5 @@ ca: enumeration_issue_priorities: Prioritat dels assumptes enumeration_doc_categories: Categories del document enumeration_activities: Activitats (seguidor de temps) - label_greater_or_equal: ">=" - label_less_or_equal: <= - text_wiki_page_destroy_question: This page has {{descendants}} child page(s) and descendant(s). What do you want to do? - text_wiki_page_reassign_children: Reassign child pages to this parent page - text_wiki_page_nullify_children: Keep child pages as root pages - text_wiki_page_destroy_children: Delete child pages and all their descendants - setting_password_min_length: Minimum password length - field_group_by: Group results by - mail_subject_wiki_content_updated: "'{{page}}' wiki page has been updated" - label_wiki_content_added: Wiki page added - mail_subject_wiki_content_added: "'{{page}}' wiki page has been added" - mail_body_wiki_content_added: The '{{page}}' wiki page has been added by {{author}}. - label_wiki_content_updated: Wiki page updated - mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. - permission_add_project: Create project - setting_new_project_user_role_id: Role given to a non-admin user who creates a project - label_view_all_revisions: View all revisions - label_tag: Tag - label_branch: Branch - error_no_tracker_in_project: No tracker is associated to this project. Please check the Project settings. - error_no_default_issue_status: No default issue status is defined. Please check your configuration (Go to "Administration -> Issue statuses"). - text_journal_changed: "{{label}} changed from {{old}} to {{new}}" - text_journal_set_to: "{{label}} set to {{value}}" - text_journal_deleted: "{{label}} deleted ({{old}})" - label_group_plural: Groups - label_group: Group - label_group_new: New group - label_time_entry_plural: Spent time - text_journal_added: "{{label}} {{value}} added" - field_active: Active - enumeration_system_activity: System Activity - permission_delete_issue_watchers: Delete watchers - version_status_closed: closed - version_status_locked: locked - version_status_open: open - error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened - label_user_anonymous: Anonymous - button_move_and_follow: Move and follow - setting_default_projects_modules: Default enabled modules for new projects - setting_gravatar_default: Default Gravatar image - field_sharing: Sharing - label_version_sharing_hierarchy: With project hierarchy - label_version_sharing_system: With all projects - label_version_sharing_descendants: With subprojects - label_version_sharing_tree: With project tree - label_version_sharing_none: Not shared - error_can_not_archive_project: This project can not be archived - button_duplicate: Duplicate - button_copy_and_follow: Copy and follow - label_copy_source: Source - setting_issue_done_ratio: Calculate the issue done ratio with - setting_issue_done_ratio_issue_status: Use the issue status - error_issue_done_ratios_not_updated: Issue done ratios not updated. - error_workflow_copy_target: Please select target tracker(s) and role(s) - setting_issue_done_ratio_issue_field: Use the issue field - label_copy_same_as_target: Same as target - label_copy_target: Target - notice_issue_done_ratios_updated: Issue done ratios updated. - error_workflow_copy_source: Please select a source tracker or role - label_update_issue_done_ratios: Update issue done ratios - setting_start_of_week: Start calendars on - permission_view_issues: View Issues - label_display_used_statuses_only: Only display statuses that are used by this tracker - label_revision_id: Revision {{value}} - label_api_access_key: API access key - label_api_access_key_created_on: API access key created {{value}} ago - label_feeds_access_key: RSS access key - notice_api_access_key_reseted: Your API access key was reset. - setting_rest_api_enabled: Enable REST web service - label_missing_api_access_key: Missing an API access key - label_missing_feeds_access_key: Missing a RSS access key - button_show: Show - text_line_separated: Multiple values allowed (one line for each value). - setting_mail_handler_body_delimiters: Truncate emails after one of these lines - permission_add_subprojects: Create subprojects - label_subproject_new: New subproject - 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. - Are you sure you want to continue? - label_close_versions: Close completed versions - label_board_sticky: Sticky - label_board_locked: Locked - permission_export_wiki_pages: Export wiki pages - setting_cache_formatted_text: Cache formatted text - permission_manage_project_activities: Manage project activities - error_unable_delete_issue_status: Unable to delete issue status - label_profile: Profile - permission_manage_subtasks: Manage subtasks - field_parent_issue: Parent task - label_subtask_plural: Subtasks - label_project_copy_notifications: Send email notifications during the project copy - error_can_not_delete_custom_field: Unable to delete custom field - error_unable_to_connect: Unable to connect ({{value}}) - error_can_not_remove_role: This role is in use and can not be deleted. - error_can_not_delete_tracker: This tracker contains issues and can't be deleted. - field_principal: Principal - label_my_page_block: My page block - notice_failed_to_save_members: "Failed to save member(s): {{errors}}." - text_zoom_out: Zoom out - text_zoom_in: Zoom in - notice_unable_delete_time_entry: Unable to delete time log entry. - label_overall_spent_time: Overall spent time - field_time_entries: Log time - project_module_gantt: Gantt - project_module_calendar: Calendar + enumeration_system_activity: Activitat del sistema + diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 1e1489940cf..6dfe989b52e 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -701,7 +701,7 @@ nl: setting_date_format: Datumformaat setting_default_language: Standaard taal setting_default_projects_public: Nieuwe projecten zijn standaard publiek - setting_diff_max_lines_displayed: Max number of diff lines displayed + setting_diff_max_lines_displayed: Max aantal diff regels weer te geven setting_display_subprojects_issues: Standaard issues van subproject tonen setting_emails_footer: E-mails footer setting_enabled_scm: SCM ingeschakeld @@ -709,7 +709,7 @@ nl: setting_gravatar_enabled: Gebruik Gravatar gebruikersiconen setting_host_name: Hostnaam setting_issue_list_default_columns: Standaardkolommen getoond op de lijst met issues - setting_issues_export_limit: Limiet export issues + setting_issues_export_limit: Max aantal te exporteren issues setting_login_required: Authenticatie vereist setting_mail_from: Afzender e-mail adres setting_mail_handler_api_enabled: Schakel WS in voor inkomende mail. @@ -727,7 +727,7 @@ nl: setting_welcome_text: Welkomsttekst setting_wiki_compression: Wikigeschiedenis comprimeren status_active: actief - status_locked: gelockt + status_locked: vergrendeld status_registered: geregistreerd text_are_you_sure: Weet u het zeker? text_assign_time_entries_to_project: Gerapporteerde uren toevoegen aan dit project @@ -753,7 +753,7 @@ nl: text_load_default_configuration: Laad de standaardconfiguratie text_min_max_length_info: 0 betekent geen restrictie text_no_configuration_data: "Rollen, trackers, issue statussen en workflows zijn nog niet geconfigureerd.\nHet is ten zeerste aangeraden om de standaard configuratie in te laden. U kunt deze aanpassen nadat deze is ingeladen." - text_plugin_assets_writable: Plugin assets directory writable + text_plugin_assets_writable: Plugin assets directory beschrijfbaar text_project_destroy_confirmation: Weet u zeker dat u dit project en alle gerelateerde gegevens wilt verwijderen? text_project_identifier_info: 'kleine letters (a-z), cijfers en liggende streepjes toegestaan.
    Eenmaal bewaard kan de identificatiecode niet meer worden gewijzigd.' text_reassign_time_entries: 'Gerapporteerde uren opnieuw toewijzen:' @@ -778,7 +778,7 @@ nl: text_custom_field_possible_values_info: 'Per lijn een waarde' label_display: Toon field_editable: Bewerkbaar - setting_repository_log_display_limit: Maximum hoeveelheid van revisies zichbaar + setting_repository_log_display_limit: Max aantal revisies zichbaar setting_file_max_size_displayed: Max grootte van tekst bestanden inline zichtbaar field_watcher: Watcher setting_openid: Sta OpenID login en registratie toe @@ -824,7 +824,7 @@ nl: version_status_closed: gesloten version_status_locked: vergrendeld version_status_open: open - error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened + error_can_not_reopen_issue_on_closed_version: Een issue toegewezen aan een gesloten versie kan niet heropend worden label_user_anonymous: Anoniem button_move_and_follow: Verplaats en volg setting_default_projects_modules: Standaard geactiveerde modules voor nieuwe projecten @@ -833,36 +833,36 @@ nl: label_version_sharing_hierarchy: Met project hiërarchie label_version_sharing_system: Met alle projecten label_version_sharing_descendants: Met subprojecten - label_version_sharing_tree: With project tree + label_version_sharing_tree: Met project boom label_version_sharing_none: Niet gedeeld error_can_not_archive_project: Dit project kan niet worden gearchiveerd button_duplicate: Dupliceer button_copy_and_follow: Kopiëer en volg label_copy_source: Bron - setting_issue_done_ratio: Bereken issue done ratio met + setting_issue_done_ratio: Bereken issue percentage voldaan met setting_issue_done_ratio_issue_status: Gebruik de issue status - error_issue_done_ratios_not_updated: Issue done ratios niet geupdate. + error_issue_done_ratios_not_updated: Issue percentage voldaan niet geupdate. error_workflow_copy_target: Selecteer tracker(s) en rol(len) setting_issue_done_ratio_issue_field: Gebruik het issue veld label_copy_same_as_target: Zelfde als doel label_copy_target: Doel - notice_issue_done_ratios_updated: Issue done ratios updated. + notice_issue_done_ratios_updated: Issue percentage voldaan geupdate. error_workflow_copy_source: Selecteer een bron tracker of rol - label_update_issue_done_ratios: Update issue done ratios + label_update_issue_done_ratios: Update issue percentage voldaan setting_start_of_week: Week begint op permission_view_issues: Bekijk Issues label_display_used_statuses_only: Laat alleen statussen zien die gebruikt worden door deze tracker - label_revision_id: Revision {{value}} + label_revision_id: Revisie {{value}} label_api_access_key: API access key label_api_access_key_created_on: API access key gemaakt {{value}} geleden label_feeds_access_key: RSS access key notice_api_access_key_reseted: Uw API access key was gereset. - setting_rest_api_enabled: Enable REST web service + setting_rest_api_enabled: Activeer REST web service label_missing_api_access_key: Geen API access key label_missing_feeds_access_key: Geen RSS access key button_show: Laat zien text_line_separated: Meerdere waarden toegestaan (elke regel is een waarde). - setting_mail_handler_body_delimiters: Truncate emails after one of these lines + setting_mail_handler_body_delimiters: Breek email verwerking af na een van deze regels permission_add_subprojects: Maak subprojecten label_subproject_new: Nieuw subproject text_own_membership_delete_confirmation: |- @@ -873,10 +873,10 @@ nl: label_board_locked: Vergrendeld permission_export_wiki_pages: Exporteer wiki pagina's setting_cache_formatted_text: Cache opgemaakte tekst - permission_manage_project_activities: Manage project activities + permission_manage_project_activities: Beheer project activiteiten error_unable_delete_issue_status: Verwijderen van issue status niet gelukt label_profile: Profiel - permission_manage_subtasks: Manage subtasks + permission_manage_subtasks: Beheer subtasks field_parent_issue: Parent task label_subtask_plural: Subtasks label_project_copy_notifications: Stuur email notificaties voor de project kopie @@ -891,6 +891,6 @@ nl: text_zoom_in: Zoom in notice_unable_delete_time_entry: Verwijderen niet mogelijk van tijd log invoer. label_overall_spent_time: Totaal bestede tijd - field_time_entries: Log time + field_time_entries: Log tijd project_module_gantt: Gantt - project_module_calendar: Calendar + project_module_calendar: Kalender diff --git a/public/javascripts/calendar/lang/calendar-ca.js b/public/javascripts/calendar/lang/calendar-ca.js index 303f21dfd10..9902680e5d6 100644 --- a/public/javascripts/calendar/lang/calendar-ca.js +++ b/public/javascripts/calendar/lang/calendar-ca.js @@ -45,7 +45,7 @@ Calendar._SDN = new Array // First day of the week. "0" means display Sunday first, "1" means display // Monday first, etc. -Calendar._FD = 0; +Calendar._FD = 1; // full month names Calendar._MN = new Array @@ -84,17 +84,17 @@ Calendar._TT["INFO"] = "Quant al calendari"; Calendar._TT["ABOUT"] = "Selector DHTML de data/hora\n" + "(c) dynarch.com 2002-2005 / Autor: Mihai Bazon\n" + // don't translate this this ;-) -"Per a aconseguir l'última versió visiteu: http://www.dynarch.com/projects/calendar/\n" + -"Distribuït sota la llicència GNU LGPL. Vegeu http://gnu.org/licenses/lgpl.html per a més detalls." + +"Per aconseguir l'última versió visiteu: http://www.dynarch.com/projects/calendar/\n" + +"Distribuït sota la llicència GNU LGPL. Vegeu http://gnu.org/licenses/lgpl.html per obtenir més detalls." + "\n\n" + "Selecció de la data:\n" + -"- Utilitzeu els botons \xab, \xbb per a seleccionar l'any\n" + -"- Utilitzeu els botons " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " per a selecciona el mes\n" + -"- Mantingueu premut el botó del ratolí sobre qualsevol d'aquests botons per a uns selecció més ràpida."; +"- Utilitzeu els botons \xab, \xbb per seleccionar l'any\n" + +"- Utilitzeu els botons " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " per seleccionar el mes\n" + +"- Mantingueu premut el botó del ratolí sobre qualsevol d'aquests botons per a una selecció més ràpida."; Calendar._TT["ABOUT_TIME"] = "\n\n" + "Selecció de l'hora:\n" + -"- Feu clic en qualsevol part de l'hora per a incrementar-la\n" + -"- o premeu majúscules per a disminuir-la\n" + +"- Feu clic en qualsevol part de l'hora per incrementar-la\n" + +"- o premeu majúscules per disminuir-la\n" + "- o feu clic i arrossegueu per a una selecció més ràpida."; Calendar._TT["PREV_YEAR"] = "Any anterior (mantenir per menú)"; @@ -102,8 +102,8 @@ Calendar._TT["PREV_MONTH"] = "Mes anterior (mantenir per menú)"; Calendar._TT["GO_TODAY"] = "Anar a avui"; Calendar._TT["NEXT_MONTH"] = "Mes següent (mantenir per menú)"; Calendar._TT["NEXT_YEAR"] = "Any següent (mantenir per menú)"; -Calendar._TT["SEL_DATE"] = "Sel·lecciona data"; -Calendar._TT["DRAG_TO_MOVE"] = "Arrossega per a moure"; +Calendar._TT["SEL_DATE"] = "Sel·lecciona la data"; +Calendar._TT["DRAG_TO_MOVE"] = "Arrossega per moure"; Calendar._TT["PART_TODAY"] = " (avui)"; // the following is to inform that "%s" is to be the first day of week @@ -117,7 +117,7 @@ Calendar._TT["WEEKEND"] = "0,6"; Calendar._TT["CLOSE"] = "Tanca"; Calendar._TT["TODAY"] = "Avui"; -Calendar._TT["TIME_PART"] = "(Majúscules-)Feu clic o arrossegueu per a canviar el valor"; +Calendar._TT["TIME_PART"] = "(Majúscules-)Feu clic o arrossegueu per canviar el valor"; // date formats Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%Y"; From cbe266079e9105c61bbda84c5cef89927548fcfe Mon Sep 17 00:00:00 2001 From: Azamat Hackimov Date: Sun, 5 Sep 2010 13:01:38 +0000 Subject: [PATCH 25/25] Added string "cant_link_an_issue_with_a_descendant" to translations missed in #443 Solves #6278 git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4061 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/locales/bg.yml | 1 + config/locales/bs.yml | 1 + config/locales/cs.yml | 1 + config/locales/da.yml | 1 + config/locales/el.yml | 1 + config/locales/en-GB.yml | 1 + config/locales/es.yml | 1 + config/locales/eu.yml | 1 + config/locales/fi.yml | 2 +- config/locales/gl.yml | 1 + config/locales/he.yml | 1 + config/locales/hr.yml | 1 + config/locales/hu.yml | 1 + config/locales/id.yml | 1 + config/locales/it.yml | 1 + config/locales/ja.yml | 1 + config/locales/ko.yml | 1 + config/locales/lt.yml | 3 ++- config/locales/lv.yml | 1 + config/locales/mn.yml | 1 + config/locales/nl.yml | 1 + config/locales/no.yml | 1 + config/locales/pl.yml | 1 + config/locales/pt-BR.yml | 1 + config/locales/pt.yml | 1 + config/locales/ro.yml | 1 + config/locales/ru.yml | 7 ++++--- config/locales/sk.yml | 1 + config/locales/sl.yml | 1 + config/locales/sv.yml | 1 + config/locales/th.yml | 1 + config/locales/tr.yml | 1 + config/locales/uk.yml | 1 + config/locales/vi.yml | 1 + config/locales/zh-TW.yml | 1 + config/locales/zh.yml | 1 + 36 files changed, 40 insertions(+), 5 deletions(-) diff --git a/config/locales/bg.yml b/config/locales/bg.yml index d4fd50c933f..f334633e274 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -116,6 +116,7 @@ bg: greater_than_start_date: "трябва да е след началната дата" not_same_project: "не е от същия проект" circular_dependency: "Тази релация ще доведе до безкрайна зависимост" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Изберете diff --git a/config/locales/bs.yml b/config/locales/bs.yml index 6d729b0ce8e..90ec9dea237 100644 --- a/config/locales/bs.yml +++ b/config/locales/bs.yml @@ -130,6 +130,7 @@ bs: greater_than_start_date: "mora biti veći nego početni datum" not_same_project: "ne pripada istom projektu" circular_dependency: "Ova relacija stvar cirkularnu zavisnost" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Molimo odaberite diff --git a/config/locales/cs.yml b/config/locales/cs.yml index f1abeff5b70..f2b11460517 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -116,6 +116,7 @@ cs: greater_than_start_date: "musí být větší než počáteční datum" not_same_project: "nepatří stejnému projektu" circular_dependency: "Tento vztah by vytvořil cyklickou závislost" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" # Updated by Josef Liška # CZ translation by Maxim Krušina | Massimo Filippi, s.r.o. | maxim@mxm.cz diff --git a/config/locales/da.yml b/config/locales/da.yml index 45b33d81084..4d30dc6f346 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -130,6 +130,7 @@ da: greater_than_start_date: "skal være senere end startdatoen" not_same_project: "hører ikke til samme projekt" circular_dependency: "Denne relation vil skabe et afhængighedsforhold" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" template: header: diff --git a/config/locales/el.yml b/config/locales/el.yml index d9e224e9f1b..e4487c59fe3 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -119,6 +119,7 @@ el: greater_than_start_date: "πρέπει να είναι αργότερα από την ημερομηνία έναρξης" not_same_project: "δεν ανήκει στο ίδιο έργο" circular_dependency: "Αυτή η σχέση θα δημιουργήσει κυκλικές εξαρτήσεις" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Παρακαλώ επιλέξτε diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index bc4cb08e82a..6a8faa74698 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -122,6 +122,7 @@ en-GB: greater_than_start_date: "must be greater than start date" not_same_project: "doesn't belong to the same project" circular_dependency: "This relation would create a circular dependency" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Please select diff --git a/config/locales/es.yml b/config/locales/es.yml index 4783db72145..4ffdaf3f680 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -132,6 +132,7 @@ es: greater_than_start_date: "debe ser posterior a la fecha de comienzo" not_same_project: "no pertenece al mismo proyecto" circular_dependency: "Esta relación podría crear una dependencia circular" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" # Append your own errors here or at the model/attributes scope. diff --git a/config/locales/eu.yml b/config/locales/eu.yml index 80fcc63d099..236c5bb7d08 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -121,6 +121,7 @@ eu: greater_than_start_date: "hasiera data baino handiagoa izan behar du" not_same_project: "ez dago proiektu berdinean" circular_dependency: "Erlazio honek mendekotasun zirkular bat sortuko luke" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Hautatu mesedez diff --git a/config/locales/fi.yml b/config/locales/fi.yml index 3bde5975bc7..9aeee5f6ee8 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -147,7 +147,7 @@ fi: greater_than_start_date: "tulee olla aloituspäivän jälkeinen" not_same_project: "ei kuulu samaan projektiin" circular_dependency: "Tämä suhde loisi kehän." - + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Valitse, ole hyvä diff --git a/config/locales/gl.yml b/config/locales/gl.yml index 7daebd07436..db64fabdcbf 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -150,6 +150,7 @@ gl: greater_than_start_date: "debe ser posterior á data de comezo" not_same_project: "non pertence ao mesmo proxecto" circular_dependency: "Esta relación podería crear unha dependencia circular" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Por favor seleccione diff --git a/config/locales/he.yml b/config/locales/he.yml index 59fa6888df1..50f31c29428 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -123,6 +123,7 @@ he: greater_than_start_date: "חייב להיות מאוחר יותר מתאריך ההתחלה" not_same_project: "לא שייך לאותו הפרויקט" circular_dependency: "הקשר הזה יצור תלות מעגלית" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: בחר בבקשה diff --git a/config/locales/hr.yml b/config/locales/hr.yml index 1c6d523c31d..5727a629ecd 100644 --- a/config/locales/hr.yml +++ b/config/locales/hr.yml @@ -117,6 +117,7 @@ hr: greater_than_start_date: "mora biti veci nego pocetni datum" not_same_project: "ne pripada istom projektu" circular_dependency: "Ovaj relacija stvara kružnu ovisnost" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Molimo odaberite diff --git a/config/locales/hu.yml b/config/locales/hu.yml index 974ddf76ca9..c895f4c964a 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -143,6 +143,7 @@ greater_than_start_date: "nagyobbnak kell lennie, mint az indítás dátuma" not_same_project: "nem azonos projekthez tartozik" circular_dependency: "Ez a kapcsolat egy körkörös függőséget eredményez" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Kérem válasszon diff --git a/config/locales/id.yml b/config/locales/id.yml index 345fba4548a..65140c2d0ba 100644 --- a/config/locales/id.yml +++ b/config/locales/id.yml @@ -119,6 +119,7 @@ id: greater_than_start_date: "harus lebih besar dari tanggal mulai" not_same_project: "tidak tergabung dalam proyek yang sama" circular_dependency: "kaitan ini akan menghasilkan circular dependency" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Silakan pilih diff --git a/config/locales/it.yml b/config/locales/it.yml index f5fb21fd234..34a7820d257 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -126,6 +126,7 @@ it: greater_than_start_date: "deve essere maggiore della data di partenza" not_same_project: "non appartiene allo stesso progetto" circular_dependency: "Questa relazione creerebbe una dipendenza circolare" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Scegli diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 50ccc872946..68c4d24aa2e 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -144,6 +144,7 @@ ja: greater_than_start_date: "を開始日より後にしてください" not_same_project: "同じプロジェクトに属していません" circular_dependency: "この関係では、循環依存になります" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: 選んでください diff --git a/config/locales/ko.yml b/config/locales/ko.yml index b30d7518fcd..0a5fa44e160 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -173,6 +173,7 @@ ko: greater_than_start_date: "는 시작날짜보다 커야 합니다" not_same_project: "는 같은 프로젝트에 속해 있지 않습니다" circular_dependency: "이 관계는 순환 의존관계를 만들 수 있습니다" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: 선택하세요 diff --git a/config/locales/lt.yml b/config/locales/lt.yml index f0c9551a318..9a3684e910b 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -143,7 +143,7 @@ lt: other: "Išsaugant objektą {{model}} rastos {{count}} klaidos" body: "Šiuose laukuose yra klaidų:" - pranešimus: + messages: inclusion: "nenumatyta reikšmė" exclusion: "užimtas" invalid: "neteisingas" @@ -179,6 +179,7 @@ lt: greater_than_start_date: "turi būti didesnė negu pradžios data" not_same_project: "nepriklauso tam pačiam projektui" circular_dependency: "Šis ryšys sukurtų ciklinę priklausomybę" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: prašom parinkti diff --git a/config/locales/lv.yml b/config/locales/lv.yml index 4b2421fe4f3..0ec9b4f4f80 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -113,6 +113,7 @@ lv: greater_than_start_date: "jābūt vēlākam par sākuma datumu" not_same_project: "nepieder pie tā paša projekta" circular_dependency: "Šī relācija radītu ciklisku atkarību" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Izvēlieties diff --git a/config/locales/mn.yml b/config/locales/mn.yml index 55d7cf168b4..73791bb74e3 100644 --- a/config/locales/mn.yml +++ b/config/locales/mn.yml @@ -117,6 +117,7 @@ mn: greater_than_start_date: "must be greater than start date" not_same_project: "нэг ижил төсөлд хамаарахгүй байна" circular_dependency: "Энэ харьцаа нь гинжин(рекурсив) харьцаа үүсгэх юм байна" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Сонгоно уу diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 6dfe989b52e..c55dadb47b4 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -116,6 +116,7 @@ nl: greater_than_start_date: "moet na de startdatum liggen" not_same_project: "hoort niet bij hetzelfde project" circular_dependency: "Deze relatie zou een circulaire afhankelijkheid tot gevolg hebben" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Selecteer diff --git a/config/locales/no.yml b/config/locales/no.yml index 8845d12b8e6..b1746fd4195 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -111,6 +111,7 @@ greater_than_start_date: "må være større enn startdato" not_same_project: "hører ikke til samme prosjekt" circular_dependency: "Denne relasjonen ville lagd en sirkulær avhengighet" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Vennligst velg diff --git a/config/locales/pl.yml b/config/locales/pl.yml index f36bb12772a..d48b3d93514 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -129,6 +129,7 @@ pl: greater_than_start_date: "musi być większe niż początkowa data" not_same_project: "nie należy do tego samego projektu" circular_dependency: "Ta relacja może wytworzyć kołową zależność" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" support: array: diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index d5b54e50929..c41e4e0dcd9 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -143,6 +143,7 @@ pt-BR: greater_than_start_date: "deve ser maior que a data inicial" not_same_project: "não pertence ao mesmo projeto" circular_dependency: "Esta relação geraria uma dependência circular" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Selecione diff --git a/config/locales/pt.yml b/config/locales/pt.yml index b2a2c08c8d0..3127f4044e9 100644 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -128,6 +128,7 @@ pt: greater_than_start_date: "deve ser maior que a data inicial" not_same_project: "não pertence ao mesmo projecto" circular_dependency: "Esta relação iria criar uma dependência circular" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" ## Translated by: Pedro Araújo actionview_instancetag_blank_option: Seleccione diff --git a/config/locales/ro.yml b/config/locales/ro.yml index fd6e2b94214..a0458932c42 100644 --- a/config/locales/ro.yml +++ b/config/locales/ro.yml @@ -110,6 +110,7 @@ ro: greater_than_start_date: "trebuie să fie după data de început" not_same_project: "trebuie să aparțină aceluiași proiect" circular_dependency: "Această relație ar crea o dependență circulară" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Selectați diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 913c81c81b6..586e2fbcc3a 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -192,11 +192,12 @@ ru: equal_to: "может иметь лишь значение, равное {{count}}" less_than: "может иметь значение меньшее чем {{count}}" less_than_or_equal_to: "может иметь значение меньшее или равное {{count}}" - odd: "может иметь лишь четное значение" - even: "может иметь лишь нечетное значение" + odd: "может иметь лишь нечетное значение" + even: "может иметь лишь четное значение" greater_than_start_date: "должна быть позднее даты начала" - not_same_project: "не относятся к одному проекту" + not_same_project: "не относится к одному проекту" circular_dependency: "Такая связь приведет к циклической зависимости" + cant_link_an_issue_with_a_descendant: "Задача не может быть связана со своей подзадачей" support: array: diff --git a/config/locales/sk.yml b/config/locales/sk.yml index 94facc047e1..52c57c79c43 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -112,6 +112,7 @@ sk: greater_than_start_date: "musí byť neskôr ako počiatočný dátum" not_same_project: "nepatrí rovnakému projektu" circular_dependency: "Tento vzťah by vytvoril cyklickú závislosť" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" # SK translation by Stanislav Pach | stano.pach@seznam.cz diff --git a/config/locales/sl.yml b/config/locales/sl.yml index 7307d0d9378..8ee68f15d2e 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -116,6 +116,7 @@ sl: greater_than_start_date: "mora biti kasnejši kot začeten datum" not_same_project: "ne pripada istemu projektu" circular_dependency: "Ta odnos bi povzročil krožno odvisnost" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Prosimo izberite diff --git a/config/locales/sv.yml b/config/locales/sv.yml index e02ee7867c9..657a9adcd6f 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -130,6 +130,7 @@ sv: greater_than_start_date: "måste vara senare än startdatumet" not_same_project: "tillhör inte samma projekt" circular_dependency: "Denna relation skulle skapa ett cirkulärt beroende" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" direction: ltr date: diff --git a/config/locales/th.yml b/config/locales/th.yml index 01d19c4d03b..67bf3c4cc05 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -116,6 +116,7 @@ th: greater_than_start_date: "ต้องมากกว่าวันเริ่ม" not_same_project: "ไม่ได้อยู่ในโครงการเดียวกัน" circular_dependency: "ความสัมพันธ์อ้างอิงเป็นวงกลม" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: กรุณาเลือก diff --git a/config/locales/tr.yml b/config/locales/tr.yml index f3f9788b1f0..e0f23078dc5 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -143,6 +143,7 @@ tr: greater_than_start_date: "başlangıç tarihinden büyük olmalı" not_same_project: "aynı projeye ait değil" circular_dependency: "Bu ilişki döngüsel bağımlılık meydana getirecektir" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" models: actionview_instancetag_blank_option: Lütfen Seçin diff --git a/config/locales/uk.yml b/config/locales/uk.yml index c5846db2aae..d0191618b6c 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -116,6 +116,7 @@ uk: greater_than_start_date: "повинна бути пізніша за дату початку" not_same_project: "не відносяться до одного проекту" circular_dependency: "Такий зв'язок приведе до циклічної залежності" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: Оберіть diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 5e964896dac..66fdbc115d1 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -139,6 +139,7 @@ vi: greater_than_start_date: "phải đi sau ngày bắt đầu" not_same_project: "không thuộc cùng dự án" circular_dependency: "quan hệ có thể gây ra lặp vô tận" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" direction: ltr date: diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 0216525b0cb..56d8c9b2918 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -177,6 +177,7 @@ greater_than_start_date: "必須在起始日期之後" not_same_project: "不屬於同一個專案" circular_dependency: "這個關聯會導致環狀相依" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" # You can define own errors for models or model attributes. # The values :model, :attribute and :value are always available for interpolation. diff --git a/config/locales/zh.yml b/config/locales/zh.yml index 0ffdcdb3b93..a05d96cae12 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -137,6 +137,7 @@ zh: greater_than_start_date: "必须在起始日期之后" not_same_project: "不属于同一个项目" circular_dependency: "此关联将导致循环依赖" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" actionview_instancetag_blank_option: 请选择
  • <%= link_to image_tag('toggle_check.png'), {}, :onclick => 'toggleIssuesSelection(Element.up(this, "form")); return false;', + <%= link_to image_tag('toggle_check.png'), {}, :onclick => 'toggleIssuesSelection(Element.up(this, "form")); return false;', :title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}" %>
    <%= check_box_tag("ids[]", issue.id, false, :id => nil) %><%= check_box_tag("ids[]", issue.id, false, :id => nil) %> <%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %>