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 << '
'
- else
- checkbox_id = "#{object_name}_#{cat.full_name.downcase.gsub(/\s+|\//, '_')}"
- result << content_tag('li', labelled_check_box(
- cat.full_name_without_leading(1, " → "),
- "#{object_name}[category_ids][]", cat.id,
- object.category_ids.include?(cat.id), :id => checkbox_id,
- :onchange => 'this.parentNode.className=(this.checked?"cat_checked":"")' ),
- :class => ( object.category_ids.include?(cat.id) ? 'cat_checked' : '' ) ) + "\n"
- end
- end
- 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