diff --git a/app/controllers/my_profile/cms_controller.rb b/app/controllers/my_profile/cms_controller.rb index 0e222d6..fee4241 100644 --- a/app/controllers/my_profile/cms_controller.rb +++ b/app/controllers/my_profile/cms_controller.rb @@ -115,6 +115,12 @@ class CmsController < MyProfileController render :action => params[:action], :layout => false end + def update_categories + @current_category = Category.find(params[:category_id]) + @categories = @current_category.children + render :partial => 'shared/select_categories', :locals => {:object_name => 'article'}, :layout => false + end + protected def redirect_back diff --git a/app/controllers/my_profile/profile_editor_controller.rb b/app/controllers/my_profile/profile_editor_controller.rb index 04b5530..191aab7 100644 --- a/app/controllers/my_profile/profile_editor_controller.rb +++ b/app/controllers/my_profile/profile_editor_controller.rb @@ -38,4 +38,10 @@ class ProfileEditorController < MyProfileController end end + def update_categories + @current_category = Category.find(params[:category_id]) + @categories = @current_category.children + render :partial => 'shared/select_categories', :locals => {:object_name => 'profile_data'}, :layout => false + end + end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index f9240a6..4d6e547 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -216,11 +216,29 @@ module ApplicationHelper end def button_to_function(type, label, js_code, html_options = {}) - html_options[:class] = "" unless html_options[:class] - html_options[:class] << " button #{type}" + html_options[:class] = "button with-text" unless html_options[:class] + html_options[:class] << " icon-#{type}" link_to_function(label, js_code, html_options) end + def button_to_function(type, label, js_code, html_options = {}, &block) + html_options[:class] = "button with-text" unless html_options[:class] + html_options[:class] << " icon-#{type}" + link_to_function(label, js_code, html_options, &block) + end + + def button_to_function_without_text(type, label, js_code, html_options = {}) + html_options[:class] = "" unless html_options[:class] + html_options[:class] << " button icon-#{type}" + link_to_function(content_tag('span', label), js_code, html_options) + end + + def button_to_function_without_text(type, label, js_code, html_options = {}, &block) + html_options[:class] = "" unless html_options[:class] + html_options[:class] << " button icon-#{type}" + link_to_function(content_tag('span', label), js_code, html_options, &block) + end + def icon(icon_name, html_options = {}) the_class = "button #{icon_name}" if html_options.has_key?(:class) @@ -420,40 +438,29 @@ module ApplicationHelper object = instance_variable_get("@#{object_name}") - result = content_tag 'h'+title_size.to_s(), title - result << javascript_tag( 'function open_close_cat( link ) { - var div = link.parentNode.getElementsByTagName("div")[0]; - var end = function(){ - if ( div.style.display == "none" ) { - this.link.className="button icon-button icon-down" - } else { - this.link.className="button icon-button icon-up-red" - } - } - Effect.toggle( div, "slide", { link:link, div:div, afterFinish:end } ) - }') - environment.top_level_categories.select{|i| !i.children.empty?}.each do |toplevel| - next unless object.accept_category?(toplevel) - # FIXME - ([toplevel] + toplevel.children_for_menu).each do |cat| - if cat.top_level? - result << '
' - result << icon_button( :down, _('open'), '#', :onclick => 'open_close_cat(this); return false' ) - result << content_tag('h5', toplevel.name) - result << '
' + result = content_tag("h#{title_size}", title) + + content_tag('ul', object.categories.map{|i| content_tag('li', i.full_name + hidden_field_tag("#{object_name}[category_ids][]", i.id) + button_to_function_without_text(:cancel, _('Remove'), nil, :id => "remove-selected-category-#{i.id}-button"){|page| page["selected-category-#{i.id}"].remove}, :id => "selected-category-#{i.id}")}, :id => 'selected-categories') + + content_tag('div', nil, :id => 'select-categories') + + button_to_function(:add, _('Add category'), nil, :id => 'add-category-button') do |page| + page['add-category-button'].hide + page['select-categories'].replace_html :partial => 'shared/select_categories', :locals => {:object_name => object_name} end + #environment.top_level_categories.select{|i| !i.children.empty?}.each do |toplevel| + # next unless object.accept_category?(toplevel) + # ([toplevel] + toplevel.children_for_menu).each do |cat| + # if cat.top_level? + # result << '
' + # result << icon_button( :down, _('open'), '#', :onclick => remote_function(:update => "categories_#{cat.id}", :url => { :action => :update_categories, :id => cat, :object_name => object_name, :object_id => object.id})) + # result << content_tag('h5', toplevel.name) + # result << "
" + # else + # ... + # end + # end + # result << '
' + #end + content_tag('div', result) end diff --git a/app/views/profile_editor/edit.rhtml b/app/views/profile_editor/edit.rhtml index 8bacceb..fdfe34d 100644 --- a/app/views/profile_editor/edit.rhtml +++ b/app/views/profile_editor/edit.rhtml @@ -38,7 +38,6 @@ <%= select_categories(:profile_data, _('Select the categories of your interest'), 1) %> - <% button_bar do %> <%= submit_button('save', _('Save'), :cancel => {:action => 'index'}) %> <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> diff --git a/app/views/shared/_select_categories.rhtml b/app/views/shared/_select_categories.rhtml new file mode 100644 index 0000000..e92f577 --- /dev/null +++ b/app/views/shared/_select_categories.rhtml @@ -0,0 +1,40 @@ +<% if !@current_category.nil? %> + <% + categories = [@current_category] + categories.push(@current_category) while @current_category = @current_category.parent + %> + <% if categories.size > 0 %> + <%= categories.compact.reverse.map{|i| + link_to_remote(i.name, + :update => "select-categories", + :url => { :action => 'update_categories', :category_id => i.id, :loaded => visual_effect(:highlight, "select-categories") }, + :class => 'select-current-category-link')}.join(' → ') + %> + + <%= button_to_function_without_text(:save, _('Save'), nil, :id => 'save-category-button') do |page| + page.replace_html 'select-categories', '' + page['add-category-button'].show + page.insert_html :bottom, 'selected-categories', content_tag('li', categories.first.full_name + + hidden_field_tag("#{object_name}[category_ids][]", categories.first.id) + + button_to_function_without_text(:cancel, _('Remove'), nil, :id => "remove-selected-category-#{categories.first.id}-button") {|page| page["selected-category-#{categories.first.id}"].remove}, :id => "selected-category-#{categories.first.id}") + end %> + <%= button_to_function_without_text(:cancel, _('Cancel'), nil, :id => 'cancel-category-button') do |page| + page.replace_html 'select-categories', '' + page['add-category-button'].show + end %> + + <% end %> +
+<% end %> +<% if @categories.nil? + @categories = environment.top_level_categories.select{|i| !i.children.empty?} +end %> +<% for category in @categories.each do %> + <%= link_to_remote category.name, { + :update => "select-categories", + :url => { :action => "update_categories", :category_id => category.id }, + :loaded => visual_effect(:highlight, "select-categories") }, + :class => 'select-subcategory-link' + %> +<% end %> + diff --git a/test/functional/cms_controller_test.rb b/test/functional/cms_controller_test.rb index 2e2cb13..d54a3cd 100644 --- a/test/functional/cms_controller_test.rb +++ b/test/functional/cms_controller_test.rb @@ -286,6 +286,19 @@ class CmsControllerTest < Test::Unit::TestCase assert_not_includes saved.categories, c2 assert_includes saved.categories, c3 end + + should 'not associate articles with category twice' do + env = Environment.default + c1 = env.categories.build(:name => "Test category 1"); c1.save! + c2 = env.categories.build(:name => "Test category 2"); c2.save! + c3 = env.categories.build(:name => "Test Category 3"); c3.save! + + # post is in c1, c3 and c3 + post :new, :type => TextileArticle.name, :profile => profile.identifier, :article => { :name => 'adding-categories-test', :category_ids => [ c1.id, c3.id, c3.id ] } + + saved = profile.articles.find_by_name('adding-categories-test') + assert_equal [c1, c3, c3], saved.categories + end should 'filter html from textile article name' do post :new, :type => 'TextileArticle', :profile => profile.identifier, :article => { :name => 'a test article', :body => 'the text of the article ...' } @@ -480,4 +493,15 @@ class CmsControllerTest < Test::Unit::TestCase assert_includes @controller.available_article_types, EnterpriseHomepage end + should 'update categories' do + env = Environment.default + top = env.categories.create!(:display_in_menu => true, :name => 'Top-Level category') + c1 = env.categories.create!(:display_in_menu => true, :name => "Test category 1", :parent_id => top.id) + c2 = env.categories.create!(:display_in_menu => true, :name => "Test category 2", :parent_id => top.id) + get :update_categories, :profile => profile.identifier, :category_id => top.id + assert_template 'shared/_select_categories' + assert_equal top, assigns(:current_category) + assert_equal [c1, c2], assigns(:categories) + end + end diff --git a/test/functional/profile_editor_controller_test.rb b/test/functional/profile_editor_controller_test.rb index 1448158..40ff945 100644 --- a/test/functional/profile_editor_controller_test.rb +++ b/test/functional/profile_editor_controller_test.rb @@ -12,7 +12,9 @@ class ProfileEditorControllerTest < Test::Unit::TestCase @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new login_as('ze') + @profile = Person['ze'] end + attr_reader :profile def test_local_files_reference assert_local_files_reference :get, :index, :profile => 'ze' @@ -432,5 +434,16 @@ class ProfileEditorControllerTest < Test::Unit::TestCase get :index, :profile => 'testuser' assert_tag :tag => 'a', :content => 'Register a new Enterprise' end + + should 'update categories' do + env = Environment.default + top = env.categories.create!(:display_in_menu => true, :name => 'Top-Level category') + c1 = env.categories.create!(:display_in_menu => true, :name => "Test category 1", :parent_id => top.id) + c2 = env.categories.create!(:display_in_menu => true, :name => "Test category 2", :parent_id => top.id) + get :update_categories, :profile => profile.identifier, :category_id => top.id + assert_template 'shared/_select_categories' + assert_equal top, assigns(:current_category) + assert_equal [c1, c2], assigns(:categories) + end end diff --git a/test/selenium/edit_article_categories.rsel b/test/selenium/edit_article_categories.rsel new file mode 100644 index 0000000..c0d2482 --- /dev/null +++ b/test/selenium/edit_article_categories.rsel @@ -0,0 +1,29 @@ +setup :fixtures => :all +include_partial 'login' + +Category.destroy_all +env = Environment.default +top = env.categories.create!(:display_in_menu => true, :name => 'Top-Level category') +c1 = env.categories.create!(:display_in_menu => true, :name => "Test category 1", :parent_id => top.id) +c2 = env.categories.create!(:display_in_menu => true, :name => "Test category 2", :parent_id => top.id) +c3 = env.categories.create!(:display_in_menu => true, :name => "Test Category 3", :parent_id => top.id) + +click_and_wait 'link=Manage Content' +click 'link=New article' +click_and_wait 'link=Text article with Textile markup language' +click 'link=Add category' + +assert_visible 'css=div[id=select-categories]' +assert_visible 'css=a[class=select-subcategory-link]' +assert_text 'css=a[class=select-subcategory-link]', 'Top-Level category' + +click 'link=Top-Level category' + +assert_visible 'css=a[class=select-subcategory-link]' +assert_text 'css=a[class=select-subcategory-link]', 'Test category 1' +click 'link=Test category 1' +assert_not_visible 'css=div[id=select-categories]' + +#assert_visible 'css=a[class=select-subcategory-link]' + +# vim: ft=ruby diff --git a/test/unit/article_test.rb b/test/unit/article_test.rb index 2de5d6f..0efc56a 100644 --- a/test/unit/article_test.rb +++ b/test/unit/article_test.rb @@ -349,7 +349,16 @@ class ArticleTest < Test::Unit::TestCase a = p.articles.create!(:name => 'test', :category_ids => [c1.id, c2.id]) assert_equivalent [c1, c2], a.categories(true) + end + should 'not add a category twice to article' do + c1 = Category.create!(:environment => Environment.default, :name => 'c1') + c2 = c1.children.create!(:environment => Environment.default, :name => 'c2') + c3 = c2.children.create!(:environment => Environment.default, :name => 'c3') + owner = create_user('testuser').person + art = owner.articles.create!(:name => 'ytest') + art.category_ids = [c2,c3,c3].map(&:id) + assert_equal [c2, c3], art.categories(true) end should 'not accept Product category as category' do -- libgit2 0.21.2