Commit 894e8962bae842f50f754f91e813a9f36d988fb2

Authored by Victor Costa
1 parent bd4954d3

New way to categorize contents

app/controllers/box_organizer_controller.rb
@@ -99,6 +99,17 @@ class BoxOrganizerController < ApplicationController @@ -99,6 +99,17 @@ class BoxOrganizerController < ApplicationController
99 end 99 end
100 end 100 end
101 101
  102 + def update_categories
  103 + @object = params[:id] ? boxes_holder.blocks.find(params[:id]) : nil
  104 + if params[:category_id]
  105 + @current_category = Category.find(params[:category_id])
  106 + @categories = @current_category.children
  107 + else
  108 + @categories = environment.top_level_categories
  109 + end
  110 + render :partial => 'shared/select_categories', :locals => {:object_name => 'block', :multiple => true}, :layout => false
  111 + end
  112 +
102 protected :boxes_editor? 113 protected :boxes_editor?
103 114
104 end 115 end
app/controllers/my_profile/cms_controller.rb
@@ -208,7 +208,7 @@ class CmsController < MyProfileController @@ -208,7 +208,7 @@ class CmsController < MyProfileController
208 @current_category = Category.find(params[:category_id]) 208 @current_category = Category.find(params[:category_id])
209 @categories = @current_category.children 209 @categories = @current_category.children
210 else 210 else
211 - @categories = environment.top_level_categories.select{|i| !i.children.empty?} 211 + @categories = environment.top_level_categories
212 end 212 end
213 render :partial => 'shared/select_categories', :locals => {:object_name => 'article', :multiple => true}, :layout => false 213 render :partial => 'shared/select_categories', :locals => {:object_name => 'article', :multiple => true}, :layout => false
214 end 214 end
app/controllers/my_profile/profile_editor_controller.rb
@@ -59,7 +59,7 @@ class ProfileEditorController < MyProfileController @@ -59,7 +59,7 @@ class ProfileEditorController < MyProfileController
59 @current_category = Category.find(params[:category_id]) 59 @current_category = Category.find(params[:category_id])
60 @categories = @current_category.children 60 @categories = @current_category.children
61 else 61 else
62 - @categories = environment.top_level_categories.select{|i| !i.children.empty?} 62 + @categories = environment.top_level_categories
63 end 63 end
64 render :partial => 'shared/select_categories', :locals => {:object_name => 'profile_data', :multiple => true}, :layout => false 64 render :partial => 'shared/select_categories', :locals => {:object_name => 'profile_data', :multiple => true}, :layout => false
65 end 65 end
app/helpers/application_helper.rb
@@ -619,49 +619,18 @@ module ApplicationHelper @@ -619,49 +619,18 @@ module ApplicationHelper
619 end 619 end
620 620
621 attr_reader :environment 621 attr_reader :environment
  622 +
622 def select_categories(object_name, title=nil, title_size=4) 623 def select_categories(object_name, title=nil, title_size=4)
623 return nil if environment.enabled?(:disable_categories) 624 return nil if environment.enabled?(:disable_categories)
624 if title.nil? 625 if title.nil?
625 title = _('Categories') 626 title = _('Categories')
626 end 627 end
627 628
628 - object = instance_variable_get("@#{object_name}")  
629 -  
630 - result = content_tag 'h'+title_size.to_s(), title  
631 - result << javascript_tag( 'function open_close_cat( link ) {  
632 - var div = link.parentNode.getElementsByTagName("div")[0];  
633 - var end = function(){  
634 - if ( div.style.display == "none" ) {  
635 - this.link.className="button icon-button icon-down"  
636 - } else {  
637 - this.link.className="button icon-button icon-up-red"  
638 - }  
639 - }  
640 - Effect.toggle( div, "slide", { link:link, div:div, afterFinish:end } )  
641 - }')  
642 - environment.top_level_categories.select{|i| !i.children.empty?}.each do |toplevel|  
643 - next unless object.accept_category?(toplevel)  
644 - # FIXME  
645 - ([toplevel] + toplevel.children_for_menu).each do |cat|  
646 - if cat.top_level?  
647 - result << '<div class="categorie_box">'.html_safe  
648 - result << icon_button( :down, _('open'), '#', :onclick => 'open_close_cat(this); return false' )  
649 - result << content_tag('h5', toplevel.name)  
650 - result << '<div style="display:none"><ul class="categories">'.html_safe  
651 - else  
652 - checkbox_id = "#{object_name}_#{cat.full_name.downcase.gsub(/\s+|\//, '_')}"  
653 - result << content_tag('li', labelled_check_box(  
654 - cat.full_name_without_leading(1, " &rarr; "),  
655 - "#{object_name}[category_ids][]", cat.id,  
656 - object.category_ids.include?(cat.id), :id => checkbox_id,  
657 - :onchange => 'this.parentNode.className=(this.checked?"cat_checked":"")' ),  
658 - :class => ( object.category_ids.include?(cat.id) ? 'cat_checked' : '' ) ) + "\n"  
659 - end  
660 - end  
661 - result << '</ul></div></div>'.html_safe  
662 - end 629 + @object = instance_variable_get("@#{object_name}")
  630 + @categories = environment.top_level_categories
