From 90eea5cb16937f7490ac5ab2706becd1539bc0eb Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Tue, 29 Jul 2014 15:23:10 +1000 Subject: [PATCH 01/40] Switching to a single directive to render variants on /shop --- .../directives/shop_variant.js.coffee | 6 ++ .../templates/shop_variant.html.haml} | 13 ++--- app/views/shop/products/_form.html.haml | 8 +-- app/views/shop/products/_master.html.haml | 58 ------------------- 4 files changed, 14 insertions(+), 71 deletions(-) create mode 100644 app/assets/javascripts/darkswarm/directives/shop_variant.js.coffee rename app/{views/shop/products/_variants.html.haml => assets/javascripts/templates/shop_variant.html.haml} (83%) delete mode 100644 app/views/shop/products/_master.html.haml diff --git a/app/assets/javascripts/darkswarm/directives/shop_variant.js.coffee b/app/assets/javascripts/darkswarm/directives/shop_variant.js.coffee new file mode 100644 index 0000000000..e4cbed11c5 --- /dev/null +++ b/app/assets/javascripts/darkswarm/directives/shop_variant.js.coffee @@ -0,0 +1,6 @@ +Darkswarm.directive "shopVariant", -> + restrict: 'E' + replace: true + templateUrl: 'shop_variant.html' + scope: + variant: '=' diff --git a/app/views/shop/products/_variants.html.haml b/app/assets/javascripts/templates/shop_variant.html.haml similarity index 83% rename from app/views/shop/products/_variants.html.haml rename to app/assets/javascripts/templates/shop_variant.html.haml index 3427d23a5f..d0eb4b67c7 100644 --- a/app/views/shop/products/_variants.html.haml +++ b/app/assets/javascripts/templates/shop_variant.html.haml @@ -1,16 +1,15 @@ -.row.variants{bindonce: true, - "ng-repeat" => "variant in product.variants track by variant.id"} - +.variants.row .small-12.medium-4.large-4.columns.variant-name .table-cell .inline {{ variant.name_to_display }} - .bulk-buy.inline{"bo-if" => "product.group_buy"} + .bulk-buy.inline{"bo-if" => "variant.product.group_buy"} %i.ofn-i_056-bulk>< %em>< \ Bulk -# WITHOUT GROUP BUY - .small-5.medium-3.large-3.columns.text-right{"bo-if" => "!product.group_buy"} + .small-5.medium-3.large-3.columns.text-right{"bo-if" => "!variant.product.group_buy"} + %input{type: :number, value: nil, min: 0, @@ -22,7 +21,7 @@ -# WITH GROUP BUY - .small-5.medium-3.large-3.columns.text-right{"bo-if" => "product.group_buy"} + .small-5.medium-3.large-3.columns.text-right{"bo-if" => "variant.product.group_buy"} %span.bulk-input-container %span.bulk-input %input.bulk.first{type: :number, @@ -33,7 +32,7 @@ "ofn-disable-scroll" => true, max: "{{variant.on_demand && 9999 || variant.count_on_hand }}", name: "variants[{{variant.id}}]", id: "variants_{{variant.id}}"} - %span.bulk-input{"bo-if" => "product.group_buy"} + %span.bulk-input{"bo-if" => "variant.product.group_buy"} %input.bulk.second{type: :number, min: 0, "ng-model" => "variant.line_item.max_quantity", diff --git a/app/views/shop/products/_form.html.haml b/app/views/shop/products/_form.html.haml index 25004f97b4..a10edd7fb9 100644 --- a/app/views/shop/products/_form.html.haml +++ b/app/views/shop/products/_form.html.haml @@ -20,12 +20,8 @@ "ng-repeat" => "product in filteredProducts = (Products.products | products:query | taxons:activeTaxons | orderBy:ordering.order) track by product.id "} = render partial: "shop/products/summary" - - %span{"bo-if" => "product.hasVariants"} - = render partial: "shop/products/variants" - - .variants.row{"bo-if" => "!product.hasVariants"} - = render partial: "shop/products/master" + %shop-variant{variant: 'product.master', "bo-if" => "!product.hasVariants"} + %shop-variant{variant: 'variant', "ng-repeat" => "variant in product.variants track by variant.id"} %product{"ng-show" => "Products.loading"} .row.summary diff --git a/app/views/shop/products/_master.html.haml b/app/views/shop/products/_master.html.haml deleted file mode 100644 index f12df1b881..0000000000 --- a/app/views/shop/products/_master.html.haml +++ /dev/null @@ -1,58 +0,0 @@ -.small-12.medium-4.large-4.columns.variant-name - .table-cell - .inline {{ product.master.name_to_display }} - .bulk-buy.inline{"bo-if" => "product.group_buy"} - %i.ofn-i_056-bulk>< - %em>< - \ Bulk - --# WITHOUT GROUP BUY -.small-5.medium-3.large-3.columns.text-right{"bo-if" => "!product.group_buy"} - %input{type: :number, - min: 0, - placeholder: "0", - "ofn-disable-scroll" => true, - max: "{{product.on_demand && 9999 || product.count_on_hand }}", - name: "variants[{{product.master.id}}]", - "ng-model" => "product.master.line_item.quantity", - id: "variants_{{product.master.id}}"} - --# WITH GROUP BUY -.small-5.medium-3.large-3.columns.text-right{"bo-if" => "product.group_buy"} - %span.bulk-input-container - %span.bulk-input - %input.bulk.first{type: :number, - min: 0, - "ng-model" => "product.master.line_item.quantity", - placeholder: "min", - "ofn-disable-scroll" => true, - max: "{{product.on_demand && 9999 || product.count_on_hand }}", - name: "variants[{{product.master.id}}]", - id: "variants_{{product.master.id}}"} - - %span.bulk-input{"bo-if" => "product.group_buy"} - %input.bulk.second{type: :number, - min: 0, - "ng-model" => "product.master.line_item.max_quantity", - placeholder: "max", - "ofn-disable-scroll" => true, - max: "{{product.on_demand && 9999 || product.count_on_hand }}", - name: "variant_attributes[{{product.master.id}}][max_quantity]"} - -.small-3.medium-1.large-1.columns.variant-unit - .table-cell - %em {{ product.master.unit_to_display }} - -.small-4.medium-2.large-2.columns.variant-price - .table-cell - %i.ofn-i_009-close - {{ product.master.price | currency }} - -#%button.graph-button{"price-breakdown" => "_", - -#"variant" => "product.master", - -#"price-breakdown-animation" => "true"} - -#%i.ofn-i-058-graph - -.small-12.medium-2.large-2.columns.total-price.text-right - .table-cell - %strong - {{ product.master.getPrice() | currency }} From 6873b33e1f3fb20c8e706345c700cbc70bfa6033 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Tue, 29 Jul 2014 15:32:19 +1000 Subject: [PATCH 02/40] Directive restored --- app/assets/javascripts/templates/shop_variant.html.haml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/templates/shop_variant.html.haml b/app/assets/javascripts/templates/shop_variant.html.haml index d0eb4b67c7..938259d80f 100644 --- a/app/assets/javascripts/templates/shop_variant.html.haml +++ b/app/assets/javascripts/templates/shop_variant.html.haml @@ -50,8 +50,10 @@ %i.ofn-i_009-close {{ variant.price | currency }} - / %button.graph-button{popover: "This is the popover text", "popover-title" => "The title.", "popover-animation" => "true", "popover-trigger" =>"mouseenter", "popover-placement" => "top", "tabindex" => "-1"} - / %i.ofn-i-058-graph + %button.graph-button{"price-breakdown" => "_", + "variant" => "variant", + "price-breakdown-animation" => "true"} + %i.ofn-i-058-graph .small-12.medium-2.large-2.columns.total-price.text-right .table-cell From 682b04287e98a5d0f363d0fa3b9c398ac6d9fbf0 Mon Sep 17 00:00:00 2001 From: summerscope Date: Tue, 29 Jul 2014 16:03:13 +1000 Subject: [PATCH 03/40] Make product thumbnail background white by default --- app/assets/stylesheets/darkswarm/_shop-product-thumb.css.sass | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/darkswarm/_shop-product-thumb.css.sass b/app/assets/stylesheets/darkswarm/_shop-product-thumb.css.sass index 8bc1550d54..7a69707a60 100644 --- a/app/assets/stylesheets/darkswarm/_shop-product-thumb.css.sass +++ b/app/assets/stylesheets/darkswarm/_shop-product-thumb.css.sass @@ -13,7 +13,7 @@ float: left display: block z-index: 999999 - background-color: #999 + background-color: white overflow: hidden @media all and (max-width: 768px) From 62d5149e7a0c515e615c65bbbe3dbeb74dcf9ddf Mon Sep 17 00:00:00 2001 From: summerscope Date: Tue, 29 Jul 2014 16:15:35 +1000 Subject: [PATCH 04/40] Add back styling which sort of works for modals until i can pair with will to fix it --- app/assets/stylesheets/darkswarm/modals.css.sass | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/assets/stylesheets/darkswarm/modals.css.sass b/app/assets/stylesheets/darkswarm/modals.css.sass index 182ab5bec0..77f0b2fb54 100644 --- a/app/assets/stylesheets/darkswarm/modals.css.sass +++ b/app/assets/stylesheets/darkswarm/modals.css.sass @@ -5,6 +5,8 @@ dialog, .reveal-modal border: none outline: none padding: 1rem + + // TO DO: deal with scroll container inheritance (kirsten box) + bigger scrolling on mobile device issue div overflow: scroll @media only screen and (min-width: 40.063em) From 8ed79c6e55ba1faa7c7b84b846eec2cdbcc155d9 Mon Sep 17 00:00:00 2001 From: summerscope Date: Tue, 29 Jul 2014 16:50:26 +1000 Subject: [PATCH 05/40] Make scrolling on outer container only --- .../stylesheets/darkswarm/modals.css.sass | 79 +++++++++++-------- 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/app/assets/stylesheets/darkswarm/modals.css.sass b/app/assets/stylesheets/darkswarm/modals.css.sass index 77f0b2fb54..086ab8b076 100644 --- a/app/assets/stylesheets/darkswarm/modals.css.sass +++ b/app/assets/stylesheets/darkswarm/modals.css.sass @@ -5,47 +5,56 @@ dialog, .reveal-modal border: none outline: none padding: 1rem - - // TO DO: deal with scroll container inheritance (kirsten box) + bigger scrolling on mobile device issue - div - overflow: scroll - @media only screen and (min-width: 40.063em) - max-height: 580px - @media all and (max-width: 768px) - max-height: 440px - @media all and (max-width: 640px) - max-height: 400px - @media all and (max-width: 640px) - max-height: inherit - overflow: scroll + // TO DO: look at bigger issue scrolling on mobile device + overflow-y: scroll + @media only screen and (min-width: 40.063em) + max-height: 580px + @media all and (max-width: 768px) + max-height: 440px + @media all and (max-width: 640px) + max-height: 400px + @media all and (max-width: 640px) + max-height: inherit + overflow-y: scroll .reveal-modal-bg background-color: rgba(0,0,0,0.65) -dialog .close-reveal-modal.outside, .reveal-modal .close-reveal-modal.outside - top: -2.5rem - right: -2.5rem - font-size: 2rem - color: white +dialog .close-reveal-modal, .reveal-modal .close-reveal-modal + top: 0.45rem + right: 0.4rem + background-color: rgba(235,235,235,0.85) text-shadow: none - padding: 0.25rem + padding: 0.3rem @include border-radius(999999) - border: 1px solid transparent &:hover, &:active, &:focus - text-shadow: 0 1px 3px #333 - border: 1px solid white + background-color: rgba(235,235,235,1) + color: #333 - @media all and (max-width: 640px) - top: 0.5rem - right: 0.5rem - font-size: 2rem - color: white - text-shadow: none - padding: 0.25rem - background-color: rgba(150,150,150,0.85) - @include border-radius(999999) - border: 1px solid transparent - &:hover, &:active, &:focus - text-shadow: 0 1px 3px #333 - border: 1px solid white +// dialog .close-reveal-modal.outside, .reveal-modal .close-reveal-modal.outside +// top: -2.5rem +// right: -2.5rem +// font-size: 2rem +// color: white +// text-shadow: none +// padding: 0.25rem +// @include border-radius(999999) +// border: 1px solid transparent +// &:hover, &:active, &:focus +// text-shadow: 0 1px 3px #333 +// border: 1px solid white + +// @media all and (max-width: 640px) +// top: 0.5rem +// right: 0.5rem +// font-size: 2rem +// color: white +// text-shadow: none +// padding: 0.25rem +// background-color: rgba(150,150,150,0.85) +// @include border-radius(999999) +// border: 1px solid transparent +// &:hover, &:active, &:focus +// text-shadow: 0 1px 3px #333 +// border: 1px solid white From 47a38d1815d3ebc35f8b5cc322c6170e59138b27 Mon Sep 17 00:00:00 2001 From: summerscope Date: Tue, 29 Jul 2014 16:50:48 +1000 Subject: [PATCH 06/40] Tweak the styling on producer modals so no grey background --- app/assets/stylesheets/darkswarm/images.css.sass | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/darkswarm/images.css.sass b/app/assets/stylesheets/darkswarm/images.css.sass index 39a86a93d1..ce205f0dae 100644 --- a/app/assets/stylesheets/darkswarm/images.css.sass +++ b/app/assets/stylesheets/darkswarm/images.css.sass @@ -11,9 +11,9 @@ @include box-shadow(0 1px 2px 1px rgba(0,0,0,0.25)) .hero-img - background-color: #333 + border-bottom: 1px solid $disabled-bright width: 100% - min-height: 160px + min-height: 56px height: inherit max-height: 260px overflow: hidden From cf1cf085d93cc5e0ce448038f28a036795edcf15 Mon Sep 17 00:00:00 2001 From: summerscope Date: Tue, 29 Jul 2014 17:08:31 +1000 Subject: [PATCH 07/40] Popover for shopping cart styling required for medium and small views --- app/assets/stylesheets/darkswarm/shopping-cart.css.sass | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/assets/stylesheets/darkswarm/shopping-cart.css.sass b/app/assets/stylesheets/darkswarm/shopping-cart.css.sass index 745dceb70f..3a63bb7a2e 100644 --- a/app/assets/stylesheets/darkswarm/shopping-cart.css.sass +++ b/app/assets/stylesheets/darkswarm/shopping-cart.css.sass @@ -13,13 +13,20 @@ right: 10px top: 55px width: 400px + @media screen and (max-width: 640px) + width: 96% .joyride-nub right: 22px !important left: auto + ul, li + list-style: none + margin-left: 0 + li float: none + .row .columns padding-left: 0.25rem padding-right: 0.25rem From 1ac5b79aeb0832e577534725c3826336c24f0ca0 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 30 Jul 2014 14:33:36 +1000 Subject: [PATCH 08/40] Fix failing JS specs --- .../javascripts/darkswarm/services/products.js.coffee | 2 +- config/ng-test.conf.js | 1 - spec/javascripts/application_spec.js | 1 + .../controllers/products_controller_spec.js.coffee | 3 ++- .../darkswarm/filters/filter_groups_spec.js.coffee | 4 ++-- .../unit/darkswarm/filters/strip_url_spec.js.coffee | 11 ++++------- .../unit/darkswarm/services/product_spec.js.coffee | 7 ++++++- 7 files changed, 16 insertions(+), 13 deletions(-) diff --git a/app/assets/javascripts/darkswarm/services/products.js.coffee b/app/assets/javascripts/darkswarm/services/products.js.coffee index cc4ffbf259..aec7b1cc3e 100644 --- a/app/assets/javascripts/darkswarm/services/products.js.coffee +++ b/app/assets/javascripts/darkswarm/services/products.js.coffee @@ -44,5 +44,5 @@ Darkswarm.factory 'Products', ($resource, Enterprises, Dereferencer, Taxons, Car product.price = Math.min.apply(null, prices) product.hasVariants = product.variants?.length > 0 - product.primaryImage = product.images[0]?.small_url + product.primaryImage = product.images[0]?.small_url if product.images product.primaryImageOrMissing = product.primaryImage || "/assets/noimage/small.png" diff --git a/config/ng-test.conf.js b/config/ng-test.conf.js index 33f95483cf..eadaf984ae 100644 --- a/config/ng-test.conf.js +++ b/config/ng-test.conf.js @@ -8,7 +8,6 @@ module.exports = function(config) { APPLICATION_SPEC, 'app/assets/javascripts/shared/jquery-1.8.0.js', // TODO: Can we link to Rails' jquery? 'app/assets/javascripts/shared/jquery.timeago.js', - 'app/assets/javascripts/shared/mm-foundation-tpls-0.2.0-SNAPSHOT.js', 'app/assets/javascripts/shared/angular-local-storage.js', 'app/assets/javascripts/shared/bindonce.min.js', 'app/assets/javascripts/shared/ng-infinite-scroll.min.js', diff --git a/spec/javascripts/application_spec.js b/spec/javascripts/application_spec.js index 44654e7b32..d9239c79ad 100644 --- a/spec/javascripts/application_spec.js +++ b/spec/javascripts/application_spec.js @@ -8,6 +8,7 @@ //= require angular-backstretch.js //= require lodash.underscore.js //= require angular-flash.min.js +//= require shared/mm-foundation-tpls-0.2.2.min.js //= require moment angular.module('templates', []) diff --git a/spec/javascripts/unit/darkswarm/controllers/products_controller_spec.js.coffee b/spec/javascripts/unit/darkswarm/controllers/products_controller_spec.js.coffee index 1d56a79d27..73ecd611ef 100644 --- a/spec/javascripts/unit/darkswarm/controllers/products_controller_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/controllers/products_controller_spec.js.coffee @@ -3,6 +3,7 @@ describe 'ProductsCtrl', -> scope = null event = null Products = null + Cart = {} beforeEach -> module('Darkswarm') @@ -15,7 +16,7 @@ describe 'ProductsCtrl', -> inject ($controller) -> scope = {} - ctrl = $controller 'ProductsCtrl', {$scope: scope, Products: Products, OrderCycle: OrderCycle} + ctrl = $controller 'ProductsCtrl', {$scope: scope, Products: Products, OrderCycle: OrderCycle, Cart: Cart} it 'fetches products from Products', -> expect(scope.Products.products).toEqual ['testy mctest'] diff --git a/spec/javascripts/unit/darkswarm/filters/filter_groups_spec.js.coffee b/spec/javascripts/unit/darkswarm/filters/filter_groups_spec.js.coffee index e7e2614f7f..0e85fe27d3 100644 --- a/spec/javascripts/unit/darkswarm/filters/filter_groups_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/filters/filter_groups_spec.js.coffee @@ -2,7 +2,7 @@ describe "filtering Groups", -> filterGroups = null groups = [{ name: "test" - long_description: "roger" + description: "roger" enterprises: [{ name: "kittens" }, { @@ -10,7 +10,7 @@ describe "filtering Groups", -> }] }, { name: "blankness" - long_description: "in the sky" + description: "in the sky" enterprises: [{ name: "ponies" }, { diff --git a/spec/javascripts/unit/darkswarm/filters/strip_url_spec.js.coffee b/spec/javascripts/unit/darkswarm/filters/strip_url_spec.js.coffee index f34df5cc71..ae0d6a7c8a 100644 --- a/spec/javascripts/unit/darkswarm/filters/strip_url_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/filters/strip_url_spec.js.coffee @@ -6,11 +6,8 @@ describe 'filtering urls', -> inject ($filter) -> filter = $filter('stripUrl') - it "removes http and www", -> - expect(filter("http://www.footle.com")).toEqual "footle.com" + it "removes http", -> + expect(filter("http://footle.com")).toEqual "footle.com" - it "removes https and www", -> - expect(filter("https://www.footle.com")).toEqual "footle.com" - - it "removes just www", -> - expect(filter("www.footle.com")).toEqual "footle.com" + it "removes https", -> + expect(filter("https://www.footle.com")).toEqual "www.footle.com" diff --git a/spec/javascripts/unit/darkswarm/services/product_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/product_spec.js.coffee index af384adcb6..237cbcd369 100644 --- a/spec/javascripts/unit/darkswarm/services/product_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/product_spec.js.coffee @@ -55,6 +55,12 @@ describe 'Products service', -> $httpBackend.flush() expect(Cart.line_items[0].variant).toBe Products.products[0].variants[0] + it "sets primaryImageOrMissing when no images are provided", -> + $httpBackend.expectGET("/shop/products").respond([product]) + $httpBackend.flush() + expect(Products.products[0].primaryImage).toBeUndefined() + expect(Products.products[0].primaryImageOrMissing).toEqual "/assets/noimage/small.png" + describe "determining the price to display for a product", -> it "displays the product price when the product does not have variants", -> $httpBackend.expectGET("/shop/products").respond([product]) @@ -66,4 +72,3 @@ describe 'Products service', -> $httpBackend.expectGET("/shop/products").respond([product]) $httpBackend.flush() expect(Products.products[0].price).toEqual 22 - From 77b279ca976491e1e04368f208802a83b002618f Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 30 Jul 2014 14:34:05 +1000 Subject: [PATCH 09/40] Stub base_price and fees on variant serializer. Calculate basePricePercentage on variant. --- .../darkswarm/services/variants.js.coffee | 1 + app/serializers/api/variant_serializer.rb | 13 ++++++++++++- .../unit/darkswarm/services/variants_spec.js.coffee | 4 ++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/darkswarm/services/variants.js.coffee b/app/assets/javascripts/darkswarm/services/variants.js.coffee index d313458b75..e95a870aa8 100644 --- a/app/assets/javascripts/darkswarm/services/variants.js.coffee +++ b/app/assets/javascripts/darkswarm/services/variants.js.coffee @@ -7,4 +7,5 @@ Darkswarm.factory 'Variants', -> extend: (variant)-> variant.getPrice = -> variant.price * variant.line_item.quantity + variant.basePricePercentage = variant.base_price / variant.price * 100 variant diff --git a/app/serializers/api/variant_serializer.rb b/app/serializers/api/variant_serializer.rb index c5dbe05634..e9234285bb 100644 --- a/app/serializers/api/variant_serializer.rb +++ b/app/serializers/api/variant_serializer.rb @@ -1,8 +1,19 @@ class Api::VariantSerializer < ActiveModel::Serializer attributes :id, :is_master, :count_on_hand, :name_to_display, :unit_to_display, - :on_demand, :price + :on_demand, :price, :fees def price object.price_with_fees(options[:current_distributor], options[:current_order_cycle]) end + + def base_price + 1.00 + end + + def fees + {admin: 1.23, sales: 4.56, packing: 7.89, transport: 0.12} + end end + + +# price_without_fees / price diff --git a/spec/javascripts/unit/darkswarm/services/variants_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/variants_spec.js.coffee index 278e0a6850..98dd57b5a7 100644 --- a/spec/javascripts/unit/darkswarm/services/variants_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/variants_spec.js.coffee @@ -5,6 +5,8 @@ describe 'Variants service', -> beforeEach -> variant = id: 1 + base_price: 80 + price: 100 module 'Darkswarm' inject ($injector)-> Variants = $injector.get("Variants") @@ -19,3 +21,5 @@ describe 'Variants service', -> it "will return the same object as passed", -> expect(Variants.register(variant)).toBe variant + it "initialises base price percentage", -> + expect(Variants.register(variant).basePricePercentage).toEqual 80 From fc95e088dfe90e7c897f1e7838cfbd42b99ed6ab Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 30 Jul 2014 14:59:16 +1000 Subject: [PATCH 10/40] Show collapsed price breakdown --- .../darkswarm/directives/price_percentage.js.coffee | 10 ++++++++++ .../javascripts/darkswarm/services/variants.js.coffee | 2 +- .../javascripts/templates/price_breakdown.html.haml | 2 +- .../javascripts/templates/price_percentage.html.haml | 4 ++++ app/serializers/api/variant_serializer.rb | 2 +- .../unit/darkswarm/services/variants_spec.js.coffee | 4 ++-- 6 files changed, 19 insertions(+), 5 deletions(-) create mode 100644 app/assets/javascripts/darkswarm/directives/price_percentage.js.coffee create mode 100644 app/assets/javascripts/templates/price_percentage.html.haml diff --git a/app/assets/javascripts/darkswarm/directives/price_percentage.js.coffee b/app/assets/javascripts/darkswarm/directives/price_percentage.js.coffee new file mode 100644 index 0000000000..35140598c4 --- /dev/null +++ b/app/assets/javascripts/darkswarm/directives/price_percentage.js.coffee @@ -0,0 +1,10 @@ +Darkswarm.directive "pricePercentage", -> + restrict: 'E' + replace: true + templateUrl: 'price_percentage.html' + scope: + percentage: '=' + + link: (scope, elem, attrs) -> + elem.find(".meter").css + width: "#{scope.percentage}%" diff --git a/app/assets/javascripts/darkswarm/services/variants.js.coffee b/app/assets/javascripts/darkswarm/services/variants.js.coffee index e95a870aa8..0f231ac030 100644 --- a/app/assets/javascripts/darkswarm/services/variants.js.coffee +++ b/app/assets/javascripts/darkswarm/services/variants.js.coffee @@ -7,5 +7,5 @@ Darkswarm.factory 'Variants', -> extend: (variant)-> variant.getPrice = -> variant.price * variant.line_item.quantity - variant.basePricePercentage = variant.base_price / variant.price * 100 + variant.basePricePercentage = Math.round(variant.base_price / variant.price * 100) variant diff --git a/app/assets/javascripts/templates/price_breakdown.html.haml b/app/assets/javascripts/templates/price_breakdown.html.haml index 5e7c82e0cf..33554b93fe 100644 --- a/app/assets/javascripts/templates/price_breakdown.html.haml +++ b/app/assets/javascripts/templates/price_breakdown.html.haml @@ -1,4 +1,4 @@ .joyride-tip-guide{"ng-class" => "{ in: tt_isOpen, fade: tt_animation }"} %span.joyride-nub.bottom .joyride-content-wrapper - {{ variant.id }} + %price-percentage{percentage: 'variant.basePricePercentage'} diff --git a/app/assets/javascripts/templates/price_percentage.html.haml b/app/assets/javascripts/templates/price_percentage.html.haml new file mode 100644 index 0000000000..ee1e8964a5 --- /dev/null +++ b/app/assets/javascripts/templates/price_percentage.html.haml @@ -0,0 +1,4 @@ +.progress + .meter + Cost + Fees diff --git a/app/serializers/api/variant_serializer.rb b/app/serializers/api/variant_serializer.rb index e9234285bb..74bc19e65c 100644 --- a/app/serializers/api/variant_serializer.rb +++ b/app/serializers/api/variant_serializer.rb @@ -1,6 +1,6 @@ class Api::VariantSerializer < ActiveModel::Serializer attributes :id, :is_master, :count_on_hand, :name_to_display, :unit_to_display, - :on_demand, :price, :fees + :on_demand, :price, :fees, :base_price def price object.price_with_fees(options[:current_distributor], options[:current_order_cycle]) diff --git a/spec/javascripts/unit/darkswarm/services/variants_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/variants_spec.js.coffee index 98dd57b5a7..ac9865a142 100644 --- a/spec/javascripts/unit/darkswarm/services/variants_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/variants_spec.js.coffee @@ -5,7 +5,7 @@ describe 'Variants service', -> beforeEach -> variant = id: 1 - base_price: 80 + base_price: 80.5 price: 100 module 'Darkswarm' inject ($injector)-> @@ -22,4 +22,4 @@ describe 'Variants service', -> expect(Variants.register(variant)).toBe variant it "initialises base price percentage", -> - expect(Variants.register(variant).basePricePercentage).toEqual 80 + expect(Variants.register(variant).basePricePercentage).toEqual 81 From 9fa0413e8e18187a9d4ff56e6a59774fd2a32f75 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 30 Jul 2014 15:11:59 +1000 Subject: [PATCH 11/40] Add full price breakdown --- .../directives/price_breakdown.js.coffee | 5 +++- .../templates/price_breakdown.html.haml | 25 ++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/darkswarm/directives/price_breakdown.js.coffee b/app/assets/javascripts/darkswarm/directives/price_breakdown.js.coffee index 4875cf81ec..0d1d6ce0b5 100644 --- a/app/assets/javascripts/darkswarm/directives/price_breakdown.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/price_breakdown.js.coffee @@ -8,4 +8,7 @@ Darkswarm.directive 'priceBreakdownPopup', -> restrict: 'EA' replace: true templateUrl: 'price_breakdown.html' - scope: true + scope: false + + link: (scope, elem, attrs) -> + scope.expanded = false unless scope.expanded? diff --git a/app/assets/javascripts/templates/price_breakdown.html.haml b/app/assets/javascripts/templates/price_breakdown.html.haml index 33554b93fe..2508dc33da 100644 --- a/app/assets/javascripts/templates/price_breakdown.html.haml +++ b/app/assets/javascripts/templates/price_breakdown.html.haml @@ -1,4 +1,27 @@ .joyride-tip-guide{"ng-class" => "{ in: tt_isOpen, fade: tt_animation }"} %span.joyride-nub.bottom .joyride-content-wrapper - %price-percentage{percentage: 'variant.basePricePercentage'} + + .collapsed{"ng-show" => "!expanded"} + %price-percentage{percentage: 'variant.basePricePercentage'} + %a{"ng-click" => "expanded = !expanded"} Full price breakdown + + .expanded{"ng-show" => "expanded"} + %ul + %li + Cost + %span {{ variant.base_price | currency }} + %li + Admin fee + %span {{ variant.fees.admin | currency }} + %li + Sales fee + %span {{ variant.fees.sales | currency }} + %li + Packing fee + %span {{ variant.fees.packing | currency }} + %li + Transport fee + %span {{ variant.fees.transport | currency }} + %a{"ng-click" => "expanded = !expanded"} Price graph + \= {{ variant.price | currency }} From 44bb53b1378a45550f81fb2b9a1a8fa823387490 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Thu, 31 Jul 2014 11:11:34 +1000 Subject: [PATCH 12/40] Moving to state_name --- app/serializers/api/address_serializer.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/serializers/api/address_serializer.rb b/app/serializers/api/address_serializer.rb index 18483da312..66e4267e1f 100644 --- a/app/serializers/api/address_serializer.rb +++ b/app/serializers/api/address_serializer.rb @@ -1,10 +1,12 @@ class Api::AddressSerializer < ActiveModel::Serializer - cached - delegate :cache_key, to: :object + #cached + #delegate :cache_key, to: :object - attributes :id, :zipcode, :city, :state, :state_id + attributes :id, :zipcode, :city, :state_name, :state_id, + :phone, :firstname, :lastname, :address1, :address2, :city, :country_id, + :zipcode - def state + def state_name object.state.andand.abbr end end From 46146c83a8dcb0c72e47486eb06c4f65bcd59307 Mon Sep 17 00:00:00 2001 From: summerscope Date: Thu, 31 Jul 2014 11:29:02 +1000 Subject: [PATCH 13/40] Make the link for product modal just go around the text and not full block --- .../stylesheets/darkswarm/_shop-product-rows.css.sass | 6 ++++-- app/views/shop/products/_summary.html.haml | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/darkswarm/_shop-product-rows.css.sass b/app/assets/stylesheets/darkswarm/_shop-product-rows.css.sass index 2dbbf46a45..fbe5949e74 100644 --- a/app/assets/stylesheets/darkswarm/_shop-product-rows.css.sass +++ b/app/assets/stylesheets/darkswarm/_shop-product-rows.css.sass @@ -100,8 +100,10 @@ h3 font-size: 1.5rem margin: 0 - a h3 - color: black + h3 a + color: #222 + &:hover, &:focus, &:active + color: black diff --git a/app/views/shop/products/_summary.html.haml b/app/views/shop/products/_summary.html.haml index 77f43702cc..25c71f276a 100644 --- a/app/views/shop/products/_summary.html.haml +++ b/app/views/shop/products/_summary.html.haml @@ -4,8 +4,9 @@ .row.summary .small-9.medium-10.large-11.columns.summary-header - %a{"ng-click" => "triggerProductModal()"} - %h3 {{ product.name }} + %h3 + %a{"ng-click" => "triggerProductModal()"} + {{ product.name }} %em from %span From 659462327c71862012eaaf4ce0c356539b8c3360 Mon Sep 17 00:00:00 2001 From: summerscope Date: Thu, 31 Jul 2014 11:29:14 +1000 Subject: [PATCH 14/40] Commenting out taxon icon for now --- app/assets/javascripts/templates/product_modal.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/templates/product_modal.html.haml b/app/assets/javascripts/templates/product_modal.html.haml index 8b35cf79c5..31f51c6655 100644 --- a/app/assets/javascripts/templates/product_modal.html.haml +++ b/app/assets/javascripts/templates/product_modal.html.haml @@ -3,7 +3,7 @@ %img.product-img{"ng-src" => "{{product.primaryImage}}", "ng-if" => "product.primaryImage"} .columns.small-12.large-6.product-header %h2 - %render-svg{path: "{{product.primary_taxon.icon}}"} + / %render-svg{path: "{{product.primary_taxon.icon}}"} {{product.name}} %p {{product.description}} %ng-include{src: "'partials/close.html'"} From e8045cac42519bfae68b6dc78ebff21908465a11 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Wed, 30 Jul 2014 17:09:31 +1000 Subject: [PATCH 15/40] Renaming to state_name --- app/serializers/api/address_serializer.rb | 2 +- app/views/home/_fat.html.haml | 17 ----------------- app/views/home/_skinny.html.haml | 2 +- app/views/json/partials/_address.rabl | 2 +- app/views/modals/_producer.html.haml | 2 +- app/views/producers/_fat.html.haml | 2 +- app/views/producers/_skinny.html.haml | 4 ++-- 7 files changed, 7 insertions(+), 24 deletions(-) diff --git a/app/serializers/api/address_serializer.rb b/app/serializers/api/address_serializer.rb index e121cfde38..18483da312 100644 --- a/app/serializers/api/address_serializer.rb +++ b/app/serializers/api/address_serializer.rb @@ -2,7 +2,7 @@ class Api::AddressSerializer < ActiveModel::Serializer cached delegate :cache_key, to: :object - attributes :id, :zipcode, :city, :state + attributes :id, :zipcode, :city, :state, :state_id def state object.state.andand.abbr diff --git a/app/views/home/_fat.html.haml b/app/views/home/_fat.html.haml index 37b4194e26..f3f74cb282 100644 --- a/app/views/home/_fat.html.haml +++ b/app/views/home/_fat.html.haml @@ -29,20 +29,3 @@ {{ enterprise.name }} %div{"bo-if" => "!hub.producers"}   - -/ .row.active_table_row.link{"ng-show" => "open()"} -/ .cta-container.columns.small-12 -/ .row -/ .columns.small-12 -/ %h5 -/ %span{"active-table-hub-link" => "hub", change: "Change hub to", shop: "Shop at"} -/ .row -/ .columns.small-12 -/ %a.button.hub{"bo-href" => "hub.path", -/ "ng-class" => "{primary: hub.active, secondary: !hub.active}", -/ "ofn-empties-cart" => "hub"} -/ %i.ofn-i_033-open-sign{"bo-if" => "hub.active"} -/ %i.ofn-i_032-closed-sign{"bo-if" => "!hub.active"} -/ {{hub.name}} -/ .button-address {{ [hub.address.city, hub.address.state] | printArray }} -/ %i.ofn-i_007-caret-right diff --git a/app/views/home/_skinny.html.haml b/app/views/home/_skinny.html.haml index dad391a287..2b59132999 100644 --- a/app/views/home/_skinny.html.haml +++ b/app/views/home/_skinny.html.haml @@ -7,7 +7,7 @@ .columns.small-4.medium-2.large-2 {{ hub.address.city }} .columns.small-2.medium-1.large-1 - {{ hub.address.state | uppercase }} + {{ hub.address.state_name | uppercase }} .columns.small-6.medium-3.large-4.text-right{"bo-if" => "hub.active"} %a.hub{"bo-href" => "hub.path", "ng-class" => "{primary: hub.active, secondary: !hub.active}", "ofn-empties-cart" => "hub"} diff --git a/app/views/json/partials/_address.rabl b/app/views/json/partials/_address.rabl index 04cc456a29..8f77f83d99 100644 --- a/app/views/json/partials/_address.rabl +++ b/app/views/json/partials/_address.rabl @@ -1,4 +1,4 @@ attributes :city, :zipcode, :phone -node :state do |address| +node :state_name do |address| address.state.abbr end diff --git a/app/views/modals/_producer.html.haml b/app/views/modals/_producer.html.haml index 8fd778b388..5d2d342f6d 100644 --- a/app/views/modals/_producer.html.haml +++ b/app/views/modals/_producer.html.haml @@ -2,7 +2,7 @@ .highlight .highlight-top %p.right - {{ [enterprise.address.city, enterprise.address.state] | printArray}} + {{ [enterprise.address.city, enterprise.address.state_name] | printArray}} %h3 %i.ofn-i_036-producers {{ enterprise.name }} diff --git a/app/views/producers/_fat.html.haml b/app/views/producers/_fat.html.haml index 10cd2f00b5..042e39dba9 100644 --- a/app/views/producers/_fat.html.haml +++ b/app/views/producers/_fat.html.haml @@ -34,5 +34,5 @@ %i.ofn-i_033-open-sign{"bo-if" => "hub.active"} %i.ofn-i_032-closed-sign{"bo-if" => "!hub.active"} {{hub.name}} - .button-address {{ [hub.address.city, hub.address.state] | printArray }} + .button-address {{ [hub.address.city, hub.address.state_name] | printArray }} %i.ofn-i_007-caret-right diff --git a/app/views/producers/_skinny.html.haml b/app/views/producers/_skinny.html.haml index 824d8f2630..e1f26f0304 100644 --- a/app/views/producers/_skinny.html.haml +++ b/app/views/producers/_skinny.html.haml @@ -5,8 +5,8 @@ .columns.small-6.medium-3.large-3 {{ producer.address.city }} .columns.small-4.medium-3.large-4 - {{ producer.address.state | uppercase }} + {{ producer.address.state_name | uppercase }} .columns.small-2.medium-2.large-1.text-right / This forces line-height to be triggered %span   - %i{"ng-class" => "{'ofn-i_005-caret-down' : !open(), 'ofn-i_006-caret-up' : open()}"} \ No newline at end of file + %i{"ng-class" => "{'ofn-i_005-caret-down' : !open(), 'ofn-i_006-caret-up' : open()}"} From 66cece5903d0ca92dd77e9e0e7f8e39a9a3dbacb Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 30 Jul 2014 17:46:21 +1000 Subject: [PATCH 16/40] WIP: Extract order cycle fee calculations to EnterpriseFeeCalculator --- app/models/order_cycle.rb | 78 +--------- .../enterprise_fee_calculator.rb | 75 ++++++++++ .../enterprise_fee_applicator_spec.rb | 1 - .../enterprise_fee_calculator_spec.rb | 138 ++++++++++++++++++ spec/models/order_cycle_spec.rb | 101 ------------- 5 files changed, 217 insertions(+), 176 deletions(-) create mode 100644 lib/open_food_network/enterprise_fee_calculator.rb create mode 100644 spec/lib/open_food_network/enterprise_fee_calculator_spec.rb diff --git a/app/models/order_cycle.rb b/app/models/order_cycle.rb index f2ad8fee3e..d5a1371876 100644 --- a/app/models/order_cycle.rb +++ b/app/models/order_cycle.rb @@ -1,5 +1,3 @@ -require 'open_food_network/enterprise_fee_applicator' - class OrderCycle < ActiveRecord::Base belongs_to :coordinator, :class_name => 'Enterprise' has_and_belongs_to_many :coordinator_fees, :class_name => 'EnterpriseFee', :join_table => 'coordinator_fees' @@ -165,77 +163,17 @@ class OrderCycle < ActiveRecord::Base exchange_for_distributor(distributor).andand.pickup_instructions end - - # -- Fees - - # TODO: The boundary of this class is ill-defined here. OrderCycle should not know about - # EnterpriseFeeApplicator. Clients should be able to query it for relevant EnterpriseFees. - # This logic would fit better in another service object. - - def fees_for(variant, distributor) - per_item_enterprise_fee_applicators_for(variant, distributor).sum do |applicator| - # Spree's Calculator interface accepts Orders or LineItems, - # so we meet that interface with a struct. - # Amount is faked, this is a method on LineItem - line_item = OpenStruct.new variant: variant, quantity: 1, amount: variant.price - applicator.enterprise_fee.compute_amount(line_item) - end + def exchanges_carrying(variant, distributor) + exchanges.supplying_to(distributor).with_variant(variant) end - def create_line_item_adjustments_for(line_item) - variant = line_item.variant - distributor = line_item.order.distributor - - per_item_enterprise_fee_applicators_for(variant, distributor).each do |applicator| - applicator.create_line_item_adjustment(line_item) - end - end - - def create_order_adjustments_for(order) - per_order_enterprise_fee_applicators_for(order).each do |applicator| - applicator.create_order_adjustment(order) - end + def exchanges_supplying(order) + exchanges.supplying_to(order.distributor).with_any_variant(order.variants) end private - # -- Fees - def per_item_enterprise_fee_applicators_for(variant, distributor) - fees = [] - - exchanges_carrying(variant, distributor).each do |exchange| - exchange.enterprise_fees.per_item.each do |enterprise_fee| - fees << OpenFoodNetwork::EnterpriseFeeApplicator.new(enterprise_fee, variant, exchange.role) - end - end - - coordinator_fees.per_item.each do |enterprise_fee| - fees << OpenFoodNetwork::EnterpriseFeeApplicator.new(enterprise_fee, variant, 'coordinator') - end - - fees - end - - def per_order_enterprise_fee_applicators_for(order) - fees = [] - - exchanges_supplying(order).each do |exchange| - exchange.enterprise_fees.per_order.each do |enterprise_fee| - fees << OpenFoodNetwork::EnterpriseFeeApplicator.new(enterprise_fee, nil, exchange.role) - end - end - - coordinator_fees.per_order.each do |enterprise_fee| - fees << OpenFoodNetwork::EnterpriseFeeApplicator.new(enterprise_fee, nil, 'coordinator') - end - - fees - end - - - # -- Misc - # If a product without variants is added to an order cycle, and then some variants are added # to that product, then the master variant is still part of the order cycle, but customers # should not be able to purchase it. @@ -246,12 +184,4 @@ class OrderCycle < ActiveRecord::Base distributed_variants.include?(product.master) && (product.variants & distributed_variants).empty? end - - def exchanges_carrying(variant, distributor) - exchanges.supplying_to(distributor).with_variant(variant) - end - - def exchanges_supplying(order) - exchanges.supplying_to(order.distributor).with_any_variant(order.variants) - end end diff --git a/lib/open_food_network/enterprise_fee_calculator.rb b/lib/open_food_network/enterprise_fee_calculator.rb new file mode 100644 index 0000000000..bbd220cfad --- /dev/null +++ b/lib/open_food_network/enterprise_fee_calculator.rb @@ -0,0 +1,75 @@ +require 'open_food_network/enterprise_fee_applicator' + +module OpenFoodNetwork + class EnterpriseFeeCalculator + def initialize(distributor=nil, order_cycle=nil) + @distributor = distributor + @order_cycle = order_cycle + end + + + def fees_for(variant) + per_item_enterprise_fee_applicators_for(variant).sum do |applicator| + # Spree's Calculator interface accepts Orders or LineItems, + # so we meet that interface with a struct. + # Amount is faked, this is a method on LineItem + line_item = OpenStruct.new variant: variant, quantity: 1, amount: variant.price + applicator.enterprise_fee.compute_amount(line_item) + end + end + + def create_line_item_adjustments_for(line_item) + variant = line_item.variant + @distributor = line_item.order.distributor + @order_cycle = line_item.order.order_cycle + + per_item_enterprise_fee_applicators_for(variant).each do |applicator| + applicator.create_line_item_adjustment(line_item) + end + end + + def create_order_adjustments_for(order) + @distributor = order.distributor + @order_cycle = order.order_cycle + + per_order_enterprise_fee_applicators_for(order).each do |applicator| + applicator.create_order_adjustment(order) + end + end + + + private + + def per_item_enterprise_fee_applicators_for(variant) + fees = [] + + @order_cycle.exchanges_carrying(variant, @distributor).each do |exchange| + exchange.enterprise_fees.per_item.each do |enterprise_fee| + fees << OpenFoodNetwork::EnterpriseFeeApplicator.new(enterprise_fee, variant, exchange.role) + end + end + + @order_cycle.coordinator_fees.per_item.each do |enterprise_fee| + fees << OpenFoodNetwork::EnterpriseFeeApplicator.new(enterprise_fee, variant, 'coordinator') + end + + fees + end + + def per_order_enterprise_fee_applicators_for(order) + fees = [] + + @order_cycle.exchanges_supplying(order).each do |exchange| + exchange.enterprise_fees.per_order.each do |enterprise_fee| + fees << OpenFoodNetwork::EnterpriseFeeApplicator.new(enterprise_fee, nil, exchange.role) + end + end + + @order_cycle.coordinator_fees.per_order.each do |enterprise_fee| + fees << OpenFoodNetwork::EnterpriseFeeApplicator.new(enterprise_fee, nil, 'coordinator') + end + + fees + end + end +end diff --git a/spec/lib/open_food_network/enterprise_fee_applicator_spec.rb b/spec/lib/open_food_network/enterprise_fee_applicator_spec.rb index d10a5e9b72..9ad1d222b3 100644 --- a/spec/lib/open_food_network/enterprise_fee_applicator_spec.rb +++ b/spec/lib/open_food_network/enterprise_fee_applicator_spec.rb @@ -27,7 +27,6 @@ module OpenFoodNetwork it "creates an adjustment for an order" do order = create(:order) - #line_item = create(:line_item) enterprise_fee = create(:enterprise_fee) product = create(:simple_product) diff --git a/spec/lib/open_food_network/enterprise_fee_calculator_spec.rb b/spec/lib/open_food_network/enterprise_fee_calculator_spec.rb new file mode 100644 index 0000000000..697bb3c702 --- /dev/null +++ b/spec/lib/open_food_network/enterprise_fee_calculator_spec.rb @@ -0,0 +1,138 @@ +require 'open_food_network/enterprise_fee_calculator' + +module OpenFoodNetwork + describe EnterpriseFeeCalculator do + describe "integration" do + let(:coordinator) { create(:distributor_enterprise) } + let(:distributor) { create(:distributor_enterprise) } + let(:order_cycle) { create(:simple_order_cycle) } + let(:product) { create(:simple_product, price: 10.00) } + + describe "calculating fees for a variant via a particular distribution" do + it "sums all the per-item fees for the variant in the specified hub + order cycle" do + enterprise_fee1 = create(:enterprise_fee, amount: 20) + enterprise_fee2 = create(:enterprise_fee, amount: 3) + enterprise_fee3 = create(:enterprise_fee, + calculator: Spree::Calculator::FlatRate.new(preferred_amount: 2)) + + create(:exchange, order_cycle: order_cycle, sender: coordinator, receiver: distributor, incoming: false, + enterprise_fees: [enterprise_fee1, enterprise_fee2, enterprise_fee3], variants: [product.master]) + + EnterpriseFeeCalculator.new(distributor, order_cycle).fees_for(product.master).should == 23 + end + + it "sums percentage fees for the variant" do + enterprise_fee1 = create(:enterprise_fee, amount: 20, fee_type: "admin", calculator: Spree::Calculator::FlatPercentItemTotal.new(preferred_flat_percent: 20)) + + create(:exchange, order_cycle: order_cycle, sender: coordinator, receiver: distributor, incoming: false, + enterprise_fees: [enterprise_fee1], variants: [product.master]) + + product.master.price.should == 10.00 + EnterpriseFeeCalculator.new(distributor, order_cycle).fees_for(product.master).should == 2.00 + end + end + + describe "creating adjustments" do + let(:order) { create(:order, distributor: distributor, order_cycle: order_cycle) } + let!(:line_item) { create(:line_item, order: order, variant: product.master) } + let(:enterprise_fee_line_item) { create(:enterprise_fee) } + let(:enterprise_fee_order) { create(:enterprise_fee, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 2)) } + let!(:exchange) { create(:exchange, order_cycle: order_cycle, sender: coordinator, receiver: distributor, incoming: false, variants: [product.master]) } + + before { order.reload } + + it "creates adjustments for a line item" do + exchange.enterprise_fees << enterprise_fee_line_item + + EnterpriseFeeCalculator.new.create_line_item_adjustments_for line_item + + a = Spree::Adjustment.last + a.metadata.fee_name.should == enterprise_fee_line_item.name + end + + it "creates adjustments for an order" do + exchange.enterprise_fees << enterprise_fee_order + + EnterpriseFeeCalculator.new.create_order_adjustments_for order + + a = Spree::Adjustment.last + a.metadata.fee_name.should == enterprise_fee_order.name + end + end + end + + describe "creating adjustments for a line item" do + let(:oc) { OrderCycle.new } + let(:variant) { double(:variant) } + let(:distributor) { double(:distributor) } + let(:order) { double(:order, distributor: distributor, order_cycle: oc) } + let(:line_item) { double(:line_item, variant: variant, order: order) } + + it "creates an adjustment for each fee" do + applicator = double(:enterprise_fee_applicator) + applicator.should_receive(:create_line_item_adjustment).with(line_item) + + efc = EnterpriseFeeCalculator.new + efc.should_receive(:per_item_enterprise_fee_applicators_for).with(variant) { [applicator] } + + efc.create_line_item_adjustments_for line_item + end + + it "makes fee applicators for a line item" do + distributor = double(:distributor) + ef1 = double(:enterprise_fee) + ef2 = double(:enterprise_fee) + ef3 = double(:enterprise_fee) + incoming_exchange = double(:exchange, role: 'supplier') + outgoing_exchange = double(:exchange, role: 'distributor') + incoming_exchange.stub_chain(:enterprise_fees, :per_item) { [ef1] } + outgoing_exchange.stub_chain(:enterprise_fees, :per_item) { [ef2] } + + oc.stub(:exchanges_carrying) { [incoming_exchange, outgoing_exchange] } + oc.stub_chain(:coordinator_fees, :per_item) { [ef3] } + + efc = EnterpriseFeeCalculator.new(distributor, oc) + efc.send(:per_item_enterprise_fee_applicators_for, line_item.variant).should == + [OpenFoodNetwork::EnterpriseFeeApplicator.new(ef1, line_item.variant, 'supplier'), + OpenFoodNetwork::EnterpriseFeeApplicator.new(ef2, line_item.variant, 'distributor'), + OpenFoodNetwork::EnterpriseFeeApplicator.new(ef3, line_item.variant, 'coordinator')] + end + end + + describe "creating adjustments for an order" do + let(:oc) { OrderCycle.new } + let(:distributor) { double(:distributor) } + let(:order) { double(:order, distributor: distributor, order_cycle: oc) } + + it "creates an adjustment for each fee" do + applicator = double(:enterprise_fee_applicator) + applicator.should_receive(:create_order_adjustment).with(order) + + efc = EnterpriseFeeCalculator.new + efc.should_receive(:per_order_enterprise_fee_applicators_for).with(order) { [applicator] } + + efc.create_order_adjustments_for order + end + + it "makes fee applicators for an order" do + distributor = double(:distributor) + ef1 = double(:enterprise_fee) + ef2 = double(:enterprise_fee) + ef3 = double(:enterprise_fee) + incoming_exchange = double(:exchange, role: 'supplier') + outgoing_exchange = double(:exchange, role: 'distributor') + incoming_exchange.stub_chain(:enterprise_fees, :per_order) { [ef1] } + outgoing_exchange.stub_chain(:enterprise_fees, :per_order) { [ef2] } + + oc.stub(:exchanges_supplying) { [incoming_exchange, outgoing_exchange] } + oc.stub_chain(:coordinator_fees, :per_order) { [ef3] } + + efc = EnterpriseFeeCalculator.new(distributor, oc) + efc.send(:per_order_enterprise_fee_applicators_for, order).should == + [OpenFoodNetwork::EnterpriseFeeApplicator.new(ef1, nil, 'supplier'), + OpenFoodNetwork::EnterpriseFeeApplicator.new(ef2, nil, 'distributor'), + OpenFoodNetwork::EnterpriseFeeApplicator.new(ef3, nil, 'coordinator')] + end + end + end +end diff --git a/spec/models/order_cycle_spec.rb b/spec/models/order_cycle_spec.rb index e4f979dc5b..9785d5ed2d 100644 --- a/spec/models/order_cycle_spec.rb +++ b/spec/models/order_cycle_spec.rb @@ -368,107 +368,6 @@ describe OrderCycle do end end - describe "calculating fees for a variant via a particular distributor" do - it "sums all the per-item fees for the variant in the specified hub + order cycle" do - coordinator = create(:distributor_enterprise) - distributor = create(:distributor_enterprise) - order_cycle = create(:simple_order_cycle) - enterprise_fee1 = create(:enterprise_fee, amount: 20) - enterprise_fee2 = create(:enterprise_fee, amount: 3) - enterprise_fee3 = create(:enterprise_fee, - calculator: Spree::Calculator::FlatRate.new(preferred_amount: 2)) - product = create(:simple_product) - - create(:exchange, order_cycle: order_cycle, sender: coordinator, receiver: distributor, incoming: false, - enterprise_fees: [enterprise_fee1, enterprise_fee2, enterprise_fee3], variants: [product.master]) - - order_cycle.fees_for(product.master, distributor).should == 23 - end - - - it "sums percentage fees for the variant" do - coordinator = create(:distributor_enterprise) - distributor = create(:distributor_enterprise) - order_cycle = create(:simple_order_cycle) - enterprise_fee1 = create(:enterprise_fee, amount: 20, fee_type: "admin", calculator: Spree::Calculator::FlatPercentItemTotal.new(preferred_flat_percent: 20)) - product = create(:simple_product, price: 10.00) - - create(:exchange, order_cycle: order_cycle, sender: coordinator, receiver: distributor, incoming: false, - enterprise_fees: [enterprise_fee1], variants: [product.master]) - - product.master.price.should == 10.00 - order_cycle.fees_for(product.master, distributor).should == 2.00 - end - end - - describe "creating adjustments for a line item" do - let(:oc) { OrderCycle.new } - let(:variant) { double(:variant) } - let(:distributor) { double(:distributor) } - let(:order) { double(:order, distributor: distributor) } - let(:line_item) { double(:line_item, variant: variant, order: order) } - - it "creates an adjustment for each fee" do - applicator = double(:enterprise_fee_applicator) - applicator.should_receive(:create_line_item_adjustment).with(line_item) - oc.should_receive(:per_item_enterprise_fee_applicators_for).with(variant, distributor) { [applicator] } - - oc.send(:create_line_item_adjustments_for, line_item) - end - - it "makes fee applicators for a line item" do - distributor = double(:distributor) - ef1 = double(:enterprise_fee) - ef2 = double(:enterprise_fee) - ef3 = double(:enterprise_fee) - incoming_exchange = double(:exchange, role: 'supplier') - outgoing_exchange = double(:exchange, role: 'distributor') - incoming_exchange.stub_chain(:enterprise_fees, :per_item) { [ef1] } - outgoing_exchange.stub_chain(:enterprise_fees, :per_item) { [ef2] } - - oc.stub(:exchanges_carrying) { [incoming_exchange, outgoing_exchange] } - oc.stub_chain(:coordinator_fees, :per_item) { [ef3] } - - oc.send(:per_item_enterprise_fee_applicators_for, line_item.variant, distributor).should == - [OpenFoodNetwork::EnterpriseFeeApplicator.new(ef1, line_item.variant, 'supplier'), - OpenFoodNetwork::EnterpriseFeeApplicator.new(ef2, line_item.variant, 'distributor'), - OpenFoodNetwork::EnterpriseFeeApplicator.new(ef3, line_item.variant, 'coordinator')] - end - end - - describe "creating adjustments for an order" do - let(:oc) { OrderCycle.new } - let(:distributor) { double(:distributor) } - let(:order) { double(:order, distributor: distributor) } - - it "creates an adjustment for each fee" do - applicator = double(:enterprise_fee_applicator) - applicator.should_receive(:create_order_adjustment).with(order) - oc.should_receive(:per_order_enterprise_fee_applicators_for).with(order) { [applicator] } - - oc.send(:create_order_adjustments_for, order) - end - - it "makes fee applicators for an order" do - distributor = double(:distributor) - ef1 = double(:enterprise_fee) - ef2 = double(:enterprise_fee) - ef3 = double(:enterprise_fee) - incoming_exchange = double(:exchange, role: 'supplier') - outgoing_exchange = double(:exchange, role: 'distributor') - incoming_exchange.stub_chain(:enterprise_fees, :per_order) { [ef1] } - outgoing_exchange.stub_chain(:enterprise_fees, :per_order) { [ef2] } - - oc.stub(:exchanges_supplying) { [incoming_exchange, outgoing_exchange] } - oc.stub_chain(:coordinator_fees, :per_order) { [ef3] } - - oc.send(:per_order_enterprise_fee_applicators_for, order).should == - [OpenFoodNetwork::EnterpriseFeeApplicator.new(ef1, nil, 'supplier'), - OpenFoodNetwork::EnterpriseFeeApplicator.new(ef2, nil, 'distributor'), - OpenFoodNetwork::EnterpriseFeeApplicator.new(ef3, nil, 'coordinator')] - end - end - describe "finding recently closed order cycles" do it "should give the most recently closed order cycle for a distributor" do distributor = create(:distributor_enterprise) From b40b6f9faf916959d5784a438a8aa85442d348f0 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 31 Jul 2014 09:19:57 +1000 Subject: [PATCH 17/40] WIP: Call fees_for on EnterpriseFeeCalculator --- app/models/spree/variant_decorator.rb | 3 ++- spec/models/spree/variant_spec.rb | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/models/spree/variant_decorator.rb b/app/models/spree/variant_decorator.rb index 63ae5e0f3a..1ad2dd75d0 100644 --- a/app/models/spree/variant_decorator.rb +++ b/app/models/spree/variant_decorator.rb @@ -1,3 +1,4 @@ +require 'open_food_network/enterprise_fee_calculator' require 'open_food_network/option_value_namer' Spree::Variant.class_eval do @@ -44,7 +45,7 @@ Spree::Variant.class_eval do end def fees_for(distributor, order_cycle) - order_cycle.fees_for(self, distributor) + OpenFoodNetwork::EnterpriseFeeCalculator.new(distributor, order_cycle).fees_for self end diff --git a/spec/models/spree/variant_spec.rb b/spec/models/spree/variant_spec.rb index 5ddff963df..d1d833664a 100644 --- a/spec/models/spree/variant_spec.rb +++ b/spec/models/spree/variant_spec.rb @@ -82,12 +82,13 @@ module Spree describe "calculating the fees" do - it "delegates to order cycle" do + it "delegates to EnterpriseFeeCalculator" do distributor = double(:distributor) order_cycle = double(:order_cycle) variant = Variant.new - order_cycle.should_receive(:fees_for).with(variant, distributor) { 23 } + OpenFoodNetwork::EnterpriseFeeCalculator.any_instance.should_receive(:fees_for).with(variant) { 23 } + variant.fees_for(distributor, order_cycle).should == 23 end end From 8fe355b6da110d4b7c81b09ab70595b8e7d9c4bb Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 31 Jul 2014 09:27:36 +1000 Subject: [PATCH 18/40] WIP: Call create_line_item_adjustments_for on EnterpriseFeeCalculator --- app/models/spree/order_decorator.rb | 5 +++-- spec/models/spree/order_spec.rb | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/models/spree/order_decorator.rb b/app/models/spree/order_decorator.rb index 4f2be99fa8..7cd5967f6e 100644 --- a/app/models/spree/order_decorator.rb +++ b/app/models/spree/order_decorator.rb @@ -1,5 +1,6 @@ -require 'open_food_network/feature_toggle' +require 'open_food_network/enterprise_fee_calculator' require 'open_food_network/distribution_change_validator' +require 'open_food_network/feature_toggle' ActiveSupport::Notifications.subscribe('spree.order.contents_changed') do |name, start, finish, id, payload| payload[:order].reload.update_distribution_charge! @@ -133,7 +134,7 @@ Spree::Order.class_eval do line_items.each do |line_item| if provided_by_order_cycle? line_item - order_cycle.create_line_item_adjustments_for line_item + OpenFoodNetwork::EnterpriseFeeCalculator.new.create_line_item_adjustments_for line_item else pd = product_distribution_for line_item diff --git a/spec/models/spree/order_spec.rb b/spec/models/spree/order_spec.rb index 898a08d075..e477e68e0e 100644 --- a/spec/models/spree/order_spec.rb +++ b/spec/models/spree/order_spec.rb @@ -82,7 +82,9 @@ describe Spree::Order do subject.stub(:provided_by_order_cycle?) { true } order_cycle = double(:order_cycle) - order_cycle.should_receive(:create_line_item_adjustments_for).with(line_item) + OpenFoodNetwork::EnterpriseFeeCalculator.any_instance. + should_receive(:create_line_item_adjustments_for). + with(line_item) order_cycle.stub(:create_order_adjustments_for) subject.stub(:order_cycle) { order_cycle } From 45fd479ade3da5eaaa82074a2660ae3a4046072a Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 31 Jul 2014 09:35:21 +1000 Subject: [PATCH 19/40] WIP: Call create_order_adjustments_for on EnterpriseFeeCalculator --- app/models/spree/order_decorator.rb | 4 +++- spec/models/spree/order_spec.rb | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/models/spree/order_decorator.rb b/app/models/spree/order_decorator.rb index 7cd5967f6e..fcc6054f3b 100644 --- a/app/models/spree/order_decorator.rb +++ b/app/models/spree/order_decorator.rb @@ -142,7 +142,9 @@ Spree::Order.class_eval do end end - order_cycle.create_order_adjustments_for self if order_cycle + if order_cycle + OpenFoodNetwork::EnterpriseFeeCalculator.new.create_order_adjustments_for self + end end def set_variant_attributes(variant, attributes) diff --git a/spec/models/spree/order_spec.rb b/spec/models/spree/order_spec.rb index e477e68e0e..085ee615c6 100644 --- a/spec/models/spree/order_spec.rb +++ b/spec/models/spree/order_spec.rb @@ -85,7 +85,7 @@ describe Spree::Order do OpenFoodNetwork::EnterpriseFeeCalculator.any_instance. should_receive(:create_line_item_adjustments_for). with(line_item) - order_cycle.stub(:create_order_adjustments_for) + OpenFoodNetwork::EnterpriseFeeCalculator.any_instance.stub(:create_order_adjustments_for) subject.stub(:order_cycle) { order_cycle } subject.update_distribution_charge! @@ -96,7 +96,10 @@ describe Spree::Order do subject.stub(:line_items) { [] } order_cycle = double(:order_cycle) - order_cycle.should_receive(:create_order_adjustments_for).with(subject) + OpenFoodNetwork::EnterpriseFeeCalculator.any_instance. + should_receive(:create_order_adjustments_for). + with(subject) + subject.stub(:order_cycle) { order_cycle } subject.update_distribution_charge! From 8c41a6c9097cd3d4476d83afe914bdbda801f024 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 31 Jul 2014 10:09:46 +1000 Subject: [PATCH 20/40] Calculate fee breakdown --- app/models/spree/variant_decorator.rb | 4 ++++ app/serializers/api/variant_serializer.rb | 7 ++---- .../enterprise_fee_calculator.rb | 23 +++++++++++++++---- .../enterprise_fee_calculator_spec.rb | 17 +++++++++++++- spec/models/spree/variant_spec.rb | 14 +++++++++++ 5 files changed, 54 insertions(+), 11 deletions(-) diff --git a/app/models/spree/variant_decorator.rb b/app/models/spree/variant_decorator.rb index 1ad2dd75d0..7d4f178488 100644 --- a/app/models/spree/variant_decorator.rb +++ b/app/models/spree/variant_decorator.rb @@ -48,6 +48,10 @@ Spree::Variant.class_eval do OpenFoodNetwork::EnterpriseFeeCalculator.new(distributor, order_cycle).fees_for self end + def fees_by_type_for(distributor, order_cycle) + OpenFoodNetwork::EnterpriseFeeCalculator.new(distributor, order_cycle).fees_by_type_for self + end + # Copied and modified from Spree::Variant def options_text diff --git a/app/serializers/api/variant_serializer.rb b/app/serializers/api/variant_serializer.rb index 74bc19e65c..e03f1e0ec8 100644 --- a/app/serializers/api/variant_serializer.rb +++ b/app/serializers/api/variant_serializer.rb @@ -7,13 +7,10 @@ class Api::VariantSerializer < ActiveModel::Serializer end def base_price - 1.00 + object.price end def fees - {admin: 1.23, sales: 4.56, packing: 7.89, transport: 0.12} + object.fees_by_type_for(options[:current_distributor], options[:current_order_cycle]) end end - - -# price_without_fees / price diff --git a/lib/open_food_network/enterprise_fee_calculator.rb b/lib/open_food_network/enterprise_fee_calculator.rb index bbd220cfad..2d76d8d280 100644 --- a/lib/open_food_network/enterprise_fee_calculator.rb +++ b/lib/open_food_network/enterprise_fee_calculator.rb @@ -10,14 +10,19 @@ module OpenFoodNetwork def fees_for(variant) per_item_enterprise_fee_applicators_for(variant).sum do |applicator| - # Spree's Calculator interface accepts Orders or LineItems, - # so we meet that interface with a struct. - # Amount is faked, this is a method on LineItem - line_item = OpenStruct.new variant: variant, quantity: 1, amount: variant.price - applicator.enterprise_fee.compute_amount(line_item) + calculate_fee_for variant, applicator end end + def fees_by_type_for(variant) + per_item_enterprise_fee_applicators_for(variant).inject({}) do |fees, applicator| + fees[applicator.enterprise_fee.fee_type.to_sym] ||= 0 + fees[applicator.enterprise_fee.fee_type.to_sym] += calculate_fee_for variant, applicator + fees + end + end + + def create_line_item_adjustments_for(line_item) variant = line_item.variant @distributor = line_item.order.distributor @@ -40,6 +45,14 @@ module OpenFoodNetwork private + def calculate_fee_for(variant, applicator) + # Spree's Calculator interface accepts Orders or LineItems, + # so we meet that interface with a struct. + # Amount is faked, this is a method on LineItem + line_item = OpenStruct.new variant: variant, quantity: 1, amount: variant.price + applicator.enterprise_fee.compute_amount(line_item) + end + def per_item_enterprise_fee_applicators_for(variant) fees = [] diff --git a/spec/lib/open_food_network/enterprise_fee_calculator_spec.rb b/spec/lib/open_food_network/enterprise_fee_calculator_spec.rb index 697bb3c702..21c4848fda 100644 --- a/spec/lib/open_food_network/enterprise_fee_calculator_spec.rb +++ b/spec/lib/open_food_network/enterprise_fee_calculator_spec.rb @@ -8,7 +8,7 @@ module OpenFoodNetwork let(:order_cycle) { create(:simple_order_cycle) } let(:product) { create(:simple_product, price: 10.00) } - describe "calculating fees for a variant via a particular distribution" do + describe "calculating fees for a variant" do it "sums all the per-item fees for the variant in the specified hub + order cycle" do enterprise_fee1 = create(:enterprise_fee, amount: 20) enterprise_fee2 = create(:enterprise_fee, amount: 3) @@ -32,6 +32,21 @@ module OpenFoodNetwork end end + describe "calculating fees by type" do + let!(:ef_admin) { create(:enterprise_fee, fee_type: 'admin', amount: 1.23) } + let!(:ef_sales) { create(:enterprise_fee, fee_type: 'sales', amount: 4.56) } + let!(:ef_packing) { create(:enterprise_fee, fee_type: 'packing', amount: 7.89) } + let!(:ef_transport) { create(:enterprise_fee, fee_type: 'transport', amount: 0.12) } + let!(:exchange) { create(:exchange, order_cycle: order_cycle, + sender: coordinator, receiver: distributor, incoming: false, + enterprise_fees: [ef_admin, ef_sales, ef_packing, ef_transport], + variants: [product.master]) } + + it "returns a breakdown of fees" do + EnterpriseFeeCalculator.new(distributor, order_cycle).fees_by_type_for(product.master).should == {admin: 1.23, sales: 4.56, packing: 7.89, transport: 0.12} + end + end + describe "creating adjustments" do let(:order) { create(:order, distributor: distributor, order_cycle: order_cycle) } let!(:line_item) { create(:line_item, order: order, variant: product.master) } diff --git a/spec/models/spree/variant_spec.rb b/spec/models/spree/variant_spec.rb index d1d833664a..7fb160ce3f 100644 --- a/spec/models/spree/variant_spec.rb +++ b/spec/models/spree/variant_spec.rb @@ -94,6 +94,20 @@ module Spree end + describe "calculating fees broken down by fee type" do + it "delegates to EnterpriseFeeCalculator" do + distributor = double(:distributor) + order_cycle = double(:order_cycle) + variant = Variant.new + fees = double(:fees) + + OpenFoodNetwork::EnterpriseFeeCalculator.any_instance.should_receive(:fees_by_type_for).with(variant) { fees } + + variant.fees_by_type_for(distributor, order_cycle).should == fees + end + end + + context "when the product has variants" do let!(:product) { create(:simple_product) } let!(:variant) { create(:variant, product: product) } From 126e0a1f6d23b47f69c9f09184103a3cc40cc221 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 31 Jul 2014 11:34:21 +1000 Subject: [PATCH 21/40] Link variants -> products, fixes group buy --- app/assets/javascripts/darkswarm/services/products.js.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/assets/javascripts/darkswarm/services/products.js.coffee b/app/assets/javascripts/darkswarm/services/products.js.coffee index aec7b1cc3e..5819c7b661 100644 --- a/app/assets/javascripts/darkswarm/services/products.js.coffee +++ b/app/assets/javascripts/darkswarm/services/products.js.coffee @@ -28,6 +28,8 @@ Darkswarm.factory 'Products', ($resource, Enterprises, Dereferencer, Taxons, Car for product in @products if product.variants product.variants = (Variants.register variant for variant in product.variants) + variant.product = product for variant in product.variants + product.master.product = product product.master = Variants.register product.master if product.master registerVariantsWithCart: -> From a1dd5dabac1d0da593e1dd4dade344a9af6f769a Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 31 Jul 2014 11:36:34 +1000 Subject: [PATCH 22/40] Replace sleep with wait, add cart_dirty spec helper --- app/views/shared/menu/_cart.html.haml | 2 +- spec/features/consumer/shopping/shopping_spec.rb | 4 +++- spec/support/request/ui_component_helper.rb | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/views/shared/menu/_cart.html.haml b/app/views/shared/menu/_cart.html.haml index 2d8fbebcb9..907fda0eff 100644 --- a/app/views/shared/menu/_cart.html.haml +++ b/app/views/shared/menu/_cart.html.haml @@ -1,4 +1,4 @@ -%span.cart-span{"ng-controller" => "CartCtrl"} +%span.cart-span{"ng-controller" => "CartCtrl", "ng-class" => "{ dirty: Cart.dirty }"} %a#cart.icon{cart: true} %span.nav-branded %i.ofn-i_027-shopping-cart diff --git a/spec/features/consumer/shopping/shopping_spec.rb b/spec/features/consumer/shopping/shopping_spec.rb index 288e628b38..56c578f91b 100644 --- a/spec/features/consumer/shopping/shopping_spec.rb +++ b/spec/features/consumer/shopping/shopping_spec.rb @@ -139,7 +139,9 @@ 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 - sleep 5 + + wait_until { !cart_dirty } + li = Spree::Order.order(:created_at).last.line_items.order(:created_at).last li.max_quantity.should == 9 li.quantity.should == 5 diff --git a/spec/support/request/ui_component_helper.rb b/spec/support/request/ui_component_helper.rb index 7ca025e235..d9f01b447b 100644 --- a/spec/support/request/ui_component_helper.rb +++ b/spec/support/request/ui_component_helper.rb @@ -68,6 +68,10 @@ module UIComponentHelper find("#cart").click end + def cart_dirty + page.find("span.cart-span")[:class].include? 'dirty' + end + def wait_for_ajax counter = 0 while page.execute_script("return $.active").to_i > 0 From 29b3a080acde70bc7754a140f82216990eceffc5 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 31 Jul 2014 11:43:02 +1000 Subject: [PATCH 23/40] Only show fees if present --- .../javascripts/templates/price_breakdown.html.haml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/templates/price_breakdown.html.haml b/app/assets/javascripts/templates/price_breakdown.html.haml index 2508dc33da..518448f565 100644 --- a/app/assets/javascripts/templates/price_breakdown.html.haml +++ b/app/assets/javascripts/templates/price_breakdown.html.haml @@ -1,4 +1,4 @@ -.joyride-tip-guide{"ng-class" => "{ in: tt_isOpen, fade: tt_animation }"} +.joyride-tip-guide{bindonce: true, "ng-class" => "{ in: tt_isOpen, fade: tt_animation }"} %span.joyride-nub.bottom .joyride-content-wrapper @@ -11,16 +11,16 @@ %li Cost %span {{ variant.base_price | currency }} - %li + %li{"bo-if" => "variant.fees.admin"} Admin fee %span {{ variant.fees.admin | currency }} - %li + %li{"bo-if" => "variant.fees.sales"} Sales fee %span {{ variant.fees.sales | currency }} - %li + %li{"bo-if" => "variant.fees.packing"} Packing fee %span {{ variant.fees.packing | currency }} - %li + %li{"bo-if" => "variant.fees.transport"} Transport fee %span {{ variant.fees.transport | currency }} %a{"ng-click" => "expanded = !expanded"} Price graph From 86c1d010e7d2501409e22bd7c0f55ae79f91e3bd Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Thu, 31 Jul 2014 11:49:34 +1000 Subject: [PATCH 24/40] Default quantity to null rather than zero --- app/assets/javascripts/darkswarm/services/cart.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/darkswarm/services/cart.js.coffee b/app/assets/javascripts/darkswarm/services/cart.js.coffee index 2d91eab370..5123bcf508 100644 --- a/app/assets/javascripts/darkswarm/services/cart.js.coffee +++ b/app/assets/javascripts/darkswarm/services/cart.js.coffee @@ -57,6 +57,6 @@ Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http)-> create_line_item: (variant)-> variant.line_item = variant: variant - quantity: 0 + quantity: null max_quantity: null @line_items.push variant.line_item From 33a177ed479bb1b68d8471a531caef3cc4f20eec Mon Sep 17 00:00:00 2001 From: summerscope Date: Thu, 31 Jul 2014 12:00:24 +1000 Subject: [PATCH 25/40] Make map input placeholder message useful --- .../javascripts/darkswarm/directives/map_search.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/darkswarm/directives/map_search.js.coffee b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee index 4942032580..88456db2a3 100644 --- a/app/assets/javascripts/darkswarm/directives/map_search.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/map_search.js.coffee @@ -3,7 +3,7 @@ Darkswarm.directive 'mapSearch', ($timeout)-> restrict: 'E' require: '^googleMap' replace: true - template: '' + template: '' link: (scope, elem, attrs, ctrl)-> $timeout => map = ctrl.getMap() From ee067d48044fa63235bebd8c0f6dbc5b9ed1f8bf Mon Sep 17 00:00:00 2001 From: summerscope Date: Thu, 31 Jul 2014 12:00:36 +1000 Subject: [PATCH 26/40] Style the map input --- app/assets/stylesheets/darkswarm/map.css.sass | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/darkswarm/map.css.sass b/app/assets/stylesheets/darkswarm/map.css.sass index 2050cf5063..78d350d6be 100644 --- a/app/assets/stylesheets/darkswarm/map.css.sass +++ b/app/assets/stylesheets/darkswarm/map.css.sass @@ -1,6 +1,8 @@ // Place all the styles related to the map controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ +@import big-input + .map-container width: 100% map, .angular-google-map-container, google-map, .angular-google-map @@ -11,6 +13,14 @@ max-width: none height: auto - #pac-input - padding: 4px - font-size: 2em + #pac-input + @include big-input(#888, #333, $clr-brick) + @include big-input-static + font-size: 1.5rem + background: rgba(255,255,255,0.85) + width: 50% + margin-top: 1.2rem + @media all and (max-width: 768px) + width: 80% + &:active, &:focus, &.active + background: rgba(255,255,255, 1) From dc1963497afe9e6a44b26313457ec2b33ce12a84 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Thu, 31 Jul 2014 12:03:26 +1000 Subject: [PATCH 27/40] SORTING BY PRIMARY TAXON NAME --- .../darkswarm/controllers/products_controller.js.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee index da595418da..8ed56f252d 100644 --- a/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee @@ -6,7 +6,8 @@ Darkswarm.controller "ProductsCtrl", ($scope, $rootScope, Products, OrderCycle, $scope.filterText = FilterSelectorsService.filterText $scope.FilterSelectorsService = FilterSelectorsService $scope.limit = 3 - $scope.ordering = {order: "name"} + $scope.ordering = + order: "primary_taxon.name" $scope.order_cycle = OrderCycle.order_cycle $scope.incrementLimit = -> From d70ed029775896056b0797948d1f44fb0cc98916 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Thu, 31 Jul 2014 12:04:12 +1000 Subject: [PATCH 28/40] Restoring caching on addresses --- app/serializers/api/address_serializer.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/serializers/api/address_serializer.rb b/app/serializers/api/address_serializer.rb index 66e4267e1f..2134c7c0b0 100644 --- a/app/serializers/api/address_serializer.rb +++ b/app/serializers/api/address_serializer.rb @@ -1,6 +1,6 @@ class Api::AddressSerializer < ActiveModel::Serializer - #cached - #delegate :cache_key, to: :object + cached + delegate :cache_key, to: :object attributes :id, :zipcode, :city, :state_name, :state_id, :phone, :firstname, :lastname, :address1, :address2, :city, :country_id, From 0f76892a5b533605ef8bf0a1e9f483910a01a1ca Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Thu, 31 Jul 2014 12:23:10 +1000 Subject: [PATCH 29/40] Handling max quantity magically --- app/assets/javascripts/darkswarm/directives/max.js.coffee | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 app/assets/javascripts/darkswarm/directives/max.js.coffee diff --git a/app/assets/javascripts/darkswarm/directives/max.js.coffee b/app/assets/javascripts/darkswarm/directives/max.js.coffee new file mode 100644 index 0000000000..ed3d7b3253 --- /dev/null +++ b/app/assets/javascripts/darkswarm/directives/max.js.coffee @@ -0,0 +1,6 @@ +Darkswarm.directive "max", -> + restrict: 'A' + link: (scope, elem, attr)-> + elem.bind 'input', -> + if elem.val() > +attr.max + elem.val attr.max From d9f3dfb5714aad2a8f06abc50791115f09b19862 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Thu, 31 Jul 2014 12:23:22 +1000 Subject: [PATCH 30/40] Removing a pointless error message --- app/assets/javascripts/darkswarm/services/cart.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/darkswarm/services/cart.js.coffee b/app/assets/javascripts/darkswarm/services/cart.js.coffee index 5123bcf508..aa6820f150 100644 --- a/app/assets/javascripts/darkswarm/services/cart.js.coffee +++ b/app/assets/javascripts/darkswarm/services/cart.js.coffee @@ -19,7 +19,7 @@ Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http)-> $http.post('/orders/populate', @data()).success (data, status)=> @saved() .error (response, status)=> - alert "There was an error on the server! Please refresh the page" + # TODO what shall we do here? data: => variants = {} From c4984144d3b701320a584416e0d4e7cad279e4d5 Mon Sep 17 00:00:00 2001 From: summerscope Date: Thu, 31 Jul 2014 15:05:29 +1000 Subject: [PATCH 31/40] Turn off blue highlight in Chrome for all buttons across the system --- app/assets/stylesheets/darkswarm/ui.css.sass | 1 + 1 file changed, 1 insertion(+) diff --git a/app/assets/stylesheets/darkswarm/ui.css.sass b/app/assets/stylesheets/darkswarm/ui.css.sass index bd740ec614..9d28e16787 100644 --- a/app/assets/stylesheets/darkswarm/ui.css.sass +++ b/app/assets/stylesheets/darkswarm/ui.css.sass @@ -46,6 +46,7 @@ .button, button @include border-radius(0.5em) + outline: none // Turn off blue highlight on chrome .button.primary, button.primary font-family: 'Open Sans', Calibri, Candara, Segoe, "Segoe UI", Optima, Arial, sans-serif From 44d7ae8b611ff1d00b91a3f9154d40659ec65e2b Mon Sep 17 00:00:00 2001 From: summerscope Date: Thu, 31 Jul 2014 15:07:22 +1000 Subject: [PATCH 32/40] Tweak the markup for brice breakdown and percentage for styling --- .../templates/price_breakdown.html.haml | 29 ++++++++++++------- .../templates/price_percentage.html.haml | 3 +- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/templates/price_breakdown.html.haml b/app/assets/javascripts/templates/price_breakdown.html.haml index 518448f565..f9919b92ff 100644 --- a/app/assets/javascripts/templates/price_breakdown.html.haml +++ b/app/assets/javascripts/templates/price_breakdown.html.haml @@ -1,27 +1,36 @@ .joyride-tip-guide{bindonce: true, "ng-class" => "{ in: tt_isOpen, fade: tt_animation }"} - %span.joyride-nub.bottom + %span.joyride-nub.right .joyride-content-wrapper .collapsed{"ng-show" => "!expanded"} %price-percentage{percentage: 'variant.basePricePercentage'} - %a{"ng-click" => "expanded = !expanded"} Full price breakdown + %a{"ng-click" => "expanded = !expanded"} + Full price breakdown + %i.ofn-i_005-caret-down .expanded{"ng-show" => "expanded"} %ul - %li + %li.cost + .right {{ variant.base_price | currency }} Cost - %span {{ variant.base_price | currency }} %li{"bo-if" => "variant.fees.admin"} + .right {{ variant.fees.admin | currency }} Admin fee - %span {{ variant.fees.admin | currency }} %li{"bo-if" => "variant.fees.sales"} + .right {{ variant.fees.sales | currency }} Sales fee - %span {{ variant.fees.sales | currency }} %li{"bo-if" => "variant.fees.packing"} + .right {{ variant.fees.packing | currency }} Packing fee - %span {{ variant.fees.packing | currency }} %li{"bo-if" => "variant.fees.transport"} + .right {{ variant.fees.transport | currency }} Transport fee - %span {{ variant.fees.transport | currency }} - %a{"ng-click" => "expanded = !expanded"} Price graph - \= {{ variant.price | currency }} + %li + %strong + .right = {{ variant.price | currency }} +   + + %a{"ng-click" => "expanded = !expanded"} + Price graph + %i.ofn-i_006-caret-up + diff --git a/app/assets/javascripts/templates/price_percentage.html.haml b/app/assets/javascripts/templates/price_percentage.html.haml index ee1e8964a5..4982f63eb7 100644 --- a/app/assets/javascripts/templates/price_percentage.html.haml +++ b/app/assets/javascripts/templates/price_percentage.html.haml @@ -1,4 +1,5 @@ .progress + .right Fees .meter Cost - Fees + From f868fe109163db3286774d5590bf6a8003b38917 Mon Sep 17 00:00:00 2001 From: summerscope Date: Thu, 31 Jul 2014 15:07:52 +1000 Subject: [PATCH 33/40] Change markup for the graph button to make it align where we want --- app/assets/javascripts/templates/shop_variant.html.haml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/templates/shop_variant.html.haml b/app/assets/javascripts/templates/shop_variant.html.haml index 938259d80f..bf0907088e 100644 --- a/app/assets/javascripts/templates/shop_variant.html.haml +++ b/app/assets/javascripts/templates/shop_variant.html.haml @@ -52,7 +52,10 @@ %button.graph-button{"price-breakdown" => "_", "variant" => "variant", - "price-breakdown-animation" => "true"} + "ng-class" => "{open: tt_isOpen}", + "price-breakdown-animation" => "true", + "price-breakdown-append-to-body" => "true", + "price-breakdown-placement" => "left"} %i.ofn-i-058-graph .small-12.medium-2.large-2.columns.total-price.text-right From 7ad10ee0767cf435b43801ccbae4ee3c1f42d87c Mon Sep 17 00:00:00 2001 From: summerscope Date: Thu, 31 Jul 2014 15:08:16 +1000 Subject: [PATCH 34/40] Style popovers and price breakdowns --- .../darkswarm/_shop-popovers.css.sass | 97 +++++++++++++------ 1 file changed, 68 insertions(+), 29 deletions(-) diff --git a/app/assets/stylesheets/darkswarm/_shop-popovers.css.sass b/app/assets/stylesheets/darkswarm/_shop-popovers.css.sass index fec2eae4a6..4eb562cb56 100644 --- a/app/assets/stylesheets/darkswarm/_shop-popovers.css.sass +++ b/app/assets/stylesheets/darkswarm/_shop-popovers.css.sass @@ -1,37 +1,76 @@ @import mixins -.darkswarm - product - // Pop over +// .darkswarm +// product - // Foundation overrides - .joyride-tip-guide - // JS needs to be tweaked to adjust for left alignment - this is dynamic can't rewrite in CSS - background-color: #ebebeb - border: 1px solid #a5a5a5 - color: #1f1f1f - - h1, h2, h3, h4, h5, h6 - color: #1f1f1f - .joyride-nub.bottom - border-color: #a5a5a5 !important - border-bottom-color: transparent !important - border-left-color: transparent !important - border-right-color: transparent !important +// Pop over +// Foundation overrides +.joyride-tip-guide + // JS needs to be tweaked to adjust for left alignment - this is dynamic can't rewrite in CSS + background-color: #d1d1d1 + color: #1f1f1f + @include box-shadow(0 1px 2px 0 rgba(0,0,0,0.7)) - button.graph-button - padding: 0 + + h1, h2, h3, h4, h5, h6 + color: #1f1f1f + + .joyride-nub.right + top: 40px + border-color: #d1d1d1 !important + border-top-color: transparent !important + border-right-color: transparent !important + border-bottom-color: transparent !important + + .progress + background-color: #148774 + padding: 0 + border: none + color: white + font-size: 0.75rem + font-style: oblique + line-height: 1 + height: auto + .right + padding: 0.5rem 0.25rem 0 0 + .meter + background-color: #097563 + padding: 0.5rem 0.25rem + border-right: 1px solid #539f92 + + .expanded + ul, li + list-style: none margin: 0 - @include border-radius(0) - display: inline - background: none + font-size: 0.875rem + li + background-color: #148774 + padding: 0 0.25rem + margin-bottom: 2px + color: white + li.cost + background-color: #097563 + + +button.graph-button + padding: 0 + margin: 0 + @include border-radius(99999) + display: inline + background: rgba(255,255,255,0.5) + padding: 0.2rem + &:hover, &:focus, &:active, &.active + background: $clr-brick-bright + i.ofn-i-058-graph + color: white + + i.ofn-i-058-graph + color: #999 + margin: 0 + padding: 0 + font-size: 1rem + + - i.ofn-i-058-graph - color: #999 - margin: 0 - padding: 0 - font-size: 1rem - &:hover, &:focus, &:active, &.active - color: #444 \ No newline at end of file From 042db2d150342ab58eef3533a1d0d5b83a022e78 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Thu, 31 Jul 2014 15:05:25 +1000 Subject: [PATCH 35/40] Some comments and refactoring --- .../darkswarm/directives/active_selector.js.coffee | 5 ++++- .../directives/active_table_hub_link.js.coffee | 5 +++-- .../darkswarm/directives/cart_popover.js.coffee | 1 + .../darkswarm/directives/price_breakdown.js.coffee | 8 +++++++- .../javascripts/templates/price_breakdown.html.haml | 1 - .../templates/price_breakdown_button.html.haml | 2 ++ .../javascripts/templates/shop_variant.html.haml | 10 ++++------ 7 files changed, 21 insertions(+), 11 deletions(-) create mode 100644 app/assets/javascripts/templates/price_breakdown_button.html.haml diff --git a/app/assets/javascripts/darkswarm/directives/active_selector.js.coffee b/app/assets/javascripts/darkswarm/directives/active_selector.js.coffee index 74523c2c3d..563b5a1716 100644 --- a/app/assets/javascripts/darkswarm/directives/active_selector.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/active_selector.js.coffee @@ -1,4 +1,6 @@ Darkswarm.directive "activeSelector", -> + # A generic selector that allows an object/scope to be toggled between active and inactive + # Used in the filters, but hypothetically useable anywhere restrict: 'E' transclude: true replace: true @@ -8,5 +10,6 @@ Darkswarm.directive "activeSelector", -> elem.bind "click", -> scope.$apply -> scope.selector.active = !scope.selector.active - scope.emit() + # This function is a convention, e.g. a callback on the scope applied when active changes + scope.emit() if scope.emit diff --git a/app/assets/javascripts/darkswarm/directives/active_table_hub_link.js.coffee b/app/assets/javascripts/darkswarm/directives/active_table_hub_link.js.coffee index 4369fced34..994a7ced48 100644 --- a/app/assets/javascripts/darkswarm/directives/active_table_hub_link.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/active_table_hub_link.js.coffee @@ -1,11 +1,12 @@ Darkswarm.directive "activeTableHubLink", (CurrentHub, CurrentOrder) -> + # Change the text of the hub link based on CurrentHub + # To be used with ofnEmptiesCart + # Takes "change" and "shop" as text string attributes restrict: "A" scope: hub: '=activeTableHubLink' template: "{{action}}" link: (scope, elm, attr)-> - # Swap out the text of the hub link depending on whether it'll change current hub - # To be used with ofnEmptiesCart if CurrentHub.hub?.id and CurrentHub.hub.id isnt scope.hub.id scope.action = attr.change else diff --git a/app/assets/javascripts/darkswarm/directives/cart_popover.js.coffee b/app/assets/javascripts/darkswarm/directives/cart_popover.js.coffee index bcc0c8bc08..1ef1b3f9c3 100644 --- a/app/assets/javascripts/darkswarm/directives/cart_popover.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/cart_popover.js.coffee @@ -1,4 +1,5 @@ Darkswarm.directive "cart", -> + # Toggles visibility of the "cart" popover restrict: 'A' link: (scope, elem, attr)-> scope.open = false diff --git a/app/assets/javascripts/darkswarm/directives/price_breakdown.js.coffee b/app/assets/javascripts/darkswarm/directives/price_breakdown.js.coffee index 0d1d6ce0b5..8b0beb17a5 100644 --- a/app/assets/javascripts/darkswarm/directives/price_breakdown.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/price_breakdown.js.coffee @@ -1,9 +1,15 @@ Darkswarm.directive "priceBreakdown", ($tooltip)-> - tooltip = $tooltip 'priceBreakdown', 'priceBreakdown', 'click' + # We use the $tooltip service from Angular foundation to give us boilerplate + # Subsequently we patch the scope, template and restrictions + tooltip = $tooltip 'priceBreakdown', 'priceBreakdown', 'click' tooltip.scope = variant: "=" + tooltip.templateUrl = "price_breakdown_button.html" + tooltip.replace = true + tooltip.restrict = 'E' tooltip +# This is automatically referenced via naming convention in $tooltip Darkswarm.directive 'priceBreakdownPopup', -> restrict: 'EA' replace: true diff --git a/app/assets/javascripts/templates/price_breakdown.html.haml b/app/assets/javascripts/templates/price_breakdown.html.haml index f9919b92ff..9317356d02 100644 --- a/app/assets/javascripts/templates/price_breakdown.html.haml +++ b/app/assets/javascripts/templates/price_breakdown.html.haml @@ -1,7 +1,6 @@ .joyride-tip-guide{bindonce: true, "ng-class" => "{ in: tt_isOpen, fade: tt_animation }"} %span.joyride-nub.right .joyride-content-wrapper - .collapsed{"ng-show" => "!expanded"} %price-percentage{percentage: 'variant.basePricePercentage'} %a{"ng-click" => "expanded = !expanded"} diff --git a/app/assets/javascripts/templates/price_breakdown_button.html.haml b/app/assets/javascripts/templates/price_breakdown_button.html.haml new file mode 100644 index 0000000000..8a86ed2618 --- /dev/null +++ b/app/assets/javascripts/templates/price_breakdown_button.html.haml @@ -0,0 +1,2 @@ +%button.graph-button{"ng-class" => "{open: tt_isOpen}"} + %i.ofn-i-058-graph diff --git a/app/assets/javascripts/templates/shop_variant.html.haml b/app/assets/javascripts/templates/shop_variant.html.haml index bf0907088e..a6db8b4e41 100644 --- a/app/assets/javascripts/templates/shop_variant.html.haml +++ b/app/assets/javascripts/templates/shop_variant.html.haml @@ -50,13 +50,11 @@ %i.ofn-i_009-close {{ variant.price | currency }} - %button.graph-button{"price-breakdown" => "_", - "variant" => "variant", - "ng-class" => "{open: tt_isOpen}", - "price-breakdown-animation" => "true", + -# Now in a template in app/assets/javascripts/templates ! + %price-breakdown{"price-breakdown" => "_", variant: "variant", "price-breakdown-append-to-body" => "true", - "price-breakdown-placement" => "left"} - %i.ofn-i-058-graph + "price-breakdown-placement" => "left", + "price-breakdown-animation" => true} .small-12.medium-2.large-2.columns.total-price.text-right .table-cell From 647495465a7e4e68a3f8d86af9a411578614caf1 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Thu, 31 Jul 2014 15:12:25 +1000 Subject: [PATCH 36/40] Comments and minor refactoring --- .../darkswarm/directives/debounce.js.coffee | 2 ++ .../directives/disable_enter.js.coffee | 1 + .../directives/disable_scroll.js.coffee | 3 ++- .../directives/empties_cart.js.coffee | 21 ++++++++++--------- .../darkswarm/services/cart.js.coffee | 3 +++ .../services/current_order.js.coffee | 2 -- 6 files changed, 19 insertions(+), 13 deletions(-) diff --git a/app/assets/javascripts/darkswarm/directives/debounce.js.coffee b/app/assets/javascripts/darkswarm/directives/debounce.js.coffee index 343fcb531a..80f55de1d7 100644 --- a/app/assets/javascripts/darkswarm/directives/debounce.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/debounce.js.coffee @@ -1,4 +1,6 @@ Darkswarm.directive "ngDebounce", ($timeout) -> + # Slows down ng-model updates, only triggering binding ngDebounce milliseconds + # after the last change. Used to prevent squirrely UI restrict: "A" require: "ngModel" priority: 99 diff --git a/app/assets/javascripts/darkswarm/directives/disable_enter.js.coffee b/app/assets/javascripts/darkswarm/directives/disable_enter.js.coffee index 352ed85fd6..ce1178e15e 100644 --- a/app/assets/javascripts/darkswarm/directives/disable_enter.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/disable_enter.js.coffee @@ -1,4 +1,5 @@ Darkswarm.directive "ofnDisableEnter", ()-> + # Stops enter from doing normal enter things restrict: 'A' link: (scope, element, attrs)-> element.bind "keydown keypress", (e)-> diff --git a/app/assets/javascripts/darkswarm/directives/disable_scroll.js.coffee b/app/assets/javascripts/darkswarm/directives/disable_scroll.js.coffee index 7c870ab860..40b8230e65 100644 --- a/app/assets/javascripts/darkswarm/directives/disable_scroll.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/disable_scroll.js.coffee @@ -1,6 +1,7 @@ Darkswarm.directive "ofnDisableScroll", ()-> + # Stops scrolling from incrementing or decrementing input value + # Useful for number inputs restrict: 'A' - link: (scope, element, attrs)-> element.bind 'focus', -> element.bind 'mousewheel', (e)-> diff --git a/app/assets/javascripts/darkswarm/directives/empties_cart.js.coffee b/app/assets/javascripts/darkswarm/directives/empties_cart.js.coffee index 75e88f3682..b49131afa6 100644 --- a/app/assets/javascripts/darkswarm/directives/empties_cart.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/empties_cart.js.coffee @@ -1,12 +1,13 @@ -Darkswarm.directive "ofnEmptiesCart", (CurrentHub, CurrentOrder, Navigation, storage) -> +Darkswarm.directive "ofnEmptiesCart", (CurrentHub, Cart, Navigation, storage) -> + # Compares scope.hub with CurrentHub. Will trigger an confirmation if they are different, + # and Cart isn't empty restrict: "A" + scope: + hub: "=ofnEmptiesCart" link: (scope, elm, attr)-> - hub = scope.$eval(attr.ofnEmptiesCart) - # A hub is selected, we're changing to a different hub, and the cart isn't empty - if CurrentHub.hub?.id and CurrentHub.hub.id isnt hub.id - unless CurrentOrder.empty() - elm.bind 'click', (ev)-> - ev.preventDefault() - if confirm "Are you sure? This will change your selected Hub and remove any items in you shopping cart." - storage.clearAll() # One day this will have to be moar GRANULAR - Navigation.go scope.hub.path + if CurrentHub.hub?.id and CurrentHub.hub.id isnt scope.hub.id and !Cart.empty() + elm.bind 'click', (ev)-> + ev.preventDefault() + if confirm "Are you sure? This will change your selected Hub and remove any items in you shopping cart." + storage.clearAll() # One day this will have to be moar GRANULAR + Navigation.go scope.hub.path diff --git a/app/assets/javascripts/darkswarm/services/cart.js.coffee b/app/assets/javascripts/darkswarm/services/cart.js.coffee index aa6820f150..def1c9b6d0 100644 --- a/app/assets/javascripts/darkswarm/services/cart.js.coffee +++ b/app/assets/javascripts/darkswarm/services/cart.js.coffee @@ -43,6 +43,9 @@ Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http)-> @line_items.filter (li)-> li.quantity > 0 + empty: => + @line_items_present().length == 0 + total: => @line_items_present().map (li)-> li.variant.getPrice() diff --git a/app/assets/javascripts/darkswarm/services/current_order.js.coffee b/app/assets/javascripts/darkswarm/services/current_order.js.coffee index a0714dc005..cd2402f0c0 100644 --- a/app/assets/javascripts/darkswarm/services/current_order.js.coffee +++ b/app/assets/javascripts/darkswarm/services/current_order.js.coffee @@ -1,5 +1,3 @@ Darkswarm.factory 'CurrentOrder', (currentOrder) -> new class CurrentOrder order: currentOrder - empty: => - @order.line_items.length == 0 From 494b572c69456e7c0cfc73c38aa2ddc99d4d46d4 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 31 Jul 2014 15:36:13 +1000 Subject: [PATCH 37/40] Do not show zero fees --- lib/open_food_network/enterprise_fee_calculator.rb | 2 +- .../lib/open_food_network/enterprise_fee_calculator_spec.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/open_food_network/enterprise_fee_calculator.rb b/lib/open_food_network/enterprise_fee_calculator.rb index 2d76d8d280..c8070f2ab2 100644 --- a/lib/open_food_network/enterprise_fee_calculator.rb +++ b/lib/open_food_network/enterprise_fee_calculator.rb @@ -19,7 +19,7 @@ module OpenFoodNetwork fees[applicator.enterprise_fee.fee_type.to_sym] ||= 0 fees[applicator.enterprise_fee.fee_type.to_sym] += calculate_fee_for variant, applicator fees - end + end.select { |fee_type, amount| amount > 0 } end diff --git a/spec/lib/open_food_network/enterprise_fee_calculator_spec.rb b/spec/lib/open_food_network/enterprise_fee_calculator_spec.rb index 21c4848fda..0ca7da4999 100644 --- a/spec/lib/open_food_network/enterprise_fee_calculator_spec.rb +++ b/spec/lib/open_food_network/enterprise_fee_calculator_spec.rb @@ -45,6 +45,12 @@ module OpenFoodNetwork it "returns a breakdown of fees" do EnterpriseFeeCalculator.new(distributor, order_cycle).fees_by_type_for(product.master).should == {admin: 1.23, sales: 4.56, packing: 7.89, transport: 0.12} end + + it "filters out zero fees" do + ef_admin.calculator.update_attribute :preferred_amount, 0 + + EnterpriseFeeCalculator.new(distributor, order_cycle).fees_by_type_for(product.master).should == {sales: 4.56, packing: 7.89, transport: 0.12} + end end describe "creating adjustments" do From b0f15aef104dbf62532330231c4ce8e3004d9d5e Mon Sep 17 00:00:00 2001 From: summerscope Date: Thu, 31 Jul 2014 15:38:12 +1000 Subject: [PATCH 38/40] Popovers finish styling for various use cases --- .../darkswarm/_shop-popovers.css.sass | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/app/assets/stylesheets/darkswarm/_shop-popovers.css.sass b/app/assets/stylesheets/darkswarm/_shop-popovers.css.sass index 4eb562cb56..4485819324 100644 --- a/app/assets/stylesheets/darkswarm/_shop-popovers.css.sass +++ b/app/assets/stylesheets/darkswarm/_shop-popovers.css.sass @@ -8,17 +8,23 @@ // Foundation overrides .joyride-tip-guide // JS needs to be tweaked to adjust for left alignment - this is dynamic can't rewrite in CSS - background-color: #d1d1d1 + background-color: #999 color: #1f1f1f @include box-shadow(0 1px 2px 0 rgba(0,0,0,0.7)) - + .joyride-content-wrapper + padding: 1.125rem 1.25rem 1.5rem + padding: 1rem + margin: 1% + width: 98% + background-color: white + h1, h2, h3, h4, h5, h6 color: #1f1f1f .joyride-nub.right top: 40px - border-color: #d1d1d1 !important + border-color: #999 !important border-top-color: transparent !important border-right-color: transparent !important border-bottom-color: transparent !important @@ -51,6 +57,8 @@ color: white li.cost background-color: #097563 + li:last-child + margin-bottom: 0.75rem button.graph-button @@ -58,12 +66,18 @@ button.graph-button margin: 0 @include border-radius(99999) display: inline - background: rgba(255,255,255,0.5) + background-color: rgba(255,255,255,0.5) padding: 0.2rem - &:hover, &:focus, &:active, &.active - background: $clr-brick-bright + + &:focus + background-color: rgba(255,255,255,0.5) i.ofn-i-058-graph - color: white + color: #999 + + &:hover, &:active + background-color: rgba(255,255,255,1) + i.ofn-i-058-graph + color: $clr-brick-bright i.ofn-i-058-graph color: #999 @@ -71,6 +85,16 @@ button.graph-button padding: 0 font-size: 1rem +button.graph-button.open + background-color: #999 + + &:hover, &:active, &:focus + background-color: #b2b2b2 + i.ofn-i-058-graph + color: $clr-brick-bright + + i.ofn-i-058-graph + color: $clr-brick From 5cff2f0f403e33eeb2ed164116e57e6f9f2d3315 Mon Sep 17 00:00:00 2001 From: summerscope Date: Thu, 31 Jul 2014 15:47:54 +1000 Subject: [PATCH 39/40] Tweak colors for popovers --- app/assets/stylesheets/darkswarm/_shop-popovers.css.sass | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/darkswarm/_shop-popovers.css.sass b/app/assets/stylesheets/darkswarm/_shop-popovers.css.sass index 4485819324..b79350818f 100644 --- a/app/assets/stylesheets/darkswarm/_shop-popovers.css.sass +++ b/app/assets/stylesheets/darkswarm/_shop-popovers.css.sass @@ -30,7 +30,7 @@ border-bottom-color: transparent !important .progress - background-color: #148774 + background-color: #13bf85 padding: 0 border: none color: white @@ -41,7 +41,7 @@ .right padding: 0.5rem 0.25rem 0 0 .meter - background-color: #097563 + background-color: #0b8c61 padding: 0.5rem 0.25rem border-right: 1px solid #539f92 @@ -51,12 +51,12 @@ margin: 0 font-size: 0.875rem li - background-color: #148774 + background-color: #13bf85 padding: 0 0.25rem margin-bottom: 2px color: white li.cost - background-color: #097563 + background-color: #0b8c61 li:last-child margin-bottom: 0.75rem From 6b00b1c14c2a5e9169c951c347c1b87e65c6de44 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Thu, 31 Jul 2014 15:38:15 +1000 Subject: [PATCH 40/40] MOAR COMMENTS --- .../directives/fill_vertical.js.coffee | 3 +-- .../darkswarm/directives/flash.js.coffee | 6 +++++- .../darkswarm/directives/focus.js.coffee | 6 +++--- .../darkswarm/directives/loading.js.coffee | 3 +-- .../darkswarm/directives/modal.js.coffee | 17 ++++++++++------- .../darkswarm/directives/render_svg.js.coffee | 4 ++++ .../directives/scroll_after_load.js.coffee | 1 + .../darkswarm/directives/scrollto.js.coffee | 2 ++ .../directives/shipping_type_selector.js.coffee | 1 + .../directives/taxon_selector.js.coffee | 11 +++++++++-- 10 files changed, 37 insertions(+), 17 deletions(-) diff --git a/app/assets/javascripts/darkswarm/directives/fill_vertical.js.coffee b/app/assets/javascripts/darkswarm/directives/fill_vertical.js.coffee index a8a2fbeebc..c9d05428ce 100644 --- a/app/assets/javascripts/darkswarm/directives/fill_vertical.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/fill_vertical.js.coffee @@ -1,10 +1,9 @@ Darkswarm.directive "fillVertical", ($window)-> + # Makes something fill the window vertically. Used on the Google Map. restrict: 'A' - link: (scope, element, attrs)-> setSize = -> element.css "height", ($window.innerHeight - element.offset().top) setSize() - angular.element($window).bind "resize", -> setSize() diff --git a/app/assets/javascripts/darkswarm/directives/flash.js.coffee b/app/assets/javascripts/darkswarm/directives/flash.js.coffee index b5c9aaddd8..74f6571f73 100644 --- a/app/assets/javascripts/darkswarm/directives/flash.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/flash.js.coffee @@ -1,5 +1,6 @@ Darkswarm.directive "ofnFlash", (flash, $timeout, RailsFlashLoader)-> - # Mappings between flash types (left) and Foundation classes + # Our own flash class. Uses the "flash" service (third party), and a directive + # called RailsFlashLoader to render typePairings = info: "info" error: "alert" @@ -13,6 +14,8 @@ Darkswarm.directive "ofnFlash", (flash, $timeout, RailsFlashLoader)-> link: ($scope, element, attr) -> $scope.flashes = [] + + # Callback when a new flash message is pushed to flash service show = (message, type)=> if message $scope.flashes.push({message: message, type: typePairings[type]}) @@ -21,5 +24,6 @@ Darkswarm.directive "ofnFlash", (flash, $timeout, RailsFlashLoader)-> $scope.delete = -> $scope.flashes.shift() + # Register our callback (above) with flash service flash.subscribe(show) RailsFlashLoader.initFlash() diff --git a/app/assets/javascripts/darkswarm/directives/focus.js.coffee b/app/assets/javascripts/darkswarm/directives/focus.js.coffee index c481702d6c..3c3bb4f05a 100644 --- a/app/assets/javascripts/darkswarm/directives/focus.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/focus.js.coffee @@ -1,9 +1,9 @@ Darkswarm.directive "ofnFocus", -> + # Takes an expression attrs.ofnFocus + # Watches value of expression, triggers element.focus() when value is truthy + # Used to automatically focus on specific inputs in various circumstances restrict: "A" link: (scope, element, attrs) -> scope.$watch attrs.ofnFocus, ((focus) -> focus and element.focus() - return ), true - - return diff --git a/app/assets/javascripts/darkswarm/directives/loading.js.coffee b/app/assets/javascripts/darkswarm/directives/loading.js.coffee index febe56de9b..c7191b4fe2 100644 --- a/app/assets/javascripts/darkswarm/directives/loading.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/loading.js.coffee @@ -1,4 +1,5 @@ Darkswarm.directive "loading", (Loading)-> + # Triggers a screen-wide "loading" thing when Ajaxy stuff is happening scope: {} restrict: 'E' templateUrl: 'loading.html' @@ -6,5 +7,3 @@ Darkswarm.directive "loading", (Loading)-> $scope.Loading = Loading $scope.show = -> $scope.Loading.message? - - link: ($scope, element, attr)-> diff --git a/app/assets/javascripts/darkswarm/directives/modal.js.coffee b/app/assets/javascripts/darkswarm/directives/modal.js.coffee index d727fa64c9..7c1babe215 100644 --- a/app/assets/javascripts/darkswarm/directives/modal.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/modal.js.coffee @@ -1,16 +1,19 @@ Darkswarm.directive "ofnModal", ($modal)-> + # Generic modal! Uses transclusion so designer-types can do stuff like: + # %ofn-modal + # CONTENT + # Only works for simple cases, so roll your own when necessary! restrict: 'E' replace: true transclude: true - scope: {} + scope: true template: "{{title}}" + # Instead of using ng-transclude we compile the transcluded template to a string + # This compiled template is sent to the $modal service! Such magic! + # In theory we could compile the template directly inside link rather than onclick, but it's performant so meh! link: (scope, elem, attrs, ctrl, transclude)-> scope.title = attrs.title - contents = null elem.on "click", => - # We're using an isolate scope, which is a child of the original scope - # We have to compile the transclude against the original scope, not the isolate - transclude scope.$parent, (clone)-> - contents = clone - scope.modalInstance = $modal.open(controller: ctrl, template: contents, scope: scope.$parent) + transclude scope, (clone)-> + scope.modalInstance = $modal.open(controller: ctrl, template: clone, scope: scope) diff --git a/app/assets/javascripts/darkswarm/directives/render_svg.js.coffee b/app/assets/javascripts/darkswarm/directives/render_svg.js.coffee index 86ffea8c5b..c53448473d 100644 --- a/app/assets/javascripts/darkswarm/directives/render_svg.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/render_svg.js.coffee @@ -1,7 +1,11 @@ Darkswarm.directive "renderSvg", ()-> + # Magical directive that'll render SVGs from URLs + # If only there were a neater way of doing this restrict: 'E' priority: 99 template: "" + + # Fetch SVG via ajax, inject into page using DOM link: (scope, elem, attr)-> if /.svg/.test attr.path # Only do this if we've got an svg $.ajax diff --git a/app/assets/javascripts/darkswarm/directives/scroll_after_load.js.coffee b/app/assets/javascripts/darkswarm/directives/scroll_after_load.js.coffee index ab2e0a6e3d..55c5a311da 100644 --- a/app/assets/javascripts/darkswarm/directives/scroll_after_load.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/scroll_after_load.js.coffee @@ -1,4 +1,5 @@ Darkswarm.directive 'scrollAfterLoad', ($timeout, $location, $document)-> + # Scroll to an element on page load restrict: "A" link: (scope, element, attr) -> if scope.$last is true diff --git a/app/assets/javascripts/darkswarm/directives/scrollto.js.coffee b/app/assets/javascripts/darkswarm/directives/scrollto.js.coffee index 3db3446596..a63337dc70 100644 --- a/app/assets/javascripts/darkswarm/directives/scrollto.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/scrollto.js.coffee @@ -1,4 +1,6 @@ Darkswarm.directive "ofnScrollTo", ($location, $anchorScroll)-> + # Onclick sets $location.hash to attrs.ofnScrollTo + # Then triggers anchorScroll restrict: 'A' link: (scope, element, attrs)-> element.bind 'click', (ev)-> diff --git a/app/assets/javascripts/darkswarm/directives/shipping_type_selector.js.coffee b/app/assets/javascripts/darkswarm/directives/shipping_type_selector.js.coffee index 3f752f8a3d..07656d84b7 100644 --- a/app/assets/javascripts/darkswarm/directives/shipping_type_selector.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/shipping_type_selector.js.coffee @@ -1,4 +1,5 @@ Darkswarm.directive "shippingTypeSelector", (FilterSelectorsService)-> + # Builds selector for shipping types restrict: 'E' replace: true templateUrl: 'shipping_type_selector.html' diff --git a/app/assets/javascripts/darkswarm/directives/taxon_selector.js.coffee b/app/assets/javascripts/darkswarm/directives/taxon_selector.js.coffee index a682176d77..633ecd22f4 100644 --- a/app/assets/javascripts/darkswarm/directives/taxon_selector.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/taxon_selector.js.coffee @@ -1,4 +1,6 @@ Darkswarm.directive "taxonSelector", (FilterSelectorsService)-> + # Automatically builds activeSelectors for taxons + # Lots of magic here restrict: 'E' replace: true scope: @@ -8,7 +10,7 @@ Darkswarm.directive "taxonSelector", (FilterSelectorsService)-> link: (scope, elem, attr)-> selectors_by_id = {} - selectors = ["foo"] + selectors = null # To get scoping/closure right scope.emit = -> scope.results = selectors.filter (selector)-> @@ -16,6 +18,7 @@ Darkswarm.directive "taxonSelector", (FilterSelectorsService)-> .map (selector)-> selector.taxon.id + # Build hash of unique taxons, each of which gets an ActiveSelector scope.selectors = -> taxons = {} selectors = [] @@ -25,7 +28,11 @@ Darkswarm.directive "taxonSelector", (FilterSelectorsService)-> if object.supplied_taxons for taxon in object.supplied_taxons taxons[taxon.id] = taxon - + + # Generate a selector for each taxon. + # NOTE: THESE ARE MEMOIZED to stop new selectors from being created constantly, otherwise function always returns non-identical results + # This means the $digest cycle can never close and times out + # See http://stackoverflow.com/questions/19306452/how-to-fix-10-digest-iterations-reached-aborting-error-in-angular-1-2-fil for id, taxon of taxons if selector = selectors_by_id[id] selectors.push selector