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