diff --git a/app/assets/javascripts/darkswarm/controllers/groups_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/groups_controller.js.coffee
new file mode 100644
index 0000000000..8fd47c49f8
--- /dev/null
+++ b/app/assets/javascripts/darkswarm/controllers/groups_controller.js.coffee
@@ -0,0 +1,3 @@
+Darkswarm.controller "GroupsCtrl", ($scope, Groups) ->
+ $scope.Groups = Groups
+ $scope.order = 'position'
diff --git a/app/assets/javascripts/darkswarm/controllers/products/product_node_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/products/product_node_controller.js.coffee
new file mode 100644
index 0000000000..4ec316e65f
--- /dev/null
+++ b/app/assets/javascripts/darkswarm/controllers/products/product_node_controller.js.coffee
@@ -0,0 +1,9 @@
+Darkswarm.controller "ProductNodeCtrl", ($scope) ->
+ $scope.price = ->
+ if $scope.product.variants.length > 0
+ prices = (v.price for v in $scope.product.variants)
+ Math.min.apply(null, prices)
+ else
+ $scope.product.price
+
+ $scope.hasVariants = $scope.product.variants.length > 0
diff --git a/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee
index 9ba11baa5b..09df18ca38 100644
--- a/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee
+++ b/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee
@@ -1,8 +1,8 @@
Darkswarm.controller "ProductsCtrl", ($scope, $rootScope, Product, OrderCycle) ->
$scope.data = Product.data
$scope.limit = 3
+ $scope.ordering = {order: "name"}
$scope.order_cycle = OrderCycle.order_cycle
- Product.update()
$scope.incrementLimit = ->
if $scope.limit < $scope.data.products.length
@@ -14,8 +14,3 @@ Darkswarm.controller "ProductsCtrl", ($scope, $rootScope, Product, OrderCycle) -
e.preventDefault()
$scope.productPrice = (product) ->
- if product.variants.length > 0
- prices = (v.price for v in product.variants)
- Math.min.apply(null, prices)
- else
- product.price
diff --git a/app/assets/javascripts/darkswarm/directives/modal.js.coffee b/app/assets/javascripts/darkswarm/directives/modal.js.coffee
index 8c34ec18a8..73217b3812 100644
--- a/app/assets/javascripts/darkswarm/directives/modal.js.coffee
+++ b/app/assets/javascripts/darkswarm/directives/modal.js.coffee
@@ -2,13 +2,14 @@ Darkswarm.directive "ofnModal", ($modal)->
restrict: 'E'
replace: true
transclude: true
+ scope: {}
template: "{{title}}"
link: (scope, elem, attrs, ctrl, transclude)->
scope.title = attrs.title
+ contents = null
+ transclude scope, (clone)->
+ contents = clone
- scope.cancel = ->
- scope.modalInstance.dismiss("cancel")
-
- elem.on "click", ->
- scope.modalInstance = $modal.open(controller: ctrl, template: transclude())
+ elem.on "click", =>
+ scope.modalInstance = $modal.open(controller: ctrl, template: contents)
diff --git a/app/assets/javascripts/darkswarm/services/groups.js.coffee b/app/assets/javascripts/darkswarm/services/groups.js.coffee
new file mode 100644
index 0000000000..e5e50615e8
--- /dev/null
+++ b/app/assets/javascripts/darkswarm/services/groups.js.coffee
@@ -0,0 +1,4 @@
+Darkswarm.factory 'Groups', (groups) ->
+ new class Groups
+ constructor: ->
+ @groups = groups
diff --git a/app/assets/javascripts/darkswarm/services/product.js.coffee b/app/assets/javascripts/darkswarm/services/product.js.coffee
index 89778b659c..ca31d5e9c0 100644
--- a/app/assets/javascripts/darkswarm/services/product.js.coffee
+++ b/app/assets/javascripts/darkswarm/services/product.js.coffee
@@ -1,12 +1,12 @@
Darkswarm.factory 'Product', ($resource) ->
new class Product
- data: {
+ constructor: ->
+ @update()
+ data:
products: null
loading: true
- }
+
update: ->
@data.products = $resource("/shop/products").query =>
@data.loading = false
@data
- all: ->
- @data.products || @update()
diff --git a/app/assets/stylesheets/darkswarm/mixins.sass b/app/assets/stylesheets/darkswarm/mixins.sass
index 1f8086d9f2..fde601f2d9 100644
--- a/app/assets/stylesheets/darkswarm/mixins.sass
+++ b/app/assets/stylesheets/darkswarm/mixins.sass
@@ -12,7 +12,7 @@
border: 1px solid #999
font-size: 18px
@extend .avenir
- padding: 22px 18px
+ padding: 0.75em 1em
height: auto
margin-bottom: 1em
diff --git a/app/assets/stylesheets/darkswarm/product_table.css.sass b/app/assets/stylesheets/darkswarm/product_table.css.sass
new file mode 100644
index 0000000000..9b0a7b4598
--- /dev/null
+++ b/app/assets/stylesheets/darkswarm/product_table.css.sass
@@ -0,0 +1,4 @@
+.product_table
+ .row
+ border: 1px solid black
+ padding: 8px inherit
diff --git a/app/assets/stylesheets/darkswarm/shop.css.sass b/app/assets/stylesheets/darkswarm/shop.css.sass
index 2107542594..0c2972367a 100644
--- a/app/assets/stylesheets/darkswarm/shop.css.sass
+++ b/app/assets/stylesheets/darkswarm/shop.css.sass
@@ -1,8 +1,7 @@
@import mixins
@import variables
+@import branding
-product
- display: block
.darkswarm
#search
@@ -77,68 +76,58 @@ product
products
display: block
- padding-top: 2.3em
+ padding-top: 2.3em
@media all and (max-width: 768px)
padding-top: 1em
input.button.right
float: left
- table
- table-layout: fixed
- width: 100%
- border-collapse: collapse
- border: none
- th
- line-height: 50px
- &.name
- width: 330px
- //&.notes
- //width: 140px
- &.variant
- width: 180px
- &.quantity, &.bulk, &.price
- width: 90px
- .notes
- max-width: 300px
- td, th
+
+
+ product:hover, product:focus, product:active
+ border-color: $clr-brick
+ @include box-shadow(0 0 3px 0 $clr-brick-bright)
+
+ .row.variants
+ border-top: 1px solid $clr-brick-light
+ background: $clr-brick-ultra-light
+
+ product
+ @include csstrans
+ border: 1px solid #989898
+ display: block
+ margin-bottom: 1em !important
+
+ input
+ margin: 0
+ width: 8em
+
+ .columns
+ padding-top: 1em
+ padding-bottom: 1em
+
+ .row.summary, .row.variants
+ @include csstrans
+ margin-left: 0
+ margin-right: 0
+ background: #f7f7f7
+ border-top: 1px solid #dfdfdf
+
+ .row.summary
+ @include csstrans
background: #fff
- > span
- min-width: 50px
- display: block
- tbody
- border: 1px solid #cccccc
- border-left: 0px
- border-right: 0px
- td
- padding: 20px 0px
- &.name
- img
- float: left
- margin-right: 30px
- @media all and (max-width: 768px)
- margin-right: 1em
- div
- min-width: 150px
- tr.product-description
- display: none
+
+ .summary-header
+ &, & *
+ @include avenir
+ color: $clr-brick
+
+ .summary-price
+ &, & *
+ @include avenir
+
+
+
- // Responsive
- @media all and (max-width: 768px)
- td.notes, th.notes
- display: none
- img
- width: 20px
- height: auto
- tr.product-description
- display: table-row
- td:empty
- display: none
-
- input[type=number]
- width: 60px
- margin: 0px
- display: block
- float: right
- padding-top: 14px
diff --git a/app/assets/stylesheets/groups.css.scss b/app/assets/stylesheets/groups.css.scss
new file mode 100644
index 0000000000..c2a5f9013b
--- /dev/null
+++ b/app/assets/stylesheets/groups.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the groups controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/controllers/admin/enterprise_groups_controller.rb b/app/controllers/admin/enterprise_groups_controller.rb
index 466bde2cd5..cc2f3ed1db 100644
--- a/app/controllers/admin/enterprise_groups_controller.rb
+++ b/app/controllers/admin/enterprise_groups_controller.rb
@@ -15,12 +15,10 @@ module Admin
redirect_to main_app.admin_enterprise_groups_path
end
-
private
def collection
EnterpriseGroup.by_position
end
-
end
end
diff --git a/app/controllers/checkout_controller.rb b/app/controllers/checkout_controller.rb
index 2bedcf5b6b..3879f16741 100644
--- a/app/controllers/checkout_controller.rb
+++ b/app/controllers/checkout_controller.rb
@@ -26,7 +26,11 @@ class CheckoutController < Spree::CheckoutController
if @order.next
state_callback(:after)
else
- flash[:error] = @order.errors.full_messages.to_sentence
+ unless @order.errors.empty?
+ flash[:error] = @order.errors.full_messages.to_sentence
+ else
+ flash[:error] = t(:payment_processing_failed)
+ end
update_failed
return
end
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
new file mode 100644
index 0000000000..84290f20a3
--- /dev/null
+++ b/app/controllers/groups_controller.rb
@@ -0,0 +1,7 @@
+class GroupsController < BaseController
+ layout 'darkswarm'
+
+ def index
+ @groups = EnterpriseGroup.on_front_page.by_position
+ end
+end
diff --git a/app/controllers/spree/admin/base_controller_decorator.rb b/app/controllers/spree/admin/base_controller_decorator.rb
index 8e876513fa..df7076345f 100644
--- a/app/controllers/spree/admin/base_controller_decorator.rb
+++ b/app/controllers/spree/admin/base_controller_decorator.rb
@@ -11,4 +11,4 @@ Spree::Admin::BaseController.class_eval do
authorize! :admin, record
authorize! action, record
end
-end
\ No newline at end of file
+end
diff --git a/app/controllers/spree/admin/overview_controller_decorator.rb b/app/controllers/spree/admin/overview_controller_decorator.rb
index dd53294f6f..5c96901c1d 100644
--- a/app/controllers/spree/admin/overview_controller_decorator.rb
+++ b/app/controllers/spree/admin/overview_controller_decorator.rb
@@ -4,4 +4,17 @@ Spree::Admin::OverviewController.class_eval do
@product_count = Spree::Product.active.managed_by(spree_current_user).count
@order_cycle_count = OrderCycle.active.managed_by(spree_current_user).count
end
-end
\ No newline at end of file
+
+ # This is in Spree::Core::ControllerHelpers::Auth
+ # But you can't easily reopen modules in Ruby
+ def unauthorized
+ if try_spree_current_user
+ flash[:error] = t(:authorization_failure)
+ redirect_to '/unauthorized'
+ else
+ store_location
+ url = respond_to?(:spree_login_path) ? spree_login_path : root_path
+ redirect_to url
+ end
+ end
+end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
new file mode 100644
index 0000000000..c091b2fc82
--- /dev/null
+++ b/app/helpers/groups_helper.rb
@@ -0,0 +1,2 @@
+module GroupsHelper
+end
diff --git a/app/models/enterprise_group.rb b/app/models/enterprise_group.rb
index 41d2a997cc..6c163b087a 100644
--- a/app/models/enterprise_group.rb
+++ b/app/models/enterprise_group.rb
@@ -4,6 +4,17 @@ class EnterpriseGroup < ActiveRecord::Base
has_and_belongs_to_many :enterprises
validates :name, presence: true
+ validates :description, presence: true
+
+ attr_accessible :name, :description, :long_description, :on_front_page, :enterprise_ids
+
+ attr_accessible :promo_image
+ has_attached_file :promo_image, styles: {medium: "800>400"}
+ validates_attachment_content_type :promo_image, :content_type => /\Aimage\/.*\Z/
+
+ attr_accessible :logo
+ has_attached_file :logo, styles: {medium: "100x100"}
+ validates_attachment_content_type :logo, :content_type => /\Aimage\/.*\Z/
scope :by_position, order('position ASC')
scope :on_front_page, where(on_front_page: true)
diff --git a/app/models/spree/product_decorator.rb b/app/models/spree/product_decorator.rb
index 282a93cfb5..ba7cbc253d 100644
--- a/app/models/spree/product_decorator.rb
+++ b/app/models/spree/product_decorator.rb
@@ -118,6 +118,10 @@ Spree::Product.class_eval do
order_cycle.variants_distributed_by(distributor).where(product_id: self)
end
+ def primary_taxon
+ self.taxons.order.first
+ end
+
# Build a product distribution for each distributor
def build_product_distributions_for_user user
Enterprise.is_distributor.managed_by(user).each do |distributor|
diff --git a/app/views/admin/enterprise_groups/_form.html.haml b/app/views/admin/enterprise_groups/_form.html.haml
index b41a68d4a5..ec4934bf19 100644
--- a/app/views/admin/enterprise_groups/_form.html.haml
+++ b/app/views/admin/enterprise_groups/_form.html.haml
@@ -3,6 +3,16 @@
%br/
= f.text_field :name
+= f.field_container :description do
+ = f.label :description
+ %br/
+ = f.text_field :description
+
+= f.field_container :long_description do
+ = f.label :long_description
+ %br/
+ = f.text_area :long_description
+
= f.field_container :on_front_page do
= f.label :on_front_page, 'On front page?'
%br/
@@ -12,3 +22,22 @@
= f.label :enterprise_ids, 'Enterprises'
%br/
= f.collection_select :enterprise_ids, Enterprise.all, :id, :name, {}, {class: "select2 fullwidth", multiple: true}
+
+
+.row
+ .alpha.three.columns
+ = f.label :logo, class: 'with-tip', 'data-powertip' => 'This is the logo'
+ .with-tip{'data-powertip' => 'This is the logo'}
+ %a What's this?
+ .omega.eight.columns
+ = image_tag @object.logo.url if @object.logo.present?
+ = f.file_field :logo
+
+.row
+ .alpha.three.columns
+ = f.label :promo_image, class: 'with-tip', 'data-powertip' => 'This image is displayed at the top of the Group profile'
+ .with-tip{'data-powertip' => 'This image is displayed at the top of the Group profile'}
+ %a What's this?
+ .omega.eight.columns
+ = image_tag @object.promo_image.url if @object.promo_image.present?
+ = f.file_field :promo_image
diff --git a/app/views/groups/index.html.haml b/app/views/groups/index.html.haml
new file mode 100644
index 0000000000..552e45fd48
--- /dev/null
+++ b/app/views/groups/index.html.haml
@@ -0,0 +1,25 @@
+#groups{"ng-controller" => "GroupsCtrl"}
+ :javascript
+ angular.module('Darkswarm').value('groups', #{render partial: "json/groups", object: @groups})
+ .row
+ .small-12.columns.text-center
+ %h1 Groups / Regions
+ %h3 Check out our food groups below
+
+ %input{type: :text,
+ "ng-model" => "query",
+ placeholder: "Search group name",
+ "ng-debounce" => "150",
+ "ofn-disable-enter" => true}
+
+ .row.group_table{bindonce: true}
+ .small.12.columns
+ .group{"ng-repeat" => "group in Groups.groups | filter:query | orderBy:order"}
+ %h2 {{ group.name }}
+ %p {{ group.description }}
+ %p {{ group.long_description }}
+ %img{"bo-src" => "group.logo"}
+
+ %ul
+ %li{"ng-repeat" => "enterprise in group.enterprises"}
+ %a{"bo-href" => "enterprise.path"} {{ enterprise.name }}
diff --git a/app/views/home/_fat.html.haml b/app/views/home/_fat.html.haml
index 7d5dfb3b80..9382844265 100644
--- a/app/views/home/_fat.html.haml
+++ b/app/views/home/_fat.html.haml
@@ -2,7 +2,8 @@
.columns.small-4
%strong Shop for
%p.trans-sentence
- {{ hub.taxons | printArrayOfObjects }}
+ %img{"ng-repeat" => "taxon in hub.taxons", "bo-src" => "taxon.icon",
+ name: "{{taxon.name}}", alt: "{{taxon.name}}"}
.columns.small-4
%strong Delivery options
%ol
@@ -10,8 +11,9 @@
%li.delivery{"bo-if" => "hub.delivery"} Delivery
.columns.small-4
%strong Our producers
- %p
- Go to our shop to see our current producers
+ %ul
+ %li{"ng-repeat" => "producer in hub.producers"}
+ = render partial: "modals/producer"
.row.active_table_row.link{"ng-show" => "open()", "ng-if" => "hub.active"}
.columns.small-11
diff --git a/app/views/json/_enterprises.rabl b/app/views/json/_enterprises.rabl
index 97e040eca9..2f2f82c944 100644
--- a/app/views/json/_enterprises.rabl
+++ b/app/views/json/_enterprises.rabl
@@ -4,3 +4,11 @@ attributes :name, :id, :description
child :address do
extends "json/partials/address"
end
+
+node :path do |enterprise|
+ shop_enterprise_path(enterprise)
+end
+
+node :hash do |enterprise|
+ enterprise.to_param
+end
diff --git a/app/views/json/_groups.rabl b/app/views/json/_groups.rabl
new file mode 100644
index 0000000000..9475b425c4
--- /dev/null
+++ b/app/views/json/_groups.rabl
@@ -0,0 +1,10 @@
+collection @groups
+attributes :id, :name, :position, :description, :long_description
+
+child enterprises: :enterprises do
+ extends 'json/enterprises'
+end
+
+node :logo do |group|
+ group.logo(:original)
+end
diff --git a/app/views/json/_hubs.rabl b/app/views/json/_hubs.rabl
index a6958840bc..dc589b878b 100644
--- a/app/views/json/_hubs.rabl
+++ b/app/views/json/_hubs.rabl
@@ -2,11 +2,15 @@ collection Enterprise.visible.is_distributor
extends 'json/enterprises'
child distributed_taxons: :taxons do
- attributes :name, :id
+ extends "json/taxon"
end
child suppliers: :producers do
- attributes :name, :id
+ attributes :name, :id, :description, :long_description
+
+ node :promo_image do |producer|
+ producer.promo_image.url
+ end
end
node :pickup do |hub|
@@ -17,14 +21,6 @@ node :delivery do |hub|
not hub.shipping_methods.where(:require_ship_address => true).empty?
end
-node :path do |hub|
- shop_enterprise_path(hub)
-end
-
-node :hash do |hub|
- hub.to_param
-end
-
node :active do |hub|
@active_distributors.include?(hub)
end
diff --git a/app/views/json/_producers.rabl b/app/views/json/_producers.rabl
index 717347e5de..95a133a182 100644
--- a/app/views/json/_producers.rabl
+++ b/app/views/json/_producers.rabl
@@ -2,7 +2,7 @@ collection @producers
extends 'json/enterprises'
child supplied_taxons: :taxons do
- attributes :name, :id
+ extends 'json/taxon'
end
child distributors: :distributors do
diff --git a/app/views/json/_taxon.rabl b/app/views/json/_taxon.rabl
new file mode 100644
index 0000000000..916abeff78
--- /dev/null
+++ b/app/views/json/_taxon.rabl
@@ -0,0 +1,5 @@
+attributes :name, :id, :permalink
+
+node :icon do |taxon|
+ taxon.icon.url
+end
diff --git a/app/views/modals/_food_hub.html.haml b/app/views/modals/_food_hub.html.haml
index e80ffe3745..9b559d26cc 100644
--- a/app/views/modals/_food_hub.html.haml
+++ b/app/views/modals/_food_hub.html.haml
@@ -2,4 +2,4 @@
%h5 Our food hubs are the point of contact between you and the people who make your food!
%p You can search for a convenient hub by location or name. Some hubs have multiple points where you can pick-up your purchases, and some will also provide delivery options. Each food hub is a sales point with independent business operations and logisitics - so variations between hubs are to be expected.
%p You can only shop one food hub at a time.
-%a.close-reveal-modal{"ng-click" => "cancel()"} ×
\ No newline at end of file
+%a.close-reveal-modal{"ng-click" => "$close()"} ×
diff --git a/app/views/modals/_learn_more.html.haml b/app/views/modals/_learn_more.html.haml
index 870d5fe0bc..4cb0534c6e 100644
--- a/app/views/modals/_learn_more.html.haml
+++ b/app/views/modals/_learn_more.html.haml
@@ -6,4 +6,4 @@
%h5 Learn more
%p If you want to learn more about the Open Food Network, how it works, and get involved, check out:
%a.button.neutral-btn.dark{:href => "http://www.openfoodnetwork.org" , :target => "_blank" } Open Food Network
-%a.close-reveal-modal{"ng-click" => "cancel()"} ×
+%a.close-reveal-modal{"ng-click" => "$close()"} ×
diff --git a/app/views/modals/_producer.html.haml b/app/views/modals/_producer.html.haml
new file mode 100644
index 0000000000..691e9378d3
--- /dev/null
+++ b/app/views/modals/_producer.html.haml
@@ -0,0 +1,13 @@
+%ofn-modal{title: "{{ producer.name }}"}
+ #producer_modal{bindonce: true}
+ .row
+ .small-12.columns
+ %img{"bo-src" => "producer.promo_image"}
+ %h3 {{ producer.name }}
+
+ .row
+ .small-6.columns
+ %p
+ {{ producer.description }}
+ .small-6.columns
+ Stay in touch with {{ producer.name }}
diff --git a/app/views/shared/menu/_large_menu.html.haml b/app/views/shared/menu/_large_menu.html.haml
index 9443dfa979..7a72b80f60 100644
--- a/app/views/shared/menu/_large_menu.html.haml
+++ b/app/views/shared/menu/_large_menu.html.haml
@@ -21,7 +21,7 @@
%span.nav-primary Producers
%li.divider
%li
- %a{href: ""}
+ %a{href: main_app.groups_path}
%span.nav-primary Groups
%li.divider
- if admin_user? or enterprise_user?
diff --git a/app/views/shared/menu/_mobile_menu.html.haml b/app/views/shared/menu/_mobile_menu.html.haml
index 7d37d9b2cb..5e9f22c597 100644
--- a/app/views/shared/menu/_mobile_menu.html.haml
+++ b/app/views/shared/menu/_mobile_menu.html.haml
@@ -36,17 +36,14 @@
%li
%a{href: root_path + "#/#hubs"}
%span.nav-primary Hubs
-
%li
%a{href: ""}
%span.nav-primary Map
-
%li
%a{href: main_app.producers_path}
%span.nav-primary Producers
-
%li
- %a{href: ""}
+ %a{href: main_app.groups_path}
%span.nav-primary Groups
diff --git a/app/views/shop/_products.html.haml b/app/views/shop/_products.html.haml
deleted file mode 100644
index 7ed6606717..0000000000
--- a/app/views/shop/_products.html.haml
+++ /dev/null
@@ -1,79 +0,0 @@
-%products{"ng-controller" => "ProductsCtrl", "ng-show" => "order_cycle.order_cycle_id != null",
-"infinite-scroll" => "incrementLimit()", "infinite-scroll-distance" => "1"}
-
- = form_for :order, :url => populate_orders_path, html: {:class => "custom"} do
-
- %input#search.text{"ng-model" => "query",
- placeholder: "Search",
- "ng-debounce" => "150",
- "ng-keypress" => "searchKeypress($event)"}
- %input.button.right{type: :submit, value: "Add to Cart"}
-
- %table
- %thead
- %th.name Item
- %th.notes Notes
- %th.variant Unit
- %th.quantity QTY
- %th.bulk Bulk
- %th.price.text-right Price
- %tbody{"ng-show" => "data.loading"}
- %tr
- %td{colspan: 6}
- %h3.text-center Loading Products
- %tbody{"ng-repeat" => "product in data.products | filter:query | limitTo: limit track by product.id"}
- %tr{"class" => "product product-{{ product.id }}"}
-
- %td.name{bindonce: "product"}
- %img{"bo-src" => "product.master.images[0].small_url"}
- %div
- %h5
- {{ product.name }}
- %a{"data-reveal-id" => "producer_details_{{product.supplier.id}}", "data-reveal" => ""}
- {{ product.supplier.name }}
-
- %td.notes{bindonce: ""} {{ product.notes | truncate:80 }}
-
- %td{bindonce: ""}
- %span{"ng-hide" => "product.variants.length > 0"} {{ product.master.options_text }}
- %span{"ng-show" => "product.variants.length > 0"}
- %img.collapse{src: "/assets/collapse.png",
- "ng-show" => "product.show_variants",
- "ng-click" => "product.show_variants = !product.show_variants"}
-
- %img.expand{src: "/assets/expand.png",
- "ng-show" => "!product.show_variants",
- "ng-click" => "product.show_variants = !product.show_variants"}
- %td
- %span{"ng-show" => "(product.variants.length == 0)"}
- %input{type: :number,
- value: nil,
- min: 0,
- "ofn-disable-scroll" => true,
- max: "{{product.on_demand && 9999 || product.count_on_hand }}",
- name: "variants[{{product.master.id}}]",
- id: "variants_{{product.master.id}}",
- "ng-model" => "product.quantity"}
-
- %td.group_buy
- %span{"ng-show" => "product.group_buy && (product.variants.length == 0)"}
- %input{type: :number,
- min: 0,
- "ofn-disable-scroll" => true,
- max: "{{product.on_demand && 9999 || product.count_on_hand }}",
- name: "variant_attributes[{{product.master.id}}][max_quantity]",
- "ng-model" => "product.max_quantity"}
-
- %td.price.text-right{bindonce: ""}
- %small{"ng-show" => "(product.variants.length > 0)"} from
- {{ productPrice(product) | currency }}
-
- %tr.product-description{bindonce: ""}
- %td{colspan: 2}{{ product.notes | truncate:80 }}
-
- %tr.variant{"ng-repeat" => "variant in product.variants", "ng-if" => "product.show_variants"}
- = render partial: "shop/variant"
-
- %input.button.right{type: :submit, value: "Add to Cart"}
-
-
diff --git a/app/views/shop/_variant.html.haml b/app/views/shop/_variant.html.haml
deleted file mode 100644
index 15d5485090..0000000000
--- a/app/views/shop/_variant.html.haml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-%td
-%td.notes
-%td{bindonce: ""} {{variant.options_text}}
-%td
- %input{type: :number,
- value: nil,
- min: 0,
- "ofn-disable-scroll" => true,
- max: "{{variant.on_demand && 9999 || variant.count_on_hand }}",
- name: "variants[{{variant.id}}]", id: "variants_{{variant.id}}",
- "ng-model" => "variant.quantity"}
-%td.group_buy
- %span{"ng-show" => "product.group_buy"}
- %input{type: :number,
- min: 0,
- "ofn-disable-scroll" => true,
- max: "{{variant.on_demand && 9999 || variant.count_on_hand }}",
- name: "variant_attributes[{{variant.id}}][max_quantity]",
- "ng-model" => "variant.max_quantity"}
-%td.price.text-right{bindonce: ""}
- {{ variant.price | currency }}
diff --git a/app/views/shop/products.rabl b/app/views/shop/products.rabl
index c92a1afaa0..c79157dae5 100644
--- a/app/views/shop/products.rabl
+++ b/app/views/shop/products.rabl
@@ -1,10 +1,6 @@
collection @products
attributes :id, :name, :permalink, :count_on_hand, :on_demand, :group_buy
-node :show_variants do
- true
-end
-
node do |product|
{
notes: strip_tags(product.notes),
@@ -17,6 +13,10 @@ child :supplier => :supplier do
attributes :id, :name, :description
end
+child :primary_taxon => :primary_taxon do
+ extends 'json/taxon'
+end
+
child :master => :master do
attributes :id, :is_master, :count_on_hand, :options_text, :count_on_hand, :on_demand
child :images => :images do
diff --git a/app/views/shop/products/_form.html.haml b/app/views/shop/products/_form.html.haml
new file mode 100644
index 0000000000..8c70f76188
--- /dev/null
+++ b/app/views/shop/products/_form.html.haml
@@ -0,0 +1,29 @@
+%products.small-12.columns{"ng-controller" => "ProductsCtrl", "ng-show" => "order_cycle.order_cycle_id != null",
+"infinite-scroll" => "incrementLimit()", "infinite-scroll-distance" => "1"}
+
+ = form_for :order, :url => populate_orders_path, html: {:class => "custom"} do
+
+ .row
+ .small-6.columns
+ %input#search.text{"ng-model" => "query",
+ placeholder: "Search",
+ "ng-debounce" => "150",
+ "ofn-disable-enter" => true}
+ .small-6.columns
+ %input.button.right{type: :submit, value: "Add to Cart"}
+
+ %div{bindonce: true}
+ %product{"ng-controller" => "ProductNodeCtrl",
+ "ng-repeat" => "product in data.products | filter:query | orderBy:ordering.order | limitTo: limit track by product.id"}
+ %div
+ = render partial: "shop/products/summary"
+
+ %div{"bo-if" => "hasVariants"}
+ = render partial: "shop/products/variants"
+
+ .variant.row{"bo-if" => "!hasVariants"}
+ = render partial: "shop/products/master"
+
+ .row
+ .small-12.columns
+ %input.button.right.add_to_cart{type: :submit, value: "Add to Cart"}
diff --git a/app/views/shop/products/_master.html.haml b/app/views/shop/products/_master.html.haml
new file mode 100644
index 0000000000..7398912bda
--- /dev/null
+++ b/app/views/shop/products/_master.html.haml
@@ -0,0 +1,39 @@
+.small-1.column
+ %span.bulk{"bo-if" => "product.group_buy"} bulk
+
+
+.small-4.columns
+ ({{ product.master.options_text }})
+
+-# WITHOUT GROUP BUY
+.small-5.columns{"bo-if" => "!product.group_buy"}
+ %input{type: :number,
+ min: 0,
+ "ofn-disable-scroll" => true,
+ max: "{{product.on_demand && 9999 || product.count_on_hand }}",
+ name: "variants[{{product.master.id}}]",
+ id: "variants_{{product.master.id}}",
+ "ng-model" => "product.quantity"}
+
+-# WITH GROUP BUY
+.small-2.columns{"bo-if" => "product.group_buy"}
+ %input{type: :number,
+ min: 0,
+ "ofn-disable-scroll" => true,
+ max: "{{product.on_demand && 9999 || product.count_on_hand }}",
+ name: "variants[{{product.master.id}}]",
+ id: "variants_{{product.master.id}}",
+ "ng-model" => "product.quantity"}
+ (min)
+
+.small-3.columns{"bo-if" => "product.group_buy"}
+ %input{type: :number,
+ min: 0,
+ "ofn-disable-scroll" => true,
+ max: "{{product.on_demand && 9999 || product.count_on_hand }}",
+ name: "variant_attributes[{{product.master.id}}][max_quantity]",
+ "ng-model" => "product.max_quantity"}
+ (max)
+
+.small-2.columns.text-right
+ {{ product.price | currency }}
diff --git a/app/views/shop/products/_modal.html.haml b/app/views/shop/products/_modal.html.haml
new file mode 100644
index 0000000000..29a023704f
--- /dev/null
+++ b/app/views/shop/products/_modal.html.haml
@@ -0,0 +1,2 @@
+%ofn-modal{title: "{{product.name}}"}
+ {{ product.description }}
diff --git a/app/views/shop/products/_summary.html.haml b/app/views/shop/products/_summary.html.haml
new file mode 100644
index 0000000000..5e777a5dbb
--- /dev/null
+++ b/app/views/shop/products/_summary.html.haml
@@ -0,0 +1,18 @@
+.row.summary
+ .small-1.column
+ %img{"bo-src" => "product.master.images[0].small_url"}
+
+ .small-4.columns.summary-header
+ %img{"bo-src" => "product.primary_taxon.icon",
+ "ng-click" => "ordering.order = 'primary_taxon.name'",
+ name: "{{product.primary_taxon.name}}"}
+ {{ product.name}}
+ -#= render partial: "shop/products/modal"
+
+ .small-5.columns.summary-header
+ {{ product.supplier.name }}
+
+ .small-2.columns.summary-price.text-right.price
+ %span{"ng-if" => "hasVariants"}
+ %em from
+ {{ price() | currency }}
diff --git a/app/views/shop/products/_variants.html.haml b/app/views/shop/products/_variants.html.haml
new file mode 100644
index 0000000000..14ff8eff24
--- /dev/null
+++ b/app/views/shop/products/_variants.html.haml
@@ -0,0 +1,42 @@
+.row.variants{bindonce: true,
+ "ng-repeat" => "variant in product.variants"}
+
+ .small-1.column
+ %span.bulk{"bo-if" => "product.group_buy"} bulk
+
+
+ .small-4.columns
+ {{ variant.options_text }}
+
+ -# WITHOUT GROUP BUY
+ .small-5.columns{"bo-if" => "!product.group_buy"}
+ %input{type: :number,
+ value: nil,
+ min: 0,
+ "ofn-disable-scroll" => true,
+ max: "{{variant.on_demand && 9999 || variant.count_on_hand }}",
+ name: "variants[{{variant.id}}]", id: "variants_{{variant.id}}",
+ "bo-model" => "variant.quantity"}
+
+ -# WITH GROUP BUY
+ .small-2.columns{"bo-if" => "product.group_buy"}
+ %input{type: :number,
+ value: nil,
+ min: 0,
+ "ofn-disable-scroll" => true,
+ max: "{{variant.on_demand && 9999 || variant.count_on_hand }}",
+ name: "variants[{{variant.id}}]", id: "variants_{{variant.id}}",
+ "bo-model" => "variant.quantity"}
+ (min)
+
+ .small-3.columns{"bo-if" => "product.group_buy"}
+ %input{type: :number,
+ min: 0,
+ "ofn-disable-scroll" => true,
+ max: "{{variant.on_demand && 9999 || variant.count_on_hand }}",
+ name: "variant_attributes[{{variant.id}}][max_quantity]",
+ "ng-model" => "variant.max_quantity"}
+ (max)
+
+ .small-2.columns.text-right.price
+ {{ variant.price | currency }}
diff --git a/app/views/shop/show.html.haml b/app/views/shop/show.html.haml
index ecfcc8e4e3..ba9493e46b 100644
--- a/app/views/shop/show.html.haml
+++ b/app/views/shop/show.html.haml
@@ -13,5 +13,5 @@
= render partial: "shopping_shared/details"
- %products.row
- = render partial: "shop/products"
+ .row
+ = render partial: "shop/products/form"
diff --git a/config/routes.rb b/config/routes.rb
index e4868d777c..310d1d9e4d 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,12 +1,15 @@
Openfoodnetwork::Application.routes.draw do
root :to => 'home#index'
+ get "/#/login", to: "home#index", as: :spree_login
+
resource :shop, controller: "shop" do
get :products
post :order_cycle
get :order_cycle
end
+ resources :groups
resources :producers
get '/checkout', :to => 'checkout#edit' , :as => :checkout
diff --git a/db/migrate/20140516042552_add_attachment_promo_image_to_enterprise_group.rb b/db/migrate/20140516042552_add_attachment_promo_image_to_enterprise_group.rb
new file mode 100644
index 0000000000..bd67cb92f0
--- /dev/null
+++ b/db/migrate/20140516042552_add_attachment_promo_image_to_enterprise_group.rb
@@ -0,0 +1,15 @@
+class AddAttachmentPromoImageToEnterpriseGroup < ActiveRecord::Migration
+ def self.up
+ add_column :enterprise_groups, :promo_image_file_name, :string
+ add_column :enterprise_groups, :promo_image_content_type, :string
+ add_column :enterprise_groups, :promo_image_file_size, :integer
+ add_column :enterprise_groups, :promo_image_updated_at, :datetime
+ end
+
+ def self.down
+ remove_column :enterprise_groups, :promo_image_file_name
+ remove_column :enterprise_groups, :promo_image_content_type
+ remove_column :enterprise_groups, :promo_image_file_size
+ remove_column :enterprise_groups, :promo_image_updated_at
+ end
+end
diff --git a/db/migrate/20140516044750_add_fields_to_groups.rb b/db/migrate/20140516044750_add_fields_to_groups.rb
new file mode 100644
index 0000000000..a50ef1db14
--- /dev/null
+++ b/db/migrate/20140516044750_add_fields_to_groups.rb
@@ -0,0 +1,6 @@
+class AddFieldsToGroups < ActiveRecord::Migration
+ def change
+ add_column :enterprise_groups, :description, :text
+ add_column :enterprise_groups, :long_description, :text
+ end
+end
diff --git a/db/migrate/20140516045323_add_attachment_logo_to_enterprise_group.rb b/db/migrate/20140516045323_add_attachment_logo_to_enterprise_group.rb
new file mode 100644
index 0000000000..525bccb63e
--- /dev/null
+++ b/db/migrate/20140516045323_add_attachment_logo_to_enterprise_group.rb
@@ -0,0 +1,15 @@
+class AddAttachmentLogoToEnterpriseGroup < ActiveRecord::Migration
+ def self.up
+ add_column :enterprise_groups, :logo_file_name, :string
+ add_column :enterprise_groups, :logo_content_type, :string
+ add_column :enterprise_groups, :logo_file_size, :integer
+ add_column :enterprise_groups, :logo_updated_at, :datetime
+ end
+
+ def self.down
+ remove_column :enterprise_groups, :logo_file_name
+ remove_column :enterprise_groups, :logo_content_type
+ remove_column :enterprise_groups, :logo_file_size
+ remove_column :enterprise_groups, :logo_updated_at
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index cacc8fc793..5394fcbd61 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20140514044959) do
+ActiveRecord::Schema.define(:version => 20140516045323) do
create_table "adjustment_metadata", :force => true do |t|
t.integer "adjustment_id"
@@ -182,9 +182,19 @@ ActiveRecord::Schema.define(:version => 20140514044959) do
add_index "enterprise_fees", ["enterprise_id"], :name => "index_enterprise_fees_on_enterprise_id"
create_table "enterprise_groups", :force => true do |t|
- t.string "name"
- t.boolean "on_front_page"
- t.integer "position"
+ t.string "name"
+ t.boolean "on_front_page"
+ t.integer "position"
+ t.string "promo_image_file_name"
+ t.string "promo_image_content_type"
+ t.integer "promo_image_file_size"
+ t.datetime "promo_image_updated_at"
+ t.text "description"
+ t.text "long_description"
+ t.string "logo_file_name"
+ t.string "logo_content_type"
+ t.integer "logo_file_size"
+ t.datetime "logo_updated_at"
end
create_table "enterprise_groups_enterprises", :id => false, :force => true do |t|
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
new file mode 100644
index 0000000000..4005d82a2a
--- /dev/null
+++ b/spec/controllers/groups_controller_spec.rb
@@ -0,0 +1,9 @@
+require 'spec_helper'
+
+describe GroupsController do
+ it "gets all visible groups" do
+ EnterpriseGroup.stub_chain :on_front_page, :by_position
+ EnterpriseGroup.should_receive :on_front_page
+ get :index
+ end
+end
diff --git a/spec/controllers/shop_controller_spec.rb b/spec/controllers/shop_controller_spec.rb
index 88cde0e6d9..f0857f54bc 100644
--- a/spec/controllers/shop_controller_spec.rb
+++ b/spec/controllers/shop_controller_spec.rb
@@ -111,90 +111,6 @@ describe ShopController do
response.body.should be_empty
end
- # TODO: this should be a controller test baby
- pending "filtering products" do
- let(:distributor) { create(:distributor_enterprise) }
- let(:supplier) { create(:supplier_enterprise) }
- let(:oc1) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise), orders_close_at: 2.days.from_now) }
- let(:p1) { create(:simple_product, on_demand: false) }
- let(:p2) { create(:simple_product, on_demand: true) }
- let(:p3) { create(:simple_product, on_demand: false) }
- let(:p4) { create(:simple_product, on_demand: false) }
- let(:p5) { create(:simple_product, on_demand: false) }
- let(:p6) { create(:simple_product, on_demand: false) }
- let(:p7) { create(:simple_product, on_demand: false) }
- let(:v1) { create(:variant, product: p4, unit_value: 2) }
- let(:v2) { create(:variant, product: p4, unit_value: 3, on_demand: false) }
- let(:v3) { create(:variant, product: p4, unit_value: 4, on_demand: true) }
- let(:v4) { create(:variant, product: p5) }
- let(:v5) { create(:variant, product: p5) }
- let(:v6) { create(:variant, product: p7) }
- let(:order) { create(:order, distributor: distributor, order_cycle: order_cycle) }
-
- before do
- p1.master.count_on_hand = 1
- p2.master.count_on_hand = 0
- p1.master.update_attribute(:count_on_hand, 1)
- p2.master.update_attribute(:count_on_hand, 0)
- p3.master.update_attribute(:count_on_hand, 0)
- p6.master.update_attribute(:count_on_hand, 1)
- p6.delete
- p7.master.update_attribute(:count_on_hand, 1)
- v1.update_attribute(:count_on_hand, 1)
- v2.update_attribute(:count_on_hand, 0)
- v3.update_attribute(:count_on_hand, 0)
- v4.update_attribute(:count_on_hand, 1)
- v5.update_attribute(:count_on_hand, 0)
- v6.update_attribute(:count_on_hand, 1)
- v6.update_attribute(:deleted_at, Time.now)
- exchange = Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id)
- exchange.update_attribute :pickup_time, "frogs"
- exchange.variants << p1.master
- exchange.variants << p2.master
- exchange.variants << p3.master
- exchange.variants << p6.master
- exchange.variants << v1
- exchange.variants << v2
- exchange.variants << v3
- # v4 is in stock but not in distribution
- # v5 is out of stock and in the distribution
- # Neither should display, nor should their product, p5
- exchange.variants << v5
- exchange.variants << v6
-
- controller.stub(:current_order).and_return order
- visit shop_path
- end
-
- it "filters products based on availability" do
- # It shows on hand products
- page.should have_content p1.name
- page.should have_content p4.name
-
- # It shows on demand products
- page.should have_content p2.name
-
- # It does not show products that are neither on hand or on demand
- page.should_not have_content p3.name
-
- # It shows on demand variants
- page.should have_content v3.options_text
-
- # It does not show variants that are neither on hand or on demand
- page.should_not have_content v2.options_text
-
- # It does not show products that have no available variants in this distribution
- page.should_not have_content p5.name
-
- # It does not show deleted products
- page.should_not have_content p6.name
-
- # It does not show deleted variants
- page.should_not have_content v6.name
- page.should_not have_content p7.name
- end
- end
-
context "RABL tests" do
render_views
before do
@@ -211,6 +127,7 @@ describe ShopController do
xhr :get, :products
response.body.should_not have_content product.name
end
+
it "strips html from description" do
product.update_attribute(:description, "turtles frogs")
xhr :get, :products
@@ -223,6 +140,14 @@ describe ShopController do
xhr :get, :products
response.body.should have_content "998.0"
end
+
+ it "includes the primary taxon" do
+ taxon = mock_model(Spree::Taxon, name: "fruitbat")
+ Spree::Product.any_instance.stub(:primary_taxon).and_return taxon
+ taxon.stub_chain(:icon, :url).and_return ""
+ xhr :get, :products
+ response.body.should have_content "fruitbat"
+ end
end
end
end
diff --git a/spec/factories.rb b/spec/factories.rb
index 710ba1c8ba..13c0bd0e8e 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -98,6 +98,7 @@ FactoryGirl.define do
factory :enterprise_group, :class => EnterpriseGroup do
name 'Enterprise group'
+ description 'this is a group'
on_front_page false
end
diff --git a/spec/features/admin/enterprise_groups_spec.rb b/spec/features/admin/enterprise_groups_spec.rb
index 012179e75a..24e89e9be7 100644
--- a/spec/features/admin/enterprise_groups_spec.rb
+++ b/spec/features/admin/enterprise_groups_spec.rb
@@ -33,6 +33,7 @@ feature %q{
click_link 'New Enterprise Group'
fill_in 'enterprise_group_name', with: 'EGEGEG'
+ fill_in 'enterprise_group_description', with: 'This is a description'
check 'enterprise_group_on_front_page'
select e1.name, from: 'enterprise_group_enterprise_ids'
select e2.name, from: 'enterprise_group_enterprise_ids'
@@ -42,6 +43,7 @@ feature %q{
eg = EnterpriseGroup.last
eg.name.should == 'EGEGEG'
+ eg.description.should == 'This is a description'
eg.on_front_page.should be_true
eg.enterprises.sort.should == [e1, e2].sort
end
@@ -62,6 +64,7 @@ feature %q{
fill_in 'enterprise_group_name', with: 'xyzzy'
uncheck 'enterprise_group_on_front_page'
unselect e1.name, from: 'enterprise_group_enterprise_ids'
+
select e2.name, from: 'enterprise_group_enterprise_ids'
click_button 'Update'
@@ -99,7 +102,6 @@ feature %q{
EnterpriseGroup.all.should_not include eg
end
-
context "as an enterprise user" do
xit "should show me only enterprises I manage when creating a new enterprise group"
end
diff --git a/spec/features/consumer/shopping/shopping_spec.rb b/spec/features/consumer/shopping/shopping_spec.rb
index 19fcb5a44b..9946be2f5b 100644
--- a/spec/features/consumer/shopping/shopping_spec.rb
+++ b/spec/features/consumer/shopping/shopping_spec.rb
@@ -90,10 +90,6 @@ feature "As a consumer I want to shop with a distributor", js: true do
it "should not show quantity field for product with variants" do
visit shop_path
page.should_not have_selector("#variants_#{product.master.id}", visible: true)
-
- #it "expands variants" do
- find(".collapse").trigger "click"
- page.should_not have_text variant1.options_text
end
it "uses the adjusted price" do
@@ -104,15 +100,16 @@ feature "As a consumer I want to shop with a distributor", js: true do
visit shop_path
# Page should not have product.price (with or without fee)
- page.should_not have_selector 'tr.product > td', text: "from $10.00"
- page.should_not have_selector 'tr.product > td', text: "from $33.00"
+ page.should_not have_price "from $10.00"
+ page.should_not have_price "from $33.00"
# Page should have variant prices (with fee)
- page.should have_selector 'tr.variant > td.price', text: "$43.00"
- page.should have_selector 'tr.variant > td.price', text: "$53.00"
+ page.should have_price "$43.00"
+ page.should have_price "$53.00"
# Product price should be listed as the lesser of these
- page.should have_selector 'tr.product > td', text: "from $43.00"
+ #page.should have_selector 'tr.product > td', text: "from $43.00"
+ page.should have_price "from $43.00"
end
end
@@ -131,7 +128,7 @@ feature "As a consumer I want to shop with a distributor", js: true do
it "should save group buy data to ze cart" do
fill_in "variants[#{product.master.id}]", with: 5
fill_in "variant_attributes[#{product.master.id}][max_quantity]", with: 9
- first("form.custom > input.button.right").click
+ add_to_cart
page.should have_content product.name
li = Spree::Order.order(:created_at).last.line_items.order(:created_at).last
li.max_quantity.should == 9
@@ -142,7 +139,7 @@ feature "As a consumer I want to shop with a distributor", js: true do
pending "adding a product with a max quantity less than quantity results in max_quantity==quantity" do
fill_in "variants[#{product.master.id}]", with: 5
fill_in "variant_attributes[#{product.master.id}][max_quantity]", with: 1
- first("form.custom > input.button.right").click
+ add_to_cart
page.should have_content product.name
li = Spree::Order.order(:created_at).last.line_items.order(:created_at).last
li.max_quantity.should == 5
@@ -161,7 +158,7 @@ feature "As a consumer I want to shop with a distributor", js: true do
it "should save group buy data to ze cart" do
fill_in "variants[#{variant.id}]", with: 6
fill_in "variant_attributes[#{variant.id}][max_quantity]", with: 7
- first("form.custom > input.button.right").click
+ add_to_cart
page.should have_content product.name
li = Spree::Order.order(:created_at).last.line_items.order(:created_at).last
li.max_quantity.should == 7
@@ -181,7 +178,7 @@ feature "As a consumer I want to shop with a distributor", js: true do
end
it "should let us add products to our cart" do
fill_in "variants[#{variant.id}]", with: "1"
- first("form.custom > input.button.right").click
+ add_to_cart
current_path.should == "/cart"
page.should have_content product.name
end
diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb
new file mode 100644
index 0000000000..08a4335bae
--- /dev/null
+++ b/spec/helpers/groups_helper_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+# Specs in this file have access to a helper object that includes
+# the GroupsHelper. For example:
+#
+# describe GroupsHelper do
+# describe "string concat" do
+# it "concats two strings with spaces" do
+# expect(helper.concat_strings("this","that")).to eq("this that")
+# end
+# end
+# end
+describe GroupsHelper do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/models/enterprise_group_spec.rb b/spec/models/enterprise_group_spec.rb
index 167a8c2f7b..3e38882064 100644
--- a/spec/models/enterprise_group_spec.rb
+++ b/spec/models/enterprise_group_spec.rb
@@ -11,6 +11,13 @@ describe EnterpriseGroup do
e = build(:enterprise_group, name: '')
e.should_not be_valid
end
+
+ it "requires a description" do
+ e = build(:enterprise_group, description: '')
+ end
+
+ it { should have_attached_file :promo_image }
+ it { should have_attached_file :logo }
end
describe "relations" do
diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb
index 6743e404e9..6d90b70761 100644
--- a/spec/models/spree/product_spec.rb
+++ b/spec/models/spree/product_spec.rb
@@ -547,5 +547,15 @@ module Spree
end
end
end
+
+ describe "Taxons" do
+ let(:taxon1) { create(:taxon) }
+ let(:taxon2) { create(:taxon) }
+ let(:product) { create(:simple_product, taxons: [taxon1, taxon2]) }
+
+ it "returns the first taxon as the primary taxon" do
+ product.primary_taxon.should == taxon1
+ end
+ end
end
end
diff --git a/spec/support/request/shop_workflow.rb b/spec/support/request/shop_workflow.rb
index bdad9e5d49..c87d33149a 100644
--- a/spec/support/request/shop_workflow.rb
+++ b/spec/support/request/shop_workflow.rb
@@ -1,4 +1,12 @@
module ShopWorkflow
+ def add_to_cart
+ first("input.add_to_cart").click
+ end
+
+ def have_price(price)
+ have_selector ".price", text: price
+ end
+
def set_order(order)
ApplicationController.any_instance.stub(:session).and_return({order_id: order.id, access_token: order.token})
end