mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Merge branch 'master' into raf_bugfix
Conflicts: app/views/spree/order_mailer/confirm_email.text.haml
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
Darkswarm.controller "HubsCtrl", ($scope, Hubs, Search, $document, $rootScope, HashNavigation, FilterSelectorsService) ->
|
||||
Darkswarm.controller "HubsCtrl", ($scope, Hubs, Search, $document, $rootScope, HashNavigation, FilterSelectorsService, MapModal) ->
|
||||
$scope.Hubs = Hubs
|
||||
$scope.hubs = Hubs.visible
|
||||
$scope.totalActive = FilterSelectorsService.totalActive
|
||||
@@ -6,6 +6,8 @@ Darkswarm.controller "HubsCtrl", ($scope, Hubs, Search, $document, $rootScope, H
|
||||
$scope.filterText = FilterSelectorsService.filterText
|
||||
$scope.FilterSelectorsService = FilterSelectorsService
|
||||
$scope.query = Search.search()
|
||||
$scope.show_profiles = false
|
||||
$scope.openModal = MapModal.open
|
||||
|
||||
$scope.$watch "query", (query)->
|
||||
Search.search query
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Darkswarm.controller "ProducersCtrl", ($scope, Producers, $filter, FilterSelectorsService, Search) ->
|
||||
Darkswarm.controller "ProducersCtrl", ($scope, Producers, $filter, FilterSelectorsService, Search, MapModal) ->
|
||||
$scope.Producers = Producers
|
||||
$scope.totalActive = FilterSelectorsService.totalActive
|
||||
$scope.clearAll = FilterSelectorsService.clearAll
|
||||
@@ -7,6 +7,8 @@ Darkswarm.controller "ProducersCtrl", ($scope, Producers, $filter, FilterSelecto
|
||||
$scope.filtersActive = false
|
||||
$scope.activeTaxons = []
|
||||
$scope.query = Search.search()
|
||||
$scope.show_profiles = false
|
||||
$scope.openModal = MapModal.open
|
||||
|
||||
$scope.$watch "query", (query)->
|
||||
Search.search query
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
Darkswarm.directive "ofnRegistrationLimitModal", (Navigation, $modal, Loading) ->
|
||||
restrict: 'A'
|
||||
link: (scope, elem, attr)->
|
||||
scope.modalInstance = $modal.open
|
||||
templateUrl: 'registration/limit_reached.html'
|
||||
windowClass: "login-modal large"
|
||||
backdrop: 'static'
|
||||
|
||||
scope.modalInstance.result.then scope.close, scope.close
|
||||
|
||||
scope.close = ->
|
||||
Loading.message = "Taking you back to the home page"
|
||||
Navigation.go "/"
|
||||
@@ -0,0 +1,7 @@
|
||||
Darkswarm.filter 'showProfiles', ()->
|
||||
(enterprises, show_profiles) ->
|
||||
enterprises ||= []
|
||||
show_profiles ?= true
|
||||
|
||||
enterprises.filter (enterprise)=>
|
||||
show_profiles or enterprise.has_shopfront
|
||||
@@ -2,7 +2,7 @@ Darkswarm.factory 'Hubs', ($filter, Enterprises, visibleFilter) ->
|
||||
new class Hubs
|
||||
constructor: ->
|
||||
@hubs = @order Enterprises.enterprises.filter (hub)->
|
||||
hub.is_distributor && hub.has_shopfront
|
||||
hub.has_hub_listing
|
||||
@visible = visibleFilter @hubs
|
||||
|
||||
order: (hubs)->
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
.highlight
|
||||
.highlight-top
|
||||
%p.right
|
||||
{{ [enterprise.address.city, enterprise.address.state_name] | printArray}}
|
||||
%h3{"ng-if" => "enterprise.is_distributor"}
|
||||
%a{"bo-href" => "enterprise.path", "ofn-empties-cart" => "enterprise", bindonce: true}
|
||||
%i.ofn-i_040-hub
|
||||
.highlight{"ng-class" => "{'has_shopfront' : enterprise.has_shopfront}"}
|
||||
.highlight-top.row
|
||||
.small-12.medium-7.large-8.columns
|
||||
%h3{"ng-if" => "enterprise.has_shopfront"}
|
||||
%a{"bo-href" => "enterprise.path", "ofn-empties-cart" => "enterprise", bindonce: true}
|
||||
%i{"ng-class" => "enterprise.icon_font"}
|
||||
%span {{ enterprise.name }}
|
||||
%h3{"ng-if" => "!enterprise.has_shopfront", "ng-class" => "{'is_producer' : enterprise.is_primary_producer}"}
|
||||
%i{"ng-class" => "enterprise.icon_font"}
|
||||
%span {{ enterprise.name }}
|
||||
%h3{"ng-if" => "!enterprise.is_distributor"}
|
||||
%i.ofn-i_036-producers
|
||||
%span {{ enterprise.name }}
|
||||
%img.hero-img{"ng-src" => "{{enterprise.promo_image}}"}
|
||||
.small-12.medium-5.large-4.columns.text-right.small-only-text-left
|
||||
%p {{ [enterprise.address.city, enterprise.address.state_name] | printArray}}
|
||||
%img.hero-img{"ng-src" => "{{enterprise.promo_image}}"}
|
||||
@@ -28,8 +28,8 @@
|
||||
.row
|
||||
.small-12.columns
|
||||
%label{ for: 'enterprise_long_desc' } Long Description:
|
||||
%textarea.chunky.small-12.columns{ id: 'enterprise_long_desc', placeholder: "We recommend keeping your description to under 600 characters or 150 words. Why? Cus people are lazy, and don't like to read too much text online. ;)", ng: { model: 'enterprise.long_description' } }
|
||||
%small {{ enterprise.long_description.length }} characters used
|
||||
%textarea.chunky.small-12.columns{ id: 'enterprise_long_desc', rows: 6, placeholder: "This is your opportunity to tell the story of your enterprise - what makes you different and wonderful? We'd suggest keeping your description to under 600 characters or 150 words.", ng: { model: 'enterprise.long_description' } }
|
||||
%small {{ enterprise.long_description.length }} characters / up to 600 recommended
|
||||
.small-12.large-4.columns
|
||||
.row
|
||||
.small-12.columns
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
%div
|
||||
.header.center
|
||||
%h2 Oh no!
|
||||
%h4 You have reached the limit!
|
||||
.row
|
||||
.small-12.medium-3.large-2.columns.text-right.hide-for-small-only
|
||||
%img{:src => "/assets/potatoes.png"}
|
||||
.small-12.medium-9.large-10.columns
|
||||
%p
|
||||
You have reached the limit for the number of enterprises you are allowed to own on the
|
||||
%strong Open Food Network.
|
||||
.row
|
||||
.small-12.columns
|
||||
%hr
|
||||
%input.button.primary{ type: "button", value: "Return to the homepage", ng: { click: "close()" } }
|
||||
@@ -17,7 +17,9 @@ $clr-blue-bright: #14b6cc
|
||||
|
||||
$disabled-light: #e5e5e5
|
||||
$disabled-bright: #ccc
|
||||
$disabled-med: #b3b3b3
|
||||
$disabled-dark: #999
|
||||
$disabled-v-dark: #808080
|
||||
$med-grey: #666
|
||||
$dark-grey: #333
|
||||
|
||||
$black: #000
|
||||
|
||||
@@ -87,6 +87,8 @@
|
||||
&.inactive
|
||||
&.closed, &.open
|
||||
&, & *
|
||||
color: $disabled-med
|
||||
a, a *
|
||||
color: $disabled-dark
|
||||
&.closed
|
||||
.active_table_row, .active_table_row:first-child, .active_table_row:last-child
|
||||
@@ -126,3 +128,13 @@
|
||||
.active_table_row:first-child .skinny-head
|
||||
background-color: $disabled-light
|
||||
|
||||
//Is Profile - profile node
|
||||
&.inactive.is_profile
|
||||
&.closed, &.open
|
||||
.active_table_row
|
||||
&:hover, &:active, &:focus
|
||||
border-color: transparent
|
||||
cursor: auto
|
||||
@media all and (max-width: 640px)
|
||||
border-color: transparent
|
||||
|
||||
|
||||
@@ -11,12 +11,16 @@
|
||||
@include box-shadow(0 1px 2px 1px rgba(0,0,0,0.25))
|
||||
|
||||
.hero-img
|
||||
border-bottom: 1px solid $disabled-bright
|
||||
outline: 1px solid $disabled-bright
|
||||
border-color: transparent
|
||||
@include box-shadow(none)
|
||||
width: 100%
|
||||
min-height: 56px
|
||||
min-height: 80px
|
||||
height: inherit
|
||||
max-height: 260px
|
||||
overflow: hidden
|
||||
@media all and (max-width: 640px)
|
||||
min-height: 68px
|
||||
|
||||
.hero-img-small
|
||||
background-color: #333
|
||||
|
||||
@@ -16,6 +16,20 @@
|
||||
-webkit-box-shadow: $box-shadow
|
||||
box-shadow: $box-shadow
|
||||
|
||||
@mixin elipse-shadow($elipse-shadow)
|
||||
content: ""
|
||||
position: absolute
|
||||
z-index: -1
|
||||
-webkit-box-shadow: $elipse-shadow
|
||||
box-shadow: $elipse-shadow
|
||||
bottom: -12%
|
||||
left: 10%
|
||||
right: 10%
|
||||
width: 80%
|
||||
height: 10%
|
||||
-moz-border-radius: 100%
|
||||
border-radius: 100%
|
||||
|
||||
@mixin border-radius($border-radius)
|
||||
-webkit-border-radius: $border-radius
|
||||
border-radius: $border-radius
|
||||
|
||||
@@ -25,23 +25,39 @@
|
||||
position: relative
|
||||
|
||||
.highlight-top
|
||||
padding: 0.75rem 0.9375rem
|
||||
width: 100%
|
||||
overflow: hidden
|
||||
padding-top: 0.75rem
|
||||
padding-bottom: 0.75rem
|
||||
background-color: rgba(255,255,255,0.65)
|
||||
position: absolute
|
||||
bottom: 0
|
||||
width: 100%
|
||||
border: 0
|
||||
outline: 0
|
||||
@media only screen and (max-width: 640px)
|
||||
padding-top: 0.5rem
|
||||
padding-bottom: 0.35rem
|
||||
|
||||
h3, p
|
||||
margin-top: 0
|
||||
margin-bottom: 0
|
||||
padding-bottom: 0
|
||||
line-height: 1
|
||||
|
||||
h3 > i
|
||||
color: $clr-brick
|
||||
|
||||
p
|
||||
line-height: 2
|
||||
line-height: 2.4
|
||||
@media all and (max-width: 640px)
|
||||
line-height: 1.4
|
||||
|
||||
h3 a:hover span
|
||||
border-bottom: 1px solid $clr-brick-bright
|
||||
|
||||
.is_producer
|
||||
&, & *
|
||||
color: $clr-turquoise
|
||||
|
||||
|
||||
// ABOUT Enterprise
|
||||
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
|
||||
// Styling for login modal to style tabs
|
||||
.reveal-modal.login-modal
|
||||
border-bottom-color: #efefef
|
||||
|
||||
.login-modal
|
||||
background: #efefef
|
||||
.tabs-content
|
||||
background: #fff
|
||||
background: #fff
|
||||
padding-top: 10px
|
||||
|
||||
|
||||
|
||||
@@ -4,8 +4,14 @@
|
||||
dialog, .reveal-modal
|
||||
border: none
|
||||
outline: none
|
||||
padding: 1rem
|
||||
padding: 30px 20px 0 20px
|
||||
border-bottom: 30px solid white
|
||||
overflow-y: scroll
|
||||
overflow-x: hidden
|
||||
// Not working yet - want a nice gradient shadow when there is overflow - needs JS too
|
||||
// &:after
|
||||
// @include elipse-shadow(0 0 40px rgba(0, 0, 0, 0.8))
|
||||
|
||||
|
||||
// Reveal.js break point:
|
||||
// @media only screen and (max-width: 40.063em)
|
||||
@@ -25,14 +31,18 @@ dialog, .reveal-modal
|
||||
max-height: 80%
|
||||
|
||||
.reveal-modal-bg
|
||||
background-color: rgba(0,0,0,0.65)
|
||||
background-color: rgba(0,0,0,0.85)
|
||||
|
||||
dialog .close-reveal-modal, .reveal-modal .close-reveal-modal
|
||||
right: 0.4rem
|
||||
background-color: rgba(235,235,235,0.85)
|
||||
right: 0.25rem
|
||||
top: 0.25rem
|
||||
background-color: rgba(205,205,205,0.65)
|
||||
text-shadow: none
|
||||
padding: 0.3rem
|
||||
font-size: 2rem
|
||||
padding: 0.45rem
|
||||
color: #666
|
||||
z-index: 9999999
|
||||
@include border-radius(999999rem)
|
||||
&:hover, &:active, &:focus
|
||||
background-color: rgba(235,235,235,1)
|
||||
background-color: rgba(205,205,205,1)
|
||||
color: #333
|
||||
|
||||
@@ -32,6 +32,11 @@
|
||||
span
|
||||
text-decoration: underline
|
||||
|
||||
&.has_shopfront, &.has_shopfront i.ofn-i_059-producer, &.has_shopfront i.ofn-i_060-producer-reversed
|
||||
color: $clr-brick
|
||||
&:hover, &:active, &:focus
|
||||
color: $clr-brick-bright
|
||||
|
||||
a.cta-hub
|
||||
&:hover, &:focus, &:active
|
||||
&.secondary
|
||||
@@ -51,9 +56,11 @@
|
||||
.fat-taxons
|
||||
background-color: $clr-turquoise-light
|
||||
|
||||
.producer-name
|
||||
color: $clr-turquoise
|
||||
|
||||
//Open row
|
||||
&.open
|
||||
|
||||
.active_table_row
|
||||
border-left: 1px solid $clr-turquoise-bright
|
||||
border-right: 1px solid $clr-turquoise-bright
|
||||
|
||||
@@ -20,6 +20,8 @@ class RegistrationController < BaseController
|
||||
def check_user
|
||||
if spree_current_user.nil?
|
||||
redirect_to registration_auth_path(anchor: "signup?after_login=#{request.env['PATH_INFO']}")
|
||||
elsif !spree_current_user.can_own_more_enterprises?
|
||||
render :limit_reached
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -51,9 +51,9 @@ class Enterprise < ActiveRecord::Base
|
||||
validates :address, presence: true, associated: true
|
||||
validates :email, presence: true
|
||||
validates_presence_of :owner
|
||||
validate :enforce_ownership_limit, if: lambda { owner_id_changed? }
|
||||
validate :enforce_ownership_limit, if: lambda { owner_id_changed? && !owner_id.nil? }
|
||||
|
||||
before_validation :ensure_owner_is_manager, if: lambda { owner_id_changed? }
|
||||
before_validation :ensure_owner_is_manager, if: lambda { owner_id_changed? && !owner_id.nil? }
|
||||
before_validation :set_unused_address_fields
|
||||
after_validation :geocode_address
|
||||
|
||||
@@ -211,6 +211,39 @@ class Enterprise < ActiveRecord::Base
|
||||
Spree::Variant.joins(:product => :product_distributions).where('product_distributions.distributor_id=?', self.id)
|
||||
end
|
||||
|
||||
# Replaces currententerprse type field.
|
||||
def sells
|
||||
# Type: full - single - profile becomes Sells: all - own - none
|
||||
# Remove this return later.
|
||||
return "none" if !is_distributor || type == "profile"
|
||||
return "own" if type == "single" || suppliers == [self]
|
||||
"all"
|
||||
end
|
||||
|
||||
# Simplify enterprise categories for frontend logic and icons, and maybe other things.
|
||||
def enterprise_category
|
||||
# Make this crazy logic human readable so we can argue about it sanely.
|
||||
# This can be simplified later, it's like this for readablitlty during changes.
|
||||
category = is_primary_producer ? "producer_" : "non_producer_"
|
||||
category << "sell_" + sells
|
||||
|
||||
# Map backend cases to front end cases.
|
||||
case category
|
||||
when "producer_sell_all"
|
||||
"producer_hub" # Producer hub who sells own and others produce and supplies other hubs.
|
||||
when "producer_sell_own"
|
||||
"producer_shop" # Producer with shopfront and supplies other hubs.
|
||||
when "producer_sell_none"
|
||||
"producer" # Producer only supplies through others.
|
||||
when "non_producer_sell_all"
|
||||
"hub" # Hub selling others products in order cycles.
|
||||
when "non_producer_sell_own"
|
||||
"hub" # Wholesaler selling through own shopfront?
|
||||
when "non_producer_sell_none"
|
||||
"hub_profile" # Hub selling outside the system.
|
||||
end
|
||||
end
|
||||
|
||||
# Return all taxons for all distributed products
|
||||
def distributed_taxons
|
||||
Spree::Taxon.
|
||||
@@ -227,7 +260,6 @@ class Enterprise < ActiveRecord::Base
|
||||
select('DISTINCT spree_taxons.*')
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def send_creation_email
|
||||
|
||||
@@ -5,6 +5,7 @@ class AbilityDecorator
|
||||
add_base_abilities user if is_new_user? user
|
||||
add_enterprise_management_abilities user if can_manage_enterprises? user
|
||||
add_product_management_abilities user if can_manage_products? user
|
||||
add_order_management_abilities user if can_manage_orders? user
|
||||
add_relationship_management_abilities user if can_manage_relationships? user
|
||||
end
|
||||
|
||||
@@ -17,11 +18,13 @@ class AbilityDecorator
|
||||
user.enterprises.present?
|
||||
end
|
||||
|
||||
|
||||
def can_manage_products?(user)
|
||||
( user.enterprises.map(&:type) & %w(single full) ).any?
|
||||
can_manage_enterprises? user
|
||||
end
|
||||
|
||||
def can_manage_orders?(user)
|
||||
( user.enterprises.map(&:type) & %w(single full) ).any?
|
||||
end
|
||||
|
||||
def can_manage_relationships?(user)
|
||||
can_manage_enterprises? user
|
||||
@@ -46,7 +49,6 @@ class AbilityDecorator
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def add_product_management_abilities(user)
|
||||
# Enterprise User can only access products that they are a supplier for
|
||||
can [:create], Spree::Product
|
||||
@@ -64,7 +66,9 @@ class AbilityDecorator
|
||||
|
||||
can [:admin, :index, :read, :search], Spree::Taxon
|
||||
can [:admin, :index, :read, :create, :edit], Spree::Classification
|
||||
end
|
||||
|
||||
def add_order_management_abilities(user)
|
||||
# Enterprise User can only access orders that they are a distributor for
|
||||
can [:index, :create], Spree::Order
|
||||
can [:read, :update, :fire, :resend], Spree::Order do |order|
|
||||
|
||||
@@ -4,7 +4,7 @@ class Api::EnterpriseSerializer < ActiveModel::Serializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
||||
def cached_serializer_hash
|
||||
Api::CachedEnterpriseSerializer.new(object, @options).serializable_hash
|
||||
end
|
||||
@@ -18,7 +18,7 @@ class Api::UncachedEnterpriseSerializer < ActiveModel::Serializer
|
||||
attributes :orders_close_at, :active
|
||||
|
||||
#TODO: Remove these later
|
||||
attributes :icon, :has_shopfront, :can_aggregate
|
||||
attributes :icon, :icon_font, :producer_icon_font, :has_shopfront, :has_hub_listing, :enterprise_category
|
||||
|
||||
def orders_close_at
|
||||
OrderCycle.first_closing_for(object).andand.orders_close_at
|
||||
@@ -28,41 +28,61 @@ class Api::UncachedEnterpriseSerializer < ActiveModel::Serializer
|
||||
@options[:active_distributors].andand.include? object
|
||||
end
|
||||
|
||||
# TODO: Move this back to uncached section when relavant properties are defined on the Enterprise model
|
||||
def icon
|
||||
# TODO: Replace with object.has_shopfront when this property exists
|
||||
if has_shopfront
|
||||
if can_aggregate
|
||||
"/assets/map_005-hub.svg"
|
||||
else
|
||||
if object.is_distributor
|
||||
"/assets/map_003-producer-shop.svg"
|
||||
else
|
||||
"/assets/map_001-producer-only.svg"
|
||||
end
|
||||
end
|
||||
else
|
||||
if can_aggregate
|
||||
"/assets/map_006-hub-profile.svg"
|
||||
else
|
||||
if object.is_distributor
|
||||
"/assets/map_004-producer-shop-profile.svg"
|
||||
else
|
||||
"/assets/map_002-producer-only-profile.svg"
|
||||
end
|
||||
end
|
||||
end
|
||||
def enterprise_category
|
||||
object.enterprise_category
|
||||
end
|
||||
|
||||
# TODO: Remove this when flags on enterprises are switched over
|
||||
def has_shopfront
|
||||
object.type != 'profile'
|
||||
object.is_distributor && object.type != 'profile'
|
||||
end
|
||||
|
||||
# TODO: Remove this when flags on enterprises are switched over
|
||||
def can_aggregate
|
||||
object.is_distributor && object.suppliers != [object]
|
||||
# Used to select enterprises for hub listing
|
||||
def has_hub_listing
|
||||
has_shopfront || object.enterprise_category == "hub_profile"
|
||||
end
|
||||
|
||||
# Map svg icons.
|
||||
def icon
|
||||
icons = {
|
||||
"hub" => "/assets/map_005-hub.svg",
|
||||
"hub_profile" => "/assets/map_006-hub-profile.svg",
|
||||
"producer_hub" => "/assets/map_005-hub.svg",
|
||||
"producer_shop" => "/assets/map_003-producer-shop.svg",
|
||||
"producer" => "/assets/map_001-producer-only.svg",
|
||||
"producer_profile" => "/assets/map_002-producer-only-profile.svg",
|
||||
}
|
||||
icons[object.enterprise_category]
|
||||
end
|
||||
|
||||
# Choose regular icon font for enterprises.
|
||||
def icon_font
|
||||
icon_fonts = {
|
||||
"hub" => "ofn-i_063-hub",
|
||||
"hub_profile" => "ofn-i_064-hub-reversed",
|
||||
"producer_hub" => "ofn-i_063-hub",
|
||||
"producer_shop" => "ofn-i_059-producer",
|
||||
"producer" => "ofn-i_059-producer",
|
||||
"producer_profile" => "ofn-i_060-producer-reversed",
|
||||
}
|
||||
icon_fonts[object.enterprise_category]
|
||||
end
|
||||
|
||||
# Choose producer page icon font - yes, sadly its got to be different.
|
||||
# This duplicates some code but covers the producer page edge case where
|
||||
# producer-hub has a producer icon without needing to duplicate the category logic in angular.
|
||||
def producer_icon_font
|
||||
icon_fonts = {
|
||||
"hub" => "",
|
||||
"hub_profile" => "",
|
||||
"producer_hub" => "ofn-i_059-producer",
|
||||
"producer_shop" => "ofn-i_059-producer",
|
||||
"producer" => "ofn-i_059-producer",
|
||||
"producer_profile" => "ofn-i_060-producer-reversed",
|
||||
"empty" => "",
|
||||
}
|
||||
icon_fonts[object.enterprise_category]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Api::CachedEnterpriseSerializer < ActiveModel::Serializer
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
= render partial: 'shared/components/filter_controls'
|
||||
.row
|
||||
= render partial: 'shared/components/filter_controls'
|
||||
= render partial: 'shared/components/show_profiles'
|
||||
|
||||
.row.animate-show{"ng-show" => "filtersActive"}
|
||||
.small-12.columns
|
||||
.small-12.columns
|
||||
.row.filter-box
|
||||
.small-12.large-9.columns
|
||||
%h5.tdhead
|
||||
%h5.tdhead
|
||||
.light Filter by
|
||||
Type
|
||||
%ul.small-block-grid-2.medium-block-grid-4.large-block-grid-5
|
||||
%taxon-selector{objects: "hubs | hubs:query",
|
||||
%taxon-selector{objects: "hubs | hubs:query",
|
||||
results: "activeTaxons"}
|
||||
.small-12.large-3.columns
|
||||
%h5.tdhead
|
||||
%h5.tdhead
|
||||
.light Filter by
|
||||
Delivery
|
||||
%ul.small-block-grid-2.medium-block-grid-4.large-block-grid-2
|
||||
%shipping-type-selector{results: "shippingTypes"}
|
||||
.row.filter-box.animate-show{"ng-show" => "filtersActive && totalActive() > 0"}
|
||||
.small-12.columns
|
||||
%a.button.secondary.small.expand{"ng-click" => "clearAll()"}
|
||||
%i.ofn-i_009-close
|
||||
Clear all filters
|
||||
%shipping-type-selector{results: "shippingTypes"}
|
||||
|
||||
= render partial: 'shared/components/filter_box'
|
||||
|
||||
@@ -1,19 +1,13 @@
|
||||
= inject_enterprises
|
||||
= inject_enterprises
|
||||
#hubs.hubs{"ng-controller" => "HubsCtrl"}
|
||||
.row
|
||||
.small-12.columns
|
||||
%h1 Shop your local area
|
||||
/ %div
|
||||
/ Shop a
|
||||
/ %ofn-modal{title: "food hub"}
|
||||
/ = render partial: "modals/food_hub"
|
||||
/ from the list below:
|
||||
%h1 Shop in your local area
|
||||
|
||||
#active-table-search.row.pad-top
|
||||
.small-12.columns
|
||||
/ %i.ofn-i_020-search
|
||||
%input{type: :text,
|
||||
"ng-model" => "query",
|
||||
%input{type: :text,
|
||||
"ng-model" => "query",
|
||||
placeholder: "Search by name or suburb...",
|
||||
"ng-debounce" => "150",
|
||||
"ofn-disable-enter" => true}
|
||||
@@ -23,11 +17,11 @@
|
||||
.row{bindonce: true}
|
||||
.small-12.columns
|
||||
.active_table
|
||||
%hub.active_table_node.row.animate-repeat{"ng-repeat" => "hub in filteredHubs = (hubs | hubs:query | taxons:activeTaxons | shipping:shippingTypes)",
|
||||
"ng-class" => "{'closed' : !open(), 'open' : open(), 'inactive' : !hub.active, 'current' : current()}",
|
||||
%hub.active_table_node.row.animate-repeat{"ng-repeat" => "hub in filteredHubs = (hubs | hubs:query | taxons:activeTaxons | shipping:shippingTypes | showProfiles:show_profiles )",
|
||||
"ng-class" => "{'is_profile' : !hub.has_shopfront, 'closed' : !open(), 'open' : open(), 'inactive' : !hub.active, 'current' : current()}",
|
||||
"scroll-after-load" => true,
|
||||
"ng-controller" => "HubNodeCtrl",
|
||||
id: "{{hub.hash}}"}
|
||||
id: "{{hub.hash}}"}
|
||||
.small-12.columns
|
||||
= render partial: 'home/skinny'
|
||||
= render partial: 'home/fat'
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
.row.active_table_row{"ng-click" => "toggle()", "ng-class" => "{'closed' : !open()}", bindonce: true}
|
||||
.row.active_table_row{"ng-if" => "hub.has_shopfront", "ng-click" => "toggle()", "ng-class" => "{'closed' : !open(), 'has_shopfront' : producer.has_shopfront}", bindonce: true}
|
||||
|
||||
.columns.small-12.medium-6.large-5.skinny-head
|
||||
%a.hub{"bo-href" => "hub.path", "ng-class" => "{primary: hub.active, secondary: !hub.active}", "ofn-empties-cart" => "hub"}
|
||||
%i{ ng: { class: "{ 'ofn-i_063-hub': hub.can_aggregate && hub.has_shopfront,
|
||||
'ofn-i_059-producer': !hub.can_aggregate && hub.has_shopfront,
|
||||
'ofn-i_060-producer-reversed': !hub.can_aggregate && !hub.has_shopfront,
|
||||
'ofn-i_064-hub-reversed': hub.can_aggregate && !hub.has_shopfront }" } }
|
||||
/ %i.ofn-i_063-hub
|
||||
%i{ng: {class: "hub.icon_font"}}
|
||||
%span.margin-top.hub-name-listing {{ hub.name | truncate:40}}
|
||||
|
||||
.columns.small-4.medium-2.large-2
|
||||
%span.margin-top {{ hub.address.city }}
|
||||
.columns.small-2.medium-1.large-1
|
||||
@@ -15,16 +13,28 @@
|
||||
.columns.small-6.medium-3.large-4.text-right{"bo-if" => "hub.active"}
|
||||
%a.hub.open_closed{"bo-href" => "hub.path", "ng-class" => "{primary: hub.active, secondary: !hub.active}", "ofn-empties-cart" => "hub"}
|
||||
%i.ofn-i_033-open-sign
|
||||
%span.margin-top{ bo: { if: "current()" } }
|
||||
%span.margin-top{ bo: { if: "current()" } }
|
||||
%em Shopping here
|
||||
%span.margin-top{ bo: { if: "!current()" } } {{ hub.orders_close_at | sensible_timeframe }}
|
||||
|
||||
.columns.small-6.medium-3.large-4.text-right{"bo-if" => "!hub.active"}
|
||||
%a.hub.open_closed{"bo-href" => "hub.path", "ng-class" => "{primary: hub.active, secondary: !hub.active}", "ofn-empties-cart" => "hub"}
|
||||
%i.ofn-i_032-closed-sign
|
||||
%span.margin-top{ bo: { if: "current()" } }
|
||||
%span.margin-top{ bo: { if: "current()" } }
|
||||
%em Shopping here
|
||||
%span.margin-top{ bo: { if: "!current()" } } Orders closed
|
||||
|
||||
.row.active_table_row{"ng-if" => "!hub.has_shopfront", "ng-class" => "closed"}
|
||||
.columns.small-12.medium-6.large-5.skinny-head
|
||||
%a.hub{"ng-click" => "openModal(hub)", "ng-class" => "{primary: hub.active, secondary: !hub.active}", "ofn-empties-cart" => "hub"}
|
||||
%i{ng: {class: "hub.icon_font"}}
|
||||
%span.margin-top.hub-name-listing {{ hub.name | truncate:40}}
|
||||
|
||||
.columns.small-4.medium-2.large-2
|
||||
%span.margin-top {{ hub.address.city }}
|
||||
.columns.small-2.medium-1.large-1
|
||||
%span.margin-top {{ hub.address.state_name | uppercase }}
|
||||
|
||||
.columns.small-6.medium-3.large-4.text-right
|
||||
%span.margin-top{ bo: { if: "!current()" } }
|
||||
%em Profile only
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
= render partial: 'shared/components/filter_controls'
|
||||
.row
|
||||
= render partial: 'shared/components/filter_controls'
|
||||
.small-12.medium-6.columns.text-right
|
||||
|
||||
|
||||
.row.animate-show{"ng-show" => "filtersActive"}
|
||||
.small-12.columns
|
||||
.row.filter-box
|
||||
.small-12.columns
|
||||
%h5.tdhead
|
||||
%h5.tdhead
|
||||
.light Filter by
|
||||
Type
|
||||
%ul.small-block-grid-2.medium-block-grid-4.large-block-grid-6
|
||||
%taxon-selector{objects: "Producers.visible | filterProducers:query",
|
||||
%taxon-selector{objects: "Producers.visible | filterProducers:query ",
|
||||
results: "activeTaxons"}
|
||||
|
||||
.row.filter-box.animate-show{"ng-show" => "filtersActive && totalActive() > 0"}
|
||||
.small-12.columns
|
||||
%a.button.secondary.small.expand{"ng-click" => "clearAll()"}
|
||||
%i.ofn-i_009-close
|
||||
Clear all filters
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
.row.active_table_row{"ng-click" => "toggle()", "ng-class" => "{'closed' : !open()}"}
|
||||
.row.active_table_row{"ng-click" => "toggle()", "ng-class" => "{'closed' : !open(), 'has_shopfront' : producer.has_shopfront}"}
|
||||
.columns.small-12.medium-4.large-4.skinny-head
|
||||
/ This needs logic to show profile only icon when available %i.ofn-i_060-producer-reversed
|
||||
%i.ofn-i_059-producer
|
||||
%span.margin-top
|
||||
%strong {{ producer.name }}
|
||||
%span{"bo-if" => "producer.has_shopfront" }
|
||||
%a.has_shopfront{"bo-href" => "producer.path" }
|
||||
%i{ng: {class: "producer.producer_icon_font"}}
|
||||
%span.margin-top
|
||||
%strong {{ producer.name }}
|
||||
%span.producer-name{"bo-if" => "!producer.has_shopfront" }
|
||||
%i{ng: {class: "producer.producer_icon_font"}}
|
||||
%span.margin-top
|
||||
%strong {{ producer.name }}
|
||||
|
||||
|
||||
.columns.small-6.medium-3.large-3
|
||||
%span.margin-top {{ producer.address.city }}
|
||||
.columns.small-4.medium-3.large-4
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
= inject_enterprises
|
||||
= inject_enterprises
|
||||
.producers.pad-top{"ng-controller" => "ProducersCtrl"}
|
||||
.row
|
||||
.small-12.columns.pad-top
|
||||
%h1 Find local producers
|
||||
/ %div
|
||||
/ Find a
|
||||
/ %div
|
||||
/ Find a
|
||||
/ %ofn-modal{title: "producer"}
|
||||
/ = render partial: "modals/producers"
|
||||
/ from the list below:
|
||||
|
||||
#active-table-search.row
|
||||
.small-12.columns
|
||||
%input.animate-show{type: :text,
|
||||
"ng-model" => "query",
|
||||
%input.animate-show{type: :text,
|
||||
"ng-model" => "query",
|
||||
placeholder: "Search by producer or suburb...",
|
||||
"ng-debounce" => "150",
|
||||
"ofn-disable-enter" => true}
|
||||
|
||||
2
app/views/registration/limit_reached.html.haml
Normal file
2
app/views/registration/limit_reached.html.haml
Normal file
@@ -0,0 +1,2 @@
|
||||
/ Directive which loads the modal
|
||||
%div{ "ofn-registration-limit-modal" => true }
|
||||
5
app/views/shared/components/_filter_box.html.haml
Normal file
5
app/views/shared/components/_filter_box.html.haml
Normal file
@@ -0,0 +1,5 @@
|
||||
.row.filter-box.animate-show{"ng-show" => "filtersActive && totalActive() > 0"}
|
||||
.small-12.columns
|
||||
%a.button.secondary.small.expand{"ng-click" => "clearAll()"}
|
||||
%i.ofn-i_009-close
|
||||
Clear all filters
|
||||
@@ -1,19 +1,9 @@
|
||||
.row
|
||||
.small-12.medium-6.columns
|
||||
%a.button.success.tiny.filterbtn{"ng-click" => "filtersActive = !filtersActive",
|
||||
"ng-show" => "FilterSelectorsService.selectors.length > 0"}
|
||||
{{ filterText(filtersActive) }}
|
||||
%i.ofn-i_005-caret-down{"ng-show" => "!filtersActive"}
|
||||
%i.ofn-i_006-caret-up{"ng-show" => "filtersActive"}
|
||||
.small-12.medium-6.columns
|
||||
%a.button.success.tiny.filterbtn{"ng-click" => "filtersActive = !filtersActive",
|
||||
"ng-show" => "FilterSelectorsService.selectors.length > 0"}
|
||||
{{ filterText(filtersActive) }}
|
||||
%i.ofn-i_005-caret-down{"ng-show" => "!filtersActive"}
|
||||
%i.ofn-i_006-caret-up{"ng-show" => "filtersActive"}
|
||||
|
||||
%a.button.secondary.tiny.filterbtn.disabled{"ng-show" => "FilterSelectorsService.selectors.length == 0"}
|
||||
No filters
|
||||
.small-12.medium-6.columns.text-right
|
||||
.profile-checkbox
|
||||
|
||||
/ Hide until we're ready to work on this:
|
||||
|
||||
/ %input{type: "checkbox", name: "profile"}><
|
||||
/ %label Show profiles
|
||||
/ %button.button.secondary.tiny.help-btn.ng-scope{:popover => "Profiles do not have a shopfront on the Open Food Network, but they may have their own physical or online shop elsewhere", "popover-placement" => "left"}><
|
||||
/ %i.ofn-i_013-help
|
||||
%a.button.secondary.tiny.filterbtn.disabled{"ng-show" => "FilterSelectorsService.selectors.length == 0"}
|
||||
No filters
|
||||
|
||||
6
app/views/shared/components/_show_profiles.html.haml
Normal file
6
app/views/shared/components/_show_profiles.html.haml
Normal file
@@ -0,0 +1,6 @@
|
||||
.small-12.medium-6.columns.text-right
|
||||
.profile-checkbox
|
||||
%input{"ng-model" => "show_profiles", type: "checkbox", name: "profile"}><
|
||||
%label Show profiles
|
||||
%button.button.secondary.tiny.help-btn.ng-scope{:popover => "Profiles do not have a shopfront on the Open Food Network, but may have their own physical or online shop elsewhere", "popover-placement" => "left"}><
|
||||
%i.ofn-i_013-help
|
||||
@@ -1,18 +1,17 @@
|
||||
= render partial: 'shared/components/filter_controls'
|
||||
.row
|
||||
= render partial: 'shared/components/filter_controls'
|
||||
.small-12.medium-6.columns.text-right
|
||||
|
||||
|
||||
.row.animate-show{"ng-show" => "filtersActive"}
|
||||
.small-12.columns
|
||||
.row.filter-box
|
||||
.small-12.columns
|
||||
%h5.tdhead
|
||||
%h5.tdhead
|
||||
.light Filter by
|
||||
Type
|
||||
%ul.small-block-grid-2.medium-block-grid-3.large-block-grid-4
|
||||
%taxon-selector{objects: "Products.products | products:query",
|
||||
%taxon-selector{objects: "Products.products | products:query | products:showProfiles",
|
||||
results: "activeTaxons"}
|
||||
|
||||
.row.filter-box.animate-show{"ng-show" => "filtersActive && totalActive() > 0"}
|
||||
.small-12.columns
|
||||
%a.button.secondary.small.expand{"ng-click" => "clearAll()"}
|
||||
%i.ofn-i_009-close
|
||||
Clear all filters
|
||||
= render partial: 'shared/components/filter_box'
|
||||
|
||||
@@ -13,7 +13,7 @@ Subtotal: #{number_to_currency checkout_cart_total_with_adjustments(@order)}
|
||||
- checkout_adjustments_for_summary(@order, exclude: [:distribution]).each do |adjustment|
|
||||
#{raw(adjustment.label)} #{adjustment.display_amount}
|
||||
Order Total: #{@order.display_total}
|
||||
- if @order.payments.first.andand.payment_method.andand.type == "Spree::PaymentMethod::Check"
|
||||
- if @order.payments.first.andand.payment_method.andand.type == "Spree::PaymentMethod::Check" and @order.payments.first.andand.payment_method.andand.description
|
||||
\
|
||||
============================================================
|
||||
Payment Details
|
||||
@@ -28,6 +28,9 @@ Order Total: #{@order.display_total}
|
||||
Your order will be delivered to:
|
||||
#{@order.ship_address.to_s}
|
||||
|
||||
- if @order.shipping_method.andand.description
|
||||
#{@order.shipping_method.description.html_safe}
|
||||
|
||||
- if @order.order_cycle.andand.pickup_time_for(@order.distributor)
|
||||
Delivery on: #{@order.order_cycle.pickup_time_for(@order.distributor)}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe RegistrationController do
|
||||
include AuthenticationWorkflow
|
||||
describe "redirecting when user not logged in" do
|
||||
it "index" do
|
||||
get :index
|
||||
@@ -13,26 +14,38 @@ describe RegistrationController do
|
||||
end
|
||||
end
|
||||
|
||||
describe "loading data when user is logged in" do
|
||||
let!(:user) { double(:user) }
|
||||
describe "redirecting when user has reached enterprise ownership limit" do
|
||||
let!(:user) { create_enterprise_user( enterprise_limit: 1 ) }
|
||||
let!(:enterprise) { create(:distributor_enterprise, owner: user) }
|
||||
|
||||
before do
|
||||
controller.stub spree_current_user: user
|
||||
end
|
||||
|
||||
it "index" do
|
||||
get :index
|
||||
response.should render_template :limit_reached
|
||||
end
|
||||
end
|
||||
|
||||
describe "loading data when user is logged in" do
|
||||
let!(:user) { create_enterprise_user }
|
||||
|
||||
before do
|
||||
controller.stub spree_current_user: user
|
||||
user.stub spree_api_key: '12345'
|
||||
user.stub last_incomplete_spree_order: nil
|
||||
end
|
||||
|
||||
describe "index" do
|
||||
it "loads the spree api key" do
|
||||
get :index
|
||||
expect(assigns(:spree_api_key)).to eq '12345'
|
||||
expect(assigns(:spree_api_key)).to eq user.spree_api_key
|
||||
end
|
||||
end
|
||||
|
||||
describe "store" do
|
||||
it "loads the spree api key" do
|
||||
get :store
|
||||
expect(assigns(:spree_api_key)).to eq '12345'
|
||||
expect(assigns(:spree_api_key)).to eq user.spree_api_key
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -89,7 +89,7 @@ feature %q{
|
||||
let!(:d1) { create(:distributor_enterprise) }
|
||||
let!(:d2) { create(:distributor_enterprise) }
|
||||
let!(:d3) { create(:distributor_enterprise) }
|
||||
let(:enterprise_user) { create_enterprise_user([d1]) }
|
||||
let(:enterprise_user) { create_enterprise_user( enterprises: [d1] ) }
|
||||
|
||||
let!(:er1) { create(:enterprise_relationship, parent: d1, child: d2) }
|
||||
let!(:er2) { create(:enterprise_relationship, parent: d2, child: d1) }
|
||||
|
||||
@@ -64,7 +64,7 @@ feature %q{
|
||||
page.should have_admin_menu_item 'Dashboard'
|
||||
page.should have_admin_menu_item 'Enterprises'
|
||||
|
||||
['Orders', 'Products', 'Reports', 'Configuration', 'Promotions', 'Users', 'Order Cycles'].each do |menu_item_name|
|
||||
['Orders', 'Reports', 'Configuration', 'Promotions', 'Users', 'Order Cycles'].each do |menu_item_name|
|
||||
page.should_not have_admin_menu_item menu_item_name
|
||||
end
|
||||
end
|
||||
@@ -79,15 +79,15 @@ feature %q{
|
||||
end
|
||||
end
|
||||
|
||||
it "does not show me product management controls" do
|
||||
page.should_not have_selector '#products'
|
||||
it "shows me product management controls, but not order_cycle controls" do
|
||||
page.should have_selector '#products'
|
||||
page.should_not have_selector '#order_cycles'
|
||||
end
|
||||
|
||||
it "does not show me enterprise product info, payment methods, shipping methods or enterprise fees" do
|
||||
it "shows me enterprise product info but not payment methods, shipping methods or enterprise fees" do
|
||||
# Producer product info
|
||||
page.should_not have_selector '.producers_tab span', text: 'Total Products'
|
||||
page.should_not have_selector '.producers_tab span', text: 'Active Products'
|
||||
page.should have_selector '.producers_tab span', text: 'Total Products'
|
||||
page.should have_selector '.producers_tab span', text: 'Active Products'
|
||||
page.should_not have_selector '.producers_tab span', text: 'Products in OCs'
|
||||
|
||||
# Payment methods, shipping methods, enterprise fees
|
||||
|
||||
@@ -10,8 +10,8 @@ feature %q{
|
||||
context "Permissions for different reports" do
|
||||
context "As an enterprise user" do
|
||||
let(:user) do
|
||||
create_enterprise_user([
|
||||
create(:distributor_enterprise)
|
||||
create_enterprise_user(enterprises: [
|
||||
create(:distributor_enterprise)
|
||||
])
|
||||
end
|
||||
it "should not show the Sales Total report" do
|
||||
@@ -99,7 +99,7 @@ feature %q{
|
||||
let(:shipping_instructions) { "pick up on thursday please!" }
|
||||
let(:order1) { create(:order, :distributor => distributor, :bill_address => bill_address, :special_instructions => shipping_instructions) }
|
||||
let(:order2) { create(:order, :distributor => distributor, :bill_address => bill_address, :special_instructions => shipping_instructions) }
|
||||
|
||||
|
||||
before do
|
||||
Timecop.travel(Time.zone.local(2013, 4, 25, 14, 0, 0)) { order1.finalize! }
|
||||
Timecop.travel(Time.zone.local(2013, 4, 25, 16, 0, 0)) { order2.finalize! }
|
||||
@@ -144,7 +144,7 @@ feature %q{
|
||||
variant_2.update_column(:count_on_hand, 20)
|
||||
product_2.master.update_column(:count_on_hand, 9)
|
||||
variant_1.option_values = [create(:option_value, :presentation => "Test")]
|
||||
|
||||
|
||||
login_to_admin_section
|
||||
click_link 'Reports'
|
||||
|
||||
@@ -165,4 +165,3 @@ feature %q{
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
//= require angular-mocks
|
||||
//= require angular-cookies
|
||||
//= require angular-backstretch.js
|
||||
//= require angularjs-file-upload
|
||||
//= require lodash.underscore.js
|
||||
//= require angular-flash.min.js
|
||||
//= require shared/mm-foundation-tpls-0.2.2.min.js
|
||||
|
||||
@@ -1,46 +1,45 @@
|
||||
describe "Hubs service", ->
|
||||
Hubs = null
|
||||
Enterprises = null
|
||||
CurrentHubMock = {}
|
||||
CurrentHubMock = {}
|
||||
hubs = [
|
||||
{
|
||||
id: 2
|
||||
active: false
|
||||
orders_close_at: new Date()
|
||||
is_distributor: true
|
||||
has_shopfront: true
|
||||
has_hub_listing: true
|
||||
}
|
||||
{
|
||||
id: 3
|
||||
active: false
|
||||
orders_close_at: new Date()
|
||||
is_distributor: true
|
||||
has_shopfront: true
|
||||
has_hub_listing: true
|
||||
}
|
||||
{
|
||||
id: 1
|
||||
active: true
|
||||
orders_close_at: new Date()
|
||||
is_distributor: true
|
||||
has_shopfront: true
|
||||
has_hub_listing: true
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
beforeEach ->
|
||||
module 'Darkswarm'
|
||||
angular.module('Darkswarm').value('enterprises', hubs)
|
||||
angular.module('Darkswarm').value('enterprises', hubs)
|
||||
module ($provide)->
|
||||
$provide.value "CurrentHub", CurrentHubMock
|
||||
$provide.value "CurrentHub", CurrentHubMock
|
||||
null
|
||||
inject ($injector)->
|
||||
Enterprises = $injector.get("Enterprises")
|
||||
Enterprises = $injector.get("Enterprises")
|
||||
Hubs = $injector.get("Hubs")
|
||||
|
||||
it "filters Enterprise.hubs into a new array", ->
|
||||
expect(Hubs.hubs[0]).toBe Enterprises.enterprises[2]
|
||||
# Because the $filter is a new sorted array
|
||||
# Because the $filter is a new sorted array
|
||||
# We check to see the objects in both arrays are still the same
|
||||
Enterprises.enterprises[2].active = false
|
||||
Enterprises.enterprises[2].active = false
|
||||
expect(Hubs.hubs[0].active).toBe false
|
||||
|
||||
|
||||
@@ -501,4 +501,65 @@ describe Enterprise do
|
||||
supplier.producer_properties.first.property.presentation.should == 'Organic Certified'
|
||||
end
|
||||
end
|
||||
|
||||
pending "provide enterprise category" do
|
||||
|
||||
# Swap type values full > sell_all, single > sell_own profile > sell_none
|
||||
# swap is_distributor for new can_supply flag.
|
||||
let(:producer_sell_all_can_supply) {
|
||||
create(:enterprise, is_primary_producer: true, type: "full", is_distributor: true)
|
||||
}
|
||||
let(:producer_sell_all_cant_supply) {
|
||||
create(:enterprise, is_primary_producer: true, type: "full", is_distributor: false)
|
||||
}
|
||||
let(:producer_sell_own_can_supply) {
|
||||
create(:enterprise, is_primary_producer: true, type: "single", is_distributor: true)
|
||||
}
|
||||
let(:producer_sell_own_cant_supply) {
|
||||
create(:enterprise, is_primary_producer: true, type: "single", is_distributor: false)
|
||||
}
|
||||
let(:producer_sell_none_can_supply) {
|
||||
create(:enterprise, is_primary_producer: true, type: "profile", is_distributor: true)
|
||||
}
|
||||
let(:producer_sell_none_cant_supply) {
|
||||
create(:enterprise, is_primary_producer: true, type: "profile", is_distributor: false)
|
||||
}
|
||||
let(:non_producer_sell_all_can_supply) {
|
||||
create(:enterprise, is_primary_producer: true, type: "full", is_distributor: true)
|
||||
}
|
||||
let(:non_producer_sell_all_cant_supply) {
|
||||
create(:enterprise, is_primary_producer: true, type: "full", is_distributor: false)
|
||||
}
|
||||
let(:non_producer_sell_own_can_supply) {
|
||||
create(:enterprise, is_primary_producer: true, type: "single", is_distributor: true)
|
||||
}
|
||||
let(:non_producer_sell_own_cant_supply) {
|
||||
create(:enterprise, is_primary_producer: true, type: "single", is_distributor: false)
|
||||
}
|
||||
let(:non_producer_sell_none_can_supply) {
|
||||
create(:enterprise, is_primary_producer: false, type: "profile", is_distributor: true)
|
||||
}
|
||||
let(:non_producer_sell_none_cant_supply) {
|
||||
create(:enterprise, is_primary_producer: false, type: "profile", is_distributor: false)
|
||||
}
|
||||
|
||||
it "should output enterprise categories" do
|
||||
producer_sell_all_can_supply.is_primary_producer.should == true
|
||||
producer_sell_all_can_supply.supplies.should == true
|
||||
producer_sell_all_can_supply.type.should == "full"
|
||||
|
||||
producer_sell_all_can_supply.enterprise_category.should == "producer_hub"
|
||||
producer_sell_all_cant_supply.enterprise_category.should == "producer_hub"
|
||||
producer_sell_own_can_supply.enterprise_category.should == "producer_shop"
|
||||
producer_sell_own_cant_supply.enterprise_category.should == "producer_shop"
|
||||
producer_sell_none_can_supply.enterprise_category.should == "producer"
|
||||
producer_sell_none_cant_supply.enterprise_category.should == "producer_profile"
|
||||
non_producer_sell_all_can_supply.enterprise_category.should == "hub"
|
||||
non_producer_sell_all_cant_supply.enterprise_category.should == "hub"
|
||||
non_producer_sell_own_can_supply.enterprise_category.should == "hub"
|
||||
non_producer_sell_own_cant_supply.enterprise_category.should == "hub"
|
||||
non_producer_sell_none_can_supply.enterprise_category.should == "hub_profile"
|
||||
non_producer_sell_none_cant_supply.enterprise_category.should == "hub_profile"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,44 +13,46 @@ module Spree
|
||||
let(:enterprise_single) { create(:enterprise, type: 'single') }
|
||||
let(:enterprise_profile) { create(:enterprise, type: 'profile') }
|
||||
|
||||
describe "creating enterprises" do
|
||||
context "as manager of a 'full' type enterprise" do
|
||||
before do
|
||||
user.enterprise_roles.create! enterprise: enterprise_full
|
||||
end
|
||||
|
||||
it { subject.can_manage_products?(user).should be_true }
|
||||
it { subject.can_manage_enterprises?(user).should be_true }
|
||||
it { subject.can_manage_orders?(user).should be_true }
|
||||
end
|
||||
|
||||
context "as manager of a 'single' type enterprise" do
|
||||
before do
|
||||
user.enterprise_roles.create! enterprise: enterprise_single
|
||||
end
|
||||
|
||||
it { subject.can_manage_products?(user).should be_true }
|
||||
it { subject.can_manage_enterprises?(user).should be_true }
|
||||
it { subject.can_manage_orders?(user).should be_true }
|
||||
end
|
||||
|
||||
context "as manager of a 'profile' type enterprise" do
|
||||
before do
|
||||
user.enterprise_roles.create! enterprise: enterprise_profile
|
||||
end
|
||||
|
||||
it { subject.can_manage_products?(user).should be_true }
|
||||
it { subject.can_manage_enterprises?(user).should be_true }
|
||||
it { subject.can_manage_orders?(user).should be_false }
|
||||
end
|
||||
|
||||
context "as a new user with no enterprises" do
|
||||
it { subject.can_manage_products?(user).should be_false }
|
||||
it { subject.can_manage_enterprises?(user).should be_false }
|
||||
it { subject.can_manage_orders?(user).should be_false }
|
||||
|
||||
it "can create enterprises straight off the bat" do
|
||||
subject.is_new_user?(user).should be_true
|
||||
expect(user).to have_ability :create, for: Enterprise
|
||||
end
|
||||
end
|
||||
|
||||
describe "managing enterprises" do
|
||||
it "can manage enterprises when the user has at least one enterprise assigned" do
|
||||
user.enterprise_roles.create! enterprise: enterprise_full
|
||||
subject.can_manage_enterprises?(user).should be_true
|
||||
end
|
||||
|
||||
it "can't otherwise" do
|
||||
subject.can_manage_enterprises?(user).should be_false
|
||||
end
|
||||
end
|
||||
|
||||
describe "managing products" do
|
||||
it "can when a user manages a 'full' type enterprise" do
|
||||
user.enterprise_roles.create! enterprise: enterprise_full
|
||||
subject.can_manage_products?(user).should be_true
|
||||
end
|
||||
|
||||
it "can when a user manages a 'single' type enterprise" do
|
||||
user.enterprise_roles.create! enterprise: enterprise_single
|
||||
subject.can_manage_products?(user).should be_true
|
||||
end
|
||||
|
||||
it "can't when a user manages a 'profile' type enterprise" do
|
||||
user.enterprise_roles.create! enterprise: enterprise_profile
|
||||
subject.can_manage_products?(user).should be_false
|
||||
end
|
||||
|
||||
it "can't when the user manages no enterprises" do
|
||||
subject.can_manage_products?(user).should be_false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Roles' do
|
||||
|
||||
@@ -37,12 +37,9 @@ module AuthenticationWorkflow
|
||||
visit spree.admin_path
|
||||
end
|
||||
|
||||
def create_enterprise_user(enterprises = [])
|
||||
new_user = create(:user, password: 'blahblah', :password_confirmation => 'blahblah')
|
||||
def create_enterprise_user( attrs = {} )
|
||||
new_user = create(:user, attrs)
|
||||
new_user.spree_roles = [] # for some reason unbeknown to me, this new user gets admin permissions by default.
|
||||
for enterprise in enterprises do
|
||||
new_user.enterprise_roles.build(enterprise: enterprise).save
|
||||
end
|
||||
new_user.save
|
||||
new_user
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user