663 631
664 - content_tag('div', result) 632 + @current_categories = environment.top_level_categories.select{|i| !i.children.empty?}
  633 + render :partial => 'shared/select_categories_top', :locals => {:object_name => object_name, :title => title, :title_size => title_size, :multiple => true, :categories_selected => @object.categories }, :layout => false
665 end 634 end
666 635
667 def theme_option(opt = nil) 636 def theme_option(opt = nil)
app/helpers/categories_helper.rb
@@ -48,4 +48,9 @@ module CategoriesHelper @@ -48,4 +48,9 @@ module CategoriesHelper
48 labelled_form_field(_('Type of category'), select_tag('type', options_for_select(TYPES, value))) 48 labelled_form_field(_('Type of category'), select_tag('type', options_for_select(TYPES, value)))
49 end 49 end
50 50
  51 + #FIXME make this test
  52 + def selected_category_link(cat)
  53 + link_to_function(cat.full_name, nil, :id => "remove-selected-category-#{cat.id}-button", :class => 'select-subcategory-link') {|page| page["selected-category-#{cat.id}"].remove}
  54 + end
  55 +
51 end 56 end
app/views/shared/_select_categories.rhtml
1 -<div id="category-ajax-selector"> 1 +<% extend CategoriesHelper %>
  2 +
  3 +<% categories_for_selection = @categories.select{|i| !@object.respond_to?(:accept_category?) || @object.accept_category?(i)} %>
  4 +
2 <% if !@current_category.nil? %> 5 <% if !@current_category.nil? %>
3 - <h3 class="box-title"><%= _('Current category:') %></h3> 6 + <div class="category-helper-label"><%= _('Selected:') %></div>
4 <%= hidden_field_tag "#{object_name}[#{object_name}_category_id]", @current_category.id unless multiple %> 7 <%= hidden_field_tag "#{object_name}[#{object_name}_category_id]", @current_category.id unless multiple %>
  8 + <%= hidden_field_tag "#{object_name}[category_ids][]", @current_category.id if multiple %>
  9 + <%= button_to_remote_without_text(:back, _('Back'),
  10 + { :update => "select-categories",
  11 + :url => { :action => 'update_categories', :id => @object },
  12 + :loaded => visual_effect(:highlight, "select-categories")
  13 + },
  14 + :id => 'cancel-category-button') %>
