Commit 0cddc2c31e8601261a77d81a1da6d4b0cb68d89b

Authored by Rodrigo Souto
2 parents fd59bb99 f8f5e910

Merge commit 'refs/merge-requests/337' of git://gitorious.org/noosfero/noosfero …

…into merge-requests/337

Conflicts:
	app/controllers/public/catalog_controller.rb
	app/helpers/application_helper.rb
	app/helpers/catalog_helper.rb
	app/views/catalog/index.rhtml
	public/stylesheets/application.css
app/controllers/my_profile/profile_design_controller.rb
... ... @@ -32,6 +32,7 @@ class ProfileDesignController < BoxOrganizerController
32 32 if profile.enterprise?
33 33 blocks << DisabledEnterpriseMessageBlock
34 34 blocks << HighlightsBlock
  35 + blocks << ProductCategoriesBlock
35 36 blocks << FeaturedProductsBlock
36 37 blocks << FansBlock
37 38 blocks += plugins.dispatch(:extra_blocks, :type => Enterprise)
... ...
app/controllers/public/catalog_controller.rb
1 1 class CatalogController < PublicController
2 2 needs_profile
3   - no_design_blocks
4 3  
5 4 before_filter :check_enterprise_and_environment
6 5  
... ...
app/helpers/application_helper.rb
... ... @@ -42,6 +42,8 @@ module ApplicationHelper
42 42  
43 43 include TokenHelper
44 44  
  45 + include CatalogHelper
  46 +
45 47 def locale
46 48 (@page && !@page.language.blank?) ? @page.language : FastGettext.locale
47 49 end
... ...
app/helpers/catalog_helper.rb
... ... @@ -9,7 +9,11 @@ module CatalogHelper
9 9 @categories = ProductCategory.on_level(params[:level]).order(:name)
10 10 end
11 11  
12   - @products = profile.products.from_category(@category).paginate(:order => 'available desc, highlighted desc, name asc', :per_page => 9, :page => options[:page])
  12 + @products = profile.products.from_category(@category).paginate(
  13 + :order => 'available desc, highlighted desc, name asc',
  14 + :per_page => @profile.products_per_catalog_page,
  15 + :page => options[:page]
  16 + )
13 17 end
14 18  
15 19 def breadcrumb(category)
... ... @@ -20,20 +24,24 @@ module CatalogHelper
20 24 content_tag('div', all_items.join(' &rarr; '), :id => 'breadcrumb')
21 25 end
22 26  
23   - def category_link(category, sub = false)
  27 + def category_link(category)
24 28 count = profile.products.from_category(category).count
25 29 name = truncate(category.name, :length => 22 - count.to_s.size)
26   - link_name = sub ? name : content_tag('strong', name)
27   - link = link_to(link_name, {:controller => :catalog, :action => 'index', :level => category.id}, :title => category.name)
28   - content_tag('li', "#{link} (#{count})") if count > 0
  30 + link = link_to(name, {:controller => 'catalog', :action => 'index', :level => category.id}, :title => category.name)
  31 + content_tag('div', "#{link} <span class=\"count\">#{count}</span>") if count > 0
29 32 end
30 33  
31   - def category_sub_links(category)
  34 + def category_with_sub_list(category)
  35 + content_tag 'li', "#{category_link(category)}\n#{sub_category_list(category)}"
  36 + end
  37 +
  38 + def sub_category_list(category)
32 39 sub_categories = []
33 40 category.children.order(:name).each do |sub_category|
34   - sub_categories << category_link(sub_category, true)
  41 + cat_link = category_link sub_category
  42 + sub_categories << content_tag('li', cat_link) unless cat_link.nil?
35 43 end
36   - content_tag('ul', sub_categories) if sub_categories.size > 1
  44 + content_tag('ul', sub_categories) if sub_categories.size > 0
37 45 end
38 46  
39 47 end
... ...
app/models/box.rb
... ... @@ -64,6 +64,7 @@ class Box &lt; ActiveRecord::Base
64 64 MyNetworkBlock,
65 65 PeopleBlock,
66 66 ProductsBlock,
  67 + ProductCategoriesBlock,
