Merge branch 'breakdowns' into laura_and_will

This commit is contained in:
Rohan Mitchell
2014-07-30 15:12:25 +10:00
32 changed files with 146 additions and 2728 deletions

View File

@@ -0,0 +1,30 @@
Darkswarm.directive 'mapSearch', ($timeout)->
# Install a basic search field in a map
restrict: 'E'
require: '^googleMap'
replace: true
template: '<input id="pac-input"></input>'
link: (scope, elem, attrs, ctrl)->
$timeout =>
map = ctrl.getMap()
input = (document.getElementById("pac-input"))
map.controls[google.maps.ControlPosition.TOP_LEFT].push input
searchBox = new google.maps.places.SearchBox((input))
google.maps.event.addListener searchBox, "places_changed", ->
places = searchBox.getPlaces()
return if places.length is 0
# For each place, get the icon, place name, and location.
markers = []
bounds = new google.maps.LatLngBounds()
for place in places
#map.setCenter place.geometry.location
map.fitBounds place.geometry.viewport
#map.fitBounds bounds
# Bias the SearchBox results towards places that are within the bounds of the
# current map's viewport.
google.maps.event.addListener map, "bounds_changed", ->
bounds = map.getBounds()
searchBox.setBounds bounds

View File

@@ -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?

View File

@@ -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}%"

View File

@@ -0,0 +1,6 @@
Darkswarm.directive "shopVariant", ->
restrict: 'E'
replace: true
templateUrl: 'shop_variant.html'
scope:
variant: '='

View File

@@ -1,4 +0,0 @@
Darkswarm.factory 'Order', (order)->
new class Order
order: order

View File

@@ -44,4 +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 || "/assets/noimage/small.png"
product.primaryImage = product.images[0]?.small_url if product.images
product.primaryImageOrMissing = product.primaryImage || "/assets/noimage/small.png"

View File

@@ -7,4 +7,5 @@ Darkswarm.factory 'Variants', ->
extend: (variant)->
variant.getPrice = ->
variant.price * variant.line_item.quantity
variant.basePricePercentage = Math.round(variant.base_price / variant.price * 100)
variant

View File

@@ -1,4 +1,27 @@
.joyride-tip-guide{"ng-class" => "{ in: tt_isOpen, fade: tt_animation }"}
%span.joyride-nub.bottom
.joyride-content-wrapper
{{ variant.id }}
.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 }}

View File

@@ -0,0 +1,4 @@
.progress
.meter
Cost
Fees

View File

@@ -1,6 +1,6 @@
.row
.columns.small-12.large-6
%img.product-img{"ng-src" => "{{product.master.images[0].large_url}}", "ng-if" => "product.master.images[0]"}
%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}}"}

View File

@@ -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",
@@ -51,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

View File

@@ -10,3 +10,7 @@
img // https://github.com/zurb/foundation/issues/112
max-width: none
height: auto
#pac-input
padding: 4px
font-size: 2em

View File

@@ -15,8 +15,12 @@ Spree::OrderPopulator.class_eval do
attempt_cart_add(variant_id, from_hash[:quantity])
end if from_hash[:products]
from_hash[:variants].each do |variant_id, args|
attempt_cart_add(variant_id, args[:quantity], args[:max_quantity])
from_hash[:variants].each do |variant_id, quantity|
if quantity.is_a?(Hash)
attempt_cart_add(variant_id, quantity[:quantity], quantity[:max_quantity])
else
attempt_cart_add(variant_id, quantity)
end
end if from_hash[:variants]
end
end

View File

@@ -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, :base_price
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

View File

@@ -11,7 +11,7 @@
%link{href: "https://fonts.googleapis.com/css?family=Open+Sans:400,700", rel: "stylesheet", type: "text/css"}/
= yield :scripts
%script{src: "//maps.googleapis.com/maps/api/js?sensor=false"}
%script{src: "//maps.googleapis.com/maps/api/js?libraries=places&sensor=false"}
= stylesheet_link_tag "darkswarm/all"
= javascript_include_tag "darkswarm/all"

View File

@@ -3,5 +3,6 @@
.map-container{"fill-vertical" => true}
%map{"ng-controller" => "MapCtrl"}
%google-map{options: "map.additional_options", center: "map.center", zoom: "map.zoom", styles: "map.styles", draggable: "true"}
%map-search
%markers{models: "OfnMap.enterprises", fit: "true",
coords: "'self'", icon: "'icon'", click: "'reveal'"}

View File

@@ -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

View File

@@ -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 }}

View File

@@ -1,6 +1,6 @@
.product-thumb
%a{"ng-click" => "triggerProductModal()"}
%img{"bo-src" => "product.primaryImage", "ng-click" => "triggerProductModal()"}
%img{"bo-src" => "product.primaryImageOrMissing", "ng-click" => "triggerProductModal()"}
.row.summary
.small-9.medium-10.large-11.columns.summary-header

View File

@@ -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',

View File

@@ -114,7 +114,8 @@ describe ShopController do
it "scopes variants for a product to the order cycle and distributor" do
controller.stub(:current_order_cycle).and_return order_cycle
controller.stub(:current_distributor).and_return d
Spree::Product.any_instance.should_receive(:variants_for).with(order_cycle, d)
Spree::Product.any_instance.should_receive(:variants_for).with(order_cycle, d).and_return(m = double())
m.stub(:in_stock).and_return []
xhr :get, :products
end

View File

@@ -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', [])

View File

@@ -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']

View File

@@ -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"
}, {

View File

@@ -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"

View File

@@ -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

View File

@@ -5,6 +5,8 @@ describe 'Variants service', ->
beforeEach ->
variant =
id: 1
base_price: 80.5
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 81

View File

@@ -1,5 +1,6 @@
require 'spec_helper'
# TODO this seems to be redundant
describe Cart do
describe "associations" do

View File

@@ -448,9 +448,9 @@ describe Enterprise do
linkedin: "https://linkedin.com")
}
it "strips http and www from url fields" do
distributor.website.should == "google.com"
distributor.facebook.should == "facebook.com/roger"
it "strips http from url fields" do
distributor.website.should == "www.google.com"
distributor.facebook.should == "www.facebook.com/roger"
distributor.linkedin.should == "linkedin.com"
end
end

View File

@@ -56,6 +56,7 @@ describe ProductDistribution do
adjustment.label.should == "Product distribution by #{distributor.name} for Pear"
adjustment.amount.should == 1.23
# TODO ROB this has an intermittent failure
# And it should have some associated metadata
md = adjustment.metadata
md.enterprise.should == distributor

View File

@@ -24,6 +24,7 @@ module UIComponentHelper
within ".login-modal" do
find("a", text: text).click
end
sleep 0.2
end
def open_login_modal