5 <% 15 <%
6 categories = [@current_category] 16 categories = [@current_category]
7 categories.push(@current_category) while @current_category = @current_category.parent 17 categories.push(@current_category) while @current_category = @current_category.parent
@@ -13,34 +23,28 @@ @@ -13,34 +23,28 @@
13 :loaded => visual_effect(:highlight, "select-categories"), 23 :loaded => visual_effect(:highlight, "select-categories"),
14 :class => 'select-current-category-link')}.join(' &rarr; ') 24 :class => 'select-current-category-link')}.join(' &rarr; ')
15 %> 25 %>
16 - <strong>  
17 - <%= button_to_function_without_text(:save, _('Save'), nil, :id => 'save-category-button') do |page|  
18 - page.insert_html :bottom, 'selected-categories', content_tag('li', categories.first.full_name + 26 + <%= button_to_function_without_text(:add, _('Add'), nil, :id => 'save-category-button') do |page|
  27 + page.insert_html :bottom, 'selected-categories', content_tag('span',
19 hidden_field_tag("#{object_name}[category_ids][]", categories.first.id) + 28 hidden_field_tag("#{object_name}[category_ids][]", categories.first.id) +
20 - 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}") 29 + selected_category_link(categories.first), :id => "selected-category-#{categories.first.id}")
21 end if multiple %> 30 end if multiple %>
22 - <%= button_to_remote_without_text(:cancel, _('Cancel'),  
23 - { :update => "select-categories",  
24 - :url => { :action => 'update_categories', :id => @object },  
25 - :loaded => visual_effect(:highlight, "select-categories")  
26 - },  
27 - :id => 'cancel-category-button') %>  
28 - </strong> 31 + <% unless categories_for_selection.empty? %>
  32 + <hr>
  33 + <div class="category-helper-label"><%= _('Click to select a subcategory') %></div>
  34 + <% end %>
29 <% else %> 35 <% else %>
30 - <h3 class="box-title"><%= _('Select a category:') %></h3> 36 + <div class="category-helper-label"><%= _('Click to select a category') %></div>
31 <% end %> 37 <% end %>
32 38
33 -<% if !@categories.empty? %>  
34 - <h3><%= _('Categories:') %></h3>  
35 - <% @categories.select{|i| !@object.respond_to?(:accept_category?) || @object.accept_category?(i)}.each do |category| %>  
36 - <%= link_to_remote category.name,  
37 - { :update => "select-categories",  
38 - :url => { :action => "update_categories", :category_id => category.id, :id => @object},  
39 - :loaded => visual_effect(:highlight, "select-categories")  
40 - },  
41 - :class => 'select-subcategory-link',  
42 - :id => "select-category-#{category.id}-link"  
43 - %>  
44 - <% end %> &nbsp; 39 +<div class="toplevel-categories">
  40 +<% categories_for_selection.each do |category| %>
  41 + <%= link_to_remote category.name,
  42 + { :update => "select-categories",
  43 + :url => { :action => "update_categories", :category_id => category.id, :id => @object},
  44 + :loaded => visual_effect(:highlight, "select-categories")
  45 + },
  46 + :class => 'select-subcategory-link',
  47 + :id => "select-category-#{category.id}-link"
  48 + %>
45 <% end %> 49 <% end %>
46 </div> 50 </div>
app/views/shared/_select_categories_top.rhtml 0 → 100644
@@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
  1 +<% categories_selected ||= nil %>
  2 +<% title ||= nil %>
  3 +
  4 +<% extend CategoriesHelper %>
  5 +
  6 +<%= content_tag "h#{title_size}", title, :class => "box-title" %>
  7 +
  8 +<%= hidden_field_tag "#{object_name}[category_ids][]", nil %>
  9 +
  10 +<div id="category-ajax-selector">
  11 +<div id="select-categories">
  12 + <%= render :partial => 'shared/select_categories', :locals => {:object_name => object_name, :multiple => true, :categories_selected => categories_selected }, :layout => false %>
  13 +</div>
  14 +
  15 +<% unless categories_selected.nil? %>
  16 +<hr>
  17 +<div id="selected-categories">
  18 + <span class="label"><%= _('Selected categories:') %></span>
  19 + <% categories_selected.each do |cat| %>
  20 + <span id="selected-category-<%= cat.id %>">
  21 + <%= hidden_field_tag("#{object_name}[category_ids][]", cat.id) %>
  22 + <%= selected_category_link(cat) %>
  23 + </span>
  24 + <% end %>
  25 +</div>
  26 +<div style="clear: both;"></div>
  27 +<% end %>
  28 +</div>
public/stylesheets/application.css
@@ -346,21 +346,25 @@ div.pending-tasks { @@ -346,21 +346,25 @@ div.pending-tasks {
346 margin-bottom: 1px; 346 margin-bottom: 1px;
347 } 347 }
348 /* * * category ajax selector * * */ 348 /* * * category ajax selector * * */
349 - 349 +#category-ajax-selector .category-helper-label {
  350 + font-size: 8pt; color: rgb(158, 158, 158);
  351 + padding: 5px 0px;
  352 +}
