spree_promo 1.2.5 → 1.3.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. data/app/assets/javascripts/admin/promotions.js +10 -1
  2. data/app/assets/stylesheets/admin/spree_promo.css +0 -1
  3. data/app/controllers/spree/admin/promotion_actions_controller.rb +2 -2
  4. data/app/controllers/spree/admin/promotion_rules_controller.rb +2 -2
  5. data/app/controllers/spree/checkout_controller_decorator.rb +5 -16
  6. data/app/controllers/spree/orders_controller_decorator.rb +2 -18
  7. data/app/controllers/spree/store_controller_decorator.rb +55 -0
  8. data/app/models/spree/order_decorator.rb +5 -14
  9. data/app/models/spree/order_updater_decorator.rb +14 -0
  10. data/app/models/spree/promotion/actions/create_adjustment.rb +12 -22
  11. data/app/models/spree/promotion/actions/create_line_items.rb +2 -18
  12. data/app/models/spree/promotion/rules/first_order.rb +2 -19
  13. data/app/models/spree/promotion/rules/user_logged_in.rb +8 -1
  14. data/app/models/spree/promotion.rb +6 -6
  15. data/app/models/spree/promotion_action_line_item.rb +2 -0
  16. data/app/overrides/promo_admin_tabs.rb +1 -1
  17. data/app/views/spree/admin/promotion_actions/create.js.erb +6 -3
  18. data/app/views/spree/admin/promotion_actions/destroy.js.erb +1 -2
  19. data/app/views/spree/admin/promotion_rules/create.js.erb +6 -0
  20. data/app/views/spree/admin/promotion_rules/destroy.js.erb +1 -1
  21. data/app/views/spree/admin/promotions/_actions.html.erb +21 -15
  22. data/app/views/spree/admin/promotions/_form.html.erb +55 -51
  23. data/app/views/spree/admin/promotions/_promotion_action.html.erb +5 -5
  24. data/app/views/spree/admin/promotions/_promotion_rule.html.erb +5 -4
  25. data/app/views/spree/admin/promotions/_rules.html.erb +39 -26
  26. data/app/views/spree/admin/promotions/actions/_create_adjustment.html.erb +8 -9
  27. data/app/views/spree/admin/promotions/actions/_create_line_items.html.erb +19 -40
  28. data/app/views/spree/admin/promotions/edit.html.erb +22 -6
  29. data/app/views/spree/admin/promotions/index.html.erb +49 -35
  30. data/app/views/spree/admin/promotions/new.html.erb +13 -3
  31. data/app/views/spree/admin/promotions/rules/_item_total.html.erb +6 -7
  32. data/app/views/spree/admin/promotions/rules/_landing_page.html.erb +5 -8
  33. data/app/views/spree/admin/promotions/rules/_product.html.erb +7 -8
  34. data/app/views/spree/admin/promotions/rules/_user_logged_in.html.erb +0 -3
  35. data/config/locales/en.yml +8 -2
  36. data/config/routes.rb +1 -1
  37. data/db/migrate/20120831092359_spree_promo_one_two.rb +45 -0
  38. data/lib/spree/promo/engine.rb +5 -6
  39. metadata +11 -26
  40. data/app/assets/stylesheets/admin/promotions.css +0 -44
  41. data/db/migrate/20100419190933_rename_coupons_to_promotions.rb +0 -10
  42. data/db/migrate/20100426100726_create_promotion_rules.rb +0 -24
  43. data/db/migrate/20100501084722_match_policy_for_promotions.rb +0 -5
  44. data/db/migrate/20100501095202_create_promotion_rules_users.rb +0 -14
  45. data/db/migrate/20100502163939_name_for_promotions.rb +0 -5
  46. data/db/migrate/20100923095305_update_calculable_type_for_promotions.rb +0 -9
  47. data/db/migrate/20101026184833_migrate_adjustments.rb +0 -9
  48. data/db/migrate/20110331094351_promotion_changes_to_subclass_of_activator.rb +0 -22
  49. data/db/migrate/20110404123358_create_promotion_actions.rb +0 -9
  50. data/db/migrate/20110601202923_create_promotion_action_line_items.rb +0 -10
  51. data/db/migrate/20120119024707_namespace_promo_tables.rb +0 -85
  52. data/db/migrate/20120119024708_create_spree_pending_promotions.rb +0 -11
  53. data/db/migrate/20120119024721_content_visited_event.rb +0 -29
