diff options
author | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2011-01-08 10:14:00 +0000 |
---|---|---|
committer | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2011-01-08 10:14:00 +0000 |
commit | 6e695a4d1a372110eb0f59d8bb091fd59ab2269b (patch) | |
tree | 50dd2cd0feb460fc04436f89e06fb6892b2ffce4 | |
parent | e5b7c94cb423c359d207430dbf86bde28a731532 (diff) | |
download | redmine-6e695a4d1a372110eb0f59d8bb091fd59ab2269b.tar.gz redmine-6e695a4d1a372110eb0f59d8bb091fd59ab2269b.zip |
Merged r4645 to r4651 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.1-stable@4660 e93f8b46-1217-0410-a6f0-8f06a7374b81
-rw-r--r-- | app/controllers/projects_controller.rb | 12 | ||||
-rw-r--r-- | app/models/project.rb | 5 | ||||
-rw-r--r-- | app/views/projects/_form.rhtml | 19 | ||||
-rw-r--r-- | app/views/projects/new.html.erb | 12 | ||||
-rw-r--r-- | app/views/projects/settings/_modules.rhtml | 2 | ||||
-rw-r--r-- | app/views/wiki/history.rhtml | 12 | ||||
-rw-r--r-- | public/javascripts/application.js | 18 | ||||
-rw-r--r-- | public/stylesheets/application.css | 2 | ||||
-rw-r--r-- | test/fixtures/roles.yml | 1 | ||||
-rw-r--r-- | test/functional/projects_controller_test.rb | 31 | ||||
-rw-r--r-- | test/integration/api_test/projects_test.rb | 47 | ||||
-rw-r--r-- | test/unit/project_nested_set_test.rb | 126 |
12 files changed, 223 insertions, 64 deletions
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 420801c01..459b54784 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -32,9 +32,6 @@ class ProjectsController < ApplicationController end end - # TODO: convert to PUT only - verify :method => [:post, :put], :only => :update, :render => {:nothing => true, :status => :method_not_allowed } - helper :sort include SortHelper helper :custom_fields @@ -71,13 +68,13 @@ class ProjectsController < ApplicationController @project = Project.new(params[:project]) end + verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed } def create @issue_custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position") @trackers = Tracker.all @project = Project.new @project.safe_attributes = params[:project] - @project.enabled_module_names = params[:enabled_modules] if params[:enabled_modules] if validate_parent_id && @project.save @project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id') # Add current user as a project member if he is not admin @@ -184,6 +181,8 @@ class ProjectsController < ApplicationController def edit end + # TODO: convert to PUT only + verify :method => [:post, :put], :only => :update, :render => {:nothing => true, :status => :method_not_allowed } def update @project.safe_attributes = params[:project] if validate_parent_id && @project.save @@ -205,9 +204,10 @@ class ProjectsController < ApplicationController end end end - + + verify :method => :post, :only => :modules, :render => {:nothing => true, :status => :method_not_allowed } def modules - @project.enabled_module_names = params[:enabled_modules] + @project.enabled_module_names = params[:enabled_module_names] flash[:notice] = l(:notice_successful_update) redirect_to :action => 'settings', :id => @project, :tab => 'modules' end diff --git a/app/models/project.rb b/app/models/project.rb index 891db8b8c..8315a48a5 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -66,7 +66,7 @@ class Project < ActiveRecord::Base :url => Proc.new {|o| {:controller => 'projects', :action => 'show', :id => o}}, :author => nil - attr_protected :status, :enabled_module_names + attr_protected :status validates_presence_of :name, :identifier validates_uniqueness_of :identifier @@ -533,6 +533,9 @@ class Project < ActiveRecord::Base 'tracker_ids', 'issue_custom_field_ids' + safe_attributes 'enabled_module_names', + :if => lambda {|project, user| project.new_record? || user.allowed_to?(:select_project_modules, project) } + # Returns an array of projects that are in this project's hierarchy # # Example: parents, children, siblings diff --git a/app/views/projects/_form.rhtml b/app/views/projects/_form.rhtml index e8045bf2c..9772a899c 100644 --- a/app/views/projects/_form.rhtml +++ b/app/views/projects/_form.rhtml @@ -23,8 +23,22 @@ <%= call_hook(:view_projects_form, :project => @project, :form => f) %> </div> +<% if @project.new_record? %> +<fieldset class="box"><legend><%= l(:label_module_plural) %></legend> +<% Redmine::AccessControl.available_project_modules.each do |m| %> + <label class="floating"> + <%= check_box_tag 'project[enabled_module_names][]', m, @project.module_enabled?(m), :id => "project_enabled_module_names_#{m}" %> + <%= l_or_humanize(m, :prefix => "project_module_") %> + </label> +<% end %> +<%= hidden_field_tag 'project[enabled_module_names][]', '' %> +<%= javascript_tag 'observeProjectModules()' %> +</fieldset> +<% end %> + +<% if @project.new_record? || @project.module_enabled?('issue_tracking') %> <% unless @trackers.empty? %> -<fieldset class="box"><legend><%=l(:label_tracker_plural)%></legend> +<fieldset class="box" id="project_trackers"><legend><%=l(:label_tracker_plural)%></legend> <% @trackers.each do |tracker| %> <label class="floating"> <%= check_box_tag 'project[tracker_ids][]', tracker.id, @project.trackers.include?(tracker) %> @@ -36,7 +50,7 @@ <% end %> <% unless @issue_custom_fields.empty? %> -<fieldset class="box"><legend><%=l(:label_custom_field_plural)%></legend> +<fieldset class="box" id="project_issue_custom_fields"><legend><%=l(:label_custom_field_plural)%></legend> <% @issue_custom_fields.each do |custom_field| %> <label class="floating"> <%= check_box_tag 'project[issue_custom_field_ids][]', custom_field.id, (@project.all_issue_custom_fields.include? custom_field), (custom_field.is_for_all? ? {:disabled => "disabled"} : {}) %> @@ -46,4 +60,5 @@ <%= hidden_field_tag 'project[issue_custom_field_ids][]', '' %> </fieldset> <% end %> +<% end %> <!--[eoform:project]--> diff --git a/app/views/projects/new.html.erb b/app/views/projects/new.html.erb index aad9c2c29..2642241bf 100644 --- a/app/views/projects/new.html.erb +++ b/app/views/projects/new.html.erb @@ -2,18 +2,6 @@ <% labelled_tabular_form_for :project, @project, :url => { :action => "create" } do |f| %> <%= render :partial => 'form', :locals => { :f => f } %> - -<fieldset class="box"><legend><%= l(:label_module_plural) %></legend> -<% Redmine::AccessControl.available_project_modules.each do |m| %> - <label class="floating"> - <%= check_box_tag 'enabled_modules[]', m, @project.module_enabled?(m) %> - <%= l_or_humanize(m, :prefix => "project_module_") %> - </label> -<% end %> -<%= hidden_field_tag 'enabled_modules[]', '' %> - -</fieldset> - <%= submit_tag l(:button_save) %> <%= javascript_tag "Form.Element.focus('project_name');" %> <% end %> diff --git a/app/views/projects/settings/_modules.rhtml b/app/views/projects/settings/_modules.rhtml index c123b4c9c..9e0f92caa 100644 --- a/app/views/projects/settings/_modules.rhtml +++ b/app/views/projects/settings/_modules.rhtml @@ -7,7 +7,7 @@ <legend><%= l(:text_select_project_modules) %></legend> <% Redmine::AccessControl.available_project_modules.each do |m| %> -<p><label><%= check_box_tag 'enabled_modules[]', m, @project.module_enabled?(m) -%> +<p><label><%= check_box_tag 'enabled_module_names[]', m, @project.module_enabled?(m) -%> <%= l_or_humanize(m, :prefix => "project_module_") %></label></p> <% end %> </fieldset> diff --git a/app/views/wiki/history.rhtml b/app/views/wiki/history.rhtml index eac24705b..23d45099a 100644 --- a/app/views/wiki/history.rhtml +++ b/app/views/wiki/history.rhtml @@ -4,7 +4,7 @@ <% form_tag({:action => "diff"}, :method => :get) do %> <%= hidden_field_tag('project_id', h(@project.to_param)) %> -<table class="list"> +<table class="list wiki-page-versions"> <thead><tr> <th>#</th> <th></th> @@ -18,14 +18,14 @@ <% show_diff = @versions.size > 1 %> <% line_num = 1 %> <% @versions.each do |ver| %> -<tr class="<%= cycle("odd", "even") %>"> +<tr class="wiki-page-version <%= cycle("odd", "even") %>"> <td class="id"><%= link_to ver.version, :action => 'show', :id => @page.title, :project_id => @page.project, :version => ver.version %></td> <td class="checkbox"><%= radio_button_tag('version', ver.version, (line_num==1), :id => "cb-#{line_num}", :onclick => "$('cbto-#{line_num+1}').checked=true;") if show_diff && (line_num < @versions.size) %></td> <td class="checkbox"><%= radio_button_tag('version_from', ver.version, (line_num==2), :id => "cbto-#{line_num}") if show_diff && (line_num > 1) %></td> - <td align="center"><%= format_time(ver.updated_on) %></td> - <td><%= link_to_user ver.author %></td> - <td><%=h ver.comments %></td> - <td align="center"><%= link_to l(:button_annotate), :action => 'annotate', :id => @page.title, :version => ver.version %></td> + <td class="updated_on"><%= format_time(ver.updated_on) %></td> + <td class="author"><%= link_to_user ver.author %></td> + <td class="comments"><%=h ver.comments %></td> + <td class="buttons"><%= link_to l(:button_annotate), :action => 'annotate', :id => @page.title, :version => ver.version %></td> </tr> <% line_num += 1 %> <% end %> diff --git a/public/javascripts/application.js b/public/javascripts/application.js index 486623459..1679d83d9 100644 --- a/public/javascripts/application.js +++ b/public/javascripts/application.js @@ -232,6 +232,24 @@ function observeRelatedIssueField(url) { }); } +function setVisible(id, visible) { + var el = $(id); + if (el) {if (visible) {el.show();} else {el.hide();}} +} + +function observeProjectModules() { + var f = function() { + /* Hides trackers and issues custom fields on the new project form when issue_tracking module is disabled */ + var c = ($('project_enabled_module_names_issue_tracking').checked == true); + setVisible('project_trackers', c); + setVisible('project_issue_custom_fields', c); + }; + + Event.observe(window, 'load', f); + Event.observe('project_enabled_module_names_issue_tracking', 'change', f); +} + + /* shows and hides ajax indicator */ Ajax.Responders.register({ onCreate: function(){ diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index feddfcb4d..a2918abe2 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -179,6 +179,8 @@ tr.user td { white-space: nowrap; } tr.user.locked, tr.user.registered { color: #aaa; } tr.user.locked a, tr.user.registered a { color: #aaa; } +tr.wiki-page-version td.updated_on, tr.wiki-page-version td.author {text-align:center;} + tr.time-entry { text-align: center; white-space: nowrap; } tr.time-entry td.subject, tr.time-entry td.comments { text-align: left; white-space: normal; } td.hours { text-align: right; font-weight: bold; padding-right: 0.5em; } diff --git a/test/fixtures/roles.yml b/test/fixtures/roles.yml index f63203ae3..979cc3211 100644 --- a/test/fixtures/roles.yml +++ b/test/fixtures/roles.yml @@ -7,6 +7,7 @@ roles_001: --- - :add_project - :edit_project + - :select_project_modules - :manage_members - :manage_versions - :manage_categories diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index aaf6e3085..fefb8d53b 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -154,7 +154,8 @@ class ProjectsControllerTest < ActionController::TestCase :custom_field_values => { '3' => 'Beta' }, :tracker_ids => ['1', '3'], # an issue custom field that is not for all project - :issue_custom_field_ids => ['9'] + :issue_custom_field_ids => ['9'], + :enabled_module_names => ['issue_tracking', 'news', 'repository'] } assert_redirected_to '/projects/blog/settings' @@ -167,6 +168,7 @@ class ProjectsControllerTest < ActionController::TestCase assert_nil project.parent assert_equal 'Beta', project.custom_value_for(3).value assert_equal [1, 3], project.trackers.map(&:id).sort + assert_equal ['issue_tracking', 'news', 'repository'], project.enabled_module_names.sort assert project.issue_custom_fields.include?(IssueCustomField.find(9)) end @@ -197,7 +199,9 @@ class ProjectsControllerTest < ActionController::TestCase :description => "weblog", :identifier => "blog", :is_public => 1, - :custom_field_values => { '3' => 'Beta' } + :custom_field_values => { '3' => 'Beta' }, + :tracker_ids => ['1', '3'], + :enabled_module_names => ['issue_tracking', 'news', 'repository'] } assert_redirected_to '/projects/blog/settings' @@ -206,6 +210,8 @@ class ProjectsControllerTest < ActionController::TestCase assert_kind_of Project, project assert_equal 'weblog', project.description assert_equal true, project.is_public? + assert_equal [1, 3], project.trackers.map(&:id).sort + assert_equal ['issue_tracking', 'news', 'repository'], project.enabled_module_names.sort # User should be added as a project member assert User.find(9).member_of?(project) @@ -282,6 +288,12 @@ class ProjectsControllerTest < ActionController::TestCase end end + def test_create_should_not_accept_get + @request.session[:user_id] = 1 + get :create + assert_response :method_not_allowed + end + def test_show_by_id get :show, :id => 1 assert_response :success @@ -359,6 +371,21 @@ class ProjectsControllerTest < ActionController::TestCase project = Project.find(1) assert_equal 'Test changed name', project.name end + + def test_modules + @request.session[:user_id] = 2 + Project.find(1).enabled_module_names = ['issue_tracking', 'news'] + + post :modules, :id => 1, :enabled_module_names => ['issue_tracking', 'repository', 'documents'] + assert_redirected_to '/projects/ecookbook/settings/modules' + assert_equal ['documents', 'issue_tracking', 'repository'], Project.find(1).enabled_module_names.sort + end + + def test_modules_should_not_allow_get + @request.session[:user_id] = 1 + get :modules, :id => 1 + assert_response :method_not_allowed + end def test_get_destroy @request.session[:user_id] = 1 # admin diff --git a/test/integration/api_test/projects_test.rb b/test/integration/api_test/projects_test.rb index e40d6584a..6258aae89 100644 --- a/test/integration/api_test/projects_test.rb +++ b/test/integration/api_test/projects_test.rb @@ -122,12 +122,35 @@ class ApiTest::ProjectsTest < ActionController::IntegrationTest project = Project.first(:order => 'id DESC') assert_equal 'API test', project.name assert_equal 'api-test', project.identifier - assert_equal ['issue_tracking', 'repository'], project.enabled_module_names + assert_equal ['issue_tracking', 'repository'], project.enabled_module_names.sort + assert_equal Tracker.all.size, project.trackers.size assert_response :created assert_equal 'application/xml', @response.content_type assert_tag 'project', :child => {:tag => 'id', :content => project.id.to_s} end + + should "accept enabled_module_names attribute" do + @parameters[:project].merge!({:enabled_module_names => ['issue_tracking', 'news', 'time_tracking']}) + + assert_difference('Project.count') do + post '/projects.xml', @parameters, :authorization => credentials('admin') + end + + project = Project.first(:order => 'id DESC') + assert_equal ['issue_tracking', 'news', 'time_tracking'], project.enabled_module_names.sort + end + + should "accept tracker_ids attribute" do + @parameters[:project].merge!({:tracker_ids => [1, 3]}) + + assert_difference('Project.count') do + post '/projects.xml', @parameters, :authorization => credentials('admin') + end + + project = Project.first(:order => 'id DESC') + assert_equal [1, 3], project.trackers.map(&:id).sort + end end end @@ -171,6 +194,28 @@ class ApiTest::ProjectsTest < ActionController::IntegrationTest project = Project.find(2) assert_equal 'API update', project.name end + + should "accept enabled_module_names attribute" do + @parameters[:project].merge!({:enabled_module_names => ['issue_tracking', 'news', 'time_tracking']}) + + assert_no_difference 'Project.count' do + put '/projects/2.xml', @parameters, :authorization => credentials('admin') + end + assert_response :ok + project = Project.find(2) + assert_equal ['issue_tracking', 'news', 'time_tracking'], project.enabled_module_names.sort + end + + should "accept tracker_ids attribute" do + @parameters[:project].merge!({:tracker_ids => [1, 3]}) + + assert_no_difference 'Project.count' do + put '/projects/2.xml', @parameters, :authorization => credentials('admin') + end + assert_response :ok + project = Project.find(2) + assert_equal [1, 3], project.trackers.map(&:id).sort + end end end diff --git a/test/unit/project_nested_set_test.rb b/test/unit/project_nested_set_test.rb index d6bc528a9..9e9666529 100644 --- a/test/unit/project_nested_set_test.rb +++ b/test/unit/project_nested_set_test.rb @@ -19,40 +19,100 @@ require File.expand_path('../../test_helper', __FILE__) class ProjectNestedSetTest < ActiveSupport::TestCase - def setup - Project.delete_all - end - - def test_destroy_root_and_chldren_should_not_mess_up_the_tree - a = Project.create!(:name => 'Project A', :identifier => 'projecta') - a1 = Project.create!(:name => 'Project A1', :identifier => 'projecta1') - a2 = Project.create!(:name => 'Project A2', :identifier => 'projecta2') - a1.set_parent!(a) - a2.set_parent!(a) - b = Project.create!(:name => 'Project B', :identifier => 'projectb') - b1 = Project.create!(:name => 'Project B1', :identifier => 'projectb1') - b1.set_parent!(b) - - a.reload - a1.reload - a2.reload - b.reload - b1.reload - - assert_equal [nil, 1, 6], [a.parent_id, a.lft, a.rgt] - assert_equal [a.id, 2, 3], [a1.parent_id, a1.lft, a1.rgt] - assert_equal [a.id, 4, 5], [a2.parent_id, a2.lft, a2.rgt] - assert_equal [nil, 7, 10], [b.parent_id, b.lft, b.rgt] - assert_equal [b.id, 8, 9], [b1.parent_id, b1.lft, b1.rgt] + context "nested set" do + setup do + Project.delete_all + + @a = Project.create!(:name => 'Project A', :identifier => 'projecta') + @a1 = Project.create!(:name => 'Project A1', :identifier => 'projecta1') + @a1.set_parent!(@a) + @a2 = Project.create!(:name => 'Project A2', :identifier => 'projecta2') + @a2.set_parent!(@a) + + @b = Project.create!(:name => 'Project B', :identifier => 'projectb') + @b1 = Project.create!(:name => 'Project B1', :identifier => 'projectb1') + @b1.set_parent!(@b) + @b11 = Project.create!(:name => 'Project B11', :identifier => 'projectb11') + @b11.set_parent!(@b1) + @b2 = Project.create!(:name => 'Project B2', :identifier => 'projectb2') + @b2.set_parent!(@b) + + @c = Project.create!(:name => 'Project C', :identifier => 'projectc') + @c1 = Project.create!(:name => 'Project C1', :identifier => 'projectc1') + @c1.set_parent!(@c) + + [@a, @a1, @a2, @b, @b1, @b11, @b2, @c, @c1].each(&:reload) + end - assert_difference 'Project.count', -3 do - a.destroy + context "#create" do + should "build valid tree" do + assert_nested_set_values({ + @a => [nil, 1, 6], + @a1 => [@a.id, 2, 3], + @a2 => [@a.id, 4, 5], + @b => [nil, 7, 14], + @b1 => [@b.id, 8, 11], + @b11 => [@b1.id,9, 10], + @b2 => [@b.id,12, 13], + @c => [nil, 15, 18], + @c1 => [@c.id,16, 17] + }) + end end - b.reload - b1.reload - - assert_equal [nil, 1, 4], [b.parent_id, b.lft, b.rgt] - assert_equal [b.id, 2, 3], [b1.parent_id, b1.lft, b1.rgt] + context "#set_parent!" do + should "keep valid tree" do + assert_no_difference 'Project.count' do + Project.find_by_name('Project B1').set_parent!(Project.find_by_name('Project A2')) + end + assert_nested_set_values({ + @a => [nil, 1, 10], + @a2 => [@a.id, 4, 9], + @b1 => [@a2.id,5, 8], + @b11 => [@b1.id,6, 7], + @b => [nil, 11, 14], + @c => [nil, 15, 18] + }) + end + end + + context "#destroy" do + context "a root with children" do + should "not mess up the tree" do + assert_difference 'Project.count', -4 do + Project.find_by_name('Project B').destroy + end + assert_nested_set_values({ + @a => [nil, 1, 6], + @a1 => [@a.id, 2, 3], + @a2 => [@a.id, 4, 5], + @c => [nil, 7, 10], + @c1 => [@c.id, 8, 9] + }) + end + end + + context "a child with children" do + should "not mess up the tree" do + assert_difference 'Project.count', -2 do + Project.find_by_name('Project B1').destroy + end + assert_nested_set_values({ + @a => [nil, 1, 6], + @b => [nil, 7, 10], + @b2 => [@b.id, 8, 9], + @c => [nil, 11, 14] + }) + end + end + end + end + + def assert_nested_set_values(h) + assert Project.valid? + h.each do |project, expected| + project.reload + assert_equal expected, [project.parent_id, project.lft, project.rgt], "Unexpected nested set values for #{project.name}" + end end -end
\ No newline at end of file +end |