spree_zaez_banner 3.0.0

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 (50) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +12 -0
  5. data/Gemfile +7 -0
  6. data/Guardfile +90 -0
  7. data/LICENSE +26 -0
  8. data/README.md +66 -0
  9. data/Rakefile +21 -0
  10. data/app/assets/javascripts/spree/backend/app/banner_box_settings/banner_box_setting.js.coffee +65 -0
  11. data/app/assets/javascripts/spree/backend/app/banner_box_settings/banner_box_style.js.coffee +23 -0
  12. data/app/assets/javascripts/spree/backend/spree_zaez_banner.js +1 -0
  13. data/app/assets/javascripts/spree/frontend/spree_zaez_banner.js +2 -0
  14. data/app/assets/stylesheets/spree/backend/spree_zaez_banner.css +6 -0
  15. data/app/assets/stylesheets/spree/frontend/spree_zaez_banner.css +4 -0
  16. data/app/controllers/spree/admin/banner_box_settings_controller.rb +52 -0
  17. data/app/controllers/spree/admin/banner_boxes_controller.rb +54 -0
  18. data/app/helpers/spree/banner_boxes_helper.rb +39 -0
  19. data/app/models/spree/banner_box.rb +68 -0
  20. data/app/models/spree/banner_configuration.rb +10 -0
  21. data/app/overrides/spree/admin/shared/_main_menu/add_banner_tab_to_main_menu.html.erb.deface +6 -0
  22. data/app/views/spree/admin/banner_box_settings/edit.html.erb +104 -0
  23. data/app/views/spree/admin/banner_boxes/_form.html.erb +63 -0
  24. data/app/views/spree/admin/banner_boxes/edit.html.erb +10 -0
  25. data/app/views/spree/admin/banner_boxes/index.html.erb +80 -0
  26. data/app/views/spree/admin/banner_boxes/new.html.erb +17 -0
  27. data/app/views/spree/admin/shared/sub_menu/_banner.html.erb +4 -0
  28. data/app/views/spree/shared/_banner_box.html.erb +31 -0
  29. data/bin/rails +7 -0
  30. data/config/locales/en.yml +48 -0
  31. data/config/locales/pt-br.yml +48 -0
  32. data/config/routes.rb +15 -0
  33. data/db/migrate/20120116204313_create_banners.rb +17 -0
  34. data/db/migrate/20120323174800_banner_namespace.rb +5 -0
  35. data/db/migrate/20131001104524_rename_presentation_to_alt_text.rb +5 -0
  36. data/db/migrate/20150721160059_add_display_period_to_spree_banner_boxes.rb +6 -0
  37. data/lib/generators/spree_zaez_banner/install/install_generator.rb +31 -0
  38. data/lib/spree_zaez_banner/engine.rb +24 -0
  39. data/lib/spree_zaez_banner/factories.rb +8 -0
  40. data/lib/spree_zaez_banner.rb +2 -0
  41. data/spec/features/admin/banner_box_settings_spec.rb +47 -0
  42. data/spec/features/admin/banner_boxes_spec.rb +126 -0
  43. data/spec/fixtures/spree.jpg +0 -0
  44. data/spec/models/spree/banner_box_spec.rb +58 -0
  45. data/spec/models/spree/banner_configuration_spec.rb +12 -0
  46. data/spec/spec_helper.rb +89 -0
  47. data/spec/support/capybara_login.rb +13 -0
  48. data/spree_zaez_banner.gemspec +38 -0
  49. data/test +0 -0
  50. metadata +350 -0