67 68 ProfileImageBlock,
68 69 ProfileInfoBlock,
69 70 ProfileSearchBlock,
... ...
app/models/enterprise.rb
... ... @@ -23,6 +23,7 @@ class Enterprise &lt; Organization
23 23 N_('Organization website'); N_('Historic and current context'); N_('Activities short description'); N_('City'); N_('State'); N_('Country'); N_('ZIP code')
24 24  
25 25 settings_items :organization_website, :historic_and_current_context, :activities_short_description, :zip_code, :city, :state, :country
  26 + settings_items :products_per_catalog_page, :type => :integer, :default => 6
26 27  
27 28 extend SetProfileRegionFromCityState::ClassMethods
28 29 set_profile_region_from_city_state
... ... @@ -131,8 +132,11 @@ class Enterprise &lt; Organization
131 132 ]
132 133 blocks = [
133 134 [MainBlock.new],
134   - [ProfileImageBlock.new, LinkListBlock.new(:links => links)],
135   - []
  135 + [ ProfileImageBlock.new,
  136 + LinkListBlock.new(:links => links),
  137 + ProductCategoriesBlock.new
  138 + ],
  139 + [LocationBlock.new]
136 140 ]
137 141 if environment.enabled?('products_for_enterprises')
138 142 blocks[2].unshift ProductsBlock.new
... ...
app/models/environment.rb
... ... @@ -692,7 +692,8 @@ class Environment &lt; ActiveRecord::Base
692 692 end
693 693  
694 694 def community_template
695   - Community.find_by_id settings[:community_template_id]
  695 + template = Community.find_by_id settings[:community_template_id]
  696 + template if template && template.is_template
696 697 end
697 698  
698 699 def community_template=(value)
... ... @@ -700,7 +701,8 @@ class Environment &lt; ActiveRecord::Base
700 701 end
701 702  
702 703 def person_template
703   - Person.find_by_id settings[:person_template_id]
  704 + template = Person.find_by_id settings[:person_template_id]
  705 + template if template && template.is_template
704 706 end
705 707  
706 708 def person_template=(value)
... ... @@ -708,7 +710,8 @@ class Environment &lt; ActiveRecord::Base
708 710 end
709 711  
710 712 def enterprise_template
711   - Enterprise.find_by_id settings[:enterprise_template_id]
  713 + template = Enterprise.find_by_id settings[:enterprise_template_id]
  714 + template if template && template.is_template
712 715 end
713 716  
714 717 def enterprise_template=(value)
... ... @@ -716,7 +719,8 @@ class Environment &lt; ActiveRecord::Base
716 719 end
717 720  
718 721 def inactive_enterprise_template
719   - Enterprise.find_by_id settings[:inactive_enterprise_template_id]
  722 + template = Enterprise.find_by_id settings[:inactive_enterprise_template_id]
  723 + template if template && template.is_template
720 724 end
721 725  
722 726 def inactive_enterprise_template=(value)
... ...
app/models/product_categories_block.rb 0 → 100644
... ... @@ -0,0 +1,36 @@
  1 +class ProductCategoriesBlock < Block
  2 +
  3 + def self.description
  4 + _('Product category menu')
  5 + end
  6 +
  7 + # the title of the block. Probably will be overriden in subclasses.
  8 + def default_title
  9 + _('Catalog')
  10 + end
  11 +
  12 + def help
  13 + _('Helps to filter the products catalog.')
  14 + end
  15 +
  16 + def content(args={})
  17 + profile = owner
  18 + lambda do
  19 + if @categories.nil? or @categories.length == 0
  20 + categories = ProductCategory.on_level().order(:name)
  21 + if @categories and @categories.length == 0
  22 + notice = _('There are no sub-categories for %s') % @category.name
  23 + end
  24 + else
  25 + categories = @categories
  26 + end
  27 + render :file => 'blocks/product_categories',
  28 + :locals => {
  29 + :profile => profile,
  30 + :categories => categories,
  31 + :notice => notice
  32 + }
  33 + end
  34 + end
  35 +
  36 +end