350 #category-ajax-selector { 353 #category-ajax-selector {
351 border: 1px solid #AAA; 354 border: 1px solid #AAA;
352 - background: #EEE;  
353 - padding: 15px 0px 15px 20px;  
354 - margin: 30px 0px 0px 0px; 355 + padding: 3px 10px 10px 10px;
  356 + margin: 0px 0px 0px 0px;
355 position: relative; 357 position: relative;
356 - font-size: 18px; 358 + font-size: 10px;
357 } 359 }
358 #category-ajax-selector a { 360 #category-ajax-selector a {
359 - font-size: 14px; 361 + font-size: 12px;
360 } 362 }
361 -#category-ajax-selector h3 {  
362 - margin: 10px 0px;  
363 - font-size: 14px; 363 +#selected-categories span {
  364 + float: left;
  365 +}
  366 +#selected-categories .label {
  367 + font-weight: bold;
364 } 368 }
365 #category-ajax-selector .box-title { 369 #category-ajax-selector .box-title {
366 position: absolute; 370 position: absolute;
@@ -376,25 +380,28 @@ div.pending-tasks { @@ -376,25 +380,28 @@ div.pending-tasks {
376 .msie6 #category-ajax-selector .box-title { 380 .msie6 #category-ajax-selector .box-title {
377 top: -29px; 381 top: -29px;
378 } 382 }
379 -#category-ajax-selector .select-subcategory-link { 383 +#category-ajax-selector .select-subcategory-link,
  384 +.select-subcategory-link {
380 border: 1px solid #BBB; 385 border: 1px solid #BBB;
381 padding: 1px 3px; 386 padding: 1px 3px;
382 margin: 0px 1px; 387 margin: 0px 1px;
383 text-decoration: none; 388 text-decoration: none;
384 white-space: nowrap; 389 white-space: nowrap;
385 font-size: 11px; 390 font-size: 11px;
  391 + line-height: 18px;
386 } 392 }
387 -#category-ajax-selector .select-subcategory-link:hover { 393 +#category-ajax-selector .select-subcategory-link:hover,
  394 +.select-subcategory-link:hover {
388 background-color: black; 395 background-color: black;
389 } 396 }
390 #category-ajax-selector .button { 397 #category-ajax-selector .button {
391 - display: block;  
392 - position: absolute;  
393 top: 4px; 398 top: 4px;
394 right: 2px; 399 right: 2px;
395 } 400 }
396 -#category-ajax-selector .icon-save { 401 +#category-ajax-selector .icon-add {
397 right: 25px; 402 right: 25px;
  403 + display: block;
  404 + position: absolute;
398 } 405 }
399 #profile-header, #profile-footer { 406 #profile-header, #profile-footer {
400 clear: both; 407 clear: both;
test/functional/cms_controller_test.rb
@@ -451,24 +451,23 @@ class CmsControllerTest &lt; ActionController::TestCase @@ -451,24 +451,23 @@ class CmsControllerTest &lt; ActionController::TestCase
451 assert_tag :tag => 'h3', :content => /max size #{UploadedFile.max_size.to_humanreadable}/ 451 assert_tag :tag => 'h3', :content => /max size #{UploadedFile.max_size.to_humanreadable}/
452 end 452 end
453 453
454 - should 'display link for selecting categories' do  
455 - # FIXME  
456 - assert true  
457 - #env = Environment.default  
458 - #top = env.categories.build(:display_in_menu => true, :name => 'Top-Level category'); top.save!  
459 - #c1 = env.categories.build(:display_in_menu => true, :name => "Test category 1", :parent_id => top.id); c1.save!  
460 - #c2 = env.categories.build(:display_in_menu => true, :name => "Test category 2", :parent_id => top.id); c2.save!  
461 - #c3 = env.categories.build(:display_in_menu => true, :name => "Test Category 3", :parent_id => top.id); c3.save!  
462 -  
463 - #article = Article.new(:name => 'test')  
464 - #article.profile = profile  
465 - #article.save!  
466 -  
467 - #get :edit, :profile => profile.identifier, :id => article.id  
468 -  
469 - #[c1,c2,c3].each do |item|  
470 - # assert_tag :tag => 'a', :attributes => { :id => "select-category-#{item.id}-link" }  
471 - #end 454 + should 'display link for selecting top categories' do
  455 + env = Environment.default
  456 + top = env.categories.build(:display_in_menu => true, :name => 'Top-Level category'); top.save!
  457 + top2 = env.categories.build(:display_in_menu => true, :name => 'Top-Level category 2'); top2.save!
  458 + c1 = env.categories.build(:display_in_menu => true, :name => "Test category 1", :parent_id => top.id); c1.save!
  459 + c2 = env.categories.build(:display_in_menu => true, :name => "Test category 2", :parent_id => top.id); c2.save!
  460 + c3 = env.categories.build(:display_in_menu => true, :name => "Test Category 3", :parent_id => top.id); c3.save!
  461 +
  462 + article = Article.new(:name => 'test')
  463 + article.profile = profile
  464 + article.save!
  465 +
  466 + get :edit, :profile => profile.identifier, :id => article.id
  467 +
  468 + [top, top2].each do |item|
  469 + assert_tag :tag => 'a', :attributes => { :id => "select-category-#{item.id}-link" }
  470 + end