@@ -0,0 +1,39 @@
1
+ module Spree
2
+ module BannerBoxesHelper
3
+
4
+ # Monta o banner om os atributos passados
5
+ #
6
+ # Os atributos disponíveis são:
7
+ # category {default: 'home'}
8
+ # nome da categoria dos banners que serão exibidos
9
+ # class {default: ''}
10
+ # classe a ser inserida no container do carrossel
11
+ # style {default: [salvo em Spree::BannerConfig.default_style]}
12
+ # tamanho das imagens
13
+ # carousel_id {default: 'carousel'}
14
+ # id do carousel
15
+ # buttons_carousel {default: true}
16
+ # botões de controle do carrossel habilitado/desabilitado
17
+ # buttons_class {default: 'carousel-control'}
18
+ # classes para os botões de controle do carrossel
19
+ # indicators_carousel {default: true}
20
+ # indicadores dos banners habilitados/desabilitados
21
+ # image_class {default: ''}
22
+ # classes para serem inseridas na imagem
23
+ #
24
+ def insert_banner_box(params={})
25
+ params[:category] ||= 'home'
26
+ params[:style] ||= Spree::BannerConfig[:banner_default_style]
27
+ params[:carousel_id] ||= 'carousel'
28
+ params[:buttons_carousel] ||= true
29
+ params[:buttons_class] ||= 'carousel-control'
30
+ params[:indicators_carousel] ||= true
31
+
32
+ @banners = Spree::BannerBox.enabled(params[:category]).order(:position)
33
+ return '' if @banners.empty?
34
+
35
+ render :partial => 'spree/shared/banner_box', locals: { banners: @banners, params: params }
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,68 @@
1
+ module Spree
2
+ class BannerBox < ActiveRecord::Base
3
+
4
+ has_attached_file :attachment,
5
+ styles: Spree::BannerConfig[:banner_styles].symbolize_keys!,
6
+ default_style: Spree::BannerConfig[:banner_default_style].to_sym,
7
+ url: Spree::BannerConfig[:banner_url],
8
+ path: Spree::BannerConfig[:banner_path],
9
+ convert_options: { all: '-strip -auto-orient -colorspace sRGB' }
10
+ validates_attachment :attachment,
11
+ :presence => true,
12
+ :content_type => { :content_type => %w(image/jpeg image/jpg image/png image/gif) }
13
+
14
+ # save the w,h of the original image (from which others can be calculated)
15
+ # we need to look at the write-queue for images which have not been saved yet
16
+ after_post_process :find_dimensions
17
+
18
+ validates_presence_of :category
19
+
20
+ scope :enabled, lambda { |*categories|
21
+ if categories.empty?
22
+ where(:enabled => true).where('begin_display IS NULL OR begin_display <= :d) AND (end_display IS NULL OR end_display >= :d', d: Date.today)
23
+ else
24
+ where(:enabled => true)
25
+ .where('begin_display IS NULL OR begin_display <= :d) AND (end_display IS NULL OR end_display >= :d', d: Date.today)
26
+ .where(:category => categories)
27
+ end
28
+ }
29
+
30
+ # for adding banner_boxes which are closely related to existing ones
31
+ # define "duplicate_extra" for site-specific actions, eg for additional fields
32
+ def duplicate
33
+ enhance_settings
34
+ p = self.dup
35
+ p.category = 'COPY OF ' + category
36
+ p.created_at = p.updated_at = nil
37
+ p.url = url
38
+ p.attachment = attachment
39
+
40
+ # allow site to do some customization
41
+ p.send(:duplicate_extra, self) if p.respond_to?(:duplicate_extra)
42
+ p.save!
43
+ p
44
+ end
45
+
46
+ def find_dimensions
47
+ temporary = attachment.queued_for_write[:original]
48
+ filename = temporary.path unless temporary.nil?
49
+ filename = attachment.path if filename.blank?
50
+ geometry = Paperclip::Geometry.from_file(filename)
51
+ self.attachment_width = geometry.width
52
+ self.attachment_height = geometry.height
53
+ end
54
+
55
+ def enhance_settings
56
+ Spree::BannerBox.attachment_definitions[:attachment][:styles] = Spree::BannerConfig[:banner_styles].symbolize_keys!
57
+ Spree::BannerBox.attachment_definitions[:attachment][:path] = Spree::BannerConfig[:banner_path]
58
+ Spree::BannerBox.attachment_definitions[:attachment][:url] = Spree::BannerConfig[:banner_url]
59
+ Spree::BannerBox.attachment_definitions[:attachment][:default_url] = Spree::BannerConfig[:banner_default_url]
60
+ Spree::BannerBox.attachment_definitions[:attachment][:default_style] = Spree::BannerConfig[:banner_default_style].to_sym
61
+ end
62
+
63
+ def self.categories_for_select
64
+ unscoped.pluck(:category).uniq.sort
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,10 @@
1
+ module Spree
2
+ class BannerConfiguration < Preferences::Configuration
3
+ preference :banner_default_url, :string, default: '/spree/banners/:id/:style/:basename.:extension'
4
+ preference :banner_path, :string, default: ':rails_root/public/spree/banners/:id/:style/:basename.:extension'
5
+ preference :banner_url, :string, default: '/spree/banners/:id/:style/:basename.:extension'
6
+ preference :banner_styles, :hash, default: {mini: '50x50>', small: '120x120>', large: '800x200>'}
7
+ preference :banner_default_style, :string, default: 'small'
8
+
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ <!-- insert_before "erb[silent]:contains('if can? :admin, current_store')" -->
2
+ <% if can? :admin, current_store %>
3
+ <ul class="nav nav-sidebar">
4
+ <%= main_menu_tree Spree.t(:banners), icon: 'bookmark', sub_menu: 'banner', url: '#sidebar-banner' %>
5
+ </ul>
6
+ <% end %>
@@ -0,0 +1,104 @@
1
+ <%= render :partial => 'spree/admin/shared/sub_menu/banner' %>
2
+
3
+ <% content_for :page_title do %>
4
+ <%= Spree.t(:banner_box_settings) %>
5
+ <% end %>
6
+
7
+ <script type='text/template' id='banner_style_template'>
8
+ <div class="col-md-3 col-sm-6">
9
+ <label for="banner_styles_{{new_style.text}}">{{new_style.text}}</label>
10
+ <a class="destroy_banner_style with-tip" title="" alt="Destroy" data-value="{{new_style.text}}" href="#" data-original-title="Destroy">
11
+ <i class="icon icon-trash"></i>
12
+ </a>
13
+ <input type="text" name="banner_styles[{{new_style.text}}]" id="banner_styles_{{new_style.text}}" value="{{new_style.value}}" class="form-control">
14
+ </div>
15
+ </script>
16
+
17
+ <script type="text/template" id="new_banner_style_template">
18
+ {{#each new_style}}
19
+ <div class="col-md-3 col-sm-6" id="banner_style_form">
20
+ <div class="col-sm-6 p-l-n">
21
+ <label for="new_banner_styles_name"><%= Spree.t(:new_banner_style_name) %></label>
22
+ <input type="text" name="new_banner_styles_name" id="new_banner_styles_name" value="" class="form-control">
23
+ </div>
24
+ <div class="col-sm-6 p-r-n p-l-n">
25
+ <label for="new_banner_styles_value"><%= Spree.t(:new_banner_style_value) %></label>
26
+ <a href="#" title="<%= t(:confirm) %>" alt="<%= t(:confirm) %>" class="new_banner_style_form with-tip">
27
+ <i class='icon icon-ok'></i>
28
+ </a>
29
+ <input type="text" name="new_banner_styles_value" id="new_banner_styles_value" value="" class="form-control">
30
+ </div>
31
+ </div>
32
+ {{/each}}
33
+ </script>
34
+
35
+ <%= form_tag admin_banner_box_settings_path, :method => :put do %>
36
+ <div id="banner_box_preferences" data-hook="banner_box_preferences">
37
+ <div class="panel panel-default">
38
+ <div class="panel-heading">
39
+ <h1 class="panel-title">
40
+ <%= Spree.t(:general_settings) %>
41
+ </h1>
42
+ </div>
43
+ <div class="panel-body">
44
+ <div class="row">
45
+ <div class="col-sm-12">
46
+ <div class="alert alert-info no-objects-found">
47
+ <%= Spree.t(:banner_box_settings_warning) %>
48
+ </div>
49
+ </div>
50
+ </div>
51
+ <div class="row">
52
+ <div class="col-sm-6">
53
+ <%= label_tag 'preferences[banner_path]', Spree.t(:banner_path) %>
54
+ <%= preference_field_tag 'preferences[banner_path]', @config.banner_path, :type => :string %>
55
+ </div>
56
+ <div class="col-sm-6">
57
+ <%= label_tag 'preferences[banner_default_url]', Spree.t(:banner_default_url) %>
58
+ <%= preference_field_tag 'preferences[banner_default_url]', @config.banner_default_url, :type => :string %>
59
+ </div>
60
+ <div class="col-sm-6">
61
+ <%= label_tag 'preferences[banner_url]', Spree.t(:banner_url) %>
62
+ <%= preference_field_tag 'preferences[banner_url]', @config.banner_url, :type => :string %>
63
+ </div>
64
+ <div class="col-sm-6">
65
+ <%= label_tag 'preferences[banner_default_style]', Spree.t(:banner_default_style) %>
66
+ <%= collection_select 'preferences', 'banner_default_style', @config.banner_styles, :first, :first,
67
+ {:selected => @config.banner_default_style }, :class => 'select2 fullwidth' %>
68
+ </div>
69
+ </div>
70
+ </div>
71
+ </div>
72
+ </div>
73
+ <div id="banner_box_preferences" data-hook="banner_box_preferences">
74
+ <div class="panel panel-default">
75
+ <div class="panel-heading">
76
+ <h1 class="panel-title">
77
+ <%= Spree.t(:banner_styles) %>
78
+ </h1>
79
+ </div>
80
+ <div class="panel-body">
81
+ <div class="row" id="banner_styles">
82
+ <% @config.banner_styles.each do |key, value| %>
83
+ <div class="col-md-3 col-sm-6" id="banner_style_<%= key %>">
84
+ <%= label_tag "banner_styles[#{key}]", key %>
85
+ <%= link_to '#', class: 'destroy_banner_style with-tip', title: t(:destroy), alt: t(:destroy), data: {value: key} do %>
86
+ <i class='icon icon-trash'></i>
87
+ <% end if key != :mini %>
88
+ <%= text_field_tag "banner_styles[#{key}]", value, class: 'form-control' %>
89
+ </div>
90
+ <% end %>
91
+ </div>
92
+ <div class="pull-right buttons">
93
+ <%= link_to_with_icon 'plus', Spree.t(:add_new_banner_style), '#', :class => 'add_new_banner_style btn btn-primary' %>
94
+ </div>
95
+ </div>
96
+ </div>
97
+ </div>
98
+
99
+ <%= render partial: 'spree/admin/shared/edit_resource_links', locals: { collection_url: admin_banner_box_settings_path } %>
100
+ <% end %>
101
+
102
+ <script type="text/javascript">
103
+ new window.BannerBoxSetting()
104
+ </script>
@@ -0,0 +1,63 @@
1
+ <div data-hook="admin_banner_box_form_fields">
2
+ <div class="row">
3
+ <div class="col-sm-6">
4
+ <%= f.field_container :category do %>
5
+ <%= f.label :category, raw(Spree.t(:category) + content_tag(:span, ' *', :class => 'required')) %>
6
+ <%= f.text_field :category, :class => 'form-control title' %>
7
+ <%= f.error_message_on :category %>
8
+ <% end %>
9
+ </div>
10
+ <div class="col-sm-6">
11
+ <%= f.field_container :url do %>
12
+ <%= f.label :url, Spree.t(:url) %>
13
+ <%= f.text_field :url, :class => 'form-control title' %>
14
+ <%= f.error_message_on :url %>
15
+ <% end %>
16
+ </div>
17
+ </div>
18
+ <div class="row">
19
+ <div class="col-sm-6">
20
+ <%= f.field_container :alt_text do %>
21
+ <%= f.label :alt_text, Spree.t(:alt_text) %>
22
+ <%= f.text_field :alt_text, :class => 'form-control' %>
23
+ <%= f.error_message_on :alt_text %>
24
+ <% end %>
25
+ </div>
26
+ <div class="col-sm-6">
27
+ <% unless f.object.new_record? %>
28
+ <div data-hook="thumbnail" class="col-sm-3">
29
+ <%= f.label Spree.t(:thumbnail) %><br>
30
+ <%= link_to image_tag(@banner_box.attachment.url(:mini)), @banner_box.attachment.url(:small) %>
31
+ </div>
32
+ <% end %>
33
+ <%= f.field_container :attachment do %>
34
+ <%= f.label :attachment, Spree.t(:attachment) %><br />
35
+ <%= f.file_field :attachment %>
36
+ <%= f.error_message_on :attachment %>
37
+ <% end %>
38
+ </div>
39
+ </div>
40
+ <div class="row">
41
+ <div class="col-sm-4">
42
+ <%= f.field_container :begin_display do %>
43
+ <%= f.label :begin_display, Spree.t(:begin_display) %><br />
44
+ <%= f.text_field :begin_display, class: 'datepicker form-control' %>
45
+ <%= f.error_message_on :begin_display %>
46
+ <% end %>
47
+ </div>
48
+ <div class="col-sm-4">
49
+ <%= f.field_container :end_display do %>
50
+ <%= f.label :end_display, Spree.t(:end_display) %><br />
51
+ <%= f.text_field :end_display, class: 'datepicker form-control' %>
52
+ <%= f.error_message_on :end_display %>
53
+ <% end %>
54
+ </div>
55
+ <div class="col-sm-4">
56
+ <%= f.field_container :enabled do %>
57
+ <%= f.label :enabled, Spree.t(:enabled) %><br />
58
+ <%= f.check_box :enabled %>
59
+ <%= f.error_message_on :enabled %>
60
+ <% end %>
61
+ </div>
62
+ </div>
63
+ </div>
@@ -0,0 +1,10 @@
1
+ <% content_for :page_title do %>
2
+ <%= Spree.t(:editing_resource, resource: Spree::BannerBox.model_name.human) %>
3
+ <% end %>
4
+
5
+ <%= render :partial => 'spree/admin/shared/error_messages', :locals => { :target => @banner_box } %>
6
+
7
+ <%= form_for [:admin, @banner_box] do |f| %>
8
+ <%= render :partial => 'form', :locals => { :f => f } %>
9
+ <%= render :partial => 'spree/admin/shared/edit_resource_links' %>
10
+ <% end %>
@@ -0,0 +1,80 @@
1
+ <% content_for :page_title do %>
2
+ <%= Spree.t(:listing_banner_boxes) %>
3
+ <% end %>
4
+
5
+ <% content_for :page_actions do %>
6
+ <%= button_link_to Spree.t(:new_banner_box), new_admin_banner_box_path, { :icon => 'add', :class => 'btn-success' } %>
7
+ <% end if can? :create, Spree::BannerBox %>
8
+
9
+ <div data-hook="admin_banner_index_search" class="well">
10
+ <fieldset>
11
+ <legend><%= Spree.t(:search) %></legend>
12
+ <%= search_form_for @q, :url => admin_banner_boxes_path do |f| %>
13
+
14
+ <div class="row no-marginb">
15
+ <div class="col-md-4">
16
+ <div class="form-group">
17
+ <%= f.label :category_eq, Spree.t(:category) %>
18
+ <%= f.select :category_eq, Spree::BannerBox.categories_for_select, {:include_blank => true}, {:class => 'select2'} %>
19
+ </div>
20
+ </div>
21
+
22
+ <div class="col-md-8">
23
+ <div class="form-group">
24
+ <%= f.label :url_cont, Spree.t(:url) %>
25
+ <%= f.text_field :url_cont, size: 15, class: 'form-control' %>
26
+ </div>
27
+ </div>
28
+
29
+ <div class="col-md-12">
30
+ <div class="form-group">
31
+ <%= f.check_box :enabled_true %>
32
+ <%= f.label :enabled_true, Spree.t(:show_only_enabled) %>
33
+ </div>
34
+ </div>
35
+ </div>
36
+
37
+ <div class="form-actions">
38
+ <div data-hook="admin_banner_box_index_search_buttons">
39
+ <%= button Spree.t(:filter_results), 'search' %>
40
+ </div>
41
+ </div>
42
+ <% end %>
43
+ </fieldset>
44
+ </div>
45
+
46
+ <div id="new_banner_box" data-hook></div>
47
+
48
+ <% if @collection.any? %>
49
+ <table class="table" id="listing_banner_boxes">
50
+ <thead>
51
+ <tr data-hook="rate_header">
52
+ <th><%= Spree.t(:thumbnail) %></th>
53
+ <th><%= Spree.t(:category) %></th>
54
+ <th><%= Spree.t(:url) %></th>
55
+ <th></th>
56
+ </tr>
57
+ </thead>
58
+ <tbody data-hook="admin_banner_boxes_index_rows">
59
+ <% @collection.each do |banner_box|%>
60
+ <tr id="<%= spree_dom_id banner_box %>" data-hook="banner_box_row">
61
+ <td><%= image_tag(banner_box.attachment(:mini)) %></td>
62
+ <td><%= banner_box.category rescue '' %></td>
63
+ <td><%= banner_box.url rescue '' %></td>
64
+ <td class="actions actions-2 text-right">
65
+ <%= link_to_edit banner_box, no_text: true if can?(:edit, banner_box) %>
66
+ <%= link_to_with_icon 'clone', Spree.t(:clone), clone_admin_banner_box_url(banner_box),
67
+ no_text: true, class: 'btn btn-primary btn-sm' if can?(:clone, banner_box) %>
68
+ <%= link_to_delete banner_box, no_text: true if can?(:delete, banner_box) %>
69
+ </td>
70
+ </tr>
71
+ <% end %>
72
+ </tbody>
73
+ </table>
74
+ <% else %>
75
+ <div class="alert alert-info no-objects-found">
76
+ <%= t(:no_results) %>
77
+ </div>
78
+ <% end %>
79
+
80
+ <%= paginate @collection %>
@@ -0,0 +1,17 @@
1
+ <% content_for :page_title do %>
2
+ <%= Spree.t(:new_banner_box) %>
3
+ <% end %>
4
+
5
+ <div data-hook="admin_banner_box_new_form_header">
6
+ <%= render :partial => 'spree/admin/shared/error_messages', :locals => { :target => @banner_box } %>
7
+ </div>
8
+
9
+ <div data-hook="admin_banner_box_new_form">
10
+ <%= form_for [:admin, @banner_box], url: spree.admin_banner_boxes_url, method: :post, :html => { :multipart => true } do |f| %>
11
+ <%= render :partial => 'form', :locals => { :f => f } %>
12
+
13
+ <div data-hook="admin_banner_box_new_form_buttons">
14
+ <%= render :partial => 'spree/admin/shared/new_resource_links' %>
15
+ </div>
16
+ <% end %>
17
+ </div>
@@ -0,0 +1,4 @@
1
+ <ul id="sidebar-banner" class="collapse nav nav-pills nav-stacked" data-hook="admin_banner_sub_tabs">
2
+ <%= tab :banner_box_settings, edit_admin_banner_box_settings_url %>
3
+ <%= tab :banner_boxes, :match_path => '/banner_boxes' %>
4
+ </ul>
@@ -0,0 +1,31 @@
1
+ <div id="<%= params[:carousel_id] %>" class="carousel slide <%= params[:class] %>" data-ride="carousel">
2
+ <% if params[:indicators_carousel] %>
3
+ <ol class="carousel-indicators">
4
+ <% @banners.each_with_index do |banner, index| %>
5
+ <li data-target="#<%= params[:carousel_id] %>" data-slide-to="<%= index %>"
6
+ class="<%= 'active' if banner == @banners.first %>"></li>
7
+ <% end %>
8
+ </ol>
9
+ <% end %>
10
+
11
+ <div class="carousel-inner" role="listbox">
12
+ <% @banners.each do |banner| %>
13
+ <div class="item <%= 'active' if banner == @banners.first %>">
14
+ <%= link_to (banner.url.blank? ? 'javascript: void(0)' : banner.url) do %>
15
+ <%= image_tag banner.attachment.url(params[:style]), alt: banner.alt_text, class: params[:image_class] %>
16
+ <% end %>
17
+ </div>
18
+ <% end %>
19
+ </div>
20
+
21
+ <% if params[:buttons_carousel] %>
22
+ <a class="left <%= params[:buttons_class] %>" href="#<%= params[:carousel_id] %>" role="button" data-slide="prev">
23
+ <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
24
+ <span class="sr-only"><%= Spree.t(:previous) %></span>
25
+ </a>
26
+ <a class="right <%= params[:buttons_class] %>" href="#<%= params[:carousel_id] %>" role="button" data-slide="next">
27
+ <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
28
+ <span class="sr-only"><%= Spree.t(:next) %></span>
29
+ </a>
30
+ <% end %>
31
+ </div>