... ...
app/views/blocks/product_categories.html.erb 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +<%= link_to _('Catalog start'), profile.catalog_url, :class=>'catalog-home-link' %>
  2 +<ul class="catalog-categories-list">
  3 + <% categories.each do |category| %>
  4 + <%= category_with_sub_list(category) %>
  5 + <% end %>
  6 +</ul>
  7 +<% if notice %>
  8 + <div class="catalog-categories-notice"><%= notice %></div>
  9 +<% end %>
... ...
app/views/catalog/index.rhtml
1 1 <% extra_content = [] %>
2 2 <% extra_content_list = [] %>
3 3  
4   -<h1><%= _('Products/Services') %></h1>
5   -
6   -<% if @categories %>
7   - <%= breadcrumb(@category) if params[:level] %>
8   -
9   - <div class='l-sidebar-left-bar'>
10   - <ul>
11   - <%= content_tag('li', link_to(_('Homepage'), profile.url), :class => 'catalog-categories-link') %>
12   - <%= content_tag('li', link_to(_('Catalog start'), profile.catalog_url), :class => 'catalog-categories-link') %>
13   - <% if @categories.present? %>
14   - <% @categories.each do |category| %>
15   - <%= category_link(category) %>
16   - <%= category_sub_links(category) %>
17   - <% end %>
18   - <% elsif @category.present? %>
19   - <%= content_tag('li', _('There are no sub-categories for %s') % @category.name, :id => 'catalog-categories-notice') %>
20   - <% else %>
21   - <%= content_tag('li', _('There are no categories available.'), :id => 'catalog-categories-notice') %>
22   - <% end %>
23   - </ul>
  4 +<div id="product-catalog">
  5 +<% if !user.nil? && ( user.is_admin?(profile.environment) || user.is_admin?(profile) ) %>
  6 + <div class="product-catalog-ctrl">
  7 + <%= button :product, _('Manage Products/Services'), :controller => 'manage_products' %>
24 8 </div>
25 9 <% end %>
26 10  
27   -<ul id="product-list" class="<%="l-sidebar-left-content" if @categories %>">
  11 +<h1><%= _('Products/Services') %></h1>
  12 +
  13 +<%= breadcrumb(@category) if params[:level] %>
  14 +
  15 +<ul id="product-list">
28 16 <% @products.each do |product| %>
29 17 <% extra_content = @plugins.dispatch(:catalog_item_extras, product).collect { |content| instance_eval(&content) } %>
30 18 <% extra_content_list = @plugins.dispatch(:catalog_list_item_extras, product).collect { |content| instance_eval(&content) } %>
... ... @@ -132,10 +120,11 @@
132 120 </ul>
133 121 </li>
134 122 <% end %>
135   -</ul>
  123 +</ul><!-- end id="product-list" -->
136 124  
137 125 <%= pagination_links @products, :params => {:controller => :catalog, :action => :index, :profile => profile.identifier} %>
138 126  
139 127 <%= add_zoom_to_images %>
140 128  
141 129 <br style="clear:both"/>
  130 +</div><!-- end id="product-catalog" -->
... ...
app/views/profile_editor/_organization.rhtml
... ... @@ -65,3 +65,7 @@
65 65 <%= labelled_check_box(_('Enable "contact us"'), 'profile_data[enable_contact_us]', "1", @profile.enable_contact_us) if @profile.enterprise? %>
66 66  
67 67 <%= render :partial => 'moderation', :locals => { :profile => @profile } %>
  68 +
  69 +<h2><%=_('Product/Service catalog')%></h2>
  70 +
  71 +<%= f.text_field(:products_per_catalog_page, :size=>3) %>
