spree_active_sale 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. data/README.md +15 -5
  2. data/app/controllers/spree/admin/active_sale_events_controller.rb +26 -11
  3. data/app/controllers/spree/admin/active_sales_controller.rb +30 -0
  4. data/app/controllers/spree/admin/resource_controller_decorator.rb +19 -0
  5. data/app/controllers/spree/home_controller_decorator.rb +2 -1
  6. data/app/helpers/spree/active_sale_events_helper.rb +6 -1
  7. data/app/helpers/spree/active_sales_helper.rb +42 -0
  8. data/app/helpers/spree/base_helper_decorator.rb +3 -0
  9. data/app/models/spree/active_sale.rb +35 -7
  10. data/app/models/spree/active_sale_configuration.rb +1 -0
  11. data/app/models/spree/active_sale_event.rb +14 -7
  12. data/app/models/spree/product_decorator.rb +9 -2
  13. data/app/models/spree/sale_event.rb +17 -10
  14. data/app/models/spree/sale_image.rb +4 -0
  15. data/app/models/spree/taxon_decorator.rb +8 -1
  16. data/app/models/spree/variant_decorator.rb +15 -1
  17. data/app/views/spree/admin/active_sale_events/_form.html.erb +40 -41
  18. data/app/views/spree/admin/active_sale_events/edit.html.erb +4 -4
  19. data/app/views/spree/admin/active_sale_events/index.html.erb +1 -12
  20. data/app/views/spree/admin/active_sale_events/new.html.erb +3 -1
  21. data/app/views/spree/admin/active_sales/edit.html.erb +1 -17
  22. data/app/views/spree/admin/active_sales/get_children.json.erb +9 -0
  23. data/app/views/spree/admin/active_sales/index.html.erb +12 -11
  24. data/app/views/spree/admin/active_sales/new.html.erb +10 -1
  25. data/app/views/spree/admin/sale_images/_form.html.erb +1 -1
  26. data/app/views/spree/admin/shared/_js_head.html.erb +8 -0
  27. data/app/views/spree/admin/shared/_list_events.html.erb +50 -29
  28. data/config/locales/active_sales_en.yml +5 -0
  29. data/config/locales/active_sales_es.yml +2 -2
  30. data/config/routes.rb +10 -1
  31. data/lib/spree_active_sale/engine.rb +1 -1
  32. metadata +13 -10
  33. data/app/views/spree/admin/active_sales/_form.html.erb +0 -35
data/README.md CHANGED
@@ -9,8 +9,8 @@ Spree Active Sale makes it easy to handle flash sale/ daily deals behavior withi
9
9
  ## FEATURES
10
10
 
11
11
  * Provides a quick implementation of flash sales/ daily deals behavior by a easy scheduler a.k.a *ActiveSale*.
12
- * Provides an admin interface for creating/ scheduling, managing, or re-scheduling sale events.
13
- * Provides a view helper for countdown timer to show sale's ending time, which will be shown to your customers. This eventually makes a sense of urgency in your customers' mind.
12
+ * Provides an admin interface for creating/ scheduling, managing, sorting, bundeling, or re-scheduling sale events.
13
+ * Provides a view helper for countdown timer to show sale's ending time, which will be shown to your customers. This eventually makes a sense of urgency on your customers' mind.
14
14
  * Supplies methods for class <tt>Spree::ActiveSaleEvent</tt> like: <tt>live</tt>, <tt>active</tt>, <tt>live_active</tt>, <tt>hidden</tt>, <tt>live_active_and_hidden</tt>, <tt>upcoming_events</tt>, <tt>starting_today</tt>, <tt>ending_today</tt>.
15
15
 
16
16
  ## LINKS