472 end 471 end
473 472
474 should 'be able to associate articles with categories' do 473 should 'be able to associate articles with categories' do
test/functional/environment_design_controller_test.rb
@@ -366,4 +366,16 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase @@ -366,4 +366,16 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase
366 assert @controller.instance_variable_get('@side_block_types').include?(CustomBlock8) 366 assert @controller.instance_variable_get('@side_block_types').include?(CustomBlock8)
367 end 367 end
368 368
  369 + should 'update categories' do
  370 + env = Environment.default
  371 + login_as(create_admin_user(env))
  372 + top = env.categories.create!(:display_in_menu => true, :name => 'Top-Level category')
  373 + c1 = env.categories.create!(:display_in_menu => true, :name => "Test category 1", :parent_id => top.id)
  374 + c2 = env.categories.create!(:display_in_menu => true, :name => "Test category 2", :parent_id => top.id)
  375 + get :update_categories, :category_id => top.id
  376 + assert_template 'shared/_select_categories'
  377 + assert_equal top, assigns(:current_category)
  378 + assert_equal [c1, c2], assigns(:categories)
  379 + end
  380 +
369 end 381 end
test/functional/profile_editor_controller_test.rb
@@ -73,7 +73,8 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase @@ -73,7 +73,8 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase
73 get :edit, :profile => profile.identifier 73 get :edit, :profile => profile.identifier
74 assert_response :success 74 assert_response :success
75 assert_template 'edit' 75 assert_template 'edit'
76 - assert_tag :tag => 'input', :attributes => {:name => 'profile_data[category_ids][]', :value => cat2.id} 76 + assert_tag :tag => 'input', :attributes => {:name => 'profile_data[category_ids][]'}
  77 + assert_tag :tag => 'a', :attributes => { :class => 'select-subcategory-link', :id => "select-category-#{cat1.id}-link" }
77 end 78 end
78 79
79 should 'save categorization of profile' do 80 should 'save categorization of profile' do
@@ -236,7 +237,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase @@ -236,7 +237,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase
236 cat2 = Environment.default.categories.create!(:display_in_menu => true, :name => 'sub category', :parent => cat1) 237 cat2 = Environment.default.categories.create!(:display_in_menu => true, :name => 'sub category', :parent => cat1)
237 person = create_user('testuser').person 238 person = create_user('testuser').person
238 get :edit, :profile => 'testuser' 239 get :edit, :profile => 'testuser'
239 - assert_tag :tag => 'input', :attributes => { :type => 'checkbox', :name => 'profile_data[category_ids][]', :value => cat2.id} 240 + assert_tag :tag => 'a', :attributes => { :class => 'select-subcategory-link', :id => "select-category-#{cat1.id}-link" }
240 end 241 end
241 242
242 should 'render edit template' do 243 should 'render edit template' do