... ...
db/migrate/20130626152300_add_product_categories_block_to_enterprises.rb 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +class AddProductCategoriesBlockToEnterprises < ActiveRecord::Migration
  2 + def self.up
  3 + Enterprise.find_each do |enterprise|
  4 + enterprise.boxes << Box.new while enterprise.boxes.length < 2
  5 + enterprise.boxes[1].blocks << ProductCategoriesBlock.new
  6 + end
  7 + end
  8 +
  9 + def self.down
  10 + Enterprise.find_each do |enterprise|
  11 + enterprise.boxes.each do |box|
  12 + box.blocks.each do |block|
  13 + block.destroy if block.class == ProductCategoriesBlock
  14 + end
  15 + end
  16 + end
  17 + end
  18 +end
... ...
public/designs/themes/base/style.css
... ... @@ -729,6 +729,110 @@ div#notice {
729 729 filter:alpha(opacity=50);
730 730 }
731 731  
  732 +
  733 +/********************* Product Categories Block **********************/
  734 +
  735 +.product-categories-block .catalog-home-link {
  736 + display: block;
  737 + background: rgba(0,0,0,0.08);
  738 + font-weight: bold;
  739 + text-align: center;
  740 + border-radius: 5px;
  741 + padding: 0px;
  742 + line-height: 200%;
  743 + text-decoration: none;
  744 + color: #000;
  745 +}
  746 +.product-categories-block .catalog-home-link:hover {
  747 + background: rgba(0,0,0,0.6);
  748 + color: #FFF;
  749 + text-decoration: none;
  750 +}
  751 +
  752 +.product-categories-block .catalog-categories-list {
  753 + margin-top: 0.5em;
  754 +}
  755 +
  756 +.product-categories-block ul {
  757 + list-style-type: none;
  758 + margin: 0px;
  759 + padding: 0px;
  760 + border-radius: 5px;
  761 + color: rgba(0,0,0,0.4);
  762 +}
  763 +
  764 +.product-categories-block li {
  765 + margin: 0;
  766 + padding: 0;
  767 + white-space: nowrap;
  768 +}
  769 +
  770 +.product-categories-block li li div {
  771 + padding: 0 0 0 1.5em;
  772 +}
  773 +
  774 +.product-categories-block .catalog-categories-list a {
  775 + text-decoration: none;
  776 + font-size: 120%;
  777 + line-height: 150%;
  778 + color: #333;
  779 + overflow: hidden;
  780 + text-overflow: ellipsis;
  781 + display: inline-block;
  782 + padding: 0 0.3em 0 0.5em;
  783 + border-radius: 5px;
  784 + max-width: 80%;
  785 + vertical-align: middle;
  786 +}
  787 +.product-categories-block .catalog-categories-list ul a {
  788 + text-decoration: none;
  789 + font-size: 110%;
  790 + line-height: 163.6%;
  791 +}
  792 +.product-categories-block .catalog-categories-list div:hover a:hover {
  793 + background: rgba(0,0,0,0.6);
  794 + color: #FFF;
  795 + text-decoration: none;
  796 +}
  797 +
  798 +.product-categories-block .catalog-categories-list div:hover a,
  799 +.product-categories-block .catalog-categories-list div:hover .count {
  800 + background: rgba(0,0,0,0.08);
  801 +}
  802 +
  803 +.block.product-categories-block .catalog-categories-list a {
  804 + font-weight: bold;
  805 +}
  806 +
  807 +.block.product-categories-block .catalog-categories-list ul a {
  808 + font-weight: normal;
  809 +}
  810 +
  811 +.product-categories-block a:hover {
  812 + text-decoration: underline;
  813 +}
  814 +
  815 +.product-categories-block .count {
  816 + display: inline-block;
  817 + vertical-align: middle;
  818 + margin-left: -0.2em;
  819 + padding: 0 0.2em;
  820 + line-height: 180%;
  821 + border-radius: 5px;
  822 +}
  823 +
  824 +.block.product-categories-block .count:before {
  825 + content: "(";
  826 +}
  827 +.block.product-categories-block .count:after {
  828 + content: ")";
  829 +}
  830 +
  831 +.catalog-categories-notice {
  832 + color: rgba(0,0,0,0.3);
  833 + padding: 0.5em 1em;
  834 +}
  835 +
732 836 /********************* Environment Statistics ************************/
733 837  
734 838 #content .environment-statistics-block ul {
... ...
public/stylesheets/application.css
... ... @@ -2645,7 +2645,17 @@ div#activation_enterprise label, div#activation_enterprise input, div#activation
2645 2645 /* ==> @import url('products.css'); <== */
2646 2646 /* * * Products catalog * * * * * * * * * * * * */
2647 2647  
  2648 +#product-catalog {
  2649 + text-align: center;
  2650 +}
  2651 +
  2652 +.product-catalog-ctrl {
  2653 + float: right;
  2654 +}
  2655 +
2648 2656 #product-list {
  2657 + display: inline-block;
  2658 + text-align: left;
2649 2659 line-height: 20px;
2650 2660 margin: 0px;
2651 2661 padding: 0px;
... ... @@ -2657,11 +2667,11 @@ div#activation_enterprise label, div#activation_enterprise input, div#activation
2657 2667 list-style: none;
2658 2668 }
2659 2669 #product-list li.product {
  2670 + display: inline-block;
2660 2671 width: 200px;
2661 2672 min-height: 280px;
2662   - padding: 10px 30px 10px 0;
  2673 + padding: 10px 15px;
2663 2674 margin-bottom: 10px;
2664   - display: inline-block;
2665 2675 vertical-align: top;
2666 2676 }
2667 2677 #product-list .expand-box:hover {
... ... @@ -2871,67 +2881,13 @@ div#activation_enterprise label, div#activation_enterprise input, div#activation
2871 2881 margin-top: -15px;
2872 2882 }
2873 2883  
2874   -.l-sidebar-left-bar ul,
2875   -.l-sidebar-right-bar ul {
2876   - list-style-type: none;
2877   - margin-left: 0;
2878   - padding: 1em 1em 0.5em 1em;
2879   -}
2880   -
2881   -.l-sidebar-left-bar ul ul,
2882   -.l-sidebar-right-bar ul ul {
2883   - padding-top: 0;
2884   -}
2885   -
2886   -.l-sidebar-left-bar ul{
2887   - background-color: #eeeeec;
2888   - border-radius: 5px;
2889   -}
2890   -
2891   -.l-sidebar-left-bar a,
2892   -.l-sidebar-right-bar a {
2893   - text-decoration: none;
2894   -}
2895   -
2896   -.l-sidebar-left-bar a:hover,
2897   -.l-sidebar-right-bar a:hover {
2898   - text-decoration: underline;
2899   -}
2900   -
2901   -.l-sidebar-left-bar li,
2902   -.l-sidebar-right-bar li {
2903   - margin: 0;
2904   - padding: 0;
2905   -}
2906   -
2907   -#catalog-categories-notice {
2908   - color: #555753;
2909   - padding-bottom: 0.5em;
2910   -}
2911   -
2912   -.l-sidebar-left-bar .catalog-categories-link {
2913   - background-color: #d3d7cf;
2914   - font-weight: bold;
2915   - height: 28px;
2916   - text-align: center;
2917   - border-radius: 5px;
2918   - margin-bottom: 10px;
2919   -}
2920   -
2921   -
2922   -.l-sidebar-left-bar .catalog-categories-link:hover {
2923   - background-color: #babdb6;
  2884 +#product-list .highlighted img.star {
  2885 + position: absolute;
  2886 + top: 2px;
  2887 + right: 2px;
  2888 + z-index: 1;
2924 2889 }
2925 2890  
2926   -
2927   -.l-sidebar-left-bar .catalog-categories-link a{
2928   - display: inline-block;
2929   - height: 100%;
2930   - width: 100%;
2931   - line-height: 28px;
2932   - text-decoration: none;
2933   - color: #2e3436;
2934   -}
2935 2891 /* * * Show Product * * * * * * * * * * * * */
2936 2892  
2937 2893 .controller-catalog #show_product .product-pic {
... ... @@ -6454,33 +6410,12 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
6454 6410 line-height: 1.5;
6455 6411 }
6456 6412  
6457   -/* Sidebar Layout */
6458   -
6459   -.l-sidebar-left-bar {
6460   - float: left;
6461   - width: 20%;
6462   -}
6463   -
6464   -.l-sidebar-left-content {
6465   - float: right;
6466   - width: 78%;
6467   -}
6468   -
6469   -.l-sidebar-right-bar {
6470   - float: right;
6471   - width: 20%;
6472   -}
6473   -
6474   -.l-sidebar-right-content {
6475   - float: left;
6476   - width: 78%;
6477   -}
6478   -
6479 6413 /* Breadcrumb */
6480 6414  
6481 6415 #breadcrumb {
6482 6416 font-size: 16px;
6483 6417 margin: 15px 0;
  6418 + text-align: left;
