Commit 53d8ceb4d43536a7311c19bc15d4ed5911f5b88a
Exists in
master
and in
28 other branches
Merge branch 'merge-requests/248' into redemoinho
Conflicts: lib/noosfero/plugin/settings.rb test/unit/plugin_settings_test.rb
Showing
37 changed files
with
690 additions
and
117 deletions
Show diff stats
app/controllers/public/catalog_controller.rb
1 | class CatalogController < PublicController | 1 | class CatalogController < PublicController |
2 | needs_profile | 2 | needs_profile |
3 | + no_design_blocks | ||
3 | 4 | ||
4 | before_filter :check_enterprise_and_environment | 5 | before_filter :check_enterprise_and_environment |
5 | 6 | ||
6 | def index | 7 | def index |
7 | - @products = @profile.products.paginate(:order => 'name asc', :per_page => 9, :page => params[:page]) | 8 | + @category = params[:level] ? ProductCategory.find(params[:level]) : nil |
9 | + @products = @profile.products.from_category(@category).paginate(:order => 'available desc, highlighted desc, name asc', :per_page => 9, :page => params[:page]) | ||
10 | + @categories = ProductCategory.on_level(params[:level]) | ||
8 | end | 11 | end |
9 | 12 | ||
10 | protected | 13 | protected |
app/helpers/catalog_helper.rb
@@ -3,4 +3,28 @@ module CatalogHelper | @@ -3,4 +3,28 @@ module CatalogHelper | ||
3 | include DisplayHelper | 3 | include DisplayHelper |
4 | include ManageProductsHelper | 4 | include ManageProductsHelper |
5 | 5 | ||
6 | + def breadcrumb(category) | ||
7 | + start = link_to(_('Start'), {:action => 'index'}) | ||
8 | + ancestors = category.ancestors.map { |c| link_to(c.name, {:action => 'index', :level => c.id}) }.reverse | ||
9 | + current_level = content_tag('strong', category.name) | ||
10 | + all_items = [start] + ancestors + [current_level] | ||
11 | + content_tag('div', all_items.join(' → '), :id => 'breadcrumb') | ||
12 | + end | ||
13 | + | ||
14 | + def category_link(category, sub = false) | ||
15 | + count = profile.products.from_category(category).count | ||
16 | + name = truncate(category.name, :length => 22 - count.to_s.size) | ||
17 | + link_name = sub ? name : content_tag('strong', name) | ||
18 | + link = link_to(link_name, {:action => 'index', :level => category.id}, :title => category.name) | ||
19 | + content_tag('li', "#{link} (#{count})") if count > 0 | ||
20 | + end | ||
21 | + | ||
22 | + def category_sub_links(category) | ||
23 | + sub_categories = [] | ||
24 | + category.children.each do |sub_category| | ||
25 | + sub_categories << category_link(sub_category, true) | ||
26 | + end | ||
27 | + content_tag('ul', sub_categories) if sub_categories.size > 1 | ||
28 | + end | ||
29 | + | ||
6 | end | 30 | end |
app/helpers/display_helper.rb
@@ -8,6 +8,14 @@ module DisplayHelper | @@ -8,6 +8,14 @@ module DisplayHelper | ||
8 | opts | 8 | opts |
9 | end | 9 | end |
10 | 10 | ||
11 | + def themed_path(file) | ||
12 | + if File.exists?(File.join(Rails.root, 'public', theme_path, file)) | ||
13 | + File.join(theme_path, file) | ||
14 | + else | ||
15 | + file | ||
16 | + end | ||
17 | + end | ||
18 | + | ||
11 | def image_link_to_product(product, opts={}) | 19 | def image_link_to_product(product, opts={}) |
12 | return _('No product') unless product | 20 | return _('No product') unless product |
13 | target = product_path(product) | 21 | target = product_path(product) |
app/models/category.rb
@@ -13,6 +13,16 @@ class Category < ActiveRecord::Base | @@ -13,6 +13,16 @@ class Category < ActiveRecord::Base | ||
13 | {:conditions => ['parent_id is null and environment_id = ?', environment.id ]} | 13 | {:conditions => ['parent_id is null and environment_id = ?', environment.id ]} |
14 | } | 14 | } |
15 | 15 | ||
16 | + named_scope :on_level, lambda { |parent| {:conditions => {:parent_id => parent}} } | ||
17 | + | ||
18 | + named_scope :sub_categories, lambda { |category| | ||
19 | + {:conditions => ['categories.path LIKE ? AND categories.id != ?', "%#{category.slug}%", category.id]} | ||
20 | + } | ||
21 | + | ||
22 | + named_scope :sub_tree, lambda { |category| | ||
23 | + {:conditions => ['categories.path LIKE ?', "%#{category.slug}%"]} | ||
24 | + } | ||
25 | + | ||
16 | acts_as_filesystem | 26 | acts_as_filesystem |
17 | 27 | ||
18 | has_many :article_categorizations, :dependent => :destroy | 28 | has_many :article_categorizations, :dependent => :destroy |
app/models/organization.rb
@@ -78,6 +78,8 @@ class Organization < Profile | @@ -78,6 +78,8 @@ class Organization < Profile | ||
78 | country | 78 | country |
79 | tag_list | 79 | tag_list |
80 | template_id | 80 | template_id |
81 | + district | ||
82 | + address_reference | ||
81 | ] | 83 | ] |
82 | 84 | ||
83 | def self.fields | 85 | def self.fields |
@@ -96,8 +98,8 @@ class Organization < Profile | @@ -96,8 +98,8 @@ class Organization < Profile | ||
96 | [] | 98 | [] |
97 | end | 99 | end |
98 | 100 | ||
99 | - N_('Display name'); N_('Description'); N_('Contact person'); N_('Contact email'); N_('Acronym'); N_('Foundation year'); N_('Legal form'); N_('Economic activity'); N_('Management information'); N_('Tag list') | ||
100 | - settings_items :display_name, :description, :contact_person, :contact_email, :acronym, :foundation_year, :legal_form, :economic_activity, :management_information | 101 | + N_('Display name'); N_('Description'); N_('Contact person'); N_('Contact email'); N_('Acronym'); N_('Foundation year'); N_('Legal form'); N_('Economic activity'); N_('Management information'); N_('Tag list'); N_('District'); N_('Address reference') |
102 | + settings_items :display_name, :description, :contact_person, :contact_email, :acronym, :foundation_year, :legal_form, :economic_activity, :management_information, :district, :address_reference | ||
101 | 103 | ||
102 | validates_format_of :foundation_year, :with => Noosfero::Constants::INTEGER_FORMAT | 104 | validates_format_of :foundation_year, :with => Noosfero::Constants::INTEGER_FORMAT |
103 | validates_format_of :contact_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda { |org| !org.contact_email.blank? }) | 105 | validates_format_of :contact_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda { |org| !org.contact_email.blank? }) |
app/models/person.rb
@@ -147,6 +147,9 @@ class Person < Profile | @@ -147,6 +147,9 @@ class Person < Profile | ||
147 | contact_phone | 147 | contact_phone |
148 | contact_information | 148 | contact_information |
149 | description | 149 | description |
150 | + image | ||
151 | + district | ||
152 | + address_reference | ||
150 | ] | 153 | ] |
151 | 154 | ||
152 | validates_multiparameter_assignments | 155 | validates_multiparameter_assignments |
@@ -201,8 +204,8 @@ class Person < Profile | @@ -201,8 +204,8 @@ class Person < Profile | ||
201 | N_('Education'); N_('Custom education'); N_('Custom area of study'); | 204 | N_('Education'); N_('Custom education'); N_('Custom area of study'); |
202 | settings_items :formation, :custom_formation, :custom_area_of_study | 205 | settings_items :formation, :custom_formation, :custom_area_of_study |
203 | 206 | ||
204 | - N_('Contact information'); N_('City'); N_('State'); N_('Country'); N_('Sex'); N_('Zip code') | ||
205 | - settings_items :photo, :contact_information, :sex, :city, :state, :country, :zip_code | 207 | + N_('Contact information'); N_('City'); N_('State'); N_('Country'); N_('Sex'); N_('Zip code'); N_('District'); N_('Address reference') |
208 | + settings_items :photo, :contact_information, :sex, :city, :state, :country, :zip_code, :district, :address_reference | ||
206 | 209 | ||
207 | extend SetProfileRegionFromCityState::ClassMethods | 210 | extend SetProfileRegionFromCityState::ClassMethods |
208 | set_profile_region_from_city_state | 211 | set_profile_region_from_city_state |
app/models/product.rb
@@ -23,6 +23,10 @@ class Product < ActiveRecord::Base | @@ -23,6 +23,10 @@ class Product < ActiveRecord::Base | ||
23 | 23 | ||
24 | named_scope :more_recent, :order => "created_at DESC" | 24 | named_scope :more_recent, :order => "created_at DESC" |
25 | 25 | ||
26 | + named_scope :from_category, lambda { |category| | ||
27 | + {:joins => :product_category, :conditions => ['categories.path LIKE ?', "%#{category.slug}%"]} if category | ||
28 | + } | ||
29 | + | ||
26 | after_update :save_image | 30 | after_update :save_image |
27 | 31 | ||
28 | def lat | 32 | def lat |
app/models/profile.rb
@@ -141,6 +141,10 @@ class Profile < ActiveRecord::Base | @@ -141,6 +141,10 @@ class Profile < ActiveRecord::Base | ||
141 | 141 | ||
142 | acts_as_having_settings :field => :data | 142 | acts_as_having_settings :field => :data |
143 | 143 | ||
144 | + def settings | ||
145 | + data | ||
146 | + end | ||
147 | + | ||
144 | settings_items :redirect_l10n, :type => :boolean, :default => false | 148 | settings_items :redirect_l10n, :type => :boolean, :default => false |
145 | settings_items :public_content, :type => :boolean, :default => true | 149 | settings_items :public_content, :type => :boolean, :default => true |
146 | settings_items :description | 150 | settings_items :description |
@@ -229,7 +233,7 @@ class Profile < ActiveRecord::Base | @@ -229,7 +233,7 @@ class Profile < ActiveRecord::Base | ||
229 | if myregion | 233 | if myregion |
230 | myregion.hierarchy.reverse.first(2).map(&:name).join(separator) | 234 | myregion.hierarchy.reverse.first(2).map(&:name).join(separator) |
231 | else | 235 | else |
232 | - %w[address city state country_name zip_code ].map {|item| (self.respond_to?(item) && !self.send(item).blank?) ? self.send(item) : nil }.compact.join(separator) | 236 | + %w[address district city state country_name zip_code ].map {|item| (self.respond_to?(item) && !self.send(item).blank?) ? self.send(item) : nil }.compact.join(separator) |
233 | end | 237 | end |
234 | end | 238 | end |
235 | 239 | ||
@@ -694,7 +698,7 @@ private :generate_url, :url_options | @@ -694,7 +698,7 @@ private :generate_url, :url_options | ||
694 | def custom_footer_expanded | 698 | def custom_footer_expanded |
695 | footer = custom_footer | 699 | footer = custom_footer |
696 | if footer | 700 | if footer |
697 | - %w[contact_person contact_email contact_phone location address economic_activity city state country zip_code].each do |att| | 701 | + %w[contact_person contact_email contact_phone location address district address_reference economic_activity city state country zip_code].each do |att| |
698 | if self.respond_to?(att) && footer.match(/\{[^{]*#{att}\}/) | 702 | if self.respond_to?(att) && footer.match(/\{[^{]*#{att}\}/) |
699 | if !self.send(att).nil? && !self.send(att).blank? | 703 | if !self.send(att).nil? && !self.send(att).blank? |
700 | footer = footer.gsub(/\{([^{]*)#{att}\}/, '\1' + self.send(att)) | 704 | footer = footer.gsub(/\{([^{]*)#{att}\}/, '\1' + self.send(att)) |
app/views/catalog/index.rhtml
1 | <% extra_content = [] %> | 1 | <% extra_content = [] %> |
2 | <% extra_content_list = [] %> | 2 | <% extra_content_list = [] %> |
3 | 3 | ||
4 | -<ul id="product-list"> | ||
5 | - <li><h1><%= _('Products/Services') %></h1></li> | 4 | +<h1><%= _('Products/Services') %></h1> |
6 | 5 | ||
6 | +<%= breadcrumb(@category) if params[:level] %> | ||
7 | + | ||
8 | +<div class='l-sidebar-left-bar'> | ||
9 | + <ul> | ||
10 | + <% if @categories.size > 0 %> | ||
11 | + <% @categories.each do |category| %> | ||
12 | + <%= category_link(category) %> | ||
13 | + <%= category_sub_links(category) %> | ||
14 | + <% end %> | ||
15 | + <% else %> | ||
16 | + <%= content_tag('li', _('There are no sub-categories for %s') % @category.name, :style => 'color: #555753; padding-bottom: 0.5em;') %> | ||
17 | + <% end %> | ||
18 | + </ul> | ||
19 | +</div> | ||
20 | + | ||
21 | +<ul id="product-list" class="l-sidebar-left-content"> | ||
7 | <% @products.each do |product| %> | 22 | <% @products.each do |product| %> |
8 | <% extra_content = @plugins.dispatch(:catalog_item_extras, product).collect { |content| instance_eval(&content) } %> | 23 | <% extra_content = @plugins.dispatch(:catalog_item_extras, product).collect { |content| instance_eval(&content) } %> |
9 | <% extra_content_list = @plugins.dispatch(:catalog_list_item_extras, product).collect { |content| instance_eval(&content) } %> | 24 | <% extra_content_list = @plugins.dispatch(:catalog_list_item_extras, product).collect { |content| instance_eval(&content) } %> |
10 | 25 | ||
11 | - <li class="product <%= "not-available" unless product.available %>"> | 26 | + <% status = [] %> |
27 | + <% status << 'not-available' if !product.available %> | ||
28 | + <% status << 'highlighted' if product.highlighted %> | ||
29 | + | ||
30 | + <li class="product <%= status.join(' ') %>"> | ||
12 | <ul> | 31 | <ul> |
13 | <li class="product-image-link"> | 32 | <li class="product-image-link"> |
33 | + <% if product.highlighted? %> | ||
34 | + <%= link_to image_tag(themed_path('/images/star.png'), :class => 'star', :alt => _('Highlighted product')), product_path(product) %> | ||
35 | + <% end %> | ||
14 | <% if product.image %> | 36 | <% if product.image %> |
15 | <div class="zoomable-image"> | 37 | <div class="zoomable-image"> |
16 | <%= link_to_product product, :class => 'product-big', :style => "background-image: url(#{product.default_image(:big)})" %> | 38 | <%= link_to_product product, :class => 'product-big', :style => "background-image: url(#{product.default_image(:big)})" %> |
app/views/profile_editor/_person_form.rhtml
@@ -21,6 +21,8 @@ | @@ -21,6 +21,8 @@ | ||
21 | <%= optional_field(@person, 'city', f.text_field(:city, :rel => _('City'))) %> | 21 | <%= optional_field(@person, 'city', f.text_field(:city, :rel => _('City'))) %> |
22 | <%= optional_field(@person, 'zip_code', labelled_form_field(_('ZIP code'), text_field(:profile_data, :zip_code, :rel => _('ZIP code')))) %> | 22 | <%= optional_field(@person, 'zip_code', labelled_form_field(_('ZIP code'), text_field(:profile_data, :zip_code, :rel => _('ZIP code')))) %> |
23 | <%= optional_field(@person, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address, :rel => _('Address')))) %> | 23 | <%= optional_field(@person, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address, :rel => _('Address')))) %> |
24 | +<%= optional_field(profile, 'address_reference', labelled_form_field(_('Address reference'), text_field(object_name, :address_reference, :rel => _('Address reference')))) %> | ||
25 | +<%= optional_field(@person, 'district', labelled_form_field(_('District'), text_field(:profile_data, :district, :rel => _('District')))) %> | ||
24 | 26 | ||
25 | <% optional_field(@person, 'schooling') do %> | 27 | <% optional_field(@person, 'schooling') do %> |
26 | <div class="formfieldline"> | 28 | <div class="formfieldline"> |
app/views/search/_product.rhtml
1 | <% extra_content = @plugins.dispatch(:asset_product_extras, product, product.enterprise).collect { |content| instance_eval(&content) } %> | 1 | <% extra_content = @plugins.dispatch(:asset_product_extras, product, product.enterprise).collect { |content| instance_eval(&content) } %> |
2 | <% extra_properties = @plugins.dispatch(:asset_product_properties, product)%> | 2 | <% extra_properties = @plugins.dispatch(:asset_product_properties, product)%> |
3 | 3 | ||
4 | -<li class="search-product-item"> | 4 | +<li class="search-product-item <%= 'highlighted' if product.highlighted? %>"> |
5 | 5 | ||
6 | <div class="search-product-item-first-column"> | 6 | <div class="search-product-item-first-column"> |
7 | <%= render :partial => 'search/image', :object => product %> | 7 | <%= render :partial => 'search/image', :object => product %> |
app/views/shared/_organization_custom_fields.rhtml
@@ -10,6 +10,8 @@ | @@ -10,6 +10,8 @@ | ||
10 | <%= optional_field(profile, 'economic_activity', f.text_field(:economic_activity)) %> | 10 | <%= optional_field(profile, 'economic_activity', f.text_field(:economic_activity)) %> |
11 | <%= optional_field(profile, 'management_information', f.text_area(:management_information, :rows => 5)) %> | 11 | <%= optional_field(profile, 'management_information', f.text_area(:management_information, :rows => 5)) %> |
12 | <%= optional_field(profile, 'address', labelled_form_field(_('Address (street and number)'), text_field(object_name, :address))) %> | 12 | <%= optional_field(profile, 'address', labelled_form_field(_('Address (street and number)'), text_field(object_name, :address))) %> |
13 | +<%= optional_field(profile, 'address_reference', labelled_form_field(_('Address reference'), text_field(object_name, :address_reference))) %> | ||
14 | +<%= optional_field(profile, 'district', labelled_form_field(_('District'), text_field(object_name, :district))) %> | ||
13 | <%= optional_field(profile, 'zip_code', labelled_form_field(_('ZIP code'), text_field(object_name, :zip_code))) %> | 15 | <%= optional_field(profile, 'zip_code', labelled_form_field(_('ZIP code'), text_field(object_name, :zip_code))) %> |
14 | <%= optional_field(profile, 'city', f.text_field(:city)) %> | 16 | <%= optional_field(profile, 'city', f.text_field(:city)) %> |
15 | <%= optional_field(profile, 'state', f.text_field(:state)) %> | 17 | <%= optional_field(profile, 'state', f.text_field(:state)) %> |
lib/noosfero/plugin/settings.rb
1 | class Noosfero::Plugin::Settings | 1 | class Noosfero::Plugin::Settings |
2 | 2 | ||
3 | - def initialize(environment, plugin, attributes = nil) | ||
4 | - @environment = environment | 3 | + def initialize(base, plugin, attributes = nil) |
4 | + @base = base | ||
5 | @plugin = plugin | 5 | @plugin = plugin |
6 | attributes ||= {} | 6 | attributes ||= {} |
7 | attributes.each do |k,v| | 7 | attributes.each do |k,v| |
@@ -10,7 +10,7 @@ class Noosfero::Plugin::Settings | @@ -10,7 +10,7 @@ class Noosfero::Plugin::Settings | ||
10 | end | 10 | end |
11 | 11 | ||
12 | def settings | 12 | def settings |
13 | - @environment.settings["#{@plugin.public_name}_plugin".to_sym] ||= {} | 13 | + @base.settings["#{@plugin.public_name}_plugin".to_sym] ||= {} |
14 | end | 14 | end |
15 | 15 | ||
16 | def method_missing(method, *args, &block) | 16 | def method_missing(method, *args, &block) |
@@ -38,7 +38,11 @@ class Noosfero::Plugin::Settings | @@ -38,7 +38,11 @@ class Noosfero::Plugin::Settings | ||
38 | end | 38 | end |
39 | 39 | ||
40 | def save! | 40 | def save! |
41 | +<<<<<<< HEAD | ||
41 | @environment.save! | 42 | @environment.save! |
43 | +======= | ||
44 | + @base.save! | ||
45 | +>>>>>>> merge-requests/248 | ||
42 | end | 46 | end |
43 | 47 | ||
44 | end | 48 | end |
plugins/shopping_cart/controllers/shopping_cart_plugin_myprofile_controller.rb
@@ -4,9 +4,12 @@ class ShoppingCartPluginMyprofileController < MyProfileController | @@ -4,9 +4,12 @@ class ShoppingCartPluginMyprofileController < MyProfileController | ||
4 | append_view_path File.join(File.dirname(__FILE__) + '/../views') | 4 | append_view_path File.join(File.dirname(__FILE__) + '/../views') |
5 | 5 | ||
6 | def edit | 6 | def edit |
7 | + params[:settings] = treat_cart_options(params[:settings]) | ||
8 | + | ||
9 | + @settings = Noosfero::Plugin::Settings.new(profile, ShoppingCartPlugin, params[:settings]) | ||
7 | if request.post? | 10 | if request.post? |
8 | begin | 11 | begin |
9 | - profile.update_attributes!(params[:profile_attr]) | 12 | + @settings.save! |
10 | session[:notice] = _('Option updated successfully.') | 13 | session[:notice] = _('Option updated successfully.') |
11 | rescue Exception => exception | 14 | rescue Exception => exception |
12 | session[:notice] = _('Option wasn\'t updated successfully.') | 15 | session[:notice] = _('Option wasn\'t updated successfully.') |
@@ -46,4 +49,25 @@ class ShoppingCartPluginMyprofileController < MyProfileController | @@ -46,4 +49,25 @@ class ShoppingCartPluginMyprofileController < MyProfileController | ||
46 | order.save! | 49 | order.save! |
47 | redirect_to :action => 'reports', :from => params[:context_from], :to => params[:context_to], :filter_status => params[:context_status] | 50 | redirect_to :action => 'reports', :from => params[:context_from], :to => params[:context_to], :filter_status => params[:context_status] |
48 | end | 51 | end |
52 | + | ||
53 | + private | ||
54 | + | ||
55 | + def treat_cart_options(settings) | ||
56 | + return if settings.blank? | ||
57 | + settings[:enabled] = settings[:enabled] == '1' | ||
58 | + settings[:delivery] = settings[:delivery] == '1' | ||
59 | + settings[:free_delivery_price] = settings[:free_delivery_price].blank? ? nil : settings[:free_delivery_price].to_d | ||
60 | + settings[:delivery_options] = treat_delivery_options(settings[:delivery_options]) | ||
61 | + settings | ||
62 | + end | ||
63 | + | ||
64 | + def treat_delivery_options(params) | ||
65 | + result = {} | ||
66 | + params[:options].size.times do |counter| | ||
67 | + if params[:options][counter].present? && params[:prices][counter].present? | ||
68 | + result[params[:options][counter]] = params[:prices][counter] | ||
69 | + end | ||
70 | + end | ||
71 | + result | ||
72 | + end | ||
49 | end | 73 | end |
plugins/shopping_cart/controllers/shopping_cart_plugin_profile_controller.rb
@@ -85,14 +85,15 @@ class ShoppingCartPluginProfileController < ProfileController | @@ -85,14 +85,15 @@ class ShoppingCartPluginProfileController < ProfileController | ||
85 | 85 | ||
86 | def buy | 86 | def buy |
87 | @environment = profile.environment | 87 | @environment = profile.environment |
88 | + @settings = Noosfero::Plugin::Settings.new(profile, ShoppingCartPlugin) | ||
88 | render :layout => false | 89 | render :layout => false |
89 | end | 90 | end |
90 | 91 | ||
91 | def send_request | 92 | def send_request |
92 | register_order(params[:customer], session[:cart][:items]) | 93 | register_order(params[:customer], session[:cart][:items]) |
93 | begin | 94 | begin |
94 | - ShoppingCartPlugin::Mailer.deliver_customer_notification(params[:customer], profile, session[:cart][:items]) | ||
95 | - ShoppingCartPlugin::Mailer.deliver_supplier_notification(params[:customer], profile, session[:cart][:items]) | 95 | + ShoppingCartPlugin::Mailer.deliver_customer_notification(params[:customer], profile, session[:cart][:items], params[:delivery_option]) |
96 | + ShoppingCartPlugin::Mailer.deliver_supplier_notification(params[:customer], profile, session[:cart][:items], params[:delivery_option]) | ||
96 | render :text => { | 97 | render :text => { |
97 | :ok => true, | 98 | :ok => true, |
98 | :message => _('Request sent successfully. Check your email.'), | 99 | :message => _('Request sent successfully. Check your email.'), |
@@ -151,6 +152,24 @@ class ShoppingCartPluginProfileController < ProfileController | @@ -151,6 +152,24 @@ class ShoppingCartPluginProfileController < ProfileController | ||
151 | end | 152 | end |
152 | end | 153 | end |
153 | 154 | ||
155 | + def update_delivery_option | ||
156 | + settings = Noosfero::Plugin::Settings.new(profile, ShoppingCartPlugin) | ||
157 | + delivery_price = settings.delivery_options[params[:delivery_option]] | ||
158 | + delivery = Product.new(:name => params[:delivery_option], :price => delivery_price) | ||
159 | + delivery.save(false) | ||
160 | + items = session[:cart][:items].clone | ||
161 | + items[delivery.id] = 1 | ||
162 | + total_price = get_total_on_currency(items, environment) | ||
163 | + delivery.destroy | ||
164 | + render :text => { | ||
165 | + :ok => true, | ||
166 | + :delivery_price => float_to_currency_cart(delivery_price, environment), | ||
167 | + :total_price => total_price, | ||
168 | + :message => _('Delivery option updated.'), | ||
169 | + :error => {:code => 0} | ||
170 | + }.to_json | ||
171 | + end | ||
172 | + | ||
154 | private | 173 | private |
155 | 174 | ||
156 | def validate_same_enterprise | 175 | def validate_same_enterprise |
plugins/shopping_cart/db/migrate/20121022190819_move_fields_included_on_profiles_table_to_settings.rb
0 → 100644
@@ -0,0 +1,19 @@ | @@ -0,0 +1,19 @@ | ||
1 | +class MoveFieldsIncludedOnProfilesTableToSettings < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + Profile.find_each do |profile| | ||
4 | + settings = Noosfero::Plugin::Settings.new(profile, ShoppingCartPlugin) | ||
5 | + settings.enabled = profile.shopping_cart | ||
6 | + settings.delivery = profile.shopping_cart_delivery | ||
7 | + settings.delivery_price = profile.shopping_cart_delivery_price | ||
8 | + settings.save! | ||
9 | + end | ||
10 | + | ||
11 | + remove_column :profiles, :shopping_cart | ||
12 | + remove_column :profiles, :shopping_cart_delivery | ||
13 | + remove_column :profiles, :shopping_cart_delivery_price | ||
14 | + end | ||
15 | + | ||
16 | + def self.down | ||
17 | + say "This migration can not be reverted!" | ||
18 | + end | ||
19 | +end |
plugins/shopping_cart/lib/shopping_cart_plugin.rb
@@ -3,16 +3,35 @@ require_dependency 'shopping_cart_plugin/ext/person' | @@ -3,16 +3,35 @@ require_dependency 'shopping_cart_plugin/ext/person' | ||
3 | 3 | ||
4 | class ShoppingCartPlugin < Noosfero::Plugin | 4 | class ShoppingCartPlugin < Noosfero::Plugin |
5 | 5 | ||
6 | - def self.plugin_name | 6 | + class << self |
7 | + def plugin_name | ||
7 | "Shopping Basket" | 8 | "Shopping Basket" |
8 | - end | 9 | + end |
10 | + | ||
11 | + def plugin_description | ||
12 | + _("A shopping basket feature for enterprises") | ||
13 | + end | ||
14 | + | ||
15 | + def enabled_default_setting | ||
16 | + true | ||
17 | + end | ||
9 | 18 | ||
10 | - def self.plugin_description | ||
11 | - _("A shopping basket feature for enterprises") | 19 | + def delivery_default_setting |
20 | + false | ||
21 | + end | ||
22 | + | ||
23 | + def delivery_price_default_setting | ||
24 | + 0 | ||
25 | + end | ||
26 | + | ||
27 | + def delivery_options_default_setting | ||
28 | + {} | ||
29 | + end | ||
12 | end | 30 | end |
13 | 31 | ||
14 | def add_to_cart_button(item, enterprise = context.profile) | 32 | def add_to_cart_button(item, enterprise = context.profile) |
15 | - if enterprise.shopping_cart && item.available | 33 | + settings = Noosfero::Plugin::Settings.new(enterprise, ShoppingCartPlugin) |
34 | + if settings.enabled && item.available | ||
16 | lambda { | 35 | lambda { |
17 | link_to(_('Add to basket'), "add:#{item.name}", | 36 | link_to(_('Add to basket'), "add:#{item.name}", |
18 | :class => 'cart-add-item', | 37 | :class => 'cart-add-item', |
@@ -39,11 +58,12 @@ class ShoppingCartPlugin < Noosfero::Plugin | @@ -39,11 +58,12 @@ class ShoppingCartPlugin < Noosfero::Plugin | ||
39 | end | 58 | end |
40 | 59 | ||
41 | def control_panel_buttons | 60 | def control_panel_buttons |
61 | + settings = Noosfero::Plugin::Settings.new(context.profile, ShoppingCartPlugin) | ||
42 | buttons = [] | 62 | buttons = [] |
43 | if context.profile.enterprise? | 63 | if context.profile.enterprise? |
44 | buttons << { :title => _('Shopping basket'), :icon => 'shopping-cart-icon', :url => {:controller => 'shopping_cart_plugin_myprofile', :action => 'edit'} } | 64 | buttons << { :title => _('Shopping basket'), :icon => 'shopping-cart-icon', :url => {:controller => 'shopping_cart_plugin_myprofile', :action => 'edit'} } |
45 | end | 65 | end |
46 | - if context.profile.enterprise? && context.profile.shopping_cart | 66 | + if context.profile.enterprise? && settings.enabled |
47 | buttons << { :title => _('Purchase reports'), :icon => 'shopping-cart-purchase-report', :url => {:controller => 'shopping_cart_plugin_myprofile', :action => 'reports'} } | 67 | buttons << { :title => _('Purchase reports'), :icon => 'shopping-cart-purchase-report', :url => {:controller => 'shopping_cart_plugin_myprofile', :action => 'reports'} } |
48 | end | 68 | end |
49 | 69 |
plugins/shopping_cart/lib/shopping_cart_plugin/cart_helper.rb
@@ -7,46 +7,69 @@ module ShoppingCartPlugin::CartHelper | @@ -7,46 +7,69 @@ module ShoppingCartPlugin::CartHelper | ||
7 | product.discount ? product.price_with_discount : product.price | 7 | product.discount ? product.price_with_discount : product.price |
8 | end | 8 | end |
9 | 9 | ||
10 | - def get_price(product, environment) | ||
11 | - float_to_currency_cart(sell_price(product), environment) | 10 | + def get_price(product, environment, quantity=1) |
11 | + float_to_currency_cart(price_with_quantity(product,quantity), environment) | ||
12 | end | 12 | end |
13 | 13 | ||
14 | - def get_total(items, environment) | ||
15 | - float_to_currency_cart(items.map { |id, quantity| sell_price(Product.find(id)) * quantity}.sum, environment) | 14 | + def price_with_quantity(product, quantity=1) |
15 | + quantity = 1 if !quantity.kind_of?(Numeric) | ||
16 | + sell_price(product)*quantity | ||
16 | end | 17 | end |
17 | 18 | ||
18 | - def items_table(items, profile, by_mail = false) | 19 | + def get_total(items) |
20 | + items.map { |id, quantity| price_with_quantity(Product.find(id),quantity)}.sum | ||
21 | + end | ||
22 | + | ||
23 | + def get_total_on_currency(items, environment) | ||
24 | + float_to_currency_cart(get_total(items), environment) | ||
25 | + end | ||
26 | + | ||
27 | + def items_table(items, profile, delivery_option = nil, by_mail = false) | ||
19 | environment = profile.environment | 28 | environment = profile.environment |
29 | + settings = Noosfero::Plugin::Settings.new(profile, ShoppingCartPlugin) | ||
20 | items = items.to_a | 30 | items = items.to_a |
21 | - if profile.shopping_cart_delivery | ||
22 | - delivery = Product.create!(:name => _('Delivery'), :price => profile.shopping_cart_delivery_price, :product_category => ProductCategory.last) | ||
23 | - items << [delivery.id, 1] | ||
24 | - end | ||
25 | 31 | ||
26 | quantity_opts = { :class => 'cart-table-quantity' } | 32 | quantity_opts = { :class => 'cart-table-quantity' } |
27 | quantity_opts.merge!({:align => 'center'}) if by_mail | 33 | quantity_opts.merge!({:align => 'center'}) if by_mail |
28 | price_opts = {:class => 'cart-table-price'} | 34 | price_opts = {:class => 'cart-table-price'} |
29 | price_opts.merge!({:align => 'right'}) if by_mail | 35 | price_opts.merge!({:align => 'right'}) if by_mail |
36 | + items.sort! {|a, b| Product.find(a.first).name <=> Product.find(b.first).name} | ||
37 | + | ||
38 | + if settings.delivery | ||
39 | + if settings.free_delivery_price && get_total(items) >= settings.free_delivery_price | ||
40 | + delivery = Product.new(:name => _('Free delivery'), :price => 0) | ||
41 | + else | ||
42 | + delivery = Product.new(:name => delivery_option || _('Delivery'), :price => settings.delivery_options[delivery_option]) | ||
43 | + end | ||
44 | + delivery.save(false) | ||
45 | + items << [delivery.id, ''] | ||
46 | + end | ||
30 | 47 | ||
31 | table = '<table id="cart-items-table" cellpadding="2" cellspacing="0" | 48 | table = '<table id="cart-items-table" cellpadding="2" cellspacing="0" |
32 | border="'+(by_mail ? '1' : '0')+'" | 49 | border="'+(by_mail ? '1' : '0')+'" |
33 | style="'+(by_mail ? 'border-collapse:collapse' : '')+'">' + | 50 | style="'+(by_mail ? 'border-collapse:collapse' : '')+'">' + |
34 | content_tag('tr', | 51 | content_tag('tr', |
35 | - content_tag('th', _('Item name')) + | ||
36 | - content_tag('th', by_mail ? ' # ' : '#') + | ||
37 | - content_tag('th', _('Price')) | 52 | + content_tag('th', _('Item name')) + |
53 | + content_tag('th', by_mail ? ' # ' : '#') + | ||
54 | + content_tag('th', _('Price')) | ||
38 | ) + | 55 | ) + |
39 | items.map do |id, quantity| | 56 | items.map do |id, quantity| |
40 | product = Product.find(id) | 57 | product = Product.find(id) |
58 | + name_opts = {} | ||
59 | + is_delivery = quantity.kind_of?(String) | ||
60 | + if is_delivery | ||
61 | + price_opts.merge!({:id => 'delivery-price'}) | ||
62 | + name_opts.merge!({:id => 'delivery-name'}) | ||
63 | + end | ||
41 | content_tag('tr', | 64 | content_tag('tr', |
42 | - content_tag('td', product.name) + | ||
43 | - content_tag('td', quantity, quantity_opts ) + | ||
44 | - content_tag('td', get_price(product, environment), price_opts ) | ||
45 | - ) | 65 | + content_tag('td', product.name, name_opts) + |
66 | + content_tag('td', quantity, quantity_opts ) + | ||
67 | + content_tag('td', get_price(product, environment, quantity), price_opts) | ||
68 | + ) | ||
46 | end.join("\n") | 69 | end.join("\n") |
47 | 70 | ||
48 | - total = get_total(items, environment) | ||
49 | - delivery.destroy if profile.shopping_cart_delivery | 71 | + total = get_total_on_currency(items, environment) |
72 | + delivery.destroy if settings.delivery | ||
50 | 73 | ||
51 | table + | 74 | table + |
52 | content_tag('th', _('Total:'), :colspan => 2, :class => 'cart-table-total-label') + | 75 | content_tag('th', _('Total:'), :colspan => 2, :class => 'cart-table-total-label') + |
@@ -55,6 +78,14 @@ module ShoppingCartPlugin::CartHelper | @@ -55,6 +78,14 @@ module ShoppingCartPlugin::CartHelper | ||
55 | end | 78 | end |
56 | 79 | ||
57 | def float_to_currency_cart(value, environment) | 80 | def float_to_currency_cart(value, environment) |
58 | - number_to_currency(value, :unit => environment.currency_unit, :separator => environment.currency_separator, :delimiter => environment.currency_delimiter, :precision => 2, :format => "%u %n") | 81 | + number_to_currency(value, :unit => environment.currency_unit, :separator => environment.currency_separator, :delimiter => environment.currency_delimiter, :precision => 2, :format => "%u%n") |
82 | + end | ||
83 | + | ||
84 | + def select_delivery_options(options, environment) | ||
85 | + result = options.map do |option, price| | ||
86 | + ["#{option} (#{float_to_currency_cart(price, environment)})", option] | ||
87 | + end | ||
88 | + result << ["#{_('Delivery')} (#{float_to_currency_cart(0, environment)})", 'delivery'] if result.empty? | ||
89 | + result | ||
59 | end | 90 | end |
60 | end | 91 | end |
plugins/shopping_cart/lib/shopping_cart_plugin/mailer.rb
1 | class ShoppingCartPlugin::Mailer < Noosfero::Plugin::MailerBase | 1 | class ShoppingCartPlugin::Mailer < Noosfero::Plugin::MailerBase |
2 | 2 | ||
3 | - def customer_notification(customer, supplier, items) | 3 | + def customer_notification(customer, supplier, items, delivery_option) |
4 | domain = supplier.hostname || supplier.environment.default_hostname | 4 | domain = supplier.hostname || supplier.environment.default_hostname |
5 | recipients customer[:email] | 5 | recipients customer[:email] |
6 | from 'no-reply@' + domain | 6 | from 'no-reply@' + domain |
@@ -10,10 +10,11 @@ class ShoppingCartPlugin::Mailer < Noosfero::Plugin::MailerBase | @@ -10,10 +10,11 @@ class ShoppingCartPlugin::Mailer < Noosfero::Plugin::MailerBase | ||
10 | body :customer => customer, | 10 | body :customer => customer, |
11 | :supplier => supplier, | 11 | :supplier => supplier, |
12 | :items => items, | 12 | :items => items, |
13 | - :environment => supplier.environment | 13 | + :environment => supplier.environment, |
14 | + :delivery_option => delivery_option | ||
14 | end | 15 | end |
15 | 16 | ||
16 | - def supplier_notification(customer, supplier, items) | 17 | + def supplier_notification(customer, supplier, items, delivery_option) |
17 | domain = supplier.environment.default_hostname | 18 | domain = supplier.environment.default_hostname |
18 | recipients supplier.contact_email | 19 | recipients supplier.contact_email |
19 | from 'no-reply@' + domain | 20 | from 'no-reply@' + domain |
@@ -23,6 +24,7 @@ class ShoppingCartPlugin::Mailer < Noosfero::Plugin::MailerBase | @@ -23,6 +24,7 @@ class ShoppingCartPlugin::Mailer < Noosfero::Plugin::MailerBase | ||
23 | body :customer => customer, | 24 | body :customer => customer, |
24 | :supplier => supplier, | 25 | :supplier => supplier, |
25 | :items => items, | 26 | :items => items, |
26 | - :environment => supplier.environment | 27 | + :environment => supplier.environment, |
28 | + :delivery_option => delivery_option | ||
27 | end | 29 | end |
28 | end | 30 | end |
@@ -0,0 +1,34 @@ | @@ -0,0 +1,34 @@ | ||
1 | +jQuery(document).ready(function(){ | ||
2 | + jQuery("#cart-request-form").validate({ | ||
3 | + submitHandler: function(form) { | ||
4 | + jQuery(form).find('input.submit').attr('disabled', true); | ||
5 | + jQuery('#cboxLoadingOverlay').show().addClass('loading'); | ||
6 | + jQuery('#cboxLoadingGraphic').show().addClass('loading'); | ||
7 | + } | ||
8 | + }); | ||
9 | +}); | ||
10 | + | ||
11 | +jQuery('#delivery_option').change(function(){ | ||
12 | + jQuery('#cboxLoadingGraphic').show(); | ||
13 | + me = this; | ||
14 | + enterprise = jQuery(me).attr('data-profile-identifier'); | ||
15 | + option = jQuery(me).val(); | ||
16 | + jQuery.ajax({ | ||
17 | + url: '/profile/'+ enterprise +'/plugin/shopping_cart/update_delivery_option', | ||
18 | + dataType: "json", | ||
19 | + data: 'delivery_option='+option, | ||
20 | + success: function(data, st, ajax) { | ||
21 | + jQuery('#delivery-price').text(data.delivery_price); | ||
22 | + jQuery('.cart-table-total-value').text(data.total_price); | ||
23 | + jQuery('#delivery-name').text(option); | ||
24 | + jQuery('#cboxLoadingGraphic').hide(); | ||
25 | + }, | ||
26 | + error: function(ajax, st, errorThrown) { | ||
27 | + alert('Update delivery option - HTTP '+st+': '+errorThrown); | ||
28 | + }, | ||
29 | + }); | ||
30 | +}); | ||
31 | + | ||
32 | +jQuery('#customer_payment').change(function(){ | ||
33 | + jQuery(this).closest('.formfieldline').next().slideToggle('fast'); | ||
34 | +}); |
plugins/shopping_cart/public/cart.js
@@ -14,7 +14,7 @@ function Cart(config) { | @@ -14,7 +14,7 @@ function Cart(config) { | ||
14 | this.enterprise = config.enterprise; | 14 | this.enterprise = config.enterprise; |
15 | me = this; | 15 | me = this; |
16 | $.ajax({ | 16 | $.ajax({ |
17 | - url: '/profile/'+ this.enterprise +'/plugins/shopping_cart/visibility', | 17 | + url: '/profile/'+ this.enterprise +'/plugin/shopping_cart/visibility', |
18 | dataType: 'json', | 18 | dataType: 'json', |
19 | success: function(data, status, ajax){ | 19 | success: function(data, status, ajax){ |
20 | me.visible = /^true$/i.test(data); | 20 | me.visible = /^true$/i.test(data); |
@@ -25,7 +25,7 @@ function Cart(config) { | @@ -25,7 +25,7 @@ function Cart(config) { | ||
25 | alert('Visibility - HTTP '+status+': '+errorThrown); | 25 | alert('Visibility - HTTP '+status+': '+errorThrown); |
26 | } | 26 | } |
27 | }); | 27 | }); |
28 | - $(".cart-buy", this.cartElem).colorbox({href: '/profile/' + this.enterprise + '/plugins/shopping_cart/buy'}); | 28 | + $(".cart-buy", this.cartElem).colorbox({href: '/profile/' + this.enterprise + '/plugin/shopping_cart/buy'}); |
29 | } | 29 | } |
30 | } | 30 | } |
31 | 31 | ||
@@ -34,7 +34,7 @@ function Cart(config) { | @@ -34,7 +34,7 @@ function Cart(config) { | ||
34 | Cart.prototype.listProducts = function() { | 34 | Cart.prototype.listProducts = function() { |
35 | var me = this; | 35 | var me = this; |
36 | $.ajax({ | 36 | $.ajax({ |
37 | - url: '/profile/'+ this.enterprise +'/plugins/shopping_cart/list', | 37 | + url: '/profile/'+ this.enterprise +'/plugin/shopping_cart/list', |
38 | dataType: 'json', | 38 | dataType: 'json', |
39 | success: function(data, ststus, ajax){ | 39 | success: function(data, ststus, ajax){ |
40 | if ( !data.ok ) alert(data.error.message); | 40 | if ( !data.ok ) alert(data.error.message); |
@@ -100,7 +100,7 @@ function Cart(config) { | @@ -100,7 +100,7 @@ function Cart(config) { | ||
100 | var me = this; | 100 | var me = this; |
101 | if( quantity == NaN ) return input.value = input.lastValue; | 101 | if( quantity == NaN ) return input.value = input.lastValue; |
102 | $.ajax({ | 102 | $.ajax({ |
103 | - url: '/profile/'+ this.enterprise +'/plugins/shopping_cart/update_quantity/'+ itemId +'?quantity='+ quantity, | 103 | + url: '/profile/'+ this.enterprise +'/plugin/shopping_cart/update_quantity/'+ itemId +'?quantity='+ quantity, |
104 | dataType: 'json', | 104 | dataType: 'json', |
105 | success: function(data, status, ajax){ | 105 | success: function(data, status, ajax){ |
106 | if ( !data.ok ) { | 106 | if ( !data.ok ) { |
@@ -150,12 +150,12 @@ function Cart(config) { | @@ -150,12 +150,12 @@ function Cart(config) { | ||
150 | Cart.prototype.addItem = function(enterprise, itemId, callback) { | 150 | Cart.prototype.addItem = function(enterprise, itemId, callback) { |
151 | if(!this.enterprise) { | 151 | if(!this.enterprise) { |
152 | this.enterprise = enterprise; | 152 | this.enterprise = enterprise; |
153 | - $(".cart-buy", this.cartElem).colorbox({href: '/profile/' + this.enterprise + '/plugins/shopping_cart/buy'}); | 153 | + $(".cart-buy", this.cartElem).colorbox({href: '/profile/' + this.enterprise + '/plugin/shopping_cart/buy'}); |
154 | // $(this.cartElem).show(); | 154 | // $(this.cartElem).show(); |
155 | } | 155 | } |
156 | var me = this; | 156 | var me = this; |
157 | $.ajax({ | 157 | $.ajax({ |
158 | - url: '/profile/'+ enterprise +'/plugins/shopping_cart/add/'+ itemId, | 158 | + url: '/profile/'+ enterprise +'/plugin/shopping_cart/add/'+ itemId, |
159 | dataType: 'json', | 159 | dataType: 'json', |
160 | success: function(data, status, ajax){ | 160 | success: function(data, status, ajax){ |
161 | if ( !data.ok ) alert(data.error.message); | 161 | if ( !data.ok ) alert(data.error.message); |
@@ -178,7 +178,7 @@ function Cart(config) { | @@ -178,7 +178,7 @@ function Cart(config) { | ||
178 | if ($("li", this.itemsBox).size() < 2) return this.clean(); | 178 | if ($("li", this.itemsBox).size() < 2) return this.clean(); |
179 | var me = this; | 179 | var me = this; |
180 | $.ajax({ | 180 | $.ajax({ |
181 | - url: '/profile/'+ enterprise +'/plugins/shopping_cart/remove/'+ itemId, | 181 | + url: '/profile/'+ enterprise +'/plugin/shopping_cart/remove/'+ itemId, |
182 | dataType: 'json', | 182 | dataType: 'json', |
183 | success: function(data, status, ajax){ | 183 | success: function(data, status, ajax){ |
184 | if ( !data.ok ) alert(data.error.message); | 184 | if ( !data.ok ) alert(data.error.message); |
@@ -200,7 +200,7 @@ function Cart(config) { | @@ -200,7 +200,7 @@ function Cart(config) { | ||
200 | 200 | ||
201 | Cart.prototype.show = function() { | 201 | Cart.prototype.show = function() { |
202 | $.ajax({ | 202 | $.ajax({ |
203 | - url: '/profile/'+ this.enterprise +'/plugins/shopping_cart/show', | 203 | + url: '/profile/'+ this.enterprise +'/plugin/shopping_cart/show', |
204 | dataType: 'json', | 204 | dataType: 'json', |
205 | cache: false, | 205 | cache: false, |
206 | error: function(ajax, status, errorThrown) { | 206 | error: function(ajax, status, errorThrown) { |
@@ -215,7 +215,7 @@ function Cart(config) { | @@ -215,7 +215,7 @@ function Cart(config) { | ||
215 | } | 215 | } |
216 | Cart.prototype.hide = function() { | 216 | Cart.prototype.hide = function() { |
217 | $.ajax({ | 217 | $.ajax({ |
218 | - url: '/profile/'+ this.enterprise +'/plugins/shopping_cart/hide', | 218 | + url: '/profile/'+ this.enterprise +'/plugin/shopping_cart/hide', |
219 | dataType: 'json', | 219 | dataType: 'json', |
220 | cache: false, | 220 | cache: false, |
221 | error: function(ajax, status, errorThrown) { | 221 | error: function(ajax, status, errorThrown) { |
@@ -252,7 +252,7 @@ function Cart(config) { | @@ -252,7 +252,7 @@ function Cart(config) { | ||
252 | Cart.prototype.clean = function() { | 252 | Cart.prototype.clean = function() { |
253 | var me = this; | 253 | var me = this; |
254 | $.ajax({ | 254 | $.ajax({ |
255 | - url: '/profile/'+ me.enterprise +'/plugins/shopping_cart/clean', | 255 | + url: '/profile/'+ me.enterprise +'/plugin/shopping_cart/clean', |
256 | dataType: 'json', | 256 | dataType: 'json', |
257 | success: function(data, status, ajax){ | 257 | success: function(data, status, ajax){ |
258 | if ( !data.ok ) alert(data.error.message); | 258 | if ( !data.ok ) alert(data.error.message); |
@@ -284,7 +284,7 @@ function Cart(config) { | @@ -284,7 +284,7 @@ function Cart(config) { | ||
284 | var me = this; | 284 | var me = this; |
285 | $.ajax({ | 285 | $.ajax({ |
286 | type: 'POST', | 286 | type: 'POST', |
287 | - url: '/profile/'+ me.enterprise +'/plugins/shopping_cart/send_request', | 287 | + url: '/profile/'+ me.enterprise +'/plugin/shopping_cart/send_request', |
288 | data: params, | 288 | data: params, |
289 | dataType: 'json', | 289 | dataType: 'json', |
290 | success: function(data, status, ajax){ | 290 | success: function(data, status, ajax){ |
@@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
1 | +jQuery('#settings_delivery').click(function(){ | ||
2 | + jQuery('#delivery_settings').toggle('fast'); | ||
3 | +}); | ||
4 | + | ||
5 | +jQuery('#add-new-option').click(function(){ | ||
6 | + new_option = jQuery('#empty-option').clone(); | ||
7 | + new_option.removeAttr('id'); | ||
8 | + jQuery('#add-new-option-row').before(new_option); | ||
9 | + new_option.show(); | ||
10 | + return false; | ||
11 | +}); | ||
12 | + | ||
13 | +jQuery('.remove-option').live('click', function(){ | ||
14 | + jQuery(this).closest('tr').remove(); | ||
15 | + return false; | ||
16 | +}); |
plugins/shopping_cart/test/functional/shopping_cart_plugin_myprofile_controller_test.rb
@@ -13,46 +13,42 @@ class ShoppingCartPluginMyprofileControllerTest < ActionController::TestCase | @@ -13,46 +13,42 @@ class ShoppingCartPluginMyprofileControllerTest < ActionController::TestCase | ||
13 | attr_reader :enterprise | 13 | attr_reader :enterprise |
14 | 14 | ||
15 | should 'be able to enable shopping cart' do | 15 | should 'be able to enable shopping cart' do |
16 | - enterprise.shopping_cart = false | ||
17 | - enterprise.save | ||
18 | - post :edit, :profile => enterprise.identifier, :profile_attr => {:shopping_cart => '1'} | ||
19 | - enterprise.reload | 16 | + settings.enabled = false |
17 | + settings.save! | ||
18 | + post :edit, :profile => enterprise.identifier, :settings => {:enabled => '1'} | ||
20 | 19 | ||
21 | - assert enterprise.shopping_cart | 20 | + assert settings.enabled |
22 | end | 21 | end |
23 | 22 | ||
24 | should 'be able to disable shopping cart' do | 23 | should 'be able to disable shopping cart' do |
25 | - enterprise.shopping_cart = true | ||
26 | - enterprise.save | ||
27 | - post :edit, :profile => enterprise.identifier, :profile_attr => {:shopping_cart => '0'} | ||
28 | - enterprise.reload | 24 | + settings.enabled = true |
25 | + settings.save! | ||
26 | + post :edit, :profile => enterprise.identifier, :settings => {:enabled => '0'} | ||
29 | 27 | ||
30 | - assert !enterprise.shopping_cart | 28 | + assert !settings.enabled |
31 | end | 29 | end |
32 | 30 | ||
33 | should 'be able to enable shopping cart delivery' do | 31 | should 'be able to enable shopping cart delivery' do |
34 | - enterprise.shopping_cart_delivery = false | ||
35 | - enterprise.save | ||
36 | - post :edit, :profile => enterprise.identifier, :profile_attr => {:shopping_cart_delivery => '1'} | ||
37 | - enterprise.reload | 32 | + settings.delivery = false |
33 | + settings.save! | ||
34 | + post :edit, :profile => enterprise.identifier, :settings => {:delivery => '1'} | ||
38 | 35 | ||
39 | - assert enterprise.shopping_cart_delivery | 36 | + assert settings.delivery |
40 | end | 37 | end |
41 | 38 | ||
42 | should 'be able to disable shopping cart delivery' do | 39 | should 'be able to disable shopping cart delivery' do |
43 | - enterprise.shopping_cart_delivery = true | ||
44 | - enterprise.save | ||
45 | - post :edit, :profile => enterprise.identifier, :profile_attr => {:shopping_cart_delivery => '0'} | ||
46 | - enterprise.reload | 40 | + settings.delivery = true |
41 | + settings.save! | ||
42 | + post :edit, :profile => enterprise.identifier, :settings => {:delivery => '0'} | ||
47 | 43 | ||
48 | - assert !enterprise.shopping_cart_delivery | 44 | + assert !settings.delivery |
49 | end | 45 | end |
50 | 46 | ||
51 | should 'be able to choose the delivery price' do | 47 | should 'be able to choose the delivery price' do |
52 | price = 4.35 | 48 | price = 4.35 |
53 | - post :edit, :profile => enterprise.identifier, :profile_attr => {:shopping_cart_delivery_price => price} | ||
54 | - enterprise.reload | ||
55 | - assert enterprise.shopping_cart_delivery_price == price | 49 | + post :edit, :profile => enterprise.identifier, :settings => {:delivery_price => price} |
50 | + | ||
51 | + assert settings.delivery_price == price | ||
56 | end | 52 | end |
57 | 53 | ||
58 | should 'filter the reports correctly' do | 54 | should 'filter the reports correctly' do |
@@ -112,4 +108,11 @@ class ShoppingCartPluginMyprofileControllerTest < ActionController::TestCase | @@ -112,4 +108,11 @@ class ShoppingCartPluginMyprofileControllerTest < ActionController::TestCase | ||
112 | po.reload | 108 | po.reload |
113 | assert_equal ShoppingCartPlugin::PurchaseOrder::Status::CONFIRMED, po.status | 109 | assert_equal ShoppingCartPlugin::PurchaseOrder::Status::CONFIRMED, po.status |
114 | end | 110 | end |
111 | + | ||
112 | + private | ||
113 | + | ||
114 | + def settings | ||
115 | + @enterprise.reload | ||
116 | + Noosfero::Plugin::Settings.new(@enterprise, ShoppingCartPlugin) | ||
117 | + end | ||
115 | end | 118 | end |
plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb
@@ -17,25 +17,35 @@ | @@ -17,25 +17,35 @@ | ||
17 | <li><b><%= _('Full name') %>: </b><%= @customer[:name] %></li> | 17 | <li><b><%= _('Full name') %>: </b><%= @customer[:name] %></li> |
18 | <li><b><%= _('Email') %>: </b><%= @customer[:email] %></li> | 18 | <li><b><%= _('Email') %>: </b><%= @customer[:email] %></li> |
19 | <li><b><%= _('Phone number') %>: </b><%= @customer[:contact_phone] %></li> | 19 | <li><b><%= _('Phone number') %>: </b><%= @customer[:contact_phone] %></li> |
20 | - <% if !@customer[:address].blank? || !@customer[:city].blank? || !@customer[:zip_code].blank? %> | 20 | + <li><b><%= _('Payment') %>: </b><%= @customer[:payment] == 'money' ? _('Money') : _('Check') %></li> |
21 | + <% if @customer[:payment] == 'money' %> | ||
22 | + <li><b><%= _('Change') %>: </b><%= @customer[:change] %></li> | ||
23 | + <% end %> | ||
24 | + <% if !@customer[:address].blank? || !@customer[:city].blank? || !@customer[:zip_code].blank? || !@customer[:district].blank? || !@customer[:address_reference].blank? %> | ||
21 | <li><b><%= _('Address') %>:</b> | 25 | <li><b><%= _('Address') %>:</b> |
22 | <% end %> | 26 | <% end %> |
23 | <% if !@customer[:address].blank? %> | 27 | <% if !@customer[:address].blank? %> |
24 | <%= @customer[:address] %><br \> | 28 | <%= @customer[:address] %><br \> |
25 | <% end %> | 29 | <% end %> |
30 | + <% if !@customer[:district].blank? %> | ||
31 | + <%= @customer[:district] %><br \> | ||
32 | + <% end %> | ||
26 | <% if !@customer[:city].blank? %> | 33 | <% if !@customer[:city].blank? %> |
27 | <%= @customer[:city] %><br \> | 34 | <%= @customer[:city] %><br \> |
28 | <% end %> | 35 | <% end %> |
29 | <% if !@customer[:zip_code].blank? %> | 36 | <% if !@customer[:zip_code].blank? %> |
30 | <%= @customer[:zip_code] %> | 37 | <%= @customer[:zip_code] %> |
31 | <% end %> | 38 | <% end %> |
32 | - <% if !@customer[:address].blank? || !@customer[:city].blank? || !@customer[:zip_code].blank? %> | 39 | + <% if !@customer[:address_reference].blank? %> |
40 | + <%= @customer[:address_reference] %><br \> | ||
41 | + <% end %> | ||
42 | + <% if !@customer[:address].blank? || !@customer[:city].blank? || !@customer[:zip_code].blank? || !@customer[:district].blank? || !@customer[:address_reference].blank? %> | ||
33 | </li> | 43 | </li> |
34 | <% end %> | 44 | <% end %> |
35 | </ul> | 45 | </ul> |
36 | 46 | ||
37 | <p><%=_('Here are the products you bought:')%></p> | 47 | <p><%=_('Here are the products you bought:')%></p> |
38 | - <%= items_table(@items, @supplier, true) %> | 48 | + <%= items_table(@items, @supplier, @delivery_option, true) %> |
39 | 49 | ||
40 | <p> | 50 | <p> |
41 | --<br/> | 51 | --<br/> |
plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb
@@ -15,25 +15,35 @@ | @@ -15,25 +15,35 @@ | ||
15 | <li><b><%= _('Full name') %>: </b><%= @customer[:name] %></li> | 15 | <li><b><%= _('Full name') %>: </b><%= @customer[:name] %></li> |
16 | <li><b><%= _('Email') %>: </b><%= @customer[:email] %></li> | 16 | <li><b><%= _('Email') %>: </b><%= @customer[:email] %></li> |
17 | <li><b><%= _('Phone number') %>: </b><%= @customer[:contact_phone] %></li> | 17 | <li><b><%= _('Phone number') %>: </b><%= @customer[:contact_phone] %></li> |
18 | - <% if !@customer[:address].blank? || !@customer[:city].blank? || !@customer[:zip_code].blank? %> | 18 | + <li><b><%= _('Payment') %>: </b><%= @customer[:payment] == 'money' ? _('Money') : _('Check') %></li> |
19 | + <% if @customer[:payment] == 'money' %> | ||
20 | + <li><b><%= _('Change') %>: </b><%= @customer[:change] %></li> | ||
21 | + <% end %> | ||
22 | + <% if !@customer[:address].blank? || !@customer[:city].blank? || !@customer[:zip_code].blank? || !@customer[:district].blank? || !@customer[:address_reference].blank? %> | ||
19 | <li><b><%= _('Address') %>:</b> | 23 | <li><b><%= _('Address') %>:</b> |
20 | <% end %> | 24 | <% end %> |
21 | <% if !@customer[:address].blank? %> | 25 | <% if !@customer[:address].blank? %> |
22 | <%= @customer[:address] %><br \> | 26 | <%= @customer[:address] %><br \> |
23 | <% end %> | 27 | <% end %> |
28 | + <% if !@customer[:district].blank? %> | ||
29 | + <%= @customer[:district] %><br \> | ||
30 | + <% end %> | ||
24 | <% if !@customer[:city].blank? %> | 31 | <% if !@customer[:city].blank? %> |
25 | <%= @customer[:city] %><br \> | 32 | <%= @customer[:city] %><br \> |
26 | <% end %> | 33 | <% end %> |
27 | <% if !@customer[:zip_code].blank? %> | 34 | <% if !@customer[:zip_code].blank? %> |
28 | <%= @customer[:zip_code] %> | 35 | <%= @customer[:zip_code] %> |
29 | <% end %> | 36 | <% end %> |
30 | - <% if !@customer[:address].blank? || !@customer[:city].blank? || !@customer[:zip_code].blank? %> | 37 | + <% if !@customer[:address_reference].blank? %> |
38 | + <%= @customer[:address_reference] %><br \> | ||
39 | + <% end %> | ||
40 | + <% if !@customer[:address].blank? || !@customer[:city].blank? || !@customer[:zip_code].blank? || !@customer[:district].blank? || !@customer[:address_reference].blank? %> | ||
31 | </li> | 41 | </li> |
32 | <% end %> | 42 | <% end %> |
33 | </ul> | 43 | </ul> |
34 | 44 | ||
35 | <p><%=_('And here are the items bought by this customer:')%></p> | 45 | <p><%=_('And here are the items bought by this customer:')%></p> |
36 | - <%= items_table(@items, @supplier, true) %> | 46 | + <%= items_table(@items, @supplier, @delivery_option, true) %> |
37 | 47 | ||
38 | <p> | 48 | <p> |
39 | --<br/> | 49 | --<br/> |
plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb
1 | <h1> <%= _('Basket options') %> </h1> | 1 | <h1> <%= _('Basket options') %> </h1> |
2 | 2 | ||
3 | -<% form_for(:profile_attr, profile, :url => {:action => 'edit'}, :html => {:method => 'post'}) do |f| %> | ||
4 | - <%= labelled_form_field(_('Enabled?'), f.check_box(:shopping_cart)) %> | ||
5 | - <%= labelled_form_field(_('Delivery?'), f.check_box(:shopping_cart_delivery)) %> | ||
6 | - <%= labelled_form_field(_('Delivery price:'), f.text_field(:shopping_cart_delivery_price)) %> | 3 | +<% form_for(:settings, @settings, :url => {:action => 'edit'}, :html => {:method => 'post'}) do |f| %> |
4 | + <%= labelled_form_field(_('Enabled?'), f.check_box(:enabled)) %> | ||
5 | + <%= labelled_form_field(_('Delivery?'), f.check_box(:delivery)) %> | ||
6 | + <% display_delivery_settings = @settings.delivery ? 'auto' : 'none' %> | ||
7 | + <fieldset id='delivery_settings' style="display: <%= display_delivery_settings %>"><legend><%=_('Delivery')%></legend> | ||
8 | + <table> | ||
9 | + <tr> | ||
10 | + <th><%= _('Option') %></th> | ||
11 | + <th><%= _('Price') %></th> | ||
12 | + <th> </th> | ||
13 | + </tr> | ||
14 | + <% @settings.delivery_options.each do |option, price| %> | ||
15 | + <tr> | ||
16 | + <td><%= text_field_tag('settings[delivery_options][options][]', option, :style => 'width: 100%') %></td> | ||
17 | + <td><%= text_field_tag('settings[delivery_options][prices][]', price, :style => 'width: 100%') %></td> | ||
18 | + <td><%= button_without_text(:close, _('Remove option'), '', :class => 'remove-option') %></td> | ||
19 | + </tr> | ||
20 | + <% end %> | ||
21 | + <tr> | ||
22 | + <td><%= text_field_tag('settings[delivery_options][options][]', nil, :style => 'width: 100%') %></td> | ||
23 | + <td><%= text_field_tag('settings[delivery_options][prices][]', nil, :style => 'width: 100%') %></td> | ||
24 | + <td><%= button_without_text(:close, _('Remove option'), '', :class => 'remove-option') %></td> | ||
25 | + </tr> | ||
26 | + <tr id='add-new-option-row'> | ||
27 | + <td colspan='3' style='background-color: #EEE; text-align: center'><%= link_to(_('ADD NEW OPTION'), '', :id => 'add-new-option') %></td> | ||
28 | + </tr> | ||
29 | + <tr id="empty-option" style='display: none'> | ||
30 | + <td><%= text_field_tag('settings[delivery_options][options][]', nil, :style => 'width: 100%') %></td> | ||
31 | + <td><%= text_field_tag('settings[delivery_options][prices][]', nil, :style => 'width: 100%') %></td> | ||
32 | + <td><%= button_without_text(:close, _('Remove option'), '', :class => 'remove-option') %></td> | ||
33 | + </tr> | ||
34 | + </table> | ||
35 | + | ||
36 | + <%= labelled_form_field(_('Free delivery price:'), f.text_field(:free_delivery_price)) %> | ||
37 | + <%= content_tag('small', _('Empty stands for no free delivery price.')) %> | ||
38 | + </fieldset> | ||
7 | <br style='clear: both'/> | 39 | <br style='clear: both'/> |
8 | <br style='clear: both'/> | 40 | <br style='clear: both'/> |
9 | <div> | 41 | <div> |
@@ -11,3 +43,5 @@ | @@ -11,3 +43,5 @@ | ||
11 | <%= button :back, _('Back to control panel'), :controller => 'profile_editor' %> | 43 | <%= button :back, _('Back to control panel'), :controller => 'profile_editor' %> |
12 | </div> | 44 | </div> |
13 | <% end%> | 45 | <% end%> |
46 | + | ||
47 | +<%= javascript_include_tag '../plugins/shopping_cart/edit' %> |
plugins/shopping_cart/views/shopping_cart_plugin_profile/buy.html.erb
@@ -6,30 +6,26 @@ | @@ -6,30 +6,26 @@ | ||
6 | <%= labelled_form_field('* ' + _("Name"), f.text_field(:name, :class => 'required') ) %> | 6 | <%= labelled_form_field('* ' + _("Name"), f.text_field(:name, :class => 'required') ) %> |
7 | <%= labelled_form_field('* ' + _("Email"), f.text_field(:email, :class => 'required email') ) %> | 7 | <%= labelled_form_field('* ' + _("Email"), f.text_field(:email, :class => 'required email') ) %> |
8 | <%= labelled_form_field('* ' + _("Contact phone"), f.text_field(:contact_phone, :class => 'required') ) %> | 8 | <%= labelled_form_field('* ' + _("Contact phone"), f.text_field(:contact_phone, :class => 'required') ) %> |
9 | + <%= labelled_form_field(_('Delivery option'), select_tag(:delivery_option, options_for_select(select_delivery_options(@settings.delivery_options, environment)), 'data-profile-identifier' => profile.identifier)) unless !@settings.delivery || (@settings.free_delivery_price && get_total(session[:cart][:items]) >= @settings.free_delivery_price) %> | ||
10 | + <%= labelled_form_field(_('Payment'), select_tag('customer[payment]', options_for_select([[_("Money"), :money],[_('Check'), :check]]))) %> | ||
11 | + <%= labelled_form_field(_('Change'), text_field_tag('customer[change]')) %> | ||
9 | </div> | 12 | </div> |
10 | - <fieldset><legend><%=_('Delivery Address')%></legend> | ||
11 | - <%= labelled_form_field(_('Address (street and number)'), f.text_field(:address)) %> | ||
12 | - <%= labelled_form_field( _("City"), f.text_field(:city)) %> | ||
13 | - <%= labelled_form_field(_('ZIP code'), f.text_field(:zip_code)) %> | ||
14 | - </fieldset> | 13 | + <% if @settings.delivery %> |
14 | + <fieldset><legend><%=_('Delivery Address')%></legend> | ||
15 | + <%= labelled_form_field(_('Address (street and number)'), f.text_field(:address)) %> | ||
16 | + <%= labelled_form_field(_('Address reference'), f.text_field(:address_reference)) %> | ||
17 | + <%= labelled_form_field(_('District'), f.text_field(:district)) %> | ||
18 | + <%= labelled_form_field( _("City"), f.text_field(:city)) %> | ||
19 | + <%= labelled_form_field(_('ZIP code'), f.text_field(:zip_code)) %> | ||
20 | + </fieldset> | ||
21 | + <% end %> | ||
15 | <div id="cart-form-actions"> | 22 | <div id="cart-form-actions"> |
16 | <%= submit_button(:send, _('Send buy request')) %> | 23 | <%= submit_button(:send, _('Send buy request')) %> |
17 | </div> | 24 | </div> |
18 | <% end %> | 25 | <% end %> |
19 | - <%= items_table(session[:cart][:items], profile) %> | 26 | + <% delivery_option = @settings.delivery_options.first && @settings.delivery_options.first.first %> |
27 | + <%= items_table(session[:cart][:items], profile, delivery_option) %> | ||
20 | <%= link_to '', '#', :onclick => "Cart.colorbox_close(this);", :class => 'cart-box-close icon-cancel' %> | 28 | <%= link_to '', '#', :onclick => "Cart.colorbox_close(this);", :class => 'cart-box-close icon-cancel' %> |
21 | </div> | 29 | </div> |
22 | 30 | ||
23 | -<script type="text/javascript"> | ||
24 | -//<![CDATA[ | ||
25 | - jQuery(document).ready(function(){ | ||
26 | - jQuery("#cart-request-form").validate({ | ||
27 | - submitHandler: function(form) { | ||
28 | - jQuery(form).find('input.submit').attr('disabled', true); | ||
29 | - jQuery('#cboxLoadingOverlay').show().addClass('loading'); | ||
30 | - jQuery('#cboxLoadingGraphic').show().addClass('loading'); | ||
31 | - } | ||
32 | - }); | ||
33 | - }); | ||
34 | -//]]> | ||
35 | -</script> | 31 | +<%= javascript_include_tag '../plugins/shopping_cart/buy' %> |
1.75 KB
3.58 KB
public/stylesheets/application.css
@@ -2677,6 +2677,40 @@ div#activation_enterprise label, div#activation_enterprise input, div#activation | @@ -2677,6 +2677,40 @@ div#activation_enterprise label, div#activation_enterprise input, div#activation | ||
2677 | .msie #product-list h3 { | 2677 | .msie #product-list h3 { |
2678 | margin-top: -15px; | 2678 | margin-top: -15px; |
2679 | } | 2679 | } |
2680 | + | ||
2681 | +.l-sidebar-left-bar ul, | ||
2682 | +.l-sidebar-right-bar ul { | ||
2683 | + list-style-type: none; | ||
2684 | + margin-left: 0; | ||
2685 | + padding: 1em 1em 0.5em 1em; | ||
2686 | +} | ||
2687 | + | ||
2688 | +.l-sidebar-left-bar ul ul, | ||
2689 | +.l-sidebar-right-bar ul ul { | ||
2690 | + padding-top: 0; | ||
2691 | +} | ||
2692 | + | ||
2693 | +.l-sidebar-left-bar ul{ | ||
2694 | + background-color: #eeeeec; | ||
2695 | + border-radius: 5px; | ||
2696 | +} | ||
2697 | + | ||
2698 | +.l-sidebar-left-bar a, | ||
2699 | +.l-sidebar-right-bar a { | ||
2700 | + text-decoration: none; | ||
2701 | +} | ||
2702 | + | ||
2703 | +.l-sidebar-left-bar a:hover, | ||
2704 | +.l-sidebar-right-bar a:hover { | ||
2705 | + text-decoration: underline; | ||
2706 | +} | ||
2707 | + | ||
2708 | +.l-sidebar-left-bar li, | ||
2709 | +.l-sidebar-right-bar li { | ||
2710 | + margin: 0; | ||
2711 | + padding: 0; | ||
2712 | +} | ||
2713 | + | ||
2680 | /* * * Show Product * * * * * * * * * * * * */ | 2714 | /* * * Show Product * * * * * * * * * * * * */ |
2681 | 2715 | ||
2682 | .controller-catalog #show_product .product-pic { | 2716 | .controller-catalog #show_product .product-pic { |
@@ -6066,6 +6100,35 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { | @@ -6066,6 +6100,35 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { | ||
6066 | line-height: 1.5; | 6100 | line-height: 1.5; |
6067 | } | 6101 | } |
6068 | 6102 | ||
6103 | +/* Sidebar Layout */ | ||
6104 | + | ||
6105 | +.l-sidebar-left-bar { | ||
6106 | + float: left; | ||
6107 | + width: 20%; | ||
6108 | +} | ||
6109 | + | ||
6110 | +.l-sidebar-left-content { | ||
6111 | + float: right; | ||
6112 | + width: 78%; | ||
6113 | +} | ||
6114 | + | ||
6115 | +.l-sidebar-right-bar { | ||
6116 | + float: right; | ||
6117 | + width: 20%; | ||
6118 | +} | ||
6119 | + | ||
6120 | +.l-sidebar-right-content { | ||
6121 | + float: left; | ||
6122 | + width: 78%; | ||
6123 | +} | ||
6124 | + | ||
6125 | +/* Breadcrumb */ | ||
6126 | + | ||
6127 | +#breadcrumb { | ||
6128 | + font-size: 16px; | ||
6129 | + margin: 15px 0; | ||
6130 | +} | ||
6131 | + | ||
6069 | .controller-profile_editor #profile-data { | 6132 | .controller-profile_editor #profile-data { |
6070 | display: table; | 6133 | display: table; |
6071 | width: auto; | 6134 | width: auto; |
@@ -6114,3 +6177,10 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { | @@ -6114,3 +6177,10 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { | ||
6114 | width: 100px; | 6177 | width: 100px; |
6115 | text-align: center; | 6178 | text-align: center; |
6116 | } | 6179 | } |
6180 | + | ||
6181 | +#product-list .highlighted img.star { | ||
6182 | + position: absolute; | ||
6183 | + top: 2px; | ||
6184 | + right: 2px; | ||
6185 | + z-index: 10; | ||
6186 | +} |
test/functional/catalog_controller_test.rb
@@ -109,4 +109,71 @@ class CatalogControllerTest < ActionController::TestCase | @@ -109,4 +109,71 @@ class CatalogControllerTest < ActionController::TestCase | ||
109 | assert_tag :tag => 'span', :content => 'This is Plugin2 speaking!', :attributes => {:id => 'plugin2'} | 109 | assert_tag :tag => 'span', :content => 'This is Plugin2 speaking!', :attributes => {:id => 'plugin2'} |
110 | end | 110 | end |
111 | 111 | ||
112 | + should 'get categories of the right level' do | ||
113 | + pc1 = ProductCategory.create!(:name => "PC1", :environment => @enterprise.environment) | ||
114 | + pc2 = ProductCategory.create!(:name => "PC2", :environment => @enterprise.environment, :parent_id => pc1.id) | ||
115 | + pc3 = ProductCategory.create!(:name => "PC3", :environment => @enterprise.environment, :parent_id => pc1.id) | ||
116 | + pc4 = ProductCategory.create!(:name => "PC4", :environment => @enterprise.environment, :parent_id => pc2.id) | ||
117 | + p1 = fast_create(Product, :product_category_id => pc1.id, :enterprise_id => @enterprise.id) | ||
118 | + p2 = fast_create(Product, :product_category_id => pc2.id, :enterprise_id => @enterprise.id) | ||
119 | + p3 = fast_create(Product, :product_category_id => pc3.id, :enterprise_id => @enterprise.id) | ||
120 | + p4 = fast_create(Product, :product_category_id => pc4.id, :enterprise_id => @enterprise.id) | ||
121 | + | ||
122 | + get :index, :profile => @enterprise.identifier, :level => pc1.id | ||
123 | + | ||
124 | + assert_not_includes assigns(:categories), pc1 | ||
125 | + assert_includes assigns(:categories), pc2 | ||
126 | + assert_includes assigns(:categories), pc3 | ||
127 | + assert_not_includes assigns(:categories), pc4 | ||
128 | + end | ||
129 | + | ||
130 | + should 'filter products based on level selected' do | ||
131 | + pc1 = ProductCategory.create!(:name => "PC1", :environment => @enterprise.environment) | ||
132 | + pc2 = ProductCategory.create!(:name => "PC2", :environment => @enterprise.environment, :parent_id => pc1.id) | ||
133 | + pc3 = ProductCategory.create!(:name => "PC3", :environment => @enterprise.environment, :parent_id => pc1.id) | ||
134 | + pc4 = ProductCategory.create!(:name => "PC4", :environment => @enterprise.environment, :parent_id => pc2.id) | ||
135 | + p1 = fast_create(Product, :product_category_id => pc1.id, :enterprise_id => @enterprise.id) | ||
136 | + p2 = fast_create(Product, :product_category_id => pc2.id, :enterprise_id => @enterprise.id) | ||
137 | + p3 = fast_create(Product, :product_category_id => pc3.id, :enterprise_id => @enterprise.id) | ||
138 | + p4 = fast_create(Product, :product_category_id => pc4.id, :enterprise_id => @enterprise.id) | ||
139 | + | ||
140 | + get :index, :profile => @enterprise.identifier, :level => pc2.id | ||
141 | + | ||
142 | + assert_not_includes assigns(:products), p1 | ||
143 | + assert_includes assigns(:products), p2 | ||
144 | + assert_not_includes assigns(:products), p3 | ||
145 | + assert_includes assigns(:products), p4 | ||
146 | + end | ||
147 | + | ||
148 | + should 'get products ordered by availability, highlighted and then name' do | ||
149 | + p1 = fast_create(Product, :enterprise_id => @enterprise.id, :name => 'Zebra', :available => true, :highlighted => true) | ||
150 | + p2 = fast_create(Product, :enterprise_id => @enterprise.id, :name => 'Car', :available => true) | ||
151 | + p3 = fast_create(Product, :enterprise_id => @enterprise.id, :name => 'Panda', :available => true) | ||
152 | + p4 = fast_create(Product, :enterprise_id => @enterprise.id, :name => 'Pen', :available => false, :highlighted => true) | ||
153 | + p5 = fast_create(Product, :enterprise_id => @enterprise.id, :name => 'Ball', :available => false) | ||
154 | + p6 = fast_create(Product, :enterprise_id => @enterprise.id, :name => 'Medal', :available => false) | ||
155 | + | ||
156 | + get :index, :profile => @enterprise.identifier | ||
157 | + | ||
158 | + assert_equal [p1,p2,p3,p4,p5,p6], assigns(:products) | ||
159 | + end | ||
160 | + | ||
161 | + should 'add highlighted CSS class around a highlighted product' do | ||
162 | + prod = @enterprise.products.create!(:name => 'Highlighted Product', :product_category => @product_category, :highlighted => true) | ||
163 | + get :index, :profile => @enterprise.identifier | ||
164 | + assert_tag :tag => 'li', :attributes => { :class => 'product highlighted' }, :content => /Highlighted Product/ | ||
165 | + end | ||
166 | + | ||
167 | + should 'do not add highlighted CSS class around an ordinary product' do | ||
168 | + prod = @enterprise.products.create!(:name => 'Ordinary Product', :product_category => @product_category, :highlighted => false) | ||
169 | + get :index, :profile => @enterprise.identifier | ||
170 | + assert_no_tag :tag => 'li', :attributes => { :class => 'product highlighted' }, :content => /Ordinary Product/ | ||
171 | + end | ||
172 | + | ||
173 | + should 'display star image in highlighted product' do | ||
174 | + prod = @enterprise.products.create!(:name => 'The Eyes Are The Light', :product_category => @product_category, :highlighted => true) | ||
175 | + get :index, :profile => @enterprise.identifier | ||
176 | + assert_tag :tag => 'img', :attributes => { :class => 'star', :src => /star.png/ } | ||
177 | + end | ||
178 | + | ||
112 | end | 179 | end |
test/functional/search_controller_test.rb
@@ -926,6 +926,20 @@ class SearchControllerTest < ActionController::TestCase | @@ -926,6 +926,20 @@ class SearchControllerTest < ActionController::TestCase | ||
926 | end | 926 | end |
927 | end | 927 | end |
928 | 928 | ||
929 | + should 'add highlighted CSS class around a highlighted product' do | ||
930 | + enterprise = fast_create(Enterprise) | ||
931 | + product = Product.create!(:name => 'Enter Sandman', :enterprise_id => enterprise.id, :product_category_id => @product_category.id, :highlighted => true) | ||
932 | + get :products | ||
933 | + assert_tag :tag => 'li', :attributes => { :class => 'search-product-item highlighted' }, :content => /Enter Sandman/ | ||
934 | + end | ||
935 | + | ||
936 | + should 'do not add highlighted CSS class around an ordinary product' do | ||
937 | + enterprise = fast_create(Enterprise) | ||
938 | + product = Product.create!(:name => 'Holier Than Thou', :enterprise_id => enterprise.id, :product_category_id => @product_category.id, :highlighted => false) | ||
939 | + get :products | ||
940 | + assert_no_tag :tag => 'li', :attributes => { :class => 'search-product-item highlighted' }, :content => /Holier Than Thou/ | ||
941 | + end | ||
942 | + | ||
929 | ################################################################## | 943 | ################################################################## |
930 | ################################################################## | 944 | ################################################################## |
931 | 945 |
test/unit/category_test.rb
@@ -552,4 +552,62 @@ class CategoryTest < ActiveSupport::TestCase | @@ -552,4 +552,62 @@ class CategoryTest < ActiveSupport::TestCase | ||
552 | cat.save! | 552 | cat.save! |
553 | end | 553 | end |
554 | 554 | ||
555 | + should 'return categories of a level' do | ||
556 | + c1 = fast_create(Category) | ||
557 | + c2 = fast_create(Category) | ||
558 | + c3 = fast_create(Category, :parent_id => c1) | ||
559 | + c4 = fast_create(Category, :parent_id => c1) | ||
560 | + c5 = fast_create(Category, :parent_id => c2) | ||
561 | + c6 = fast_create(Category, :parent_id => c3) | ||
562 | + | ||
563 | + assert_includes Category.on_level(nil), c1 | ||
564 | + assert_includes Category.on_level(nil), c2 | ||
565 | + assert_includes Category.on_level(c1), c3 | ||
566 | + assert_includes Category.on_level(c1), c4 | ||
567 | + assert_includes Category.on_level(c2), c5 | ||
568 | + assert_includes Category.on_level(c3), c6 | ||
569 | + end | ||
570 | + | ||
571 | + should 'on level named_scope must be able to receive parent or parent_id' do | ||
572 | + parent = fast_create(Category) | ||
573 | + category = fast_create(Category, :parent_id => parent) | ||
574 | + | ||
575 | + assert_includes Category.on_level(parent), category | ||
576 | + assert_includes Category.on_level(parent.id), category | ||
577 | + end | ||
578 | + | ||
579 | + should 'list category sub-categories' do | ||
580 | + c1 = Category.create!(:name => 'Category 1', :environment => Environment.default) | ||
581 | + c2 = Category.create!(:name => 'Category 2', :environment => Environment.default) | ||
582 | + c3 = Category.create!(:name => 'Category 3', :environment => Environment.default, :parent_id => c1) | ||
583 | + c4 = Category.create!(:name => 'Category 4', :environment => Environment.default, :parent_id => c1) | ||
584 | + c5 = Category.create!(:name => 'Category 5', :environment => Environment.default, :parent_id => c3) | ||
585 | + | ||
586 | + sub_categories = Category.sub_categories(c1) | ||
587 | + | ||
588 | + assert ActiveRecord::NamedScope::Scope, sub_categories.class | ||
589 | + assert_not_includes sub_categories, c1 | ||
590 | + assert_not_includes sub_categories, c2 | ||
591 | + assert_includes sub_categories, c3 | ||
592 | + assert_includes sub_categories, c4 | ||
593 | + assert_includes sub_categories, c5 | ||
594 | + end | ||
595 | + | ||
596 | + should 'list category sub-tree' do | ||
597 | + c1 = Category.create!(:name => 'Category 1', :environment => Environment.default) | ||
598 | + c2 = Category.create!(:name => 'Category 2', :environment => Environment.default) | ||
599 | + c3 = Category.create!(:name => 'Category 3', :environment => Environment.default, :parent_id => c1) | ||
600 | + c4 = Category.create!(:name => 'Category 4', :environment => Environment.default, :parent_id => c1) | ||
601 | + c5 = Category.create!(:name => 'Category 5', :environment => Environment.default, :parent_id => c3) | ||
602 | + | ||
603 | + sub_tree = Category.sub_tree(c1) | ||
604 | + | ||
605 | + assert ActiveRecord::NamedScope::Scope, sub_tree.class | ||
606 | + assert_includes sub_tree, c1 | ||
607 | + assert_not_includes sub_tree, c2 | ||
608 | + assert_includes sub_tree, c3 | ||
609 | + assert_includes sub_tree, c4 | ||
610 | + assert_includes sub_tree, c5 | ||
611 | + end | ||
612 | + | ||
555 | end | 613 | end |
test/unit/display_helper_test.rb
@@ -44,4 +44,14 @@ class DisplayHelperTest < ActiveSupport::TestCase | @@ -44,4 +44,14 @@ class DisplayHelperTest < ActiveSupport::TestCase | ||
44 | assert_equal 'go to <a href="http://www.noosfero.org" onclick="return confirm(\'Are you sure you want to visit this web site?\')" rel="nofolow" target="_blank">www.​noos​fero​.org</a> yeah!', html | 44 | assert_equal 'go to <a href="http://www.noosfero.org" onclick="return confirm(\'Are you sure you want to visit this web site?\')" rel="nofolow" target="_blank">www.​noos​fero​.org</a> yeah!', html |
45 | end | 45 | end |
46 | 46 | ||
47 | + should 'return path to file under theme dir if theme has that file' do | ||
48 | + stubs(:theme_path).returns('/designs/themes/noosfero') | ||
49 | + assert_equal '/designs/themes/noosfero/images/rails.png', themed_path('/images/rails.png') | ||
50 | + end | ||
51 | + | ||
52 | + should 'return path to file under public dir if theme hasnt that file' do | ||
53 | + stubs(:theme_path).returns('/designs/themes/noosfero') | ||
54 | + assert_equal '/images/invalid-file.png', themed_path('/images/invalid-file.png') | ||
55 | + end | ||
56 | + | ||
47 | end | 57 | end |
test/unit/person_test.rb
@@ -64,7 +64,7 @@ class PersonTest < ActiveSupport::TestCase | @@ -64,7 +64,7 @@ class PersonTest < ActiveSupport::TestCase | ||
64 | 64 | ||
65 | should "have person info fields" do | 65 | should "have person info fields" do |
66 | p = Person.new(:environment => Environment.default) | 66 | p = Person.new(:environment => Environment.default) |
67 | - [ :name, :photo, :contact_information, :birth_date, :sex, :address, :city, :state, :country, :zip_code, :image ].each do |i| | 67 | + [ :name, :photo, :contact_information, :birth_date, :sex, :address, :city, :state, :country, :zip_code, :image, :district, :address_reference ].each do |i| |
68 | assert_respond_to p, i | 68 | assert_respond_to p, i |
69 | end | 69 | end |
70 | end | 70 | end |
test/unit/plugin_settings_test.rb
@@ -10,29 +10,41 @@ class PluginSettingsTest < ActiveSupport::TestCase | @@ -10,29 +10,41 @@ class PluginSettingsTest < ActiveSupport::TestCase | ||
10 | 10 | ||
11 | def setup | 11 | def setup |
12 | @environment = Environment.new | 12 | @environment = Environment.new |
13 | + @profile = Profile.new | ||
13 | @plugin = SolarSystemPlugin | 14 | @plugin = SolarSystemPlugin |
14 | - @settings = Noosfero::Plugin::Settings.new(@environment, @plugin) | ||
15 | end | 15 | end |
16 | 16 | ||
17 | - attr_accessor :environment, :plugin, :settings | 17 | + attr_accessor :environment, :profile, :plugin, :settings |
18 | 18 | ||
19 | - should 'store setttings in environment' do | 19 | + should 'store setttings on any model that offers settings' do |
20 | + base = environment | ||
21 | + settings = Noosfero::Plugin::Settings.new(base, plugin) | ||
20 | settings.star = 'sun' | 22 | settings.star = 'sun' |
21 | settings.planets = 8 | 23 | settings.planets = 8 |
22 | - assert_equal 'sun', environment.settings[:solar_system_plugin][:star] | ||
23 | - assert_equal 8, environment.settings[:solar_system_plugin][:planets] | 24 | + assert_equal 'sun', base.settings[:solar_system_plugin][:star] |
25 | + assert_equal 8, base.settings[:solar_system_plugin][:planets] | ||
26 | + assert_equal 'sun', settings.star | ||
27 | + assert_equal 8, settings.planets | ||
28 | + | ||
29 | + base = profile | ||
30 | + settings = Noosfero::Plugin::Settings.new(base, plugin) | ||
31 | + settings.star = 'sun' | ||
32 | + settings.planets = 8 | ||
33 | + assert_equal 'sun', base.settings[:solar_system_plugin][:star] | ||
34 | + assert_equal 8, base.settings[:solar_system_plugin][:planets] | ||
24 | assert_equal 'sun', settings.star | 35 | assert_equal 'sun', settings.star |
25 | assert_equal 8, settings.planets | 36 | assert_equal 8, settings.planets |
26 | end | 37 | end |
27 | 38 | ||
28 | - should 'save environment on save' do | 39 | + should 'save base on save' do |
29 | environment.expects(:save!) | 40 | environment.expects(:save!) |
41 | + settings = Noosfero::Plugin::Settings.new(environment, plugin) | ||
30 | settings.save! | 42 | settings.save! |
31 | end | 43 | end |
32 | 44 | ||
33 | should 'use default value defined on the plugin class' do | 45 | should 'use default value defined on the plugin class' do |
46 | + settings = Noosfero::Plugin::Settings.new(profile, plugin) | ||
34 | assert_equal 42, settings.secret | 47 | assert_equal 42, settings.secret |
35 | end | 48 | end |
36 | 49 | ||
37 | end | 50 | end |
38 | - |
test/unit/product_test.rb
@@ -772,4 +772,40 @@ class ProductTest < ActiveSupport::TestCase | @@ -772,4 +772,40 @@ class ProductTest < ActiveSupport::TestCase | ||
772 | assert_equal [prod3, prod2, prod1], Product.more_recent | 772 | assert_equal [prod3, prod2, prod1], Product.more_recent |
773 | end | 773 | end |
774 | 774 | ||
775 | + should 'return products from a category' do | ||
776 | + pc1 = ProductCategory.create!(:name => 'PC1', :environment => Environment.default) | ||
777 | + pc2 = ProductCategory.create!(:name => 'PC2', :environment => Environment.default) | ||
778 | + pc3 = ProductCategory.create!(:name => 'PC3', :environment => Environment.default, :parent => pc1) | ||
779 | + p1 = fast_create(Product, :product_category_id => pc1) | ||
780 | + p2 = fast_create(Product, :product_category_id => pc1) | ||
781 | + p3 = fast_create(Product, :product_category_id => pc2) | ||
782 | + p4 = fast_create(Product, :product_category_id => pc3) | ||
783 | + | ||
784 | + products = Product.from_category(pc1) | ||
785 | + | ||
786 | + assert_includes products, p1 | ||
787 | + assert_includes products, p2 | ||
788 | + assert_not_includes products, p3 | ||
789 | + assert_includes products, p4 | ||
790 | + end | ||
791 | + | ||
792 | + should 'not crash if nil is passed to from_category' do | ||
793 | + assert_nothing_raised do | ||
794 | + Product.from_category(nil) | ||
795 | + end | ||
796 | + end | ||
797 | + | ||
798 | + should 'return from_category scope untouched if passed nil' do | ||
799 | + enterprise = fast_create(Enterprise) | ||
800 | + p1 = fast_create(Product, :enterprise_id => enterprise.id) | ||
801 | + p2 = fast_create(Product, :enterprise_id => enterprise.id) | ||
802 | + p3 = fast_create(Product, :enterprise_id => enterprise.id) | ||
803 | + | ||
804 | + products = enterprise.products.from_category(nil) | ||
805 | + | ||
806 | + assert_includes products, p1 | ||
807 | + assert_includes products, p2 | ||
808 | + assert_includes products, p3 | ||
809 | + end | ||
810 | + | ||
775 | end | 811 | end |