@@ -1,6 +1,15 @@
1
1
  var initProductActions = function(){
2
2
 
3
- $(".product_autocomplete").product_autocomplete();
3
+ // Add classes on promotion items for design
4
+ $('a.delete').live('mouseover mouseout', function(event) {
5
+ if (event.type == 'mouseover') {
6
+ $(this).parent().addClass('action-remove');
7
+ } else {
8
+ $(this).parent().removeClass('action-remove');
9
+ }
10
+ });
11
+
12
+ $(".variant_autocomplete").variantAutocomplete();
4
13
 
5
14
  $('.calculator-fields').each(function(){
6
15
  var $fields_container = $(this);
@@ -1,4 +1,3 @@
1
1
  /*
2
2
  *= require admin/spree_core
3
- *= require admin/promotions
4
3
  */
@@ -5,7 +5,7 @@ class Spree::Admin::PromotionActionsController < Spree::Admin::BaseController
5
5
  @promotion_action = params[:action_type].constantize.new(params[:promotion_action])
6
6
  @promotion_action.promotion = @promotion
7
7
  if @promotion_action.save
8
- flash.notice = I18n.t(:successfully_created, :resource => I18n.t(:promotion_action))
8
+ flash[:success] = I18n.t(:successfully_created, :resource => I18n.t(:promotion_action))
9
9
  end
10
10
  respond_to do |format|
11
11
  format.html { redirect_to spree.edit_admin_promotion_path(@promotion)}
@@ -17,7 +17,7 @@ class Spree::Admin::PromotionActionsController < Spree::Admin::BaseController
17
17
  @promotion = Spree::Promotion.find(params[:promotion_id])
18
18
  @promotion_action = @promotion.promotion_actions.find(params[:id])
19
19
  if @promotion_action.destroy
20
- flash.notice = I18n.t(:successfully_removed, :resource => I18n.t(:promotion_action))
20
+ flash[:success] = I18n.t(:successfully_removed, :resource => I18n.t(:promotion_action))
21
21
  end
22
22
  respond_to do |format|
23
23
  format.html { redirect_to spree.edit_admin_promotion_path(@promotion)}
@@ -10,7 +10,7 @@ class Spree::Admin::PromotionRulesController < Spree::Admin::BaseController
10
10
  @promotion_rule = promotion_rule_type.constantize.new(params[:promotion_rule])
11
11
  @promotion_rule.promotion = @promotion
12
12
  if @promotion_rule.save
13
- flash.notice = I18n.t(:successfully_created, :resource => I18n.t(:promotion_rule))
13
+ flash[:success] = I18n.t(:successfully_created, :resource => I18n.t(:promotion_rule))
14
14
  end
15
15
  respond_to do |format|
16
16
  format.html { redirect_to spree.edit_admin_promotion_path(@promotion)}
@@ -22,7 +22,7 @@ class Spree::Admin::PromotionRulesController < Spree::Admin::BaseController
22
22
  @promotion = Spree::Promotion.find(params[:promotion_id])
23
23
  @promotion_rule = @promotion.promotion_rules.find(params[:id])
24
24
  if @promotion_rule.destroy
25
- flash.notice = I18n.t(:successfully_removed, :resource => I18n.t(:promotion_rule))
25
+ flash[:success] = I18n.t(:successfully_removed, :resource => I18n.t(:promotion_rule))
26
26
  end
27
27
  respond_to do |format|
28
28
  format.html { redirect_to spree.edit_admin_promotion_path(@promotion)}
@@ -5,36 +5,25 @@ Spree::CheckoutController.class_eval do
5
5
  if @order.update_attributes(object_params)
6
6
 
7
7
  fire_event('spree.checkout.update')
8
-
9
- if @order.coupon_code.present?
10
- event_name = "spree.checkout.coupon_code_added"
11
- if promo = Spree::Promotion.with_coupon_code(@order.coupon_code).where(:event_name => event_name).first
12
- fire_event(event_name, :coupon_code => @order.coupon_code)
13
- # If it doesn't exist, raise an error!
14
- # Giving them another chance to enter a valid coupon code
15
- else
16
- flash[:error] = t(:promotion_not_found)
17
- render :edit and return
18
- end
19
- end
8
+ render :edit and return unless apply_coupon_code
20
9
 
21
10
  if @order.next
22
11
  state_callback(:after)
23
12
  else
24
13
  flash[:error] = t(:payment_processing_failed)
25
- respond_with(@order, :location => checkout_state_path(@order.state))
14
+ redirect_to checkout_state_path(@order.state)
26
15
  return
27
16
  end
28
17
 
29
18
  if @order.state == 'complete' || @order.completed?
30
19
  flash.notice = t(:order_processed_successfully)
31
20
  flash[:commerce_tracking] = 'nothing special'
32
- respond_with(@order, :location => completion_route)
21
+ redirect_to completion_route
33
22
  else
34
- respond_with(@order, :location => checkout_state_path(@order.state))
23
+ redirect_to checkout_state_path(@order.state)
35
24
  end
36
25
  else
37
- respond_with(@order) { |format| format.html { render :edit } }
26
+ render :edit
38
27
  end
39
28
  end
40
29
 
@@ -3,14 +3,8 @@ Spree::OrdersController.class_eval do
3
3
  def update
4
4
  @order = current_order
5
5
  if @order.update_attributes(params[:order])
6
- if @order.coupon_code.present?
7
- if apply_coupon_code
8
- flash[:notice] = t(:coupon_code_applied)
9
- else
10
- flash[:error] = t(:promotion_not_found)
11
- render :edit and return
12
- end
13
- end
6
+ render :edit and return unless apply_coupon_code
7
+
14
8
  @order.line_items = @order.line_items.select {|li| li.quantity > 0 }
15
9
  fire_event('spree.order.contents_changed')
16
10
  respond_with(@order) do |format|
@@ -27,14 +21,4 @@ Spree::OrdersController.class_eval do
27
21
  end
28
22
  end
29
23
 
30
- def apply_coupon_code
31
- return if @order.coupon_code.blank?
32
- if promo = Spree::Promotion.with_coupon_code(@order.coupon_code).first
33
- if promo.order_activatable?(@order)
34
- fire_event('spree.checkout.coupon_code_added', :coupon_code => @order.coupon_code)
35
- true
36
- end
37
- end
38
- end
39
-
40
24
  end
@@ -0,0 +1,55 @@
1
+ Spree::StoreController.class_eval do
2
+
3
+ protected
4
+ def apply_coupon_code
5
+ if @order.coupon_code.present?
6
+ # check if coupon code is already applied
7
+ if @order.adjustments.promotion.eligible.detect { |p| p.originator.promotion.code == @order.coupon_code }.present?
8
+ flash[:notice] = t(:coupon_code_already_applied)
9
+ true
10
+ else
11
+ event_name = "spree.checkout.coupon_code_added"
12
+
13
+ # TODO should restrict to payload's event name?
14
+ promotion = Spree::Promotion.find_by_code(@order.coupon_code)
15
+
16
+ if promotion.present?
17
+ if promotion.expired?
18
+ flash[:error] = t(:coupon_code_expired)
19
+ return false
20
+ end
21
+
22
+ if promotion.usage_limit_exceeded?
23
+ flash[:error] = t(:coupon_code_max_usage)
24
+ return false
25
+ end
26
+
27
+ previous_promo = @order.adjustments.promotion.eligible.first
28
+ fire_event(event_name, :coupon_code => @order.coupon_code)
29
+ promo = @order.adjustments.promotion.detect { |p| p.originator.promotion.code == @order.coupon_code }
30
+
31
+ if promo.present? and promo.eligible
32
+ flash[:success] = t(:coupon_code_applied)
33
+ true
34
+ elsif previous_promo.present? and promo.present?
35
+ flash[:error] = t(:coupon_code_better_exists)
36
+ false
37
+ elsif promo.present?
38
+ flash[:error] = t(:coupon_code_not_eligible)
39
+ false
40
+ else
41
+ # if the promotion was created after the order
42
+ flash[:error] = t(:coupon_code_not_found)
43
+ false
44
+ end
45
+ else
46
+ flash[:error] = t(:coupon_code_not_found)
47
+ false
48
+ end
49
+ end
50
+ else
51
+ true
52
+ end
53
+ end
54
+
55
+ end
@@ -1,6 +1,10 @@
1
1
  Spree::Order.class_eval do
2
2
  attr_accessible :coupon_code
3
- attr_accessor :coupon_code
3
+ attr_reader :coupon_code
4
+
5
+ def coupon_code=(code)
6
+ @coupon_code = code.strip.downcase rescue nil
7
+ end
4
8
 
5
9
  # Tells us if there if the specified promotion is already associated with the order
6
10
  # regardless of whether or not its currently eligible. Useful because generally
@@ -9,19 +13,6 @@ Spree::Order.class_eval do
9
13
  !! adjustments.promotion.reload.detect { |credit| credit.originator.promotion.id == promotion.id }
10
14
  end
11
15
 
12
- unless self.method_defined?('update_adjustments_with_promotion_limiting')
13
- def update_adjustments_with_promotion_limiting
14
- update_adjustments_without_promotion_limiting
15
- return if adjustments.promotion.eligible.none?
16
- most_valuable_adjustment = adjustments.promotion.eligible.max{|a,b| a.amount.abs <=> b.amount.abs}
17
- current_adjustments = (adjustments.promotion.eligible - [most_valuable_adjustment])
18
- current_adjustments.each do |adjustment|
19
- adjustment.update_attribute_without_callbacks(:eligible, false)
20
- end
21
- end
22
- alias_method_chain :update_adjustments, :promotion_limiting
23
- end
24
-
25
16
  def promo_total
26
17
  adjustments.eligible.promotion.map(&:amount).sum
27
18
  end
@@ -0,0 +1,14 @@
1
+ Spree::OrderUpdater.class_eval do
2
+ unless self.method_defined?('update_adjustments_with_promotion_limiting')
3
+ def update_adjustments_with_promotion_limiting
4
+ update_adjustments_without_promotion_limiting
5
+ return if adjustments.promotion.eligible.none?
6
+ most_valuable_adjustment = adjustments.promotion.eligible.max{|a,b| a.amount.abs <=> b.amount.abs}
7
+ current_adjustments = (adjustments.promotion.eligible - [most_valuable_adjustment])
8
+ current_adjustments.each do |adjustment|
9
+ adjustment.update_attribute_without_callbacks(:eligible, false)
10
+ end
11
+ end
12
+ alias_method_chain :update_adjustments, :promotion_limiting
13
+ end
14
+ end
@@ -1,36 +1,27 @@
1
1
  module Spree
2
2
  class Promotion
3
3
  module Actions
4
- # Responsible for the creation and management of an adjustment since an
5
- # an adjustment uses its originator to also update its eligiblity and amount
6
4
  class CreateAdjustment < PromotionAction
7
5
  calculated_adjustments
8
6
 
9
- has_many :adjustments, :as => :originator, :dependent => :destroy
10
-
11
7
  delegate :eligible?, :to => :promotion
12
8
 
13
9
  before_validation :ensure_action_has_calculator
14
10
 
15
- # Creates the adjustment related to a promotion for the order passed
16
- # through options hash
17
11
  def perform(options = {})
18
- order = options[:order]
19
- return if order.promotion_credit_exists?(self.promotion)
20
-
21
- self.create_adjustment("#{I18n.t(:promotion)} (#{promotion.name})", order, order)
12
+ return unless order = options[:order]
13
+ # Nothing to do if the promotion is already associated with the order
14
+ return if order.promotion_credit_exists?(promotion)
15
+
16
+ order.adjustments.promotion.reload.clear
17
+ order.update!
18
+ create_adjustment("#{I18n.t(:promotion)} (#{promotion.name})", order, order)
19
+ order.update!
22
20
  end
23
21
 
24
- # Override of CalculatedAdjustments#create_adjustment so promotional
25
- # adjustments are added all the time. They will get their eligibility
26
- # set to false if the amount is 0.
27
- #
28
- # Currently an adjustment is created even when its promotion is not eligible.
29
- # This helps to figure out later which adjustments should be eligible
30
- # as the order is being updated
31
- #
32
- # BTW The order is updated (through order#update) every time an adjustment
33
- # is saved
22
+ # override of CalculatedAdjustments#create_adjustment so promotional
23
+ # adjustments are added all the time. They will get their eligability
24
+ # set to false if the amount is 0
34
25
  def create_adjustment(label, target, calculable, mandatory=false)
35
26
  amount = compute_amount(calculable)
36
27
  params = { :amount => amount,
@@ -41,8 +32,7 @@ module Spree
41
32
  target.adjustments.create(params, :without_protection => true)
42
33
  end
43
34
 
44
- # Ensure a negative amount which does not exceed the sum of the order's
45
- # item_total and ship_total
35
+ # Ensure a negative amount which does not exceed the sum of the order's item_total and ship_total
46
36
  def compute_amount(calculable)
47
37
  [(calculable.item_total + calculable.ship_total), super.to_f.abs].min * -1
48
38
  end
@@ -3,14 +3,12 @@ module Spree
3
3
  module Actions
4
4
  class CreateLineItems < PromotionAction
5
5
  has_many :promotion_action_line_items, :foreign_key => :promotion_action_id
6
+ accepts_nested_attributes_for :promotion_action_line_items
7
+ attr_accessible :promotion_action_line_items_attributes
6
8
 
7
- delegate :eligible?, :to => :promotion
8
-
9
- attr_accessor :line_items_string
10
9
 
11
10
  def perform(options = {})
12
11
  return unless order = options[:order]
13
- return unless eligible?(order)
14
12
  promotion_action_line_items.each do |item|
15
13
  current_quantity = order.quantity_of(item.variant)
16
14
  if current_quantity < item.quantity
@@ -19,20 +17,6 @@ module Spree
19
17
  end
20
18
  end
21
19
  end
22
-
23
- def line_items_string
24
- promotion_action_line_items.map { |li| "#{li.variant_id}x#{li.quantity}" }.join(',')
25
- end
26
-
27
- def line_items_string=(value)
28
- promotion_action_line_items.destroy_all
29
- value.to_s.split(',').each do |str|
30
- variant_id, quantity = str.split('x')
31
- if variant_id && quantity && variant = Variant.find_by_id(variant_id)
32
- promotion_action_line_items.create({:variant => variant, :quantity => quantity.to_i}, :without_protection => true)
33
- end
34
- end
35
- end
36
20
  end
37
21
  end
38
22
  end
@@ -2,27 +2,10 @@ module Spree
2
2
  class Promotion
3
3
  module Rules
4
4
  class FirstOrder < PromotionRule
5
- attr_reader :user, :email
6
-
7
5
  def eligible?(order, options = {})
8
- @user = order.try(:user) || options[:user]
9
- @email = order.email
10
-
11
- if user || email
12
- completed_orders.blank? || (completed_orders.first == order)
13
- else
14
- false
15
- end
6
+ user = order.try(:user) || options[:user]
7
+ !!(user && user.orders.complete.count == 0)
16
8
  end
17
-
18
- private
19
- def completed_orders
20
- user ? user.orders.complete : orders_by_email
21
- end
22
-
23
- def orders_by_email
24
- Spree::Order.where(:email => email).complete
25
- end
26
9
  end
27
10
  end
28
11
  end
@@ -4,7 +4,14 @@ module Spree
4
4
  class UserLoggedIn < PromotionRule
5
5
 
6
6
  def eligible?(order, options = {})
7
- return order.try(:user).try(:anonymous?) == false
7
+ # this is tricky. We couldn't use any of the devise methods since we aren't in the controller.
8
+ # we need to rely on the controller already having done this for us.
9
+
10
+ # The thinking is that the controller should have some sense of what state
11
+ # we should be in before firing events,
12
+ # so the controller will have to set this field.
13
+
14
+ return options && options[:user_signed_in]
8
15
  end
9
16
 
10
17
  end
@@ -36,16 +36,12 @@ module Spree
36
36
  where(:advertise => true)
37
37
  end
38
38
 
39
- def self.with_coupon_code(coupon_code)
40
- search(:code_cont => coupon_code).result
41
- end
42
-
43
39
  def activate(payload)
44
40
  return unless order_activatable? payload[:order]
45
41
 
46
42
  if code.present?
47
- event_code = payload[:coupon_code].to_s.strip.downcase
48
- return unless event_code == self.code.to_s.strip.downcase
43
+ event_code = payload[:coupon_code]
44
+ return unless event_code == self.code
49
45
  end
50
46
 
51
47
  if path.present?
@@ -101,5 +97,9 @@ module Spree
101
97
  credits.count
102
98
  end
103
99
 
100
+ def code=(coupon_code)
101
+ write_attribute(:code, (coupon_code.downcase.strip rescue nil))
102
+ end
103
+
104
104
  end
105
105
  end
@@ -2,5 +2,7 @@ module Spree
2
2
  class PromotionActionLineItem < ActiveRecord::Base
3
3
  belongs_to :promotion_action, :class_name => 'Spree::Promotion::Actions::CreateLineItems'
4
4
  belongs_to :variant, :class_name => "Spree::Variant"
5
+
6
+ attr_accessible :quantity, :variant_id
5
7
  end
6
8
  end
@@ -1,6 +1,6 @@
1
1
  Deface::Override.new(:virtual_path => "spree/layouts/admin",
2
2
  :name => "promo_admin_tabs",
3
3
  :insert_bottom => "[data-hook='admin_tabs'], #admin_tabs[data-hook]",
4
- :text => "<%= tab(:promotions, :url => spree.admin_promotions_path) %>",
4
+ :text => "<%= tab(:promotions, :url => spree.admin_promotions_path, :icon => 'icon-bullhorn') %>",
5
5
  :disabled => false,
6
6
  :original => '3e847740dc3e7f924aba1ccb4cb00c7b841649e3')
@@ -1,9 +1,12 @@
1
1
  $('#actions').append('<%= escape_javascript( render(:partial => 'spree/admin/promotions/promotion_action', :object => @promotion_action) ) %>');
2
-
2
+ $('#actions .no-objects-found').hide();
3
3
  initProductActions();
4
4
 
5
+ <% unless Rails.env.test? %>
6
+ $('.type-select.select2').select2();
7
+ <% end %>
8
+
5
9
  $('#<%= dom_id @promotion_action %>').hide();
6
10
  $('#<%= dom_id @promotion_action %>').fadeIn();
7
11
  $('#<%= dom_id @promotion_action %> .tokeninput.products').productPicker();
8
- $('.product_autocomplete').product_autocomplete();
9
-
12
+ $('.product_autocomplete').product_autocomplete();
@@ -1,2 +1 @@
1
- $('#<%= dom_id @promotion_action %>').fadeOut().remove();
2
-
1
+ $('#<%= dom_id @promotion_action %>').fadeOut().remove();
@@ -1,7 +1,13 @@
1
1
  $('#rules').append('<%= escape_javascript( render(:partial => 'spree/admin/promotions/promotion_rule', :object => @promotion_rule) ) %>');
2
+ $('#rules .no-objects-found').hide();
3
+
2
4
  $('#<%= dom_id @promotion_rule %>').hide();
3
5
  $('#<%= dom_id @promotion_rule %>').fadeIn();
4
6
  $('#<%= dom_id @promotion_rule %> .tokeninput.products').productPicker();
5
7
  $('#<%= dom_id @promotion_rule %> .tokeninput.users').userPicker();
6
8
 
7
9
  $('#promotion_rule_type').html('<%= escape_javascript options_for_promotion_rule_types(@promotion) %>');
10
+
11
+ <% unless Rails.env.test? %>
12
+ $('.select_item_total.select2, .select_product.select2').select2();
13
+ <% end %>
@@ -1,3 +1,3 @@
1
1
  $('#<%= dom_id @promotion_rule %>').fadeOut().remove();
2
- $('#promotion_rule_type').html('<%= escape_javascript options_for_promotion_rule_types(@promotion) %>');
3
2
 
3
+ $('#promotion_rule_type').html('<%= escape_javascript options_for_promotion_rule_types(@promotion) %>');
@@ -1,26 +1,32 @@
1
- <fieldset id="action_fields">
2
- <legend><%= t(:promotion_actions) %></legend>
1
+ <fieldset id="action_fields" class="eight columns omega no-border-top">
2
+
3
+ <%= form_tag spree.admin_promotion_promotion_actions_path(@promotion), :remote => true, :id => 'new_promotion_action_form' do %>
4
+ <% options = options_for_select( Rails.application.config.spree.promotions.actions.map(&:name).map {|name| [ t("promotion_action_types.#{name.demodulize.underscore}.name"), name] } ) %>
5
+ <fieldset>
6
+ <legend align="center"><%= t(:promotion_actions) %></legend>
7
+ <div class="field">
8
+ <%= label_tag :action_type, t(:add_action_of_type)%>
9
+ <%= select_tag 'action_type', options, :class => 'select2 fullwidth' %>
10
+ </div>
11
+ <div class="filter-actions actions">
12
+ <%= button t(:add), 'icon-plus', :class => 'fullwidth' %>
13
+ </div>
14
+ </fieldset>
15
+ <% end %>
3
16
 
4
17
  <%= form_for @promotion, :url => spree.admin_promotion_path(@promotion), :method => :put do |f| %>
5
18
  <div id="actions" class="filter_list">
6
19
  <% if @promotion.actions.any? %>
7
20
  <%= render :partial => 'promotion_action', :collection => @promotion.actions %>
8
21
  <% else %>
9
- <!-- <p><%= t(:no_actions_added) %></p> -->
22
+ <div class="no-objects-found">
23
+ <%= t(:no_actions_added) %>
24
+ </div>
10
25
  <% end %>
11
26
  </div>
12
- <p class="form-buttons">
13
- <%= button t(:update) %>
14
- </p>
15
- <% end %>
16
-
17
- <%= form_tag spree.admin_promotion_promotion_actions_path(@promotion), :remote => true, :id => 'new_promotion_action_form' do %>
18
- <% options = options_for_select( Rails.application.config.spree.promotions.actions.map(&:name).map {|name| [ t("promotion_action_types.#{name.demodulize.underscore}.name"), name] } ) %>
19
- <p>
20
- <%= label_tag :action_type, t(:add_action_of_type) %>
21
- <%= select_tag 'action_type', options %>
22
- <%= submit_tag t(:add) %>
23
- </p>
27
+ <div class="filter-actions actions promotion-update">
28
+ <%= button t(:update), 'icon-refresh' %>
29
+ </div>
24
30
  <% end %>
25
31
 
26
32
  </fieldset>
@@ -1,52 +1,56 @@
1
1
  <%= render :partial => 'spree/shared/error_messages', :locals => { :target => @promotion } %>
2
- <fieldset id="general_fields">
3
- <legend><%= t(:general) %></legend>
4
- <%= f.field_container :name do %>
5
- <%= f.label :name %><br />
6
- <%= f.text_field :name %>
7
- <% end %>
8
-
9
- <%= f.field_container :event_name do %>
10
- <%= f.label :event_name %><br />
11
- <%= f.select :event_name, Spree::Activator.event_names.map{|name| [t("events.#{name}"), name] } %>
12
- <% end %>
13
-
14
- <%= f.field_container :code do %>
15
- <%= f.label :code %><br />
16
- <%= f.text_field :code %>
17
- <% end %>
18
-
19
- <%= f.field_container :path do %>
20
- <%= f.label :path %><br />
21
- <%= f.text_field :path %>
22
- <% end %>
23
-
24
- <%= f.field_container :description do %>
25
- <%= f.label :description %><br />
26
- <%= f.text_area :description, :style => 'height:50px;' %>
27
- <% end %>
28
-
29
- <%= f.field_container :advertise do %>
30
- <%= f.check_box :advertise %>
31
- <%= f.label :advertise %>
32
- <% end %>
33
-
34
- </fieldset>
35
-
36
- <fieldset id="expiry_fields">
37
- <legend><%= t(:expiry) %></legend>
38
- <p>
39
- <%= f.label :usage_limit %><br />
40
- <%= f.text_field :usage_limit %><br/>
41
- <%= t(:current_promotion_usage, :count => @promotion.credits_count) %>
42
- </p>
43
-
44
- <p id="starts_at_field">
45
- <%= f.label :starts_at %>
46
- <%= f.text_field :starts_at, :class => 'datepicker' %>
47
- </p>
48
- <p id="expires_at_field">
49
- <%= f.label :expires_at %>
50
- <%= f.text_field :expires_at, :class => 'datepicker' %>
51
- </p>
52
- </fieldset>
2
+ <div class="row">
3
+ <div id="general_fields" class="alpha thirteen columns">
4
+ <div class="alpha four columns">
5
+ <%= f.field_container :name do %>
6
+ <%= f.label :name %>
7
+ <%= f.text_field :name, :class => 'fullwidth' %>
8
+ <% end %>
9
+
10
+ <%= f.field_container :event_name do %>
11
+ <%= f.label :event_name %>
12
+ <%= f.select :event_name, Spree::Activator.event_names.map{|name| [t("events.#{name}"), name] }, {}, {:class => 'select2 fullwidth'} %>
13
+ <% end %>
14
+
15
+ <%= f.field_container :code do %>
16
+ <%= f.label :code %>
17
+ <%= f.text_field :code, :class => 'fullwidth' %>
18
+ <% end %>
19
+
20
+ <%= f.field_container :path do %>
21
+ <%= f.label :path %>
22
+ <%= f.text_field :path, :class => 'fullwidth' %>
23
+ <% end %>
24
+
25
+ <%= f.field_container :advertise do %>
26
+ <%= f.check_box :advertise %>
27
+ <%= f.label :advertise %>
28
+ <% end %>
29
+ </div>
30
+
31
+ <div class="omega nine columns">
32
+ <%= f.field_container :description do %>
33
+ <%= f.label :description %><br />
34
+ <%= f.text_area :description, :rows => 7, :class => 'fullwidth' %>
35
+ <% end %>
36
+ </div>
37
+ </div>
38
+
39
+ <div id="expiry_fields" class="three columns omega">
40
+ <%= f.field_container :usage_limit do %>
41
+ <%= f.label :usage_limit %><br />
42
+ <%= f.number_field :usage_limit, :min => 0, :class => 'fullwidth' %><br>
43
+ <%= t(:current_promotion_usage, :count => @promotion.credits_count) %>
44
+ <% end %>
45
+
46
+ <div id="starts_at_field" class="field">
47
+ <%= f.label :starts_at %>
48
+ <%= f.text_field :starts_at, :class => 'datepicker datepicker-from fullwidth' %>
49
+ </div>
50
+
51
+ <div id="expires_at_field" class="field">
52
+ <%= f.label :expires_at %>
53
+ <%= f.text_field :expires_at, :class => 'datepicker datepicker-top fullwidth' %>
54
+ </div>
55
+ </div>
56
+ </div>
@@ -1,11 +1,11 @@
1
- <div class="promotion_action <%= promotion_action.type.to_s.demodulize.underscore %>" id="<%= dom_id promotion_action %>">
2
- <span class="delete">
3
- <%= link_to_with_icon 'cross', '', spree.admin_promotion_promotion_action_path(@promotion, promotion_action), :remote => true, :method => :delete %>
4
- </span>
1
+ <div class="promotion_action promotion-block <%= promotion_action.type.to_s.demodulize.underscore %>" id="<%= dom_id promotion_action %>">
5
2
  <% type_name = promotion_action.class.name.demodulize.underscore %>
3
+ <h6 class="promotion-title"><%= t("promotion_action_types.#{type_name}.description") %></h6>
4
+ <%= link_to_with_icon 'icon-trash', '', spree.admin_promotion_promotion_action_path(@promotion, promotion_action), :remote => true, :method => :delete, :class => 'delete' %>
5
+
6
6
  <% param_prefix = "promotion[promotion_actions_attributes][#{promotion_action.id}]" %>
7
7
  <%= hidden_field_tag "#{param_prefix}[id]", promotion_action.id %>
8
- <p><%= t("promotion_action_types.#{type_name}.description") %></p>
8
+
9
9
  <%= render :partial => "spree/admin/promotions/actions/#{type_name}",
10
10
  :locals => { :promotion_action => promotion_action, :param_prefix => param_prefix } %>
11
11
  </div>