6484 6419 }
6485 6420  
6486 6421 .controller-profile_editor #profile-data {
... ... @@ -6531,11 +6466,3 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
6531 6466 width: 100px;
6532 6467 text-align: center;
6533 6468 }
6534   -
6535   -#product-list .highlighted img.star {
6536   - position: absolute;
6537   - top: 2px;
6538   - right: 2px;
6539   - z-index: 1;
6540   -}
6541   -
... ...
test/unit/catalog_helper_test.rb 0 → 100644
... ... @@ -0,0 +1,58 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class CatalogHelperTest < ActiveSupport::TestCase
  4 +
  5 + include CatalogHelper
  6 + include ActionView::Helpers::TextHelper
  7 + include ActionView::Helpers::UrlHelper
  8 + include ActionView::Helpers::TagHelper
  9 + include ActionController::Assertions::SelectorAssertions
  10 +
  11 + def url_for(opts)
  12 + #{:controller => 'catalog', :action => 'index', :level => category.id}
  13 + "#{opts[:controller]}-#{opts[:action]}-level=#{opts[:level]}"
  14 + end
  15 +
  16 + def new_productcategory(parent, name)
  17 + cat = ProductCategory.new(
  18 + :name => name, :environment => Environment.default, :parent => parent
  19 + )
  20 + cat if cat.save
  21 + end
  22 +
  23 + def setup
  24 + @enterprise = Enterprise.create! :name => 'Test Enterprise',
  25 + :identifier => 'testenterprise',
  26 + :environment => Environment.default
  27 + @profile = @enterprise
  28 + @block = @enterprise.blocks.select{|b| b.class == ProductCategoriesBlock }[0]
  29 + @products = new_productcategory nil, 'Products'
  30 + @food = new_productcategory @products, 'Food'
  31 + @vegetables = new_productcategory @food, 'Vegetables'
  32 + @beans = new_productcategory @vegetables, 'Beans'
  33 + @rice = new_productcategory @vegetables, 'Rice'
  34 + @mineral = new_productcategory @products, 'Mineral'
  35 + @iron = new_productcategory @mineral, 'Iron'
  36 + @gold = new_productcategory @mineral, 'Gold'
  37 + end
  38 + attr_accessor :profile
  39 +
  40 + should 'list product category sub-list' do
  41 + @enterprise.products.create!(:name => 'Gold Ring', :product_category => @gold)
  42 + @enterprise.products.create!(:name => 'Uncle Jon Beans', :product_category => @beans)
  43 + @enterprise.products.create!(:name => 'Red Rice', :product_category => @rice)
  44 +
  45 + html = category_with_sub_list @products
  46 +
  47 + doc = HTML::Document.new "<body>#{html}</body>"
  48 + assert_select doc.root, 'div' do |divs|
  49 + assert_select divs[0], "a[href=catalog-index-level=#{@products.id}]"
  50 + assert_select divs[0], '.count', {:text=>'3'}
  51 + assert_select divs[1], "a[href=catalog-index-level=#{@food.id}]"
  52 + assert_select divs[1], '.count', {:text=>'2'}
  53 + assert_select divs[2], "a[href=catalog-index-level=#{@mineral.id}]"
  54 + assert_select divs[2], '.count', {:text=>'1'}
  55 + end
  56 + end
  57 +
  58 +end
... ...