@@ -18,7 +18,7 @@ Spree Active Sale makes it easy to handle flash sale/ daily deals behavior withi
18
18
  * Demo application: [Spree Active Sale Demo](https://github.com/suryart/spree_active_sale_demo)
19
19
  * Dependency status: [![Dependency Status](https://gemnasium.com/suryart/spree_active_sale.png)](https://gemnasium.com/suryart/spree_active_sale)
20
20
  * Code climate: [![Code Climate](https://codeclimate.com/github/suryart/spree_active_sale.png)](https://codeclimate.com/github/suryart/spree_active_sale)
21
- * Build Status: [![Build Status](https://travis-ci.org/suryart/spree_active_sale.png?branch=v1.3.0)](https://travis-ci.org/suryart/spree_active_sale)
21
+ * Build Status: [![Build Status](https://travis-ci.org/suryart/spree_active_sale.png?branch=master)](https://travis-ci.org/suryart/spree_active_sale)
22
22
  * Issues: [Project issues](https://github.com/suryart/spree_active_sale/issues)
23
23
  * Fork: [Fork this Project](https://github.com/suryart/spree_active_sale/fork_select)
24
24
 
@@ -40,7 +40,7 @@ Spree Active Sale makes it easy to handle flash sale/ daily deals behavior withi
40
40
  * Or get it from rubygems.org by mentioning the following line in your Gemfile:
41
41
 
42
42
  ```ruby
43
- gem 'spree_active_sale', '1.0.6'
43
+ gem 'spree_active_sale', '1.3.0'
44
44
  ```
45
45
 
46
46
  ### Then run the following commands:
@@ -176,6 +176,15 @@ You will have to add javascript in the bottom of your **store/all.js** file as f
176
176
  # "Spree::ActiveSaleEvent", "Spree::Variant", "Spree::Product", or "Spree::Taxon" class.
177
177
  # Which simply says if sale event for that instance is accessible for users or not.
178
178
  Spree::ActiveSaleEvent.is_live?(instance)
179
+
180
+ # You can list the rows where a column, for example- :start_date, is not blank,
181
+ # and get it sorted using not_blank_and_sorted_by(:column_name) like this:
182
+ Spree::SaleEvent.not_blank_and_sorted_by(:start_date)
183
+ Spree::ActiveSale.not_blank_and_sorted_by(:start_date)
184
+ Spree::ActiveSaleEvent.not_blank_and_sorted_by(:start_date)
185
+
186
+ # Also, you can chain this method with other scopes, like this:
187
+ Spree::ActiveSaleEvent.live_active.not_blank_and_sorted_by(:start_date)
179
188
  ```
180
189
 
181
190
  ## Overriding countdown timer's layout differently for different events
@@ -194,7 +203,7 @@ Please visit [jQuery Countdown](http://keith-wood.name/countdown.html) for more
194
203
 
195
204
  ## Overriding configuration and preferences
196
205
 
197
- You can use put this at the bottom of your **application's app/config/initializers/spree.rb**:
206
+ You can use this at the bottom of your **application's app/config/initializers/spree.rb** for configuration:
198
207
 
199
208
  ```ruby
200
209
  Spree::ActiveSale.config do |config|
@@ -211,6 +220,7 @@ Since you can not set boolean values from the block config shown above for assig
211
220
  Spree::ActiveSaleConfig[:paginate_sales_for_admin?] = true
212
221
  Spree::ActiveSaleConfig[:paginate_sale_events_for_user?] = true
213
222
  Spree::ActiveSaleConfig[:paginate_sales_for_user?] = false
223
+ Spree::ActiveSaleConfig[:name_with_event_position?] = true
214
224
  ```
215
225
 
216
226
  ## TODOs
@@ -3,15 +3,23 @@ module Spree
3
3
  class ActiveSaleEventsController < ResourceController
4
4
  belongs_to 'spree/active_sale', :find_by => :id
5
5
  before_filter :load_active_sale, :only => [:index]
6
+ before_filter :parent_id_for_event, :only => [:new, :edit, :create, :update]
6
7
  update.before :get_eventable
8
+ respond_to :json, :only => [:update_events]
7
9
 
8
10
  def show
9
11
  redirect_to( :action => :edit )
10
12
  end
11
13
 
12
- def eventables
13
- search = params[:eventable_type].constantize.search(:name_cont => params[:name])
14
- render :json => search.result.map(&:name)
14
+ def destroy
15
+ @active_sale_event = Spree::ActiveSaleEvent.find(params[:id])
16
+ @active_sale_event.destroy
17
+ respond_with(@active_sale_event) { |format| format.json { render :json => '' } }
18
+ end
19
+
20
+ def update_events
21
+ @active_sale_event.update_attributes(params[:active_sale_event])
22
+ respond_with(@active_sale_event)
15
23
  end
16
24
 
17
25
  protected
@@ -37,16 +45,23 @@ module Spree
37
45
 
38
46
  def get_eventable
39
47
  object_name = params[:active_sale_event]
40
- unless object_name[:eventable_type].nil?
41
- eventable = "#{object_name[:eventable_type]}".constantize.find_by_name(object_name[:eventable_name])
42
- object_name.delete(:eventable_name)
43
- unless eventable.nil?
44
- object_name.merge!(:eventable_id => eventable.id, :permalink => eventable.permalink)
45
- else
46
- object_name.merge!(:eventable_id => nil)
47
- end
48
+ get_eventable_object(object_name)
49
+ end
50
+
51
+ def parent_id_for_event
52
+ params[:parent_id] ||= check_active_sale_event_params
53
+ @parent_id = params[:parent_id]
54
+ if @parent_id.blank?
55
+ redirect_to edit_admin_active_sale_path(params[:active_sale_id]), :notice => I18n.t('spree.active_sale.event.parent_id_cant_be_nil')
48
56
  end
49
57
  end
58
+
59
+ def check_active_sale_event_params(event = params[:active_sale_event])
60
+ return nil if event.nil?
61
+ parent_id = event[:parent_id]
62
+ event.delete(:parent_id) if event[:parent_id].nil? || event[:parent_id] == "nil"
63
+ parent_id
64
+ end
50
65
  end
51
66
  end
52
67
  end
@@ -1,6 +1,14 @@
1
1
  module Spree
2
2
  module Admin
3
3
  class ActiveSalesController < ResourceController
4
+ before_filter :load_active_sale_events, :only => [:new, :edit]
5
+ before_filter :set_active_sale, :only => [:create, :update]
6
+ respond_to :json, :only => [:get_children]
7
+
8
+ def get_children
9
+ @active_sale_events = Spree::ActiveSaleEvent.find(params[:parent_id]).children_sorted_by_position
10
+ respond_with(@active_sale_events)
11
+ end
4
12
 
5
13
  def index
6
14
  respond_with(@collection) do |format|
@@ -13,6 +21,11 @@ module Spree
13
21
  redirect_to edit_object_url(@active_sale)
14
22
  end
15
23
 
24
+ def eventables
25
+ search = params[:eventable_type].constantize.search(:name_cont => params[:name])
26
+ render :json => search.result.map(&:name)
27
+ end
28
+
16
29
  protected
17
30
 
18
31
  def collection
@@ -20,6 +33,23 @@ module Spree
20
33
  @search = Spree::ActiveSale.includes(:active_sale_events).ransack(params[:q])
21
34
  @collection = @search.result.page(params[:page]).per(Spree::ActiveSaleConfig[:admin_active_sales_per_page])
22
35
  end
36
+
37
+ def load_active_sale_events
38
+ if @active_sale.new_record?
39
+ @active_sale_event = @active_sale.active_sale_events.build
40
+ else
41
+ @active_sale_event = @active_sale.root
42
+ @active_sale_events = @active_sale.active_sale_events
43
+ end
44
+ end
45
+
46
+ def set_active_sale
47
+ return false if params[:active_sale_event].blank?
48
+ params[:active_sale] = params[:active_sale_event]
49
+ params[:active_sale].delete(:discount)
50
+ object_name = params[:active_sale]
51
+ get_eventable_object(object_name)
52
+ end
23
53
  end
24
54
  end
25
55
  end
@@ -0,0 +1,19 @@
1
+ module Spree
2
+ module Admin
3
+ ResourceController.class_eval do
4
+
5
+ private
6
+ def get_eventable_object(object_name = {})
7
+ unless object_name[:eventable_type].nil?
8
+ eventable = "#{object_name[:eventable_type]}".constantize.find_by_name(object_name[:eventable_name])
9
+ object_name.delete(:eventable_name)
10
+ unless eventable.nil?
11
+ object_name.merge!(:eventable_id => eventable.id, :permalink => eventable.permalink)
12
+ else
13
+ object_name.merge!(:eventable_id => nil)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,9 +1,10 @@
1
1
  module Spree
2
2
  HomeController.class_eval do
3
+ include Spree::ActiveSalesHelper
3
4
 
4
5
  # List live and active sales on home page
5
6
  def index
6
- @sale_events = Spree::ActiveSaleEvent.live_active
7
+ @sale_events = all_active_sale_events
7
8
  respond_with(@sale_events)
8
9
  end
9
10
  end
@@ -4,7 +4,7 @@ module Spree
4
4
  def sale_event_timer(event = nil, layout = nil)
5
5
  return I18n.t('spree.active_sale.event.can_not_be_nil') if (event == nil) || (event.class.name != "Spree::ActiveSaleEvent")
6
6
  layout ||= '{dn} DAYS {hnn}{sep}{mnn}{sep}{snn}'
7
- content_tag(:span, I18n.t('spree.active_sale.event.ending_message'), :class => 'sale_event_message') + " " + content_tag(:span, event.end_date.strftime('%Y-%m-%dT%H:%M:%S'), "data-timer" => event.end_date.strftime('%Y-%m-%dT%H:%M:%S'), "data-layout" => layout, :class => 'sale_event_message')
7
+ content_tag(:span, I18n.t('spree.active_sale.event.ending_message'), :class => 'sale_event_message') + " " + content_tag(:span, event.end_date.strftime('%Y-%m-%dT%H:%M:%S'), "data-timer" => event.end_date.strftime('%Y-%m-%dT%H:%M:%S'), "data-layout" => layout, :class => 'sale_event_message_timer')
8
8
  end
9
9
 
10
10
  def method_missing(method_name, *args, &block)
@@ -42,5 +42,10 @@ module Spree
42
42
  end
43
43
  end
44
44
  end
45
+
46
+ def event_js_data(event)
47
+ return nil if event.blank?
48
+ Spree::ActiveSaleConfig[:name_with_event_position?] ? "#{event.name.gsub('"','\"')} - #{I18n.t('spree.active_sale.event.active_record.position')}: #{event.position}" : event.name.gsub('"','\"')
49
+ end
45
50
  end
46
51
  end
@@ -1,4 +1,46 @@
1
1
  module Spree
2
2
  module ActiveSalesHelper
3
+ # Getter to load all_sale_events
4
+ # Get the helper and load from cache when possible
5
+ def all_sale_events
6
+ @all_sale_events ||= Spree::SaleEvent.live_active
7
+ end
8
+
9
+ # Setter to set all_sale_events.
10
+ # Set the helper and load from parameter when possible
11
+ def all_sale_events=(sale_events)
12
+ return Array.new unless sale_events.class == Array
13
+ @all_sale_events = sale_events
14
+ end
15
+
16
+ # Get the helper and load from cache when possible
17
+ def all_active_sale_events
18
+ all_sale_events.select{ |e| e.type == "Spree::ActiveSaleEvent" && e.parent != nil }
19
+ end
20
+
21
+ # find sale event for the product or a taxon
22
+ # pass taxon or product object in the argument
23
+ def get_sale_event(object)
24
+ if ["Spree::Product", "Spree::Taxon"].include? object.class.name
25
+ active_sale_event = all_sale_events.detect{ |sale_event| (sale_event.eventable_type == object.class.name) && (sale_event.eventable_id == object.id) }
26
+ end
27
+ active_sale_event
28
+ end
29
+
30
+ # helper to load current_active_sale_event
31
+ def current_active_sale_event
32
+ all_sale_events.detect{ |sale_event| current_permalink?(sale_event.permalink) }
33
+ end
34
+
35
+ def current_active_sale_event=(active_sale_event)
36
+ active_sale_event.nil? ? current_active_sale_event : active_sale_event
37
+ end
38
+
39
+ # check for current permalink using request
40
+ # split with "?" as there can be parameters
41
+ def current_permalink?(permalink = nil)
42
+ return false if permalink.blank?
43
+ request.path.split('/').reject(&:blank?).join('/') == permalink
44
+ end
3
45
  end
4
46
  end
@@ -0,0 +1,3 @@
1
+ Spree::BaseHelper.module_eval do
2
+ include Spree::ActiveSalesHelper
3
+ end
@@ -1,22 +1,50 @@
1
1
  # ActiveSales
2
- # Active sales represent an entity for one sale at a time.
2
+ # Active sales represent an entity for one sale at a time, just like a taxonomy in spree.
3
3
  # For example: 'January 2013' sale, which can have many sale events in it.
4
4
  #
5
5
  module Spree
6
6
  class ActiveSale < Spree::SaleEvent
7
- acts_as_nested_set :dependent => :destroy
7
+ validates :name, :presence => true
8
+ validate :start_and_end_date_presence, :start_and_end_date_range
9
+
8
10
  has_many :active_sale_events
11
+ has_one :root, :conditions => { :parent_id => nil }, :class_name => "Spree::ActiveSaleEvent",
12
+ :dependent => :destroy
9
13
 
10
- validates :name, :presence => true
14
+ after_save :set_root
11
15
 
12
- accepts_nested_attributes_for :active_sale_events, :allow_destroy => true, :reject_if => lambda { |attrs| attrs.all? { |k, v| v.blank? } }
16
+ default_scope :order => "#{self.table_name}.position"
13
17
 
14
18
  def self.config(&block)
15
19
  yield(Spree::ActiveSaleConfig)
16
20
  end
17
21
 
18
- def children_and_active_sale_events
19
- ((self.descendants.map{ |child_sale| child_sale.children_and_active_sale_events } << self) + self.active_sale_events).flatten.reject(&:blank?)
20
- end
22
+ private
23
+ def set_root
24
+ root_hash = self.serializable_hash
25
+ root_hash["active_sale_id"] = self.id
26
+ root_hash["type"] = "Spree::ActiveSaleEvent"
27
+ %w(id created_at updated_at lft rgt parent_id).each{ |column| root_hash.delete(column) }
28
+ if root
29
+ root.update_attributes(root_hash)
30
+ else
31
+ self.root = Spree::ActiveSaleEvent.create!(root_hash, :without_protection => true)
32
+ end
33
+ end
34
+
35
+ def start_and_end_date_presence
36
+ errors.add(:start_date, I18n.t('spree.active_sale.event.validation.errors.date_empty')) if self.start_date.nil?
37
+ errors.add(:end_date, I18n.t('spree.active_sale.event.validation.errors.date_empty')) if self.end_date.nil?
38
+ end
39
+
40
+ # This should validate the start and end date range between
41
+ # its active_sale_events. To make sure that, root lives longer.
42
+ def start_and_end_date_range
43
+ unless self.start_date.nil? || self.end_date.nil?
44
+ oldest_start_date = self.active_sale_events.not_blank_and_sorted_by(:start_date).first
45
+ latest_end_date = self.active_sale_events.not_blank_and_sorted_by(:end_date).last
46
+ errors.add(:start_date, I18n.t('spree.active_sale.event.validation.errors.invalid_root_dates')) if (oldest_start_date.nil? && latest_end_date.nil?) ? false : (self.start_date > oldest_start_date || self.end_date < latest_end_date)
47
+ end
48
+ end
21
49
  end
22
50
  end
@@ -5,6 +5,7 @@ module Spree
5
5
  preference :paginate_sales_for_admin?, :boolean, :default => false
6
6
  preference :paginate_sale_events_for_user?, :boolean, :default => false
7
7
  preference :paginate_sales_for_user?, :boolean, :default => false
8
+ preference :name_with_event_position?, :boolean, :default => false
8
9
  preference :admin_active_sales_per_page, :integer, :default => 25
9
10
  preference :active_sales_per_page, :integer, :default => 25
10
11
  preference :admin_active_sale_events_per_page, :integer, :default => 25
@@ -1,9 +1,11 @@
1
1
  # EVENTS
2
2
  # Events represent an entity for active sale in a flash sale/ daily deal.
3
- # There can be many events for one sale.
3
+ # There can be many events for one sale, just like taxonomies in spree.
4
4
  #
5
5
  module Spree
6
6
  class ActiveSaleEvent < Spree::SaleEvent
7
+ acts_as_nested_set :dependent => :destroy, :polymorphic => true
8
+
7
9
  before_validation :update_permalink
8
10
  after_save :update_parent_active_sales
9
11
 
@@ -11,11 +13,12 @@ module Spree
11
13
  belongs_to :eventable, :polymorphic => true
12
14
  belongs_to :active_sale
13
15
 
14
- attr_accessible :description, :end_date, :eventable_id, :eventable_type, :is_active, :is_hidden, :is_permanent, :name, :permalink, :active_sale_id, :start_date, :eventable_name, :discount
16
+ attr_accessible :description, :end_date, :eventable_id, :eventable_type, :is_active, :is_hidden, :is_permanent, :name, :permalink, :active_sale_id, :start_date, :eventable_name, :discount, :parent_id
15
17
 
16
18
  validates :name, :permalink, :eventable_id, :start_date, :end_date, :active_sale_id, :presence => true
17
19
  validates :eventable_type, :presence => true, :uniqueness => { :scope => :eventable_id, :message => I18n.t('spree.active_sale.event.validation.errors.live_event') }, :if => :live?
18
- validate :validate_start_and_end_date
20
+
21
+ scope :non_parents, lambda { where('parent_id IS NOT NULL') }
19
22
 
20
23
  # Spree::ActiveSaleEvent.is_live? method
21
24
  # should only/ always represents live and active events and not just live events.
@@ -33,10 +36,10 @@ module Spree
33
36
  # This callback basically makes sure that parents for an event lives longer.
34
37
  # Or at least parents live for the time when event is live.
35
38
  def update_parent_active_sales
36
- active_sale_events = self.active_sale.children_and_active_sale_events
37
- parents = self.active_sale.self_and_ancestors.flatten
38
- oldest_start_date = active_sale_events.map(&:start_date).reject(&:blank?).sort.first
39
- latest_end_date = active_sale_events.map(&:end_date).reject(&:blank?).sort.last
39
+ active_sale_events = self.self_and_ancestors
40
+ parents = self.ancestors
41
+ oldest_start_date = active_sale_events.not_blank_and_sorted_by(:start_date).first
42
+ latest_end_date = active_sale_events.not_blank_and_sorted_by(:end_date).last
40
43
  parents.each{ |parent|
41
44
  parent.update_attributes(:start_date => oldest_start_date) if parent.start_date.nil? ? true : (parent.start_date > oldest_start_date)
42
45
  parent.update_attributes(:end_date => latest_end_date) if parent.end_date.nil? ? true : (parent.end_date < latest_end_date)
@@ -54,5 +57,9 @@ module Spree
54
57
  def eventable_image_available?
55
58
  !!eventable.try(:image_available?)
56
59
  end
60
+
61
+ def children_sorted_by_position
62
+ self.children.sort_by{ |child| child.position.nil? ? 0 : child.position }
63
+ end
57
64
  end
58
65
  end
@@ -1,14 +1,21 @@
1
1
  Spree::Product.class_eval do
2
+ include Spree::ActiveSalesHelper
3
+
2
4
  has_many :active_sale_events, :as => :eventable
3
5
 
4
6
  # Find live and active taxons for a product.
5
7
  def find_live_taxons
6
- Spree::ActiveSaleEvent.live_active.where(:eventable_type => "Spree::Taxon", :eventable_id => self.taxons.map(&:id))
8
+ all_sale_events.select{ |sale_event| (sale_event.eventable_type == "Spree::Taxon") && (self.taxons.map(&:id).include?(sale_event.eventable_id)) }
9
+ end
10
+
11
+ # product.live_active_sale_event gets first active sale event which is live and active
12
+ def live_active_sale_event
13
+ get_sale_event(self)
7
14
  end
8
15
 
9
16
  # if there is at least one active sale event which is live and active.
10
17
  def live?
11
- !self.active_sale_events.detect{ |event| event.live_and_active? }.nil? || !self.find_live_taxons.blank?
18
+ !self.live_active_sale_event.nil? || !self.find_live_taxons.blank?
12
19
  end
13
20
 
14
21
  # Check if image is available for this.
@@ -20,45 +20,48 @@ module Spree
20
20
  scope :starting_today, lambda { where(:start_date => zone_time..zone_time.end_of_day) }
21
21
  scope :ending_today, lambda { where(:end_date => zone_time..zone_time.end_of_day) }
22
22
 
23
-
24
- def validate_start_and_end_date
25
- errors.add(:start_date, I18n.t('spree.active_sale.event.validation.errors.invalid_dates')) if invalid_dates?
26
- end
23
+ validate :validate_start_and_end_date
27
24
 
28
25
  def live?(moment=nil)
29
26
  moment ||= object_zone_time
30
- (self.start_date <= moment and self.end_date >= moment) or self.is_permanent? if start_and_dates_available?
27
+ (self.start_date <= moment and self.end_date >= moment) or self.is_permanent? if start_and_end_dates_available?
31
28
  end
32
29
 
33
30
  def upcoming?
34
31
  current_time = object_zone_time
35
- (self.start_date >= current_time and self.end_date > self.start_date) if start_and_dates_available?
32
+ (self.start_date >= current_time and self.end_date > self.start_date) if start_and_end_dates_available?
36
33
  end
37
34
 
38
35
  def past?
39
36
  current_time = object_zone_time
40
- (self.start_date < current_time and self.end_date > self.start_date and self.end_date < current_time) if start_and_dates_available?
37
+ (self.start_date < current_time and self.end_date > self.start_date and self.end_date < current_time) if start_and_end_dates_available?
41
38
  end
42
39
 
43
40
  def live_and_active?(moment=nil)
44
41
  self.live?(moment) and self.is_active?
45
42
  end
46
43
 
47
- def start_and_dates_available?
44
+ def start_and_end_dates_available?
48
45
  self.start_date and self.end_date
49
46
  end
50
47
 
51
48
  def invalid_dates?
52
- self.start_and_dates_available? and (self.start_date >= self.end_date)
49
+ self.start_and_end_dates_available? and (self.start_date >= self.end_date)
53
50
  end
54
51
 
52
+ # Class methods
55
53
  class << self
56
- # Class methods
57
54
  def paginate(objects_per_page, options = {})
58
55
  options = prepare_pagination(objects_per_page, options)
59
56
  self.page(options[:page]).per(options[:per_page])
60
57
  end
61
58
 
59
+ def not_blank_and_sorted_by(column)
60
+ return nil if column.blank?
61
+ column = column.to_sym
62
+ self.select(&column).map(&column).reject(&:blank?).sort
63
+ end
64
+
62
65
  private
63
66
  def valid_argument args
64
67
  (args.first == nil || args.first == true)
@@ -82,5 +85,9 @@ module Spree
82
85
  def object_zone_time
83
86
  Time.zone.now
84
87
  end
88
+
89
+ def validate_start_and_end_date
90
+ errors.add(:start_date, I18n.t('spree.active_sale.event.validation.errors.invalid_dates')) if invalid_dates?
91
+ end
85
92
  end
86
93
  end
@@ -47,5 +47,9 @@ module Spree
47
47
  false
48
48
  end
49
49
  end
50
+
51
+ def viewable_type=(event_type)
52
+ super event_type.to_s.classify.constantize.base_class.to_s
53
+ end
50
54
  end
51
55
  end
@@ -1,9 +1,16 @@
1
1
  Spree::Taxon.class_eval do
2
+ include Spree::ActiveSalesHelper
3
+
2
4
  has_many :active_sale_events, :as => :eventable
3
5
 
6
+ # taxon.live_active_sale_event gets first active sale event which is live and active
7
+ def live_active_sale_event
8
+ get_sale_event(self)
9
+ end
10
+
4
11
  # if there is at least one active sale event which is live and active.
5
12
  def live?
6
- !self.active_sale_events.detect{ |event| event.live_and_active? }.nil?
13
+ !self.live_active_sale_event.nil?
7
14
  end
8
15
 
9
16
  def image_available?
@@ -1,7 +1,21 @@
1
+ # This decorator is created by keeping that in mind
2
+ # what is when a user may need or want a sale event on
3
+ # an SKU or a Variant level. Variant needs to reflect the
4
+ # same on admin dashboard for selection from dropdrown in
5
+ # edit and new view pages.
6
+ #
7
+
1
8
  Spree::Variant.class_eval do
9
+ include Spree::ActiveSalesHelper
10
+
2
11
  has_many :active_sale_events, :as => :eventable
3
12
 
13
+ # variant.live_active_sale_event gets first active sale event which is live and active
14
+ def live_active_sale_event
15
+ get_sale_event(self)
16
+ end
17
+
4
18
  def live?
5
- !self.active_sale_events.detect{ |event| event.live_and_active? }.nil? || self.product.live?
19
+ !self.live_active_sale_event.nil? || self.product.live?
6
20
  end
7
21
  end
@@ -2,96 +2,96 @@
2
2
  <%= render :partial => 'spree/shared/error_messages', :locals => { :target => @active_sale_event } %>
3
3
  <% end %>
4
4
 
5
- <%= form_for [:admin, @active_sale, @active_sale_event], :html => { :id => 'admin_active_sale_event', :multipart => true } do |f| %>
6
5
  <fieldset data-hook="admin_active_sale_event_form_fields">
7
6
 
7
+ <%= form.hidden_field :parent_id, :value => @parent_id %>
8
+
8
9
  <div class="clearfix">
9
10
  <div class="left eight columns alpha" data-hook="admin_active_sale_event_form_left">
10
- <%= f.field_container :name do %>
11
- <%= f.label :name, raw(t('spree.active_sale.event.active_record.name') + content_tag(:span, ' *', :class => 'required')) %>
12
- <%= f.text_field :name, :class => 'fullwidth' %>
13
- <%= f.error_message_on :name %>
14
- <% end %>
15
- <%= f.field_container :description do %>
16
- <%= f.label :description, t('spree.active_sale.event.active_record.description') %>
17
- <%= f.text_area :description, {:cols => 60, :rows => 10, :class => 'fullwidth'} %>
18
- <%= f.error_message_on :description %>
19
- <% end %>
11
+ <%= form.field_container :name do %>
12
+ <%= form.label :name, raw(t('spree.active_sale.event.active_record.name') + content_tag(:span, ' *', :class => 'required')) %>
13
+ <%= form.text_field :name, :class => 'fullwidth' %>
14
+ <%= form.error_message_on :name %>
15
+ <% end %>
16
+ <%= form.field_container :description do %>
17
+ <%= form.label :description, t('spree.active_sale.event.active_record.description') %>
18
+ <%= form.text_area :description, {:cols => 60, :rows => 10, :class => 'fullwidth'} %>
19
+ <%= form.error_message_on :description %>
20
+ <% end %>
20
21
  </div>
21
22
 
22
23
  <div class="right eight columns omega" data-hook="admin_active_sale_event_form_right">
23
24
  <div class="row">
24
25
  <div class="alpha four columns">
25
-
26
- <%= f.field_container :start_date do %>
27
- <%= f.label :start_date, t('spree.active_sale.event.active_record.start_date') %>
28
- <%= f.error_message_on :start_date %>
26
+ <%= form.field_container :start_date do %>
27
+ <%= form.label :start_date, t('spree.active_sale.event.active_record.start_date') %>
28
+ <%= form.error_message_on :start_date %>
29
29
  <% if @active_sale_event.start_date? %>
30
30
  <% start_date = l(@active_sale_event.start_date, :format => t('spree.active_sale.event.datetimepicker.format')) %>
31
31
  <% else %>
32
32
  <% start_date = l(Time.zone.now, :format => t('spree.active_sale.event.datetimepicker.format')) %>
33
33
  <% end %>
34
- <%= f.text_field :start_date, :value => start_date, :class => 'timepicker' %>
34
+ <%= form.text_field :start_date, :value => start_date, :class => 'timepicker' %>
35
35
  <% end %>
36
36
  </div>
37
37
 
38
38
  <div class="omega four columns">
39
- <%= f.field_container :end_date do %>
40
- <%= f.label :end_date, t('spree.active_sale.event.active_record.end_date') %>
41
- <%= f.error_message_on :end_date %>
39
+ <%= form.field_container :end_date do %>
40
+ <%= form.label :end_date, t('spree.active_sale.event.active_record.end_date') %>
41
+ <%= form.error_message_on :end_date %>
42
42
  <% end_date = l((@active_sale_event.end_date? ? @active_sale_event.end_date : Time.zone.now+1.day), :format => t('spree.active_sale.event.datetimepicker.format')) %>
43
- <%= f.text_field :end_date, :value => end_date, :class => 'timepicker' %>
43
+ <%= form.text_field :end_date, :value => end_date, :class => 'timepicker' %>
44
44
  <% end %>
45
45
  </div>
46
46
  </div>
47
47
  <div class="row">
48
48
  <div class="alpha four columns">
49
- <%= f.label :eventable, t('spree.active_sale.event.active_record.eventable_type', :default => :evenetable) %>
49
+ <%= form.label :eventable, t('spree.active_sale.event.active_record.eventable_type', :default => :evenetable) %>
50
50
  <p class='hint'><%= t('spree.active_sale.event.eventable_hint') %></p>
51
- <%= f.select :eventable_type, [["Product","Spree::Product"], ["Taxon","Spree::Taxon"]], { :include_blank => false }, { :class => 'select2' } %>
52
- <%= f.error_message_on :eventable %>
51
+ <%= form.select :eventable_type, [["Product","Spree::Product"], ["Taxon","Spree::Taxon"]], { :include_blank => false }, { :class => 'select2' } %>
52
+ <%= form.error_message_on :eventable %>
53
53
  </div>
54
54
 
55
55
  <div class="omega four columns">
56
- <%= f.label :eventable_name, t('spree.active_sale.event.active_record.eventable_name', :default => :eventable_name) %>
56
+ <%= form.label :eventable_name, t('spree.active_sale.event.active_record.eventable_name', :default => :eventable_name) %>
57
57
  <p class='hint'><%= t('spree.active_sale.event.eventable_name_hint') %></p>
58
- <%= f.error_message_on :eventable_name %>
59
- <%= f.text_field :eventable_name, :class => 'autocomplete', :data => { :auto_complete_url => eventables_admin_active_sale_active_sale_events_url(:active_sale_id => @active_sale.id) } %>
58
+ <%= form.error_message_on :eventable_name %>
59
+ <%= form.text_field :eventable_name, :class => 'autocomplete', :data => { :auto_complete_url => eventables_admin_active_sales_url } %>
60
60
  </div>
61
61
  </div>
62
62
  <div class="row">
63
63
  <div class="alpha four columns clearfix">
64
- <%= f.field_container :is_active, :class => ['checkbox'] do %>
64
+ <%= form.field_container :is_active, :class => ['checkbox'] do %>
65
65
  <label>
66
- <%= f.check_box :is_active %>
66
+ <%= form.check_box :is_active %>
67
67
  <%= t('spree.active_sale.event.active_record.is_active') %>
68
- <%= f.error_message_on :is_active %>
68
+ <%= form.error_message_on :is_active %>
69
69
  </label>
70
70
  <% end %>
71
71
 
72
- <%= f.field_container :is_hidden, :class => ['checkbox'] do %>
72
+ <%= form.field_container :is_hidden, :class => ['checkbox'] do %>
73
73
  <label>
74
- <%= f.check_box :is_hidden %>
74
+ <%= form.check_box :is_hidden %>
75
75
  <%= t('spree.active_sale.event.active_record.is_hidden') %>
76
- <%= f.error_message_on :is_hidden %>
76
+ <%= form.error_message_on :is_hidden %>
77
77
  </label>
78
78
  <% end %>
79
79
 
80
- <%= f.field_container :is_permanent, :class => ['checkbox'] do %>
80
+ <%= form.field_container :is_permanent, :class => ['checkbox'] do %>
81
81
  <label>
82
- <%= f.check_box :is_permanent %>
82
+ <%= form.check_box :is_permanent %>
83
83
  <%= t('spree.active_sale.event.active_record.is_permanent') %>
84
- <%= f.error_message_on :is_permanent %>
84
+ <%= form.error_message_on :is_permanent %>
85
85
  </label>
86
86
  <% end %>
87
87
  </div>
88
88
 
89
89
  <div class="omega four columns">
90
- <%= f.field_container :discount do %>
91
- <%= f.label :discount, t('spree.active_sale.event.active_record.discount', :default => :discount) %>
90
+ <%= form.field_container :discount do %>
91
+ <%= form.label :discount, t('spree.active_sale.event.active_record.discount', :default => :discount) %>
92
92
  <p class='hint'><%= t('spree.active_sale.event.discount_hint') %></p>
93
- <%= f.error_message_on :discount %>
94
- <%= f.text_field :discount, :size => 2, :maxlength => 2 %>
93
+ <%= form.error_message_on :discount %>
94
+ <%= form.text_field :discount, :size => 2, :maxlength => 2 %>
95
95
  <% end %>
96
96
  </div>
97
97
  </div>
@@ -116,12 +116,11 @@
116
116
  <% end %>
117
117
  </p>
118
118
  </fieldset>
119
- <% end %>
120
119
 
121
120
  <%= javascript_tag do -%>
122
121
  var properties = "<%= raw(@properties.to_json) %>";
123
122
 
124
- $("#admin_active_sale_event input.autocomplete").live("keydown", function(){
123
+ $("#admin_active_sale_event input.autocomplete").on("keydown", function(){
125
124
  var eventable_type = $('#active_sale_event_eventable_type :selected').val();
126
125
  var eventable_name = $('#active_sale_event_eventable_name').val();
127
126
  var url = $(this).data('auto-complete-url')
@@ -4,14 +4,14 @@
4
4
 
5
5
  <% content_for :page_actions do %>
6
6
  <li>
7
- <%= button_link_to t('spree.active_sale.event.link.back'), [:admin, @active_sale, :active_sale_events], :icon => 'icon-arrow-left', :id => 'admin_active_sale_events_link' %>
8
- <%= button_link_to t('spree.active_sale.event.link.new'), new_object_url, :icon => 'icon-plus', :id => 'new_admin_active_sale_event_link' %>
9
- <%= button_link_to t('spree.active_sale.link.edit'), [:edit, :admin, @active_sale], :icon => 'icon-edit', :id => 'admin_active_sale_events_link' %>
7
+ <%= button_link_to t('spree.active_sale.link.edit'), [:edit, :admin, @active_sale], :icon => 'icon-arrow-left', :id => 'admin_active_sales_link' %>
10
8
  </li>
11
9
  <% end %>
12
10
 
13
11
  <div data-hook="admin_active_sale_event_edit_form">
14
12
  <div id="active-sale-event-form-wrapper">
15
- <%= render :partial => 'form' %>
13
+ <%= form_for [:admin, @active_sale, @active_sale_event], :html => { :id => 'admin_active_sale_event', :multipart => true } do |form| %>
14
+ <%= render :partial => 'form', :locals => { :form => form } %>
15
+ <% end %>
16
16
  </div>
17
17
  </div>
@@ -1,12 +1 @@
1
- <% content_for :page_title do %>
2
- <%= @active_sale.name %> > <%= t('spree.active_sale.event.title.list') %>
3
- <% end %>
4
-
5
- <% content_for :page_actions do %>
6
- <li>
7
- <%= button_link_to t('spree.active_sale.link.edit'), [:admin, @active_sale], :icon => 'icon-arrow-left', :id => 'admin_active_sale_events_link' %>
8
- <%= button_link_to t('spree.active_sale.event.link.new'), new_object_url, :icon => 'icon-plus', :id => 'admin_new_active_sale_event_link' %>
9
- </li>
10
- <% end %>
11
-
12
- <%= render :partial => "spree/admin/shared/list_events", :locals => { :active_sale_events => @active_sale_events } %>
1
+ <%= render :partial => 'spree/admin/shared/list_events', :locals => { :active_sale => @active_sale, :active_sale_events => @active_sale_events } %>
@@ -10,6 +10,8 @@
10
10
 
11
11
  <div data-hook="admin_active_sale_event_edit_form">
12
12
  <div id="active-sale-event-form-wrapper">
13
- <%= render :partial => 'form' %>
13
+ <%= form_for [:admin, @active_sale, @active_sale_event], :html => { :id => 'admin_active_sale_event', :multipart => true } do |form| %>
14
+ <%= render :partial => 'form', :locals => { :form => form } %>
15
+ <% end %>
14
16
  </div>
15
17
  </div>
@@ -1,17 +1 @@
1
- <% content_for :page_title do %>
2
- <%= t('spree.active_sale.title.edit') %>
3
- <% end %>
4
-
5
- <% content_for :page_actions do %>
6
- <li>
7
- <% @event = Spree::ActiveSaleEvent.new %>
8
- <%= button_link_to t('spree.active_sale.link.back'), collection_url, :icon => 'icon-arrow-left', :id => 'admin_new_active_sale_link' %>
9
- <%= button_link_to t('spree.active_sale.event.link.new'), [:new, :admin, @active_sale, :active_sale_event], :icon => 'icon-plus', :id => 'admin_new_active_sale_link' %>
10
- </li>
11
- <% end %>
12
-
13
- <div data-hook="admin_active_sale_edit_form">
14
- <div id="active-sale-form-wrapper">
15
- <%= render :partial => 'form' %>
16
- </div>
17
- </div>
1
+ <%= render :partial => 'spree/admin/shared/list_events', :locals => { :active_sale => @active_sale, :active_sale_events => @active_sale_events } %>
@@ -0,0 +1,9 @@
1
+ [<% @active_sale_events.each_with_index do |t,i| %>
2
+ { "attr" :
3
+ { "id" : "<%= t.id %>", "parent_id" : "<%= t.parent_id %>" },
4
+ "data" : "<%= raw(event_js_data(t)) %>"
5
+ <% unless t.children.empty? %>
6
+ ,"state" : "closed"
7
+ <% end %>
8
+ }<%= "," if i < (@active_sale_events.size - 1) %>
9
+ <% end %>]
@@ -10,26 +10,27 @@
10
10
 
11
11
  <div id="new_active_sale" data-hook></div>
12
12
 
13
- <table class="index" id="listing_active_sales" data-hook>
13
+ <table class="index sortable" id='listing_active_sales' data-hook data-sortable-link="<%= update_positions_admin_active_sales_url %>">
14
14
  <colgroup>
15
15
  <col style="width: 85%">
16
16
  <col style="width: 15%">
17
17
  </colgroup>
18
18
  <thead>
19
- <tr data-hook="admin_active_sales_index_headers">
20
- <th><%= sort_link @search, :name, t('spree.active_sale.active_record.name'), {}, { :title => 'active_sales_name_title' } %></th>
21
- <th data-hook="admin_active_sales_index_header_actions" class="actions"></th>
19
+ <tr data-hook="active_sales_header">
20
+ <th><%= t(:name) %></th>
21
+ <th class="actions"></th>
22
22
  </tr>
23
23
  </thead>
24
24
  <tbody>
25
25
  <% @active_sales.each do |active_sale| %>
26
- <tr id="<%= spree_dom_id active_sale %>" data-hook="admin_active_sales_index_rows" class="<%= cycle('odd', 'even')%>">
27
- <td class='active_sale_name'><%= link_to active_sale.name, object_url(active_sale) %></td>
28
- <td class="actions" data-hook="admin_active_sales_index_row_actions">
29
- <p class="actions" data-hook="actions">
30
- <%= link_to_edit active_sale, :no_text => true %>
31
- <%= link_to_delete active_sale, :no_text => true %>
32
- </p>
26
+ <tr id="<%= spree_dom_id active_sale %>" data-hook="active_sales_row" class="<%= cycle('odd', 'even')%>">
27
+ <td>
28
+ <span class="handle"></span>&nbsp;
29
+ <%= active_sale.name %>
30
+ </td>
31
+ <td class="actions">
32
+ <%= link_to_edit active_sale.id, :no_text => true %>
33
+ <%= link_to_delete active_sale, :no_text => true %>
33
34
  </td>
34
35
  </tr>
35
36
  <% end %>
@@ -10,6 +10,15 @@
10
10
 
11
11
  <div data-hook="admin_active_sale_new_form">
12
12
  <div id="active-sale-form-wrapper">
13
- <%= render :partial => 'form' %>
13
+
14
+ <% if @active_sale.try(:errors).present? %>
15
+ <%= render :partial => 'spree/shared/error_messages', :locals => { :target => @active_sale } %>
16
+ <% end %>
17
+
18
+ <%= form_for [:admin, @active_sale], :html => { :id => 'admin_active_sale_event' } do |form| %>
19
+ <%= fields_for @active_sale_event do |event_form| %>
20
+ <%= render :partial => 'spree/admin/active_sale_events/form', :locals => { :form => event_form } %>
21
+ <% end %>
22
+ <% end %>
14
23
  </div>
15
24
  </div>
@@ -1,7 +1,7 @@
1
1
  <div data-hook="admin_image_form_fields">
2
2
  <div class="four columns alpha">
3
3
  <div data-hook="file" class="field">
4
- <%= f.label t(:filename) %><br>
4
+ <%= f.label :attachment, t(:filename) %><br>
5
5
  <%= f.file_field :attachment %>
6
6
  </div>
7
7
  </div>
@@ -0,0 +1,8 @@
1
+ <% content_for :head do %>
2
+ <%= javascript_tag "var active_sale_id = #{@active_sale.id};
3
+ var loading = '#{escape_javascript t(:loading)}';
4
+ var new_active_sale_event = '#{escape_javascript t(:new_active_sale_event)}';
5
+ var server_error = '#{escape_javascript t(:server_error)}';
6
+ var active_sale_tree_error = '#{escape_javascript t(:active_sale_tree_error)}';"
7
+ %>
8
+ <% end %>
@@ -1,32 +1,53 @@
1
+ <%= render :partial => 'spree/admin/shared/js_head' %>
1
2
 
2
- <div id="new_active_sale_event" data-hook></div>
3
+ <% content_for :page_title do %>
4
+ <%= t('spree.active_sale.title.edit') %> &#62; <%= @active_sale.name %>
5
+ <% end %>
3
6
 
4
- <table class="index" id="listing_active_sale_events" data-hook>
5
- <thead>
6
- <tr data-hook="admin_active_sale_events_index_headers">
7
- <th><%= t('spree.active_sale.event.active_record.name') %></th>
8
- <th><%= t('spree.active_sale.event.active_record.start_date') %></th>
9
- <th><%= t('spree.active_sale.event.active_record.end_date') %></th>
10
- <th><%= t('spree.active_sale.event.active_record.is_live') %></th>
11
- <th data-hook="admin_active_sale_events_index_header_actions" class="actions"></th>
12
- </tr>
13
- </thead>
14
- <tbody>
15
- <% @active_sale_events.each do |event| %>
16
- <tr id="<%= spree_dom_id event %>" data-hook="admin_active_sales_index_rows" class="<%= cycle('odd', 'even')%>">
17
- <td class='active_sale_name'><%= link_to event.name, [:admin, @active_sale, event] %></td>
18
- <td class='active_sale_start_date'><%= event.start_date %></td>
19
- <td class='active_sale_end_date'><%= event.end_date %></td>
20
- <td class='active_sale_is_live'><%= event.live? ? t('spree.active_sale.event.boolean.yes') : t('spree.active_sale.event.boolean.no') %></td>
7
+ <% content_for :page_actions do %>
8
+ <li>
9
+ <%= button_link_to t('spree.active_sale.link.back'), collection_url, :icon => 'icon-arrow-left', :id => 'admin_new_active_sale_link' %>
10
+ </li>
11
+ <% end %>
21
12
 
22
- <td class="actions" data-hook="admin_active_sale_events_index_row_actions">
23
- <p class="actions" data-hook="actions">
24
- <%= link_to_edit_url [:edit, :admin, @active_sale, event], :no_text => true %>
25
- &nbsp;
26
- <%= link_to_delete event, { :url => [:admin, @active_sale, event], :no_text => true } %>
27
- </p>
28
- </td>
29
- </tr>
30
- <% end %>
31
- </tbody>
32
- </table>
13
+ <div id="ajax_error" class="errorExplanation" style="display:none;"></div>
14
+
15
+ <fieldset class="no-border-top">
16
+ <div>
17
+ <%= label_tag nil, t(:tree) %><br />
18
+ <div id="active_sale_tree" class="tree" data-url="<%= admin_active_sale_active_sale_events_path @active_sale %>"></div>
19
+ </div>
20
+ <div id="progress" style="display:none;">
21
+ <%= image_tag 'spinner.gif', :title => 'Spinner', :style => "vertical-align:bottom;" %> <%= t(:updating) %>..
22
+ </div>
23
+
24
+ <p class='hint info'>
25
+ <%= t('spree.active_sale.event.active_sale_tree_hint') %>
26
+ </p>
27
+
28
+ <br>
29
+ </fieldset>
30
+
31
+ <% content_for :head do %>
32
+ <%= javascript_tag do -%>
33
+ var initial = [
34
+ { "attr" :
35
+ { "id" : "<%= @active_sale.root.id %>", "rel" : "root", "parent_id" : "nil" },
36
+ "data" : "<%= escape_javascript(raw(@active_sale.root.name)) %>",
37
+ "state" : "open",
38
+ "children" : [
39
+ <% @active_sale.root.children_sorted_by_position.each_with_index do |event,i| %>
40
+ {
41
+ "attr" :
42
+ { "id" : "<%= event.id %>", "parent_id" : "<%= event.parent_id %>" },
43
+ "data" : "<%= escape_javascript(raw(event_js_data(event))) %>"
44
+ <% unless event.children.empty? %>
45
+ ,"state" : "closed"
46
+ <% end %>
47
+ }<%= ',' if i < (@active_sale.root.children.size - 1) %>
48
+ <% end %>
49
+ ]
50
+ }
51
+ ];
52
+ <% end -%>
53
+ <% end %>
@@ -7,6 +7,7 @@ en:
7
7
  active_record:
8
8
  name: "Sale name"
9
9
  event:
10
+ active_sale_tree_hint: "Right click on any row in the tree to access the menu for adding, deleting or sorting products in a sale. Drag and drop to change their positions."
10
11
  active_record:
11
12
  description: "Event Description"
12
13
  is_active: "Active?"
@@ -20,6 +21,7 @@ en:
20
21
  eventable_name: "Add the name to add type in event"
21
22
  eventable_type: "Add a type for event"
22
23
  permalink: "Type the name or permalink"
24
+ position: "Position"
23
25
  boolean:
24
26
  yes: "Yes"
25
27
  no: "No"
@@ -57,8 +59,11 @@ en:
57
59
  list: "Listing events"
58
60
  validation:
59
61
  errors:
62
+ date_empty: "can't be left empty."
60
63
  invalid_dates: "can not be greater than or equal to the end date."
64
+ invalid_root_dates: "and end date should be in between it's sub sales' start and end dates range."
61
65
  live_event: "already running and live."
66
+ parent_id_cant_be_nil: "Parent can not be null"
62
67
  events_not_found: "There are no sales available at this moment. Try later?"
63
68
  link:
64
69
  new: "New active sale"
@@ -23,8 +23,8 @@ es:
23
23
  boolean:
24
24
  yes: "Sí"
25
25
  no: "No"
26
- can_not_be_nil: "Argument can not be nil or instance of any other class than Spree::ActiveSaleEvent"
27
- create_if_no_record: "You don't have any event in this active sale, let's create an event?"
26
+ can_not_be_nil: "El argumento no puede ser nulo y debe ser una instancia de la clase Spree::ActiveSaleEvent"
27
+ create_if_no_record: "Todavía no tienes creada ningún evento, ¿lo creamos ya?"
28
28
  datetimepicker:
29
29
  format: ! '%d/%m/%Y %H:%M:%S %z'
30
30
  js_format: 'HH:mm:ss z'
data/config/routes.rb CHANGED
@@ -2,8 +2,17 @@ Spree::Core::Engine.routes.draw do
2
2
  # Add this extension's routes here
3
3
  namespace :admin do
4
4
  resources :active_sales do
5
+ collection do
6
+ get :eventables
7
+ post :update_positions
8
+ end
9
+ member do
10
+ get :get_children
11
+ end
5
12
  resources :active_sale_events do
6
- get 'eventables', :on => :collection
13
+ member do
14
+ put :update_events
15
+ end
7
16
  resources :sale_images do
8
17
  collection do
9
18
  post :update_positions
@@ -6,7 +6,7 @@ module SpreeActiveSale
6
6
 
7
7
  config.autoload_paths += %W(#{config.root}/lib)
8
8
 
9
- initializer "spree_active_sale.environment", :after => "spree.environment" do |app|
9
+ initializer "spree_active_sale.environment", :before => "spree.environment" do |app|
10
10
  Spree::ActiveSaleConfig = Spree::ActiveSaleConfiguration.new
11
11
  %w(ActionController::Base Spree::BaseController).each { |controller| controller.constantize.send(:helper, Spree::ActiveSaleEventsHelper) }
12
12
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_active_sale
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-16 00:00:00.000000000 Z
12
+ date: 2013-06-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: spree_core
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 1.3.0
21
+ version: 1.3.2
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: 1.3.0
29
+ version: 1.3.2
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: capybara
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -112,17 +112,17 @@ dependencies:
112
112
  requirement: !ruby/object:Gem::Requirement
113
113
  none: false
114
114
  requirements:
115
- - - ~>
115
+ - - '='
116
116
  - !ruby/object:Gem::Version
117
- version: '2.3'
117
+ version: 3.0.2
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  none: false
122
122
  requirements:
123
- - - ~>
123
+ - - '='
124
124
  - !ruby/object:Gem::Version
125
- version: '2.3'
125
+ version: 3.0.2
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: sass-rails
128
128
  requirement: !ruby/object:Gem::Requirement
@@ -181,14 +181,15 @@ files:
181
181
  - app/models/spree/active_sale_event.rb
182
182
  - app/models/spree/sale_event.rb
183
183
  - app/views/spree/home/index.html.erb
184
- - app/views/spree/admin/active_sales/_form.html.erb
185
184
  - app/views/spree/admin/active_sales/new.html.erb
185
+ - app/views/spree/admin/active_sales/get_children.json.erb
186
186
  - app/views/spree/admin/active_sales/index.html.erb
187
187
  - app/views/spree/admin/active_sales/edit.html.erb
188
188
  - app/views/spree/admin/active_sale_events/_form.html.erb
189
189
  - app/views/spree/admin/active_sale_events/new.html.erb
190
190
  - app/views/spree/admin/active_sale_events/index.html.erb
191
191
  - app/views/spree/admin/active_sale_events/edit.html.erb
192
+ - app/views/spree/admin/shared/_js_head.html.erb
192
193
  - app/views/spree/admin/shared/_translations.html.erb
193
194
  - app/views/spree/admin/shared/_list_events.html.erb
194
195
  - app/views/spree/admin/shared/_sale_images.html.erb
@@ -197,6 +198,7 @@ files:
197
198
  - app/views/spree/admin/sale_images/edit.html.erb
198
199
  - app/views/spree/shared/_sale_events.html.erb
199
200
  - app/controllers/spree/admin/sale_images_controller.rb
201
+ - app/controllers/spree/admin/resource_controller_decorator.rb
200
202
  - app/controllers/spree/admin/active_sales_controller.rb
201
203
  - app/controllers/spree/admin/active_sale_events_controller.rb
202
204
  - app/controllers/spree/home_controller_decorator.rb
@@ -205,6 +207,7 @@ files:
205
207
  - app/controllers/spree/products_controller_decorator.rb
206
208
  - app/controllers/spree/store_controller_decorator.rb
207
209
  - app/controllers/spree/taxons_controller_decorator.rb
210
+ - app/helpers/spree/base_helper_decorator.rb
208
211
  - app/helpers/spree/active_sale_events_helper.rb
209
212
  - app/helpers/spree/active_sales_helper.rb
210
213
  - app/overrides/admin_active_sales_tab.rb
@@ -241,7 +244,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
241
244
  version: '0'
242
245
  segments:
243
246
  - 0
244
- hash: -3636572579804555877
247
+ hash: -430475808815195775
245
248
  requirements:
246
249
  - none
247
250
  rubyforge_project:
@@ -1,35 +0,0 @@
1
- <% if @active_sale.try(:errors).present? %>
2
- <%= render :partial => 'spree/shared/error_messages', :locals => { :target => @active_sale } %>
3
- <% end %>
4
-
5
- <%= form_for [:admin, @active_sale] do |f| %>
6
-
7
- <fieldset data-hook="new_active_sale">
8
-
9
- <%= f.field_container :name do %>
10
- <%= f.label :name, t(:name) %> <span class="required">*</span><br />
11
- <%= f.text_field :name, :class => 'fullwidth title' %>
12
- <%= f.error_message_on :name %>
13
- <% end %>
14
-
15
- <p class="form-buttons" data-hook="admin_active_sale_form_buttons">
16
- <% if @active_sale.new_record? %>
17
- <%= render :partial => 'spree/admin/shared/new_resource_links' %>
18
- <% else %>
19
- <%= render :partial => 'spree/admin/shared/edit_resource_links' %>
20
- <% end %>
21
- </p>
22
-
23
- </fieldset>
24
- <% end %>
25
-
26
- <% unless @active_sale.new_record? %>
27
- <% if @active_sale.active_sale_events.blank? %>
28
- <% @active_sale_event = @active_sale.active_sale_events.build %>
29
- <h4><%= t('spree.active_sale.event.create_if_no_record') %></h4>
30
- <%= render :partial => "spree/admin/active_sale_events/form", :locals => { :events => @active_sale_event } %>
31
- <% else %>
32
- <% @active_sale_events = @active_sale.active_sale_events %>
33
- <%= render :partial => "spree/admin/shared/list_events", :locals => { :events => @active_sale_events } %>
34
- <% end %>
35
- <% end %>