From 0f6bd7049c8b2b89587133d04c3dbbdd9ff98410 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Wed, 30 Apr 2014 12:52:47 +1000 Subject: [PATCH 01/49] Starting to build out producers Angular page --- .../producer_node_controller.js.coffee | 9 +++++++++ .../controllers/producers_controller.js.coffee | 2 ++ .../darkswarm/services/producers.js.coffee | 4 ++++ app/controllers/producers_controller.rb | 3 +++ app/views/json/_producers.rabl | 6 ++++++ app/views/producers/_fat.html.haml | 16 ++++++++++++++++ app/views/producers/_skinny.html.haml | 9 +++++++++ app/views/producers/index.haml | 15 +++++++++++++++ config/routes.rb | 2 +- spec/controllers/producers_controller_spec.rb | 3 ++- 10 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 app/assets/javascripts/darkswarm/controllers/producer_node_controller.js.coffee create mode 100644 app/assets/javascripts/darkswarm/controllers/producers_controller.js.coffee create mode 100644 app/assets/javascripts/darkswarm/services/producers.js.coffee create mode 100644 app/views/json/_producers.rabl create mode 100644 app/views/producers/_fat.html.haml create mode 100644 app/views/producers/_skinny.html.haml diff --git a/app/assets/javascripts/darkswarm/controllers/producer_node_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/producer_node_controller.js.coffee new file mode 100644 index 0000000000..03b99d7ebb --- /dev/null +++ b/app/assets/javascripts/darkswarm/controllers/producer_node_controller.js.coffee @@ -0,0 +1,9 @@ +Darkswarm.controller "ProducerNodeCtrl", ($scope, Navigation, $location, $anchorScroll) -> + $scope.toggle = -> + Navigation.navigate $scope.producer.path + + $scope.open = -> + $location.path() == $scope.producer.path + + if $scope.open() + $anchorScroll() diff --git a/app/assets/javascripts/darkswarm/controllers/producers_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/producers_controller.js.coffee new file mode 100644 index 0000000000..1a28b5b107 --- /dev/null +++ b/app/assets/javascripts/darkswarm/controllers/producers_controller.js.coffee @@ -0,0 +1,2 @@ +Darkswarm.controller "ProducersCtrl", ($scope, Producers) -> + $scope.Producers = Producers diff --git a/app/assets/javascripts/darkswarm/services/producers.js.coffee b/app/assets/javascripts/darkswarm/services/producers.js.coffee new file mode 100644 index 0000000000..62a5087642 --- /dev/null +++ b/app/assets/javascripts/darkswarm/services/producers.js.coffee @@ -0,0 +1,4 @@ +Darkswarm.factory 'Producers', (producers) -> + new class Producers + constructor: -> + @producers = producers diff --git a/app/controllers/producers_controller.rb b/app/controllers/producers_controller.rb index 615f74871c..5a3a961137 100644 --- a/app/controllers/producers_controller.rb +++ b/app/controllers/producers_controller.rb @@ -1,4 +1,7 @@ class ProducersController < BaseController + layout 'darkswarm' + def index + @producers = Enterprise.is_primary_producer.visible end end diff --git a/app/views/json/_producers.rabl b/app/views/json/_producers.rabl new file mode 100644 index 0000000000..b0fd6265c6 --- /dev/null +++ b/app/views/json/_producers.rabl @@ -0,0 +1,6 @@ +collection @producers +attributes :name, :id + +node :path do |producer| + producer_path(producer) +end diff --git a/app/views/producers/_fat.html.haml b/app/views/producers/_fat.html.haml new file mode 100644 index 0000000000..d0108680ce --- /dev/null +++ b/app/views/producers/_fat.html.haml @@ -0,0 +1,16 @@ +.row.active_table_row{"ng-show" => "open()"} + .columns.small-4 + %strong Shop for + %p.trans-sentence + {{ producer.taxons | printArray }} + .columns.small-8 + About Us + +.row.active_table_row.link{"ng-show" => "open()", "ng-repeat" => "hub in producer.hubs"} + .columns.small-11 + %a{"bo-href" => "hub.path"} + Shop at + %strong {{ hub.name }} + .columns.small-1.text-right + %a{"bo-href" => "hub.path"} + %i.fi-arrow-right diff --git a/app/views/producers/_skinny.html.haml b/app/views/producers/_skinny.html.haml new file mode 100644 index 0000000000..c87c2295ed --- /dev/null +++ b/app/views/producers/_skinny.html.haml @@ -0,0 +1,9 @@ +.row.active_table_row{"ng-click" => "toggle()", "ng-class" => "{'closed' : !open()}"} + .columns.small-4 + %strong {{ producer.name }} + .columns.small-3 + {{ producer.address.city }} + .columns.small-4 + {{ producer.address.state | uppercase }} + .columns.small-1.text-right + %i{"ng-class" => "{'fi-arrow-down' : !open(), 'fi-arrow-up' : open()}"} diff --git a/app/views/producers/index.haml b/app/views/producers/index.haml index e69de29bb2..33d5093ea3 100644 --- a/app/views/producers/index.haml +++ b/app/views/producers/index.haml @@ -0,0 +1,15 @@ +.producers{"ng-controller" => "ProducersCtrl"} + :javascript + angular.module('Darkswarm').value('producers', #{render partial: "json/producers", object: @producers}) + + .row{bindonce: true} + .small-12.columns + .active_table + %producer.active_table_node.row{id: "{{producer.path}}", + "ng-repeat" => "producer in Producers.producers", + "ng-controller" => "ProducerNodeCtrl", + "ng-class" => "{'closed' : !open(), 'open' : open(), 'inactive' : !producer.active}"} + + .small-12.columns + = render partial: 'producers/skinny' + = render partial: 'producers/fat' diff --git a/config/routes.rb b/config/routes.rb index d514641701..2352b832d6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -7,7 +7,7 @@ Openfoodnetwork::Application.routes.draw do get :order_cycle end - resources :producers, only: :index + resources :producers namespace :shop do get '/checkout', :to => 'checkout#edit' , :as => :checkout diff --git a/spec/controllers/producers_controller_spec.rb b/spec/controllers/producers_controller_spec.rb index 1d53bb90b9..885b3981a1 100644 --- a/spec/controllers/producers_controller_spec.rb +++ b/spec/controllers/producers_controller_spec.rb @@ -2,7 +2,8 @@ require 'spec_helper' describe ProducersController do it "gets all active producers" do - Enterprise.stub_chain(:active) + Enterprise.stub_chain(:is_primary_producer, :visible) + Enterprise.should_receive(:is_primary_producer) get :index end end From e901f3439a563aa894a4c51155b7de393a6b620a Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Wed, 30 Apr 2014 13:52:06 +1000 Subject: [PATCH 02/49] Starting to partialize and test the RABL partials --- app/views/json/_enterprises.rabl | 10 ++++++++++ app/views/json/_hubs.rabl | 13 +------------ app/views/json/_producers.rabl | 2 +- app/views/json/partials/_address.rabl | 4 ++++ app/views/producers/index.haml | 2 ++ spec/support/views/rabl_helper.rb | 9 +++++++++ spec/views/json/producers.json.rabl_spec.rb | 15 +++++++++++++++ 7 files changed, 42 insertions(+), 13 deletions(-) create mode 100644 app/views/json/_enterprises.rabl create mode 100644 app/views/json/partials/_address.rabl create mode 100644 spec/support/views/rabl_helper.rb create mode 100644 spec/views/json/producers.json.rabl_spec.rb diff --git a/app/views/json/_enterprises.rabl b/app/views/json/_enterprises.rabl new file mode 100644 index 0000000000..61db6f9e8d --- /dev/null +++ b/app/views/json/_enterprises.rabl @@ -0,0 +1,10 @@ +# DON'T USE DIRECTLY - for inheritance +attributes :name, :id + +child :taxons => :taxons do + attributes :name, :id +end + +child :address do + extends "json/partials/address" +end diff --git a/app/views/json/_hubs.rabl b/app/views/json/_hubs.rabl index dbd0538caf..2f91520d73 100644 --- a/app/views/json/_hubs.rabl +++ b/app/views/json/_hubs.rabl @@ -1,16 +1,5 @@ collection Enterprise.is_distributor -attributes :name, :id - -child :taxons do - attributes :name, :id -end - -child :address do - attributes :city, :zipcode - node :state do |address| - address.state.abbr - end -end +extends 'json/enterprises' node :pickup do |hub| not hub.shipping_methods.where(:require_ship_address => false).empty? diff --git a/app/views/json/_producers.rabl b/app/views/json/_producers.rabl index b0fd6265c6..318eeacbf7 100644 --- a/app/views/json/_producers.rabl +++ b/app/views/json/_producers.rabl @@ -1,5 +1,5 @@ collection @producers -attributes :name, :id +extends 'json/enterprises' node :path do |producer| producer_path(producer) diff --git a/app/views/json/partials/_address.rabl b/app/views/json/partials/_address.rabl new file mode 100644 index 0000000000..b40bbc790b --- /dev/null +++ b/app/views/json/partials/_address.rabl @@ -0,0 +1,4 @@ +attributes :city, :zipcode +node :state do |address| + address.state.abbr +end diff --git a/app/views/producers/index.haml b/app/views/producers/index.haml index 33d5093ea3..c368de6011 100644 --- a/app/views/producers/index.haml +++ b/app/views/producers/index.haml @@ -2,6 +2,8 @@ :javascript angular.module('Darkswarm').value('producers', #{render partial: "json/producers", object: @producers}) + -#%pre + -#{{ Producers.producers | json }} .row{bindonce: true} .small-12.columns .active_table diff --git a/spec/support/views/rabl_helper.rb b/spec/support/views/rabl_helper.rb new file mode 100644 index 0000000000..4ffcbef690 --- /dev/null +++ b/spec/support/views/rabl_helper.rb @@ -0,0 +1,9 @@ +module RablHelper + # See https://github.com/nesquena/rabl/issues/231 + # Allows us to test RABL views using URL helpers + class FakeContext + include Singleton + include Rails.application.routes.url_helpers + end +end + diff --git a/spec/views/json/producers.json.rabl_spec.rb b/spec/views/json/producers.json.rabl_spec.rb new file mode 100644 index 0000000000..55e9dafc35 --- /dev/null +++ b/spec/views/json/producers.json.rabl_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe 'json/_producers.json.rabl' do + let!(:producer) { create(:supplier_enterprise) } + let(:render) { Rabl.render([producer], 'json/producers', view_path: 'app/views', scope: RablHelper::FakeContext.instance) } + + it "renders a list of producers" do + render.should have_json_type(Array).at_path '' + render.should have_json_type(Object).at_path '0' + end + + it "renders names" do + render.should be_json_eql(producer.name.to_json).at_path '0/name' + end +end From dcacf01c1dc8aa2b5a77f66fcfbe74ad070887ee Mon Sep 17 00:00:00 2001 From: summerscope Date: Wed, 30 Apr 2014 15:05:41 +1000 Subject: [PATCH 03/49] Tweaking copy for food hubs modals. --- app/views/modals/_food_hub.html.haml | 1 + app/views/modals/_learn_more.html.haml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/modals/_food_hub.html.haml b/app/views/modals/_food_hub.html.haml index ceba6192f3..e80ffe3745 100644 --- a/app/views/modals/_food_hub.html.haml +++ b/app/views/modals/_food_hub.html.haml @@ -1,4 +1,5 @@ %h2 Food Hubs %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 diff --git a/app/views/modals/_learn_more.html.haml b/app/views/modals/_learn_more.html.haml index 1cfdaf6c00..870d5fe0bc 100644 --- a/app/views/modals/_learn_more.html.haml +++ b/app/views/modals/_learn_more.html.haml @@ -1,6 +1,6 @@ %h2 How it works %h5 Shop the Open Food Network -%p Search for a food hub near you to start shopping! You can expand each food hub to see what kinds of goodies are available, and click through to start shopping. +%p Search for a food hub near you to start shopping! You can expand each food hub to see what kinds of goodies are available, and click through to start shopping. (You can only shop one food hub at a time.) %h5 Pick-ups, delivery & shipping costs %p Some food hubs deliver to your door, while others require you to pick-up your purchases. You can see which options are available on the homepage, and select which you'd like at the shopping and check-out pages. Delivery will cost more, and pricing differs from hub-to-hub. Each food hub is a sales point with independent business operations and logisitics - so variations between hubs are to be expected. %h5 Learn more From 4ed81da0227d418fec0554aec48ffda1eba88f19 Mon Sep 17 00:00:00 2001 From: summerscope Date: Wed, 30 Apr 2014 15:36:42 +1000 Subject: [PATCH 04/49] Updates to styling homepage and active table --- app/assets/stylesheets/darkswarm/active_table.css.sass | 2 ++ app/assets/stylesheets/darkswarm/home_panes.css.sass | 6 ++++++ app/assets/stylesheets/darkswarm/hub_node.css.sass | 5 ----- app/assets/stylesheets/darkswarm/ui.css.sass | 1 + 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/assets/stylesheets/darkswarm/active_table.css.sass b/app/assets/stylesheets/darkswarm/active_table.css.sass index c950cad28a..2023e24cca 100644 --- a/app/assets/stylesheets/darkswarm/active_table.css.sass +++ b/app/assets/stylesheets/darkswarm/active_table.css.sass @@ -84,6 +84,8 @@ border-right: 1px solid $disabled-dark strong color: $dark-grey + &:hover, &:active, &:focus + color: $dark-grey .active_table_row:nth-child(2) border-left: 1px solid $disabled-dark border-right: 1px solid $disabled-dark diff --git a/app/assets/stylesheets/darkswarm/home_panes.css.sass b/app/assets/stylesheets/darkswarm/home_panes.css.sass index 810aaf3b17..d2c83845d5 100644 --- a/app/assets/stylesheets/darkswarm/home_panes.css.sass +++ b/app/assets/stylesheets/darkswarm/home_panes.css.sass @@ -30,3 +30,9 @@ background-image: url("/assets/home/producers-bg.svg") background-repeat: no-repeat background-position: right center + +// Responsive +@media all and (max-width: 768px) + #map, #groups, #producers + .row + background-position: center center \ No newline at end of file diff --git a/app/assets/stylesheets/darkswarm/hub_node.css.sass b/app/assets/stylesheets/darkswarm/hub_node.css.sass index f24a5e6302..b68a1462d5 100644 --- a/app/assets/stylesheets/darkswarm/hub_node.css.sass +++ b/app/assets/stylesheets/darkswarm/hub_node.css.sass @@ -20,7 +20,6 @@ &:hover background-color: $clr-brick-bright - &.closed &:hover, &:active, &:focus border: 1px solid $clr-brick @@ -34,7 +33,3 @@ .active_table_row:first-child &, & * color: $clr-brick - - - - diff --git a/app/assets/stylesheets/darkswarm/ui.css.sass b/app/assets/stylesheets/darkswarm/ui.css.sass index ddb4ab5324..29a0ee02b5 100644 --- a/app/assets/stylesheets/darkswarm/ui.css.sass +++ b/app/assets/stylesheets/darkswarm/ui.css.sass @@ -37,3 +37,4 @@ .neutral-btn.turquoise:hover, .neutral-btn.turquoise:active, .neutral-btn.turquoise:focus background-color: rgba(0, 0, 0, 0.1) text-shadow: 0 1px 0 #fff + From 8a5b93ace933ce599b2c30568185e63878bd52cc Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Wed, 30 Apr 2014 16:10:02 +1000 Subject: [PATCH 05/49] Adding a couple of basic feature tests for the sake of demonstration --- app/controllers/producers_controller.rb | 2 +- spec/features/consumer/producers_spec.rb | 11 ++++++++--- spec/spec_helper.rb | 1 - 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/controllers/producers_controller.rb b/app/controllers/producers_controller.rb index 5a3a961137..c5a133a798 100644 --- a/app/controllers/producers_controller.rb +++ b/app/controllers/producers_controller.rb @@ -1,6 +1,6 @@ class ProducersController < BaseController layout 'darkswarm' - + def index @producers = Enterprise.is_primary_producer.visible end diff --git a/spec/features/consumer/producers_spec.rb b/spec/features/consumer/producers_spec.rb index b828b2abc1..2994f27852 100644 --- a/spec/features/consumer/producers_spec.rb +++ b/spec/features/consumer/producers_spec.rb @@ -4,12 +4,17 @@ feature %q{ As a consumer I want to see a list of producers So that I can shop at hubs distributing their products -} do +}, js: true do include UIComponentHelper let!(:producer) { create(:supplier_enterprise) } - - it "shows all producers" do + + before do visit producers_path + end + + it "shows all producers with expandable details" do page.should have_content producer.name + expand_active_table_node producer.name + page.should have_content producer.taxons.join(' ') end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6cf9229252..1d66f672ec 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -41,7 +41,6 @@ Capybara.register_driver :poltergeist do |app| #options.merge! {timeout: 5.minutes} # Enable the remote inspector: Use page.driver.debug to open a remote debugger in chrome #options.merge! {inspector: true} - Capybara::Poltergeist::Driver.new(app, options) end From c1ab0c0f0b9a2d1eaf6400f4addb00eb0793e69a Mon Sep 17 00:00:00 2001 From: summerscope Date: Wed, 30 Apr 2014 16:12:39 +1000 Subject: [PATCH 06/49] Renaming sass files for relevance. Style tweaks for large input to fix firefox bug. --- .../darkswarm/{tagline.css.sass => home_tagline.css.sass} | 3 ++- app/assets/stylesheets/darkswarm/hub_search.css.sass | 5 +---- app/assets/stylesheets/darkswarm/mixins.sass | 3 ++- 3 files changed, 5 insertions(+), 6 deletions(-) rename app/assets/stylesheets/darkswarm/{tagline.css.sass => home_tagline.css.sass} (63%) diff --git a/app/assets/stylesheets/darkswarm/tagline.css.sass b/app/assets/stylesheets/darkswarm/home_tagline.css.sass similarity index 63% rename from app/assets/stylesheets/darkswarm/tagline.css.sass rename to app/assets/stylesheets/darkswarm/home_tagline.css.sass index b8a0d7cec5..950a3c216d 100644 --- a/app/assets/stylesheets/darkswarm/tagline.css.sass +++ b/app/assets/stylesheets/darkswarm/home_tagline.css.sass @@ -2,7 +2,8 @@ @import mixins #tagline - background: black url("/assets/home/tagline-bg.jpg") + background-color: black + background-image: url("/assets/home/tagline-bg.jpg") @include fullbg height: 400px padding: 40px 0px diff --git a/app/assets/stylesheets/darkswarm/hub_search.css.sass b/app/assets/stylesheets/darkswarm/hub_search.css.sass index d1b28f9ad1..6c608171ac 100644 --- a/app/assets/stylesheets/darkswarm/hub_search.css.sass +++ b/app/assets/stylesheets/darkswarm/hub_search.css.sass @@ -3,7 +3,4 @@ #hub-search input font-size: 2em - @include big-input - //.advanced - //padding-top: 8px - //@include disabled + @include big-input \ No newline at end of file diff --git a/app/assets/stylesheets/darkswarm/mixins.sass b/app/assets/stylesheets/darkswarm/mixins.sass index 1daabe34a5..1a3c81c478 100644 --- a/app/assets/stylesheets/darkswarm/mixins.sass +++ b/app/assets/stylesheets/darkswarm/mixins.sass @@ -5,7 +5,8 @@ border: 1px solid #999 font-size: 18px @extend .avenir - padding: 30px 20px + padding: 22px 18px + height: auto margin-bottom: 1em @mixin disabled From 2ff2d3dcbd0458eb60861457d4e39d35efb2eb91 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Thu, 1 May 2014 15:51:40 +1000 Subject: [PATCH 07/49] Starting to work on test format --- app/controllers/shop/checkout_controller.rb | 1 + .../consumer/shopping/checkout_spec.rb | 182 +++++++++--------- spec/support/request/shop_workflow.rb | 4 + 3 files changed, 94 insertions(+), 93 deletions(-) diff --git a/app/controllers/shop/checkout_controller.rb b/app/controllers/shop/checkout_controller.rb index 8f28645ab8..846da4d17d 100644 --- a/app/controllers/shop/checkout_controller.rb +++ b/app/controllers/shop/checkout_controller.rb @@ -8,6 +8,7 @@ class Shop::CheckoutController < Spree::CheckoutController include EnterprisesHelper def edit + binding.pry end def update diff --git a/spec/features/consumer/shopping/checkout_spec.rb b/spec/features/consumer/shopping/checkout_spec.rb index a780e9fd4e..5d473494ae 100644 --- a/spec/features/consumer/shopping/checkout_spec.rb +++ b/spec/features/consumer/shopping/checkout_spec.rb @@ -9,122 +9,118 @@ feature "As a consumer I want to check out my cart", js: true do let(:distributor) { create(:distributor_enterprise) } let(:supplier) { create(:supplier_enterprise) } - let(:order_cycle) { create(:order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise)) } + let!(:order_cycle) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise)) } let(:product) { create(:simple_product, supplier: supplier) } - let(:order) { Spree::Order.last } + let(:order) { create(:order, order_cycle: order_cycle, distributor: distributor) } before do - order_cycle # force this to load - create_enterprise_group_for distributor + set_order order + add_product_to_cart end - describe "logged out, distributor selected, order cycle selected, product in cart" do - let(:user) { create_enterprise_user } + it "shows the current distributor" do + visit shop_checkout_path + page.should have_content distributor.name + end + + pending "with shipping methods" do + let(:sm1) { create(:shipping_method, require_ship_address: true, name: "Frogs", description: "yellow") } + let(:sm2) { create(:shipping_method, require_ship_address: false, name: "Donkeys", description: "blue") } before do - select_distributor - select_order_cycle - add_product_to_cart + distributor.shipping_methods << sm1 + distributor.shipping_methods << sm2 end - describe "with shipping methods" do - let(:sm1) { create(:shipping_method, require_ship_address: true, name: "Frogs", description: "yellow") } - let(:sm2) { create(:shipping_method, require_ship_address: false, name: "Donkeys", description: "blue") } + context "on the checkout page" do before do - distributor.shipping_methods << sm1 - distributor.shipping_methods << sm2 + visit "/shop/checkout" + end + it "shows all shipping methods, but doesn't show ship address when not needed" do + toggle_accordion "Shipping" + page.should have_content "Frogs" + page.should have_content "Donkeys" end - context "on the checkout page" do + context "When shipping method requires an address" do before do - visit "/shop/checkout" - end - it "shows all shipping methods, but doesn't show ship address when not needed" do toggle_accordion "Shipping" - page.should have_content "Frogs" - page.should have_content "Donkeys" + choose(sm1.name) end - - context "When shipping method requires an address" do - before do - toggle_accordion "Shipping" - choose(sm1.name) - end - it "shows ship address forms when 'same as billing address' is unchecked" do - uncheck "Shipping address same as billing address?" - find("#ship_address > div.visible").visible?.should be_true - end + it "shows ship address forms when 'same as billing address' is unchecked" do + uncheck "Shipping address same as billing address?" + find("#ship_address > div.visible").visible?.should be_true end end + end - describe "with payment methods" do - let(:pm1) { create(:payment_method, distributors: [distributor], name: "Roger rabbit", type: "Spree::PaymentMethod::Check") } - let(:pm2) { create(:payment_method, distributors: [distributor]) } - let(:pm3) { create(:payment_method, distributors: [distributor], name: "Paypal", type: "Spree::BillingIntegration::PaypalExpress") } + describe "with payment methods" do + let(:pm1) { create(:payment_method, distributors: [distributor], name: "Roger rabbit", type: "Spree::PaymentMethod::Check") } + let(:pm2) { create(:payment_method, distributors: [distributor]) } + let(:pm3) { create(:payment_method, distributors: [distributor], name: "Paypal", type: "Spree::BillingIntegration::PaypalExpress") } - before do - pm1 # Lazy evaluation of ze create()s - pm2 - visit "/shop/checkout" + before do + pm1 # Lazy evaluation of ze create()s + pm2 + visit "/shop/checkout" + toggle_accordion "Payment Details" + end + + it "shows all available payment methods" do + page.should have_content pm1.name + page.should have_content pm2.name + end + + describe "Purchasing" do + it "takes us to the order confirmation page when we submit a complete form" do + toggle_accordion "Shipping" + choose sm2.name toggle_accordion "Payment Details" + choose pm1.name + toggle_accordion "Customer Details" + within "#details" do + fill_in "First Name", with: "Will" + fill_in "Last Name", with: "Marshall" + fill_in "Email", with: "test@test.com" + fill_in "Phone", with: "0468363090" + end + toggle_accordion "Billing" + within "#billing" do + fill_in "Address", with: "123 Your Face" + select "Australia", from: "Country" + select "Victoria", from: "State" + fill_in "City", with: "Melbourne" + fill_in "Postcode", with: "3066" + end + click_button "Purchase" + sleep 10 + page.should have_content "Your order has been processed successfully" end - it "shows all available payment methods" do - page.should have_content pm1.name - page.should have_content pm2.name - end - - describe "Purchasing" do - it "takes us to the order confirmation page when we submit a complete form" do - toggle_accordion "Shipping" - choose sm2.name - toggle_accordion "Payment Details" - choose pm1.name - toggle_accordion "Customer Details" - within "#details" do - fill_in "First Name", with: "Will" - fill_in "Last Name", with: "Marshall" - fill_in "Email", with: "test@test.com" - fill_in "Phone", with: "0468363090" - end - toggle_accordion "Billing" - within "#billing" do - fill_in "Address", with: "123 Your Face" - select "Australia", from: "Country" - select "Victoria", from: "State" - fill_in "City", with: "Melbourne" - fill_in "Postcode", with: "3066" - end - click_button "Purchase" - sleep 10 - page.should have_content "Your order has been processed successfully" + it "takes us to the order confirmation page when submitted with 'same as billing address' checked" do + toggle_accordion "Shipping" + choose sm1.name + toggle_accordion "Payment Details" + choose pm1.name + toggle_accordion "Customer Details" + within "#details" do + fill_in "First Name", with: "Will" + fill_in "Last Name", with: "Marshall" + fill_in "Email", with: "test@test.com" + fill_in "Phone", with: "0468363090" end - - it "takes us to the order confirmation page when submitted with 'same as billing address' checked" do - toggle_accordion "Shipping" - choose sm1.name - toggle_accordion "Payment Details" - choose pm1.name - toggle_accordion "Customer Details" - within "#details" do - fill_in "First Name", with: "Will" - fill_in "Last Name", with: "Marshall" - fill_in "Email", with: "test@test.com" - fill_in "Phone", with: "0468363090" - end - toggle_accordion "Billing" - within "#billing" do - fill_in "City", with: "Melbourne" - fill_in "Postcode", with: "3066" - fill_in "Address", with: "123 Your Face" - select "Australia", from: "Country" - select "Victoria", from: "State" - end - toggle_accordion "Shipping" - check "Shipping address same as billing address?" - click_button "Purchase" - sleep 10 - page.should have_content "Your order has been processed successfully" + toggle_accordion "Billing" + within "#billing" do + fill_in "City", with: "Melbourne" + fill_in "Postcode", with: "3066" + fill_in "Address", with: "123 Your Face" + select "Australia", from: "Country" + select "Victoria", from: "State" end + toggle_accordion "Shipping" + check "Shipping address same as billing address?" + click_button "Purchase" + sleep 10 + page.should have_content "Your order has been processed successfully" end end end diff --git a/spec/support/request/shop_workflow.rb b/spec/support/request/shop_workflow.rb index 2f9bd3c5ff..5c473d7f62 100644 --- a/spec/support/request/shop_workflow.rb +++ b/spec/support/request/shop_workflow.rb @@ -1,4 +1,8 @@ module ShopWorkflow + def set_order(order) + ApplicationController.any_instance.stub(:session).and_return({order_id: order.id, access_token: order.token}) + end + def select_distributor # If no order cycles are available this is much faster visit "/" From 6ad30d901d0647031897b6b4eee96b985ca3e42f Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Thu, 1 May 2014 16:22:11 +1000 Subject: [PATCH 08/49] Tidying down shop/checkout test --- app/controllers/application_controller.rb | 2 +- app/controllers/shop/checkout_controller.rb | 7 ------ app/controllers/shop/shop_controller.rb | 9 +------ app/views/shop/shop/_order_cycles.html.haml | 2 +- .../consumer/shopping/checkout_spec.rb | 24 +++++++++---------- 5 files changed, 14 insertions(+), 30 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 9e4f4d4832..d9cb36a3e9 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -15,7 +15,7 @@ class ApplicationController < ActionController::Base private def require_distributor_chosen - unless current_distributor + unless @distributor = current_distributor redirect_to spree.root_path false end diff --git a/app/controllers/shop/checkout_controller.rb b/app/controllers/shop/checkout_controller.rb index 846da4d17d..f2d79e503a 100644 --- a/app/controllers/shop/checkout_controller.rb +++ b/app/controllers/shop/checkout_controller.rb @@ -8,7 +8,6 @@ class Shop::CheckoutController < Spree::CheckoutController include EnterprisesHelper def edit - binding.pry end def update @@ -70,12 +69,6 @@ class Shop::CheckoutController < Spree::CheckoutController def skip_state_validation? true end - - def set_distributor - unless @distributor = current_distributor - redirect_to main_app.root_path - end - end def load_order @order = current_order diff --git a/app/controllers/shop/shop_controller.rb b/app/controllers/shop/shop_controller.rb index 9db927cece..5ee8cdb19f 100644 --- a/app/controllers/shop/shop_controller.rb +++ b/app/controllers/shop/shop_controller.rb @@ -1,7 +1,6 @@ class Shop::ShopController < BaseController layout "darkswarm" - - before_filter :set_distributor + before_filter :require_distributor_chosen before_filter :set_order_cycles def show @@ -32,12 +31,6 @@ class Shop::ShopController < BaseController private - def set_distributor - unless @distributor = current_distributor - redirect_to root_path - end - end - def set_order_cycles @order_cycles = OrderCycle.with_distributor(@distributor).active diff --git a/app/views/shop/shop/_order_cycles.html.haml b/app/views/shop/shop/_order_cycles.html.haml index 7c5ff51df3..1ec978dce2 100644 --- a/app/views/shop/shop/_order_cycles.html.haml +++ b/app/views/shop/shop/_order_cycles.html.haml @@ -2,7 +2,7 @@ :javascript angular.module('Darkswarm').value('orderCycleData', #{render "shop/shop/order_cycle"}) - - if @order_cycles.empty? + - if @order_cycles and @order_cycles.empty? Orders are currently closed for this hub %p Please contact your hub directly to see if they accept late orders, diff --git a/spec/features/consumer/shopping/checkout_spec.rb b/spec/features/consumer/shopping/checkout_spec.rb index 5d473494ae..efc1d1ab5b 100644 --- a/spec/features/consumer/shopping/checkout_spec.rb +++ b/spec/features/consumer/shopping/checkout_spec.rb @@ -18,12 +18,13 @@ feature "As a consumer I want to check out my cart", js: true do add_product_to_cart end - it "shows the current distributor" do + it "shows the current distributor oncheckout" do visit shop_checkout_path + current_path.should == shop_checkout_path page.should have_content distributor.name end - pending "with shipping methods" do + describe "with shipping methods" do let(:sm1) { create(:shipping_method, require_ship_address: true, name: "Frogs", description: "yellow") } let(:sm2) { create(:shipping_method, require_ship_address: false, name: "Donkeys", description: "blue") } before do @@ -33,8 +34,9 @@ feature "As a consumer I want to check out my cart", js: true do context "on the checkout page" do before do - visit "/shop/checkout" + visit shop_checkout_path end + it "shows all shipping methods, but doesn't show ship address when not needed" do toggle_accordion "Shipping" page.should have_content "Frogs" @@ -54,14 +56,12 @@ feature "As a consumer I want to check out my cart", js: true do end describe "with payment methods" do - let(:pm1) { create(:payment_method, distributors: [distributor], name: "Roger rabbit", type: "Spree::PaymentMethod::Check") } - let(:pm2) { create(:payment_method, distributors: [distributor]) } - let(:pm3) { create(:payment_method, distributors: [distributor], name: "Paypal", type: "Spree::BillingIntegration::PaypalExpress") } + let!(:pm1) { create(:payment_method, distributors: [distributor], name: "Roger rabbit", type: "Spree::PaymentMethod::Check") } + let!(:pm2) { create(:payment_method, distributors: [distributor]) } + let!(:pm3) { create(:payment_method, distributors: [distributor], name: "Paypal", type: "Spree::BillingIntegration::PaypalExpress") } before do - pm1 # Lazy evaluation of ze create()s - pm2 - visit "/shop/checkout" + visit shop_checkout_path toggle_accordion "Payment Details" end @@ -92,8 +92,7 @@ feature "As a consumer I want to check out my cart", js: true do fill_in "Postcode", with: "3066" end click_button "Purchase" - sleep 10 - page.should have_content "Your order has been processed successfully" + page.should have_content "Your order has been processed successfully", wait: 10 end it "takes us to the order confirmation page when submitted with 'same as billing address' checked" do @@ -119,8 +118,7 @@ feature "As a consumer I want to check out my cart", js: true do toggle_accordion "Shipping" check "Shipping address same as billing address?" click_button "Purchase" - sleep 10 - page.should have_content "Your order has been processed successfully" + page.should have_content "Your order has been processed successfully", wait: 10 end end end From 59d2bc908e3aff8aeca28a23f2011e7deb71c4bf Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Thu, 1 May 2014 17:11:56 +1000 Subject: [PATCH 09/49] Adding quick login, more test refactoring --- spec/controllers/shop/shop_controller_spec.rb | 84 +++++++++ .../consumer/shopping/checkout_auth_spec.rb | 52 ++---- .../consumer/shopping/checkout_spec.rb | 3 +- .../consumer/shopping/shopping_spec.rb | 164 ++++-------------- .../request/authentication_workflow.rb | 4 + 5 files changed, 139 insertions(+), 168 deletions(-) diff --git a/spec/controllers/shop/shop_controller_spec.rb b/spec/controllers/shop/shop_controller_spec.rb index b7c86fbc0e..e94e785573 100644 --- a/spec/controllers/shop/shop_controller_spec.rb +++ b/spec/controllers/shop/shop_controller_spec.rb @@ -111,6 +111,90 @@ describe Shop::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 diff --git a/spec/features/consumer/shopping/checkout_auth_spec.rb b/spec/features/consumer/shopping/checkout_auth_spec.rb index c6ac18e87d..f1650109ca 100644 --- a/spec/features/consumer/shopping/checkout_auth_spec.rb +++ b/spec/features/consumer/shopping/checkout_auth_spec.rb @@ -8,49 +8,29 @@ feature "As a consumer I want to check out my cart", js: true do let(:distributor) { create(:distributor_enterprise) } let(:supplier) { create(:supplier_enterprise) } - let(:order_cycle) { create(:order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise)) } + let!(:order_cycle) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise)) } let(:product) { create(:simple_product, supplier: supplier) } - let(:order) { Spree::Order.last } + let(:order) { create(:order, order_cycle: order_cycle, distributor: distributor) } + let(:user) { create_enterprise_user } before do - order_cycle - create_enterprise_group_for distributor + set_order order + add_product_to_cart end - # This was refactored in the new checkout - # We have monkey-patched in some of the new features - # Test suite works in that branch - describe "Login behaviour" do - let(:user) { create_enterprise_user } - before do - select_distributor - select_order_cycle - add_product_to_cart + it "does not not render the login form when logged in" do + quick_login_as user + visit shop_checkout_path + within "section[role='main']" do + page.should_not have_content "USER" end + end - context "logged in" do - before do - login_to_consumer_section - visit "/shop/checkout" - end - it "does not not render the login form" do - within "section[role='main']" do - page.should_not have_content "USER" - end - end - end - - context "logged out" do - before do - visit "/shop/checkout" - toggle_accordion "User" - end - - it "renders the login form if user is logged out" do - within "section[role='main']" do - page.should have_content "User" - end - end + it "renders the login form when logged out" do + visit shop_checkout_path + toggle_accordion "User" + within "section[role='main']" do + page.should have_content "User" end end end diff --git a/spec/features/consumer/shopping/checkout_spec.rb b/spec/features/consumer/shopping/checkout_spec.rb index efc1d1ab5b..1c0d6ff32e 100644 --- a/spec/features/consumer/shopping/checkout_spec.rb +++ b/spec/features/consumer/shopping/checkout_spec.rb @@ -20,11 +20,10 @@ feature "As a consumer I want to check out my cart", js: true do it "shows the current distributor oncheckout" do visit shop_checkout_path - current_path.should == shop_checkout_path page.should have_content distributor.name end - describe "with shipping methods" do + pending "with shipping methods" do let(:sm1) { create(:shipping_method, require_ship_address: true, name: "Frogs", description: "yellow") } let(:sm2) { create(:shipping_method, require_ship_address: false, name: "Donkeys", description: "blue") } before do diff --git a/spec/features/consumer/shopping/shopping_spec.rb b/spec/features/consumer/shopping/shopping_spec.rb index 4a91b1186a..8c72e209e9 100644 --- a/spec/features/consumer/shopping/shopping_spec.rb +++ b/spec/features/consumer/shopping/shopping_spec.rb @@ -3,48 +3,42 @@ require 'spec_helper' feature "As a consumer I want to shop with a distributor", js: true do include AuthenticationWorkflow include WebHelper + include ShopWorkflow include UIComponentHelper describe "Viewing a distributor" do - let(:supplier) { create(:supplier_enterprise) } + let(:distributor) { create(:distributor_enterprise) } - let(:oc1) { create(:order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise), orders_close_at: 2.days.from_now) } - let(:oc2) {create(:simple_order_cycle, distributors: [distributor], orders_close_at: 3.days.from_now)} - let(:exchange2) { Exchange.find(oc2.exchanges.to_enterprises(distributor).outgoing.first.id) } + 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(:oc2) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise), orders_close_at: 3.days.from_now) } + let(:product) { create(:simple_product, supplier: supplier) } + let(:order) { create(:order, distributor: distributor) } before do - oc1 - create_enterprise_group_for distributor - visit root_path - follow_active_table_node distributor.name + set_order order end it "shows a distributor with images" do visit shop_path page.should have_text distributor.name - find("#tab_about a").click first("distributor img")['src'].should == distributor.logo.url(:thumb) first("#about img")['src'].should == distributor.promo_image.url(:large) end - describe "with products in order cycles" do - let(:product) { create(:product, supplier: supplier) } - before do - exchange = Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) - exchange.variants << product.master - end + it "shows the producers for a distributor" do + exchange = Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) + exchange.variants << product.master - it "shows the suppliers/producers for a distributor" do - visit shop_path - find("#tab_producers a").click - page.should have_content supplier.name - end + visit shop_path + find("#tab_producers a").click + page.should have_content supplier.name end - # PENDING THIS because Capybara is the wrong tool to test Angular and these tests keep breaking - pending "selecting an order cycle" do + describe "selecting an order cycle" do let(:exchange1) { Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) } + let(:exchange2) { Exchange.find(oc2.exchanges.to_enterprises(distributor).outgoing.first.id) } it "selects an order cycle if only one is open" do exchange1.update_attribute :pickup_time, "turtles" @@ -56,18 +50,18 @@ feature "As a consumer I want to shop with a distributor", js: true do before do exchange1.update_attribute :pickup_time, "frogs" exchange2.update_attribute :pickup_time, "turtles" - visit shop_path end it "shows a select with all order cycles, but doesn't show the products by default" do + visit shop_path page.should have_selector "option", text: 'frogs' page.should have_selector "option", text: 'turtles' - page.should_not have_selector "option[selected]" page.should_not have_selector("input.button.right", visible: true) end - pending "shows the table after an order cycle is selected" do - select "frogs", :from => "order_cycle_id" + it "shows the table after an order cycle is selected" do + order.update_attribute(:order_cycle, oc1) + visit shop_path page.should have_selector("input.button.right", visible: true) end @@ -84,7 +78,7 @@ feature "As a consumer I want to shop with a distributor", js: true do select "frogs", :from => "order_cycle_id" page.should have_selector "products" - page.should have_content "Orders close 2 days from now" + page.should have_content "Orders close in 2 days" Spree::Order.last.order_cycle.should == oc1 page.should have_content product.name end @@ -92,31 +86,26 @@ feature "As a consumer I want to shop with a distributor", js: true do end describe "after selecting an order cycle with products visible" do - let(:oc) { create(:simple_order_cycle, distributors: [distributor]) } - let(:product) { create(:simple_product, price: 10) } let(:variant1) { create(:variant, product: product, price: 20) } let(:variant2) { create(:variant, product: product, price: 30) } - let(:exchange) { Exchange.find(oc.exchanges.to_enterprises(distributor).outgoing.first.id) } + let(:exchange) { Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) } before do exchange.update_attribute :pickup_time, "frogs" exchange.variants << product.master exchange.variants << variant1 exchange.variants << variant2 - visit shop_path - select "frogs", :from => "order_cycle_id" - exchange + order.order_cycle = oc1 end 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) - end - it "expands variants by default" do + #it "expands variants by default" do page.should have_text variant1.options_text - end - it "expands variants" do + #it "expands variants" do find(".collapse").trigger "click" page.should_not have_text variant1.options_text end @@ -126,11 +115,7 @@ feature "As a consumer I want to shop with a distributor", js: true do enterprise_fee2 = create(:enterprise_fee, amount: 3) exchange.enterprise_fees = [enterprise_fee1, enterprise_fee2] exchange.save - visit shop_path - select "frogs", :from => "order_cycle_id" - - # All prices are as above plus $23 in fees # Page should not have product.price (with or without fee) page.should_not have_selector 'tr.product > td', text: "from $10.00" @@ -144,95 +129,16 @@ feature "As a consumer I want to shop with a distributor", js: true do page.should have_selector 'tr.product > td', text: "from $43.00" end end - - describe "filtering products" do - let(:oc) { create(:simple_order_cycle, distributors: [distributor]) } - 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) } - - 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(oc.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 - visit shop_path - select "frogs", :from => "order_cycle_id" - exchange - 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 + describe "group buy products" do - let(:oc) { create(:simple_order_cycle, distributors: [distributor]) } let(:product) { create(:simple_product, group_buy: true, on_hand: 15) } let(:product2) { create(:simple_product, group_buy: false) } describe "without variants" do before do build_and_select_order_cycle + visit shop_path end it "should show group buy input" do @@ -265,6 +171,7 @@ feature "As a consumer I want to shop with a distributor", js: true do let(:variant) { create(:variant, product: product, on_hand: 10 ) } before do build_and_select_order_cycle_with_variants + visit shop_path end it "should show group buy input" do @@ -289,6 +196,7 @@ feature "As a consumer I want to shop with a distributor", js: true do let(:variant) { create(:variant, product: product) } before do build_and_select_order_cycle_with_variants + visit shop_path end it "should let us add products to our cart" do fill_in "variants[#{variant.id}]", with: "1" @@ -321,21 +229,17 @@ feature "As a consumer I want to shop with a distributor", js: true do end def build_and_select_order_cycle - exchange = Exchange.find(oc.exchanges.to_enterprises(distributor).outgoing.first.id) + exchange = Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) exchange.update_attribute :pickup_time, "frogs" exchange.variants << product.master - visit shop_path - select "frogs", :from => "order_cycle_id" - exchange + order.order_cycle = oc1 end def build_and_select_order_cycle_with_variants - exchange = Exchange.find(oc.exchanges.to_enterprises(distributor).outgoing.first.id) + exchange = Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) exchange.update_attribute :pickup_time, "frogs" exchange.variants << product.master exchange.variants << variant - visit shop_path - select "frogs", :from => "order_cycle_id" - exchange + order.order_cycle = oc1 end diff --git a/spec/support/request/authentication_workflow.rb b/spec/support/request/authentication_workflow.rb index 3bcdabfcf2..e01b02bca5 100644 --- a/spec/support/request/authentication_workflow.rb +++ b/spec/support/request/authentication_workflow.rb @@ -1,4 +1,8 @@ module AuthenticationWorkflow + def quick_login_as(user) + ApplicationController.any_instance.stub(:spree_current_user).and_return user + end + def login_to_admin_section admin_role = Spree::Role.find_or_create_by_name!('admin') admin_user = create(:user, From 2d536e01e76e07b324316d6e2cf55e11326339f8 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Thu, 1 May 2014 17:21:46 +1000 Subject: [PATCH 10/49] Patching some deadlocks --- app/controllers/shop/shop_controller.rb | 2 +- spec/features/consumer/shopping/shopping_spec.rb | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/controllers/shop/shop_controller.rb b/app/controllers/shop/shop_controller.rb index 5ee8cdb19f..d06b521e9b 100644 --- a/app/controllers/shop/shop_controller.rb +++ b/app/controllers/shop/shop_controller.rb @@ -1,7 +1,7 @@ class Shop::ShopController < BaseController layout "darkswarm" before_filter :require_distributor_chosen - before_filter :set_order_cycles + before_filter :set_order_cycles, only: :show def show end diff --git a/spec/features/consumer/shopping/shopping_spec.rb b/spec/features/consumer/shopping/shopping_spec.rb index 8c72e209e9..861351a635 100644 --- a/spec/features/consumer/shopping/shopping_spec.rb +++ b/spec/features/consumer/shopping/shopping_spec.rb @@ -60,8 +60,9 @@ feature "As a consumer I want to shop with a distributor", js: true do end it "shows the table after an order cycle is selected" do - order.update_attribute(:order_cycle, oc1) visit shop_path + select "frogs", :from => "order_cycle_id" + page.should have_content distributor.name # This forces a wait, allowing the Ajax call to finish page.should have_selector("input.button.right", visible: true) end From 1703f7503b07486c9c44d9f2ed5bf44d8337b4ac Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Thu, 1 May 2014 17:43:02 +1000 Subject: [PATCH 11/49] Removing dead weight --- ...distributor_info_rich_text_feature_spec.rb | 171 ---------- .../consumer/shopping/shopping_spec.rb | 303 ++++++++---------- spec/support/request/shop_workflow.rb | 27 +- 3 files changed, 146 insertions(+), 355 deletions(-) delete mode 100644 spec/features/chili/enterprises_distributor_info_rich_text_feature_spec.rb diff --git a/spec/features/chili/enterprises_distributor_info_rich_text_feature_spec.rb b/spec/features/chili/enterprises_distributor_info_rich_text_feature_spec.rb deleted file mode 100644 index 3628ea3b91..0000000000 --- a/spec/features/chili/enterprises_distributor_info_rich_text_feature_spec.rb +++ /dev/null @@ -1,171 +0,0 @@ -require 'spec_helper' - -feature "enterprises distributor info as rich text" do - include AuthenticationWorkflow - include WebHelper - include UIComponentHelper - - before(:each) do - OpenFoodNetwork::FeatureToggle.stub(:features).and_return({eaterprises: false, - local_organics: true, - enterprises_distributor_info_rich_text: true}) - - - ActionMailer::Base.delivery_method = :test - ActionMailer::Base.perform_deliveries = true - ActionMailer::Base.deliveries = [] - # The deployment is not set to local_organics on Rails init, so these - # - # initializers won't run. Re-call them now that the deployment is set. - end - - after do - ActionMailer::Base.deliveries.clear - end - - - scenario "setting distributor info as admin" do - # Given I'm signed in as an admin - login_to_admin_section - - # When I go to create a new enterprise - click_link 'Enterprises' - click_link 'New Enterprise' - - # Then I should see fields 'Profile Info' and 'Distributor Info' - page.should have_content 'About Us' - page.should have_content 'How does it work' - - # When I fill out the form and create the enterprise - fill_in 'enterprise_name', :with => 'Eaterprises' - fill_in 'enterprise_long_description', with: 'Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro.' - fill_in 'enterprise_distributor_info', with: 'Chu ge sai yubi dan bisento tobi ashi yubi ge omote.' - fill_in 'enterprise_address_attributes_address1', with: '35 Ballantyne St' - fill_in 'enterprise_address_attributes_city', with: 'Thornbury' - fill_in 'enterprise_address_attributes_zipcode', with: '3072' - select 'Australia', from: 'enterprise_address_attributes_country_id' - select 'Victoria', from: 'enterprise_address_attributes_state_id' - - click_button 'Create' - - # Then I should see the enterprise details - flash_message.should == 'Enterprise "Eaterprises" has been successfully created!' - click_link 'Eaterprises' - page.should have_selector "tr[data-hook='long_description'] th", text: 'Profile Info:' - page.should have_selector "tr[data-hook='long_description'] td", text: 'Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro.' - - page.should have_selector "tr[data-hook='distributor_info'] th", text: 'Distributor Info:' - page.should have_selector "tr[data-hook='distributor_info'] td", text: 'Chu ge sai yubi dan bisento tobi ashi yubi ge omote.' - end - - scenario "viewing distributor info with product distribution", js: true do - - d = create(:distributor_enterprise, distributor_info: 'Chu ge sai yubi dan bisento tobi ashi yubi ge omote.', next_collection_at: 'Thursday 2nd May') - p = create(:product, :distributors => [d]) - - setup_shipping_details d - - login_to_consumer_section - visit spree.select_distributor_order_path(d) - ActionMailer::Base.deliveries.clear - - # -- Product details page - visit spree.product_path p - within '#product-distributor-details' do - page.should have_content 'Chu ge sai yubi dan bisento tobi ashi yubi ge omote.' - page.should have_content 'Thursday 2nd May' - end - - # -- Checkout - click_button 'Add To Cart' - visit "/checkout" - within 'fieldset#shipping' do - page.should have_content 'Chu ge sai yubi dan bisento tobi ashi yubi ge omote.' - page.should have_content 'Thursday 2nd May' - end - - # -- Confirmation - complete_purchase_from_checkout_address_page - #page.should have_content 'Thursday 2nd May' - - # -- Purchase email - wait_until { ActionMailer::Base.deliveries.length == 1 } - email = ActionMailer::Base.deliveries.last - email.body.should =~ /Chu ge sai yubi dan bisento tobi ashi yubi ge omote./ - email.body.should =~ /Thursday 2nd May/ - end - - scenario "viewing distributor info with order cycle distribution", js: true do - set_feature_toggle :order_cycles, true - ActionMailer::Base.deliveries.clear - - d = create(:distributor_enterprise, name: 'Green Grass', distributor_info: 'Chu ge sai yubi dan bisento tobi ashi yubi ge omote.', next_collection_at: 'Thursday 2nd May') - create_enterprise_group_for d - p = create(:product) - oc = create(:simple_order_cycle, distributors: [d], variants: [p.master]) - ex = oc.exchanges.outgoing.last - ex = Exchange.find ex.id - ex.pickup_time = 'Friday 4th May' - ex.save! - - setup_shipping_details d - - login_to_consumer_section - ActionMailer::Base.deliveries.clear - follow_active_table_node 'Green Grass' - visit enterprise_path d - - # -- Product details page - click_link p.name - within '#product-distributor-details' do - page.should have_content 'Chu ge sai yubi dan bisento tobi ashi yubi ge omote.' - page.should have_content 'Friday 4th May' - end - - # -- Checkout - click_button 'Add To Cart' - find('#checkout-link').click - visit "/checkout" - within 'fieldset#shipping' do - page.should have_content 'Chu ge sai yubi dan bisento tobi ashi yubi ge omote.' - page.should have_content 'Friday 4th May' - end - - # -- Confirmation - complete_purchase_from_checkout_address_page - page.should have_content 'Friday 4th May' - - # -- Purchase email - wait_until { ActionMailer::Base.deliveries.length == 1 } - email = ActionMailer::Base.deliveries.last - email.body.should =~ /Chu ge sai yubi dan bisento tobi ashi yubi ge omote./ - email.body.should =~ /Friday 4th May/ - end - - - private - def setup_shipping_details(distributor) - zone = create(:zone) - c = Spree::Country.find_by_name('Australia') - Spree::ZoneMember.create(:zoneable => c, :zone => zone) - create(:shipping_method, zone: zone, require_ship_address: false) - create(:payment_method, :description => 'Cheque payment method', distributors: [distributor]) - end - - - def complete_purchase_from_checkout_address_page - fill_in_fields('order_bill_address_attributes_firstname' => 'Joe', - 'order_bill_address_attributes_lastname' => 'Luck', - 'order_bill_address_attributes_address1' => '19 Sycamore Lane', - 'order_bill_address_attributes_city' => 'Horse Hill', - 'order_bill_address_attributes_zipcode' => '3213', - 'order_bill_address_attributes_phone' => '12999911111') - - select('Australia', :from => 'order_bill_address_attributes_country_id') - select('Victoria', :from => 'order_bill_address_attributes_state_id') - - click_checkout_continue_button - click_checkout_continue_button - click_checkout_continue_button - end -end diff --git a/spec/features/consumer/shopping/shopping_spec.rb b/spec/features/consumer/shopping/shopping_spec.rb index 861351a635..2fbb4af1d5 100644 --- a/spec/features/consumer/shopping/shopping_spec.rb +++ b/spec/features/consumer/shopping/shopping_spec.rb @@ -38,7 +38,6 @@ feature "As a consumer I want to shop with a distributor", js: true do describe "selecting an order cycle" do let(:exchange1) { Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) } - let(:exchange2) { Exchange.find(oc2.exchanges.to_enterprises(distributor).outgoing.first.id) } it "selects an order cycle if only one is open" do exchange1.update_attribute :pickup_time, "turtles" @@ -47,6 +46,7 @@ feature "As a consumer I want to shop with a distributor", js: true do end describe "with multiple order cycles" do + let(:exchange2) { Exchange.find(oc2.exchanges.to_enterprises(distributor).outgoing.first.id) } before do exchange1.update_attribute :pickup_time, "frogs" exchange2.update_attribute :pickup_time, "turtles" @@ -58,189 +58,152 @@ feature "As a consumer I want to shop with a distributor", js: true do page.should have_selector "option", text: 'turtles' page.should_not have_selector("input.button.right", visible: true) end - - it "shows the table after an order cycle is selected" do + + it "shows products after selecting an order cycle" do + exchange1.variants << product.master ## add product to exchange visit shop_path + page.should_not have_content product.name + Spree::Order.last.order_cycle.should == nil + select "frogs", :from => "order_cycle_id" - page.should have_content distributor.name # This forces a wait, allowing the Ajax call to finish - page.should have_selector("input.button.right", visible: true) + page.should have_selector "products" + page.should have_content "Orders close in 2 days" + Spree::Order.last.order_cycle.should == oc1 + page.should have_content product.name + end + end + end + + describe "after selecting an order cycle with products visible" do + let(:variant1) { create(:variant, product: product, price: 20) } + let(:variant2) { create(:variant, product: product, price: 30) } + let(:exchange) { Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) } + + before do + exchange.update_attribute :pickup_time, "frogs" + exchange.variants << product.master + exchange.variants << variant1 + exchange.variants << variant2 + order.order_cycle = oc1 + end + + 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 + enterprise_fee1 = create(:enterprise_fee, amount: 20) + enterprise_fee2 = create(:enterprise_fee, amount: 3) + exchange.enterprise_fees = [enterprise_fee1, enterprise_fee2] + exchange.save + 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 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" + + # Product price should be listed as the lesser of these + page.should have_selector 'tr.product > td', text: "from $43.00" + end + end + + + describe "group buy products" do + let(:exchange) { Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) } + let(:product) { create(:simple_product, group_buy: true, on_hand: 15) } + let(:product2) { create(:simple_product, group_buy: false) } + + describe "without variants" do + before do + add_product_to_order_cycle(exchange, product) + set_order_cycle(order, oc1) + visit shop_path end - describe "with products in our order cycle" do - let(:product) { create(:simple_product) } - before do - exchange1.variants << product.master - visit shop_path - end - - it "allows us to select an order cycle, thus showing products" do - page.should_not have_content product.name - Spree::Order.last.order_cycle.should == nil - - select "frogs", :from => "order_cycle_id" - page.should have_selector "products" - page.should have_content "Orders close in 2 days" - Spree::Order.last.order_cycle.should == oc1 - page.should have_content product.name - end - end - end - - describe "after selecting an order cycle with products visible" do - let(:variant1) { create(:variant, product: product, price: 20) } - let(:variant2) { create(:variant, product: product, price: 30) } - let(:exchange) { Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) } - - before do - exchange.update_attribute :pickup_time, "frogs" - exchange.variants << product.master - exchange.variants << variant1 - exchange.variants << variant2 - order.order_cycle = oc1 - end - - 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 by default" do - page.should have_text variant1.options_text - - #it "expands variants" do - find(".collapse").trigger "click" - page.should_not have_text variant1.options_text - end - - it "uses the adjusted price" do - enterprise_fee1 = create(:enterprise_fee, amount: 20) - enterprise_fee2 = create(:enterprise_fee, amount: 3) - exchange.enterprise_fees = [enterprise_fee1, enterprise_fee2] - exchange.save - 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 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" - - # Product price should be listed as the lesser of these - page.should have_selector 'tr.product > td', text: "from $43.00" - end - end - - - describe "group buy products" do - let(:product) { create(:simple_product, group_buy: true, on_hand: 15) } - let(:product2) { create(:simple_product, group_buy: false) } - - describe "without variants" do - before do - build_and_select_order_cycle - visit shop_path - end - - it "should show group buy input" do - page.should have_field "variant_attributes[#{product.master.id}][max_quantity]", :visible => true - page.should_not have_field "variant_attributes[#{product2.master.id}][max_quantity]", :visible => true - end - - 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 - page.should have_content product.name - li = Spree::Order.order(:created_at).last.line_items.order(:created_at).last - li.max_quantity.should == 9 - li.quantity.should == 5 - end - - scenario "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 - page.should have_content product.name - li = Spree::Order.order(:created_at).last.line_items.order(:created_at).last - li.max_quantity.should == 5 - li.quantity.should == 5 - end - end - - describe "with variants on the product" do - let(:variant) { create(:variant, product: product, on_hand: 10 ) } - before do - build_and_select_order_cycle_with_variants - visit shop_path - end - - it "should show group buy input" do - page.should have_field "variant_attributes[#{variant.id}][max_quantity]", :visible => true - end - - 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 - page.should have_content product.name - li = Spree::Order.order(:created_at).last.line_items.order(:created_at).last - li.max_quantity.should == 7 - li.quantity.should == 6 - end - end - end - - describe "adding products to cart" do - let(:oc) { create(:simple_order_cycle, distributors: [distributor]) } - let(:product) { create(:simple_product) } - let(:variant) { create(:variant, product: product) } - before do - build_and_select_order_cycle_with_variants - visit shop_path - 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 - current_path.should == "/cart" + 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 page.should have_content product.name + li = Spree::Order.order(:created_at).last.line_items.order(:created_at).last + li.max_quantity.should == 9 + li.quantity.should == 5 + end + + # TODO move to controller test + 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 + page.should have_content product.name + li = Spree::Order.order(:created_at).last.line_items.order(:created_at).last + li.max_quantity.should == 5 + li.quantity.should == 5 end end - context "when no order cycles are available" do - it "tells us orders are closed" do + describe "with variants on the product" do + let(:variant) { create(:variant, product: product, on_hand: 10 ) } + before do + add_product_and_variant_to_order_cycle(exchange, product, variant) + set_order_cycle(order, oc1) visit shop_path - page.should have_content "Orders are currently closed for this hub" end - it "shows the last order cycle" do - oc1 = create(:simple_order_cycle, distributors: [distributor], orders_close_at: 10.days.ago) - visit shop_path - page.should have_content "The last cycle closed 10 days ago" - end - it "shows the next order cycle" do - oc1 = create(:simple_order_cycle, distributors: [distributor], orders_open_at: 10.days.from_now) - visit shop_path - page.should have_content "The next cycle opens in 10 days" + + 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 + page.should have_content product.name + li = Spree::Order.order(:created_at).last.line_items.order(:created_at).last + li.max_quantity.should == 7 + li.quantity.should == 6 end + end + end - it "shows nothing when there is no future order cycle" + describe "adding products to cart" do + let(:exchange) { Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) } + let(:product) { create(:simple_product) } + let(:variant) { create(:variant, product: product) } + before do + add_product_and_variant_to_order_cycle(exchange, product, variant) + set_order_cycle(order, oc1) + visit shop_path + 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 + current_path.should == "/cart" + page.should have_content product.name + end + end + + context "when no order cycles are available" do + it "tells us orders are closed" do + visit shop_path + page.should have_content "Orders are currently closed for this hub" + end + it "shows the last order cycle" do + oc1 = create(:simple_order_cycle, distributors: [distributor], orders_close_at: 10.days.ago) + visit shop_path + page.should have_content "The last cycle closed 10 days ago" + end + it "shows the next order cycle" do + oc1 = create(:simple_order_cycle, distributors: [distributor], orders_open_at: 10.days.from_now) + visit shop_path + page.should have_content "The next cycle opens in 10 days" end end end end -def build_and_select_order_cycle - exchange = Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) - exchange.update_attribute :pickup_time, "frogs" - exchange.variants << product.master - order.order_cycle = oc1 -end - - -def build_and_select_order_cycle_with_variants - exchange = Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) - exchange.update_attribute :pickup_time, "frogs" - exchange.variants << product.master - exchange.variants << variant - order.order_cycle = oc1 -end diff --git a/spec/support/request/shop_workflow.rb b/spec/support/request/shop_workflow.rb index 5c473d7f62..407cebd88e 100644 --- a/spec/support/request/shop_workflow.rb +++ b/spec/support/request/shop_workflow.rb @@ -3,20 +3,6 @@ module ShopWorkflow ApplicationController.any_instance.stub(:session).and_return({order_id: order.id, access_token: order.token}) end - def select_distributor - # If no order cycles are available this is much faster - visit "/" - follow_active_table_node distributor.name - end - - # These methods are naughty and write to the DB directly - # Because loading the whole Angular app is slow - def select_order_cycle - exchange = Exchange.find(order_cycle.exchanges.to_enterprises(distributor).outgoing.first.id) - exchange.variants << product.master - order.update_attribute :order_cycle, order_cycle - end - def add_product_to_cart create(:line_item, variant: product.master, order: order) end @@ -24,4 +10,17 @@ module ShopWorkflow def toggle_accordion(name) find("dd a", text: name).click end + + def add_product_to_order_cycle(exchange, product) + exchange.variants << product.master + end + + def add_product_and_variant_to_order_cycle(exchange, product, variant) + exchange.variants << product.master + exchange.variants << variant + end + + def set_order_cycle(order, order_cycle) + order.update_attribute(:order_cycle, order_cycle) + end end From 34f170d4f71bbc3d575f98a1d4afc0b2305ae814 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Fri, 2 May 2014 10:18:57 +1000 Subject: [PATCH 12/49] Bugged thing in the shop spec --- app/controllers/shop/shop_controller.rb | 5 ++--- spec/features/consumer/shopping/shopping_spec.rb | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/controllers/shop/shop_controller.rb b/app/controllers/shop/shop_controller.rb index d06b521e9b..7b9956cbee 100644 --- a/app/controllers/shop/shop_controller.rb +++ b/app/controllers/shop/shop_controller.rb @@ -1,7 +1,7 @@ class Shop::ShopController < BaseController layout "darkswarm" before_filter :require_distributor_chosen - before_filter :set_order_cycles, only: :show + before_filter :set_order_cycles def show end @@ -11,7 +11,6 @@ class Shop::ShopController < BaseController .valid_products_distributed_by(current_distributor).andand .select { |p| !p.deleted? && p.has_stock_for_distribution?(current_order_cycle, current_distributor) }.andand .sort_by {|p| p.name } - render json: "", status: 404 end end @@ -35,7 +34,7 @@ class Shop::ShopController < BaseController @order_cycles = OrderCycle.with_distributor(@distributor).active # And default to the only order cycle if there's only the one - if @order_cycles.count == 1 + if @order_cycles.count == 1 and current_order_cycle.nil? current_order(true).set_order_cycle! @order_cycles.first end end diff --git a/spec/features/consumer/shopping/shopping_spec.rb b/spec/features/consumer/shopping/shopping_spec.rb index 2fbb4af1d5..19fcb5a44b 100644 --- a/spec/features/consumer/shopping/shopping_spec.rb +++ b/spec/features/consumer/shopping/shopping_spec.rb @@ -115,7 +115,6 @@ feature "As a consumer I want to shop with a distributor", js: true do page.should have_selector 'tr.product > td', text: "from $43.00" end end - describe "group buy products" do let(:exchange) { Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) } From 8c319334db4c3f69c944b26231d96afd51da7d8c Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Fri, 2 May 2014 12:34:19 +1000 Subject: [PATCH 13/49] Cleaning out the spree auth stuff --- .../admin/bulk_order_management_spec.rb | 21 ++++++++++++++----- spec/spec_helper.rb | 1 + .../request/authentication_workflow.rb | 17 ++++++++++++++- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/spec/features/admin/bulk_order_management_spec.rb b/spec/features/admin/bulk_order_management_spec.rb index a56f669756..61842ff48c 100644 --- a/spec/features/admin/bulk_order_management_spec.rb +++ b/spec/features/admin/bulk_order_management_spec.rb @@ -5,8 +5,12 @@ feature %q{ I want to be able to manage orders in bulk } , js: true do include AuthenticationWorkflow + include AuthorizationHelpers include WebHelper + before(:all) { Spree::Ability.register_ability(AuthorizationHelpers::Request::SuperAbility) } + after(:all) { Spree::Ability.remove_ability(AuthorizationHelpers::Request::SuperAbility) } + before :all do @default_wait_time = Capybara.default_wait_time Capybara.default_wait_time = 10 @@ -18,12 +22,12 @@ feature %q{ context "listing orders" do before :each do - login_to_admin_section + admin_user = quick_login_as_admin + Spree::Admin::OrdersController.any_instance.stub(:spree_current_user).and_return admin_user end it "displays a Bulk Management Tab under the Orders item" do visit '/admin/orders' - page.should have_link "Bulk Order Management" click_link "Bulk Order Management" page.should have_selector "h1.page-title", text: "Bulk Order Management" @@ -107,7 +111,10 @@ feature %q{ context "altering line item properties" do before :each do - login_to_admin_section + #login_to_admin_section + #quick_login_as_admin + admin_user = quick_login_as_admin + Spree::Admin::OrdersController.any_instance.stub(:spree_current_user).and_return admin_user end context "tracking changes" do @@ -155,7 +162,10 @@ feature %q{ context "using page controls" do before :each do - login_to_admin_section + #login_to_admin_section + #quick_login_as_admin + admin_user = quick_login_as_admin + Spree::Admin::OrdersController.any_instance.stub(:spree_current_user).and_return admin_user end let!(:o1) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now ) } @@ -571,7 +581,8 @@ feature %q{ @enterprise_user.enterprise_roles.build(enterprise: s1).save @enterprise_user.enterprise_roles.build(enterprise: d1).save - login_to_admin_as @enterprise_user + #login_to_admin_as + quick_login_as @enterprise_user end it "shows only line item from orders that I supply" do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1d66f672ec..a48e062b1f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -26,6 +26,7 @@ require 'spree/core/testing_support/capybara_ext' require 'spree/api/testing_support/setup' require 'spree/api/testing_support/helpers' require 'spree/api/testing_support/helpers_decorator' +require 'spree/core/testing_support/authorization_helpers' require 'active_record/fixtures' fixtures_dir = File.expand_path('../../db/default', __FILE__) diff --git a/spec/support/request/authentication_workflow.rb b/spec/support/request/authentication_workflow.rb index e01b02bca5..53e6a48dbb 100644 --- a/spec/support/request/authentication_workflow.rb +++ b/spec/support/request/authentication_workflow.rb @@ -1,6 +1,22 @@ module AuthenticationWorkflow + def quick_login_as(user) ApplicationController.any_instance.stub(:spree_current_user).and_return user + ApplicationController.any_instance.stub(:current_api_user).and_return user + end + + def quick_login_as_admin + admin_role = Spree::Role.find_or_create_by_name!('admin') + admin_user = create(:user, + :password => 'passw0rd', + :password_confirmation => 'passw0rd', + :remember_me => false, + :persistence_token => 'pass', + :login => 'admin@ofn.org') + + admin_user.spree_roles << admin_role + quick_login_as admin_user + admin_user end def login_to_admin_section @@ -13,7 +29,6 @@ module AuthenticationWorkflow :login => 'admin@ofn.org') admin_user.spree_roles << admin_role - login_to_admin_as admin_user end From 705e247eb8defe4baa16cc1780ba0b1cf8a8e86e Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Fri, 2 May 2014 12:41:04 +1000 Subject: [PATCH 14/49] Tweaking the bulk order management spec again --- spec/features/admin/bulk_order_management_spec.rb | 4 ++-- spec/support/request/authentication_workflow.rb | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/spec/features/admin/bulk_order_management_spec.rb b/spec/features/admin/bulk_order_management_spec.rb index 61842ff48c..0cfb211178 100644 --- a/spec/features/admin/bulk_order_management_spec.rb +++ b/spec/features/admin/bulk_order_management_spec.rb @@ -8,8 +8,7 @@ feature %q{ include AuthorizationHelpers include WebHelper - before(:all) { Spree::Ability.register_ability(AuthorizationHelpers::Request::SuperAbility) } - after(:all) { Spree::Ability.remove_ability(AuthorizationHelpers::Request::SuperAbility) } + stub_authorization! before :all do @default_wait_time = Capybara.default_wait_time @@ -36,6 +35,7 @@ feature %q{ it "displays a message when number of line items is zero" do visit '/admin/orders/bulk_management' page.should have_text "No matching line items found." + end context "displaying the list of line items" do diff --git a/spec/support/request/authentication_workflow.rb b/spec/support/request/authentication_workflow.rb index 53e6a48dbb..da02535646 100644 --- a/spec/support/request/authentication_workflow.rb +++ b/spec/support/request/authentication_workflow.rb @@ -1,5 +1,4 @@ module AuthenticationWorkflow - def quick_login_as(user) ApplicationController.any_instance.stub(:spree_current_user).and_return user ApplicationController.any_instance.stub(:current_api_user).and_return user @@ -19,6 +18,11 @@ module AuthenticationWorkflow admin_user end + def stub_authorization! + before(:all) { Spree::Ability.register_ability(AuthorizationHelpers::Request::SuperAbility) } + after(:all) { Spree::Ability.remove_ability(AuthorizationHelpers::Request::SuperAbility) } + end + def login_to_admin_section admin_role = Spree::Role.find_or_create_by_name!('admin') admin_user = create(:user, @@ -70,3 +74,7 @@ module AuthenticationWorkflow click_button 'Login' end end + +RSpec.configure do |config| + config.extend AuthenticationWorkflow, :type => :feature +end From 9bd76df11695c99d1b01672b6d3626fcfece2cde Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Fri, 2 May 2014 12:52:51 +1000 Subject: [PATCH 15/49] That wasn't actually a bug! Sorry --- app/controllers/shop/shop_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/shop/shop_controller.rb b/app/controllers/shop/shop_controller.rb index 7b9956cbee..95d18a0e2e 100644 --- a/app/controllers/shop/shop_controller.rb +++ b/app/controllers/shop/shop_controller.rb @@ -34,7 +34,7 @@ class Shop::ShopController < BaseController @order_cycles = OrderCycle.with_distributor(@distributor).active # And default to the only order cycle if there's only the one - if @order_cycles.count == 1 and current_order_cycle.nil? + if @order_cycles.count == 1 current_order(true).set_order_cycle! @order_cycles.first end end From 19137ce309f14a43b532d1c32b0fee47578638a2 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Fri, 2 May 2014 12:57:33 +1000 Subject: [PATCH 16/49] Adding state to home page filtering --- app/assets/javascripts/darkswarm/filters/filter_hubs.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/darkswarm/filters/filter_hubs.js.coffee b/app/assets/javascripts/darkswarm/filters/filter_hubs.js.coffee index 5b3084caf5..29f0b993d1 100644 --- a/app/assets/javascripts/darkswarm/filters/filter_hubs.js.coffee +++ b/app/assets/javascripts/darkswarm/filters/filter_hubs.js.coffee @@ -6,4 +6,4 @@ Darkswarm.filter 'filterHubs', -> matched.toLowerCase().indexOf(text.toLowerCase()) != -1 hubs.filter (hub)-> - match(hub.name) or match(hub.address.zipcode) or match(hub.address.city) + match(hub.name) or match(hub.address.zipcode) or match(hub.address.city) or match(hub.address.state) From 123bd7963d3171c7763d08e7d62e90e2bc6c8e2c Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Fri, 2 May 2014 13:07:12 +1000 Subject: [PATCH 17/49] Adding tests for hub filter --- .../filters/filter_hubs_spec.js.coffee | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 spec/javascripts/unit/darkswarm/filters/filter_hubs_spec.js.coffee diff --git a/spec/javascripts/unit/darkswarm/filters/filter_hubs_spec.js.coffee b/spec/javascripts/unit/darkswarm/filters/filter_hubs_spec.js.coffee new file mode 100644 index 0000000000..8ef281d598 --- /dev/null +++ b/spec/javascripts/unit/darkswarm/filters/filter_hubs_spec.js.coffee @@ -0,0 +1,45 @@ +describe 'filtering Hubs', -> + filter = null + filterHubs = null + hubs = [{ + name: "frogs" + other: "roger" + address: + zipcode: "cats" + city: "cambridge" + state: "kansas" + }, { + name: "donkeys" + other: "roger" + address: + zipcode: "" + city: "Wellington" + state: "uzbekistan" + }] + + beforeEach -> + module 'Darkswarm' + inject ($filter) -> + filter = $filter + filterHubs = $filter('filterHubs') + + it 'has a hub filter', -> + expect(filter('filterHubs')).not.toBeNull() + + it "filters by name", -> + expect(filterHubs(hubs, 'donkeys').length).toEqual 1 + + it "is case insensitive", -> + expect(filterHubs(hubs, 'DONKEYS').length).toEqual 1 + + it "filters by state", -> + expect(filterHubs(hubs, 'kansas').length).toEqual 1 + + it "filters by zipcode", -> + expect(filterHubs(hubs, 'cats').length).toEqual 1 + + it "gives all hubs when no argument is specified", -> + expect(filterHubs(hubs, '').length).toEqual 2 + + it "does not filter by anything else", -> + expect(filterHubs(hubs, 'roger').length).toEqual 0 From d74265e44dba3ad1059086314975fd4d4476416a Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Fri, 2 May 2014 14:04:43 +1000 Subject: [PATCH 18/49] Ctrl-C now cancels karma --- lib/tasks/karma.rake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/tasks/karma.rake b/lib/tasks/karma.rake index 6201c66e61..33a1d05dd4 100644 --- a/lib/tasks/karma.rake +++ b/lib/tasks/karma.rake @@ -13,7 +13,9 @@ namespace :karma do Tempfile.open('karma_unit.js', Rails.root.join('tmp') ) do |f| f.write unit_js(application_spec_files) f.flush - system "karma #{command} #{f.path} #{args}" + trap('SIGINT') { puts "Killing Karma"; exit } + exec "karma #{command} #{f.path} #{args}" + #%x{karma #{command} #{f.path} #{args}} end end From dfd1dd609de61445a7f4365735c3b15db27198e3 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Fri, 2 May 2014 14:13:00 +1000 Subject: [PATCH 19/49] Re-engaging checkout spec --- lib/tasks/karma.rake | 1 - spec/features/consumer/shopping/checkout_spec.rb | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/tasks/karma.rake b/lib/tasks/karma.rake index 33a1d05dd4..4ebd4ae278 100644 --- a/lib/tasks/karma.rake +++ b/lib/tasks/karma.rake @@ -15,7 +15,6 @@ namespace :karma do f.flush trap('SIGINT') { puts "Killing Karma"; exit } exec "karma #{command} #{f.path} #{args}" - #%x{karma #{command} #{f.path} #{args}} end end diff --git a/spec/features/consumer/shopping/checkout_spec.rb b/spec/features/consumer/shopping/checkout_spec.rb index 1c0d6ff32e..309148b100 100644 --- a/spec/features/consumer/shopping/checkout_spec.rb +++ b/spec/features/consumer/shopping/checkout_spec.rb @@ -23,7 +23,7 @@ feature "As a consumer I want to check out my cart", js: true do page.should have_content distributor.name end - pending "with shipping methods" do + describe "with shipping methods" do let(:sm1) { create(:shipping_method, require_ship_address: true, name: "Frogs", description: "yellow") } let(:sm2) { create(:shipping_method, require_ship_address: false, name: "Donkeys", description: "blue") } before do From d707624525b4f240ce462831dd53e6e1d032e817 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 30 Apr 2014 12:50:56 +1000 Subject: [PATCH 20/49] Fix warnings - faker clash with ffaker, i18n enforce_available_locales --- Gemfile | 1 - Gemfile.lock | 3 --- config/application.rb | 2 ++ spec/factories.rb | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index e1c4d656b8..5050213a17 100644 --- a/Gemfile +++ b/Gemfile @@ -69,7 +69,6 @@ group :test, :development do gem 'rspec-rails' gem 'shoulda-matchers' gem 'factory_girl_rails', :require => false - gem 'faker' gem 'capybara' gem 'database_cleaner', '0.7.1', :require => false gem 'simplecov', :require => false diff --git a/Gemfile.lock b/Gemfile.lock index 1b762b786c..74ffb03923 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -250,8 +250,6 @@ GEM factory_girl_rails (3.3.0) factory_girl (~> 3.3.0) railties (>= 3.0.0) - faker (1.0.1) - i18n (~> 0.4) ffaker (1.15.0) ffi (1.9.3) fog (1.14.0) @@ -522,7 +520,6 @@ DEPENDENCIES deface! eaterprises_feature! factory_girl_rails - faker foreigner foundation-icons-sass-rails foundation-rails diff --git a/config/application.rb b/config/application.rb index 8f0728dd45..f36691ebb5 100644 --- a/config/application.rb +++ b/config/application.rb @@ -63,6 +63,8 @@ module Openfoodnetwork # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] config.i18n.default_locale = 'en' + I18n.config.enforce_available_locales = true + # Configure the default encoding used in templates for Ruby 1.9. config.encoding = "utf-8" diff --git a/spec/factories.rb b/spec/factories.rb index df1dd4d50c..710ba1c8ba 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -1,4 +1,4 @@ -require 'faker' +require 'ffaker' require 'spree/core/testing_support/factories' FactoryGirl.define do From c9aefa507a0d497e81de7c18ff4aa6e276ff2884 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 1 May 2014 10:25:34 +1000 Subject: [PATCH 21/49] Remove chili --- Gemfile | 6 --- Gemfile.lock | 51 +++++------------- .../stylesheets/store/variables.css.scss | 2 +- .../store}/variables_changes.css.scss | 0 app/models/spree/order_decorator.rb | 1 + lib/chili/eaterprises_feature/.gitignore | 3 -- lib/chili/eaterprises_feature/README.rdoc | 3 -- .../images/eaterprises_feature/.gitkeep | 0 .../eaterprises_feature/application.js | 13 ----- .../eaterprises_feature/application.css | 13 ----- .../application/assets.html.erb.deface | 3 -- .../eaterprises_feature/config/routes.rb | 3 -- .../eaterprises_feature.gemspec | 22 -------- .../lib/eaterprises_feature.rb | 7 --- .../lib/eaterprises_feature/engine.rb | 17 ------ .../lib/eaterprises_feature/version.rb | 3 -- .../eaterprises_feature_generator.rb | 3 -- lib/chili/local_organics_feature/.gitignore | 3 -- lib/chili/local_organics_feature/README.rdoc | 3 -- .../images/local_organics_feature/.gitkeep | 0 .../images/local_organics_feature/logo.png | Bin 9507 -> 0 bytes .../local_organics_feature/admin.js | 0 .../local_organics_feature/application.js | 13 ----- .../local_organics_feature/admin.css.scss | 10 ---- .../local_organics_feature/application.css | 13 ----- .../local_organics.css.scss | 48 ----------------- .../variables_changes.css.scss | 1 - .../layouts/admin/assets.html.erb.deface | 3 -- .../spree/layouts/admin/logo.html.erb.deface | 5 -- .../spree_application/assets.html.erb.deface | 3 -- .../spree_application/footer.html.erb.deface | 3 -- .../spree_application/logo.html.erb.deface | 2 - .../local.html.haml.deface | 3 -- .../remote.html.haml.deface | 3 -- .../local_organics_feature/config/routes.rb | 3 -- .../local_organics_feature_generator.rb | 3 -- .../lib/local_organics_feature.rb | 7 --- .../lib/local_organics_feature/engine.rb | 17 ------ .../lib/local_organics_feature/version.rb | 3 -- .../local_organics_feature.gemspec | 22 -------- spec/features/admin/enterprises_spec.rb | 1 + .../consumer/shopping/checkout_spec.rb | 18 ++++++- 42 files changed, 33 insertions(+), 304 deletions(-) rename {lib/chili/eaterprises_feature/app/assets/stylesheets/eaterprises_feature => app/assets/stylesheets/store}/variables_changes.css.scss (100%) delete mode 100644 lib/chili/eaterprises_feature/.gitignore delete mode 100644 lib/chili/eaterprises_feature/README.rdoc delete mode 100644 lib/chili/eaterprises_feature/app/assets/images/eaterprises_feature/.gitkeep delete mode 100644 lib/chili/eaterprises_feature/app/assets/javascripts/eaterprises_feature/application.js delete mode 100644 lib/chili/eaterprises_feature/app/assets/stylesheets/eaterprises_feature/application.css delete mode 100644 lib/chili/eaterprises_feature/app/overrides/layouts/application/assets.html.erb.deface delete mode 100644 lib/chili/eaterprises_feature/config/routes.rb delete mode 100644 lib/chili/eaterprises_feature/eaterprises_feature.gemspec delete mode 100644 lib/chili/eaterprises_feature/lib/eaterprises_feature.rb delete mode 100644 lib/chili/eaterprises_feature/lib/eaterprises_feature/engine.rb delete mode 100644 lib/chili/eaterprises_feature/lib/eaterprises_feature/version.rb delete mode 100644 lib/chili/eaterprises_feature/lib/generators/eaterprises_feature_generator.rb delete mode 100644 lib/chili/local_organics_feature/.gitignore delete mode 100644 lib/chili/local_organics_feature/README.rdoc delete mode 100644 lib/chili/local_organics_feature/app/assets/images/local_organics_feature/.gitkeep delete mode 100644 lib/chili/local_organics_feature/app/assets/images/local_organics_feature/logo.png delete mode 100644 lib/chili/local_organics_feature/app/assets/javascripts/local_organics_feature/admin.js delete mode 100644 lib/chili/local_organics_feature/app/assets/javascripts/local_organics_feature/application.js delete mode 100644 lib/chili/local_organics_feature/app/assets/stylesheets/local_organics_feature/admin.css.scss delete mode 100644 lib/chili/local_organics_feature/app/assets/stylesheets/local_organics_feature/application.css delete mode 100644 lib/chili/local_organics_feature/app/assets/stylesheets/local_organics_feature/local_organics.css.scss delete mode 100644 lib/chili/local_organics_feature/app/assets/stylesheets/local_organics_feature/variables_changes.css.scss delete mode 100644 lib/chili/local_organics_feature/app/overrides/spree/layouts/admin/assets.html.erb.deface delete mode 100644 lib/chili/local_organics_feature/app/overrides/spree/layouts/admin/logo.html.erb.deface delete mode 100644 lib/chili/local_organics_feature/app/overrides/spree/layouts/spree_application/assets.html.erb.deface delete mode 100644 lib/chili/local_organics_feature/app/overrides/spree/layouts/spree_application/footer.html.erb.deface delete mode 100644 lib/chili/local_organics_feature/app/overrides/spree/layouts/spree_application/logo.html.erb.deface delete mode 100644 lib/chili/local_organics_feature/app/overrides/spree/shared/_products_by_distributor/local.html.haml.deface delete mode 100644 lib/chili/local_organics_feature/app/overrides/spree/shared/_products_by_distributor/remote.html.haml.deface delete mode 100644 lib/chili/local_organics_feature/config/routes.rb delete mode 100644 lib/chili/local_organics_feature/lib/generators/local_organics_feature_generator.rb delete mode 100644 lib/chili/local_organics_feature/lib/local_organics_feature.rb delete mode 100644 lib/chili/local_organics_feature/lib/local_organics_feature/engine.rb delete mode 100644 lib/chili/local_organics_feature/lib/local_organics_feature/version.rb delete mode 100644 lib/chili/local_organics_feature/local_organics_feature.gemspec diff --git a/Gemfile b/Gemfile index 5050213a17..af4108c9eb 100644 --- a/Gemfile +++ b/Gemfile @@ -29,7 +29,6 @@ gem 'truncate_html' gem 'representative_view' gem 'rabl' gem 'oj' -gem 'chili', :github => 'openfoodfoundation/chili' gem 'deface', :github => 'spree/deface', :ref => '1110a13' gem 'paperclip' gem 'geocoder' @@ -84,11 +83,6 @@ group :test do gem 'webmock' end -group :chili do - gem 'eaterprises_feature', path: 'lib/chili/eaterprises_feature' - gem 'local_organics_feature', path: 'lib/chili/local_organics_feature' -end - group :development do gem 'pry-debugger' gem 'debugger-linecache' diff --git a/Gemfile.lock b/Gemfile.lock index 74ffb03923..adba98ff8a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,17 +6,9 @@ GIT actionpack (~> 3.0) activemodel (~> 3.0) -GIT - remote: git://github.com/openfoodfoundation/chili.git - revision: b82608623d504eb39f852115b138a53af5f89505 - specs: - chili (3.1.0) - deface (~> 1.0.0.rc2) - rails (~> 3.2) - GIT remote: git://github.com/openfoodfoundation/spree.git - revision: 1c133672652e1ee8b6c8d694efe258e62378062e + revision: da651b40f5c6cdd32e00b060729eb9aefd4f615f branch: 1-3-stable specs: spree (1.3.3) @@ -103,20 +95,6 @@ GIT activemodel (>= 3.0) railties (>= 3.0) -PATH - remote: lib/chili/eaterprises_feature - specs: - eaterprises_feature (0.0.1) - chili (~> 3.1) - rails (~> 3.2.11) - -PATH - remote: lib/chili/local_organics_feature - specs: - local_organics_feature (0.0.1) - chili (~> 3.1) - rails (~> 3.2.11) - GEM remote: https://rubygems.org/ specs: @@ -134,16 +112,16 @@ GEM rack-test (~> 0.6.1) sprockets (~> 2.2.1) active_link_to (1.0.0) - active_utils (2.0.1) + active_utils (2.0.2) activesupport (>= 2.3.11) i18n - activemerchant (1.40.0) + activemerchant (1.43.0) active_utils (~> 2.0, >= 2.0.1) activesupport (>= 2.3.14, < 5.0.0) builder (>= 2.1.2, < 4.0.0) i18n (~> 0.5) json (~> 1.7) - money (< 6.0.0) + money (< 7.0.0) nokogiri (~> 1.4) activemodel (3.2.17) activesupport (= 3.2.17) @@ -194,7 +172,7 @@ GEM climate_control (0.0.3) activesupport (>= 3.0) cliver (0.3.2) - cocaine (0.5.1) + cocaine (0.5.4) climate_control (>= 0.0.3, < 1.0) coderay (1.0.9) coffee-rails (3.2.2) @@ -204,7 +182,7 @@ GEM coffee-script-source execjs coffee-script-source (1.3.3) - colorize (0.6.0) + colorize (0.7.2) columnize (0.3.6) comfortable_mexican_sofa (1.6.24) active_link_to (~> 1.0.0) @@ -297,8 +275,8 @@ GEM highline (1.6.18) hike (1.2.3) http_parser.rb (0.5.3) - httparty (0.11.0) - multi_json (~> 1.0) + httparty (0.13.1) + json (~> 1.8) multi_xml (>= 0.5.2) i18n (0.6.9) immigrant (0.1.6) @@ -332,13 +310,13 @@ GEM treetop (~> 1.4.8) method_source (0.8.1) mime-types (1.25.1) - mini_portile (0.5.2) + mini_portile (0.5.3) momentjs-rails (2.5.1) railties (>= 3.1) money (5.0.0) i18n (~> 0.4) json - multi_json (1.9.2) + multi_json (1.9.3) multi_xml (0.5.5) net-scp (1.1.2) net-ssh (>= 2.6.5) @@ -397,7 +375,7 @@ GEM rdoc (~> 3.4) thor (>= 0.14.6, < 2.0) raindrops (0.9.0) - rake (10.1.1) + rake (10.3.1) ransack (0.7.2) actionpack (~> 3.0) activerecord (~> 3.0) @@ -459,7 +437,7 @@ GEM therubyracer (0.12.0) libv8 (~> 3.16.14.0) ref - thor (0.19.0) + thor (0.19.1) tilt (1.4.1) timecop (0.6.2.2) timers (1.1.0) @@ -472,7 +450,7 @@ GEM sprockets (>= 2.0.0) turn (0.8.3) ansi - tzinfo (0.3.38) + tzinfo (0.3.39) uglifier (1.2.4) execjs (>= 0.3.0) multi_json (>= 1.0.2) @@ -510,7 +488,6 @@ DEPENDENCIES aws-sdk bugsnag capybara - chili! coffee-rails (~> 3.2.1) comfortable_mexican_sofa compass-rails @@ -518,7 +495,6 @@ DEPENDENCIES db2fog debugger-linecache deface! - eaterprises_feature! factory_girl_rails foreigner foundation-icons-sass-rails @@ -536,7 +512,6 @@ DEPENDENCIES jquery-rails json_spec letter_opener - local_organics_feature! momentjs-rails newrelic_rpm oj diff --git a/app/assets/stylesheets/store/variables.css.scss b/app/assets/stylesheets/store/variables.css.scss index f33a4318e9..4cb074ae48 100644 --- a/app/assets/stylesheets/store/variables.css.scss +++ b/app/assets/stylesheets/store/variables.css.scss @@ -61,4 +61,4 @@ $ff_base: 'Ubuntu', sans-serif !default; $table_head_color: lighten($body_text_color, 60) !default; -@import "./variables_changes.css.scss"; +@import "./store/variables_changes.css.scss"; diff --git a/lib/chili/eaterprises_feature/app/assets/stylesheets/eaterprises_feature/variables_changes.css.scss b/app/assets/stylesheets/store/variables_changes.css.scss similarity index 100% rename from lib/chili/eaterprises_feature/app/assets/stylesheets/eaterprises_feature/variables_changes.css.scss rename to app/assets/stylesheets/store/variables_changes.css.scss diff --git a/app/models/spree/order_decorator.rb b/app/models/spree/order_decorator.rb index 7e5d660fc6..d37a84ce1d 100644 --- a/app/models/spree/order_decorator.rb +++ b/app/models/spree/order_decorator.rb @@ -1,3 +1,4 @@ +require 'open_food_network/feature_toggle' require 'open_food_network/distribution_change_validator' ActiveSupport::Notifications.subscribe('spree.order.contents_changed') do |name, start, finish, id, payload| diff --git a/lib/chili/eaterprises_feature/.gitignore b/lib/chili/eaterprises_feature/.gitignore deleted file mode 100644 index 8619e09c5a..0000000000 --- a/lib/chili/eaterprises_feature/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.bundle/ -log/*.log -pkg/ diff --git a/lib/chili/eaterprises_feature/README.rdoc b/lib/chili/eaterprises_feature/README.rdoc deleted file mode 100644 index 047a9eccec..0000000000 --- a/lib/chili/eaterprises_feature/README.rdoc +++ /dev/null @@ -1,3 +0,0 @@ -= Eaterprises Feature - -This feature is released under the AGPL licence. \ No newline at end of file diff --git a/lib/chili/eaterprises_feature/app/assets/images/eaterprises_feature/.gitkeep b/lib/chili/eaterprises_feature/app/assets/images/eaterprises_feature/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/chili/eaterprises_feature/app/assets/javascripts/eaterprises_feature/application.js b/lib/chili/eaterprises_feature/app/assets/javascripts/eaterprises_feature/application.js deleted file mode 100644 index 15ebed9422..0000000000 --- a/lib/chili/eaterprises_feature/app/assets/javascripts/eaterprises_feature/application.js +++ /dev/null @@ -1,13 +0,0 @@ -// This is a manifest file that'll be compiled into application.js, which will include all the files -// listed below. -// -// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, -// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. -// -// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the -// the compiled file. -// -// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD -// GO AFTER THE REQUIRES BELOW. -// -//= require_tree . diff --git a/lib/chili/eaterprises_feature/app/assets/stylesheets/eaterprises_feature/application.css b/lib/chili/eaterprises_feature/app/assets/stylesheets/eaterprises_feature/application.css deleted file mode 100644 index 3192ec897b..0000000000 --- a/lib/chili/eaterprises_feature/app/assets/stylesheets/eaterprises_feature/application.css +++ /dev/null @@ -1,13 +0,0 @@ -/* - * This is a manifest file that'll be compiled into application.css, which will include all the files - * listed below. - * - * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, - * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. - * - * You're free to add application-wide styles to this file and they'll appear at the top of the - * compiled file, but it's generally better to create a new file per style scope. - * - *= require_self - *= require_tree . - */ diff --git a/lib/chili/eaterprises_feature/app/overrides/layouts/application/assets.html.erb.deface b/lib/chili/eaterprises_feature/app/overrides/layouts/application/assets.html.erb.deface deleted file mode 100644 index 72e5ed7748..0000000000 --- a/lib/chili/eaterprises_feature/app/overrides/layouts/application/assets.html.erb.deface +++ /dev/null @@ -1,3 +0,0 @@ - -<%= stylesheet_link_tag 'eaterprises_feature/application' %> -<%= javascript_include_tag 'eaterprises_feature/application' %> diff --git a/lib/chili/eaterprises_feature/config/routes.rb b/lib/chili/eaterprises_feature/config/routes.rb deleted file mode 100644 index 38585adb71..0000000000 --- a/lib/chili/eaterprises_feature/config/routes.rb +++ /dev/null @@ -1,3 +0,0 @@ -EaterprisesFeature::Engine.automount! -EaterprisesFeature::Engine.routes.draw do -end diff --git a/lib/chili/eaterprises_feature/eaterprises_feature.gemspec b/lib/chili/eaterprises_feature/eaterprises_feature.gemspec deleted file mode 100644 index 5194c3d4dc..0000000000 --- a/lib/chili/eaterprises_feature/eaterprises_feature.gemspec +++ /dev/null @@ -1,22 +0,0 @@ -$:.push File.expand_path("../lib", __FILE__) - -# Maintain your gem's version: -require "eaterprises_feature/version" - -# Describe your gem and declare its dependencies: -Gem::Specification.new do |s| - s.name = "eaterprises_feature" - s.version = EaterprisesFeature::VERSION - s.authors = ["Rohan Mitchell"] - s.email = ["rohan@rohanmitchell.com"] - s.homepage = "" - s.summary = "Summary of EaterprisesFeature." - s.description = "Description of EaterprisesFeature." - - s.files = Dir["{app,config,db,lib}/**/*"] + ["README.rdoc"] - - s.add_dependency "rails", "~> 3.2.11" - s.add_dependency 'chili', '~> 3.1' - - s.add_development_dependency "sqlite3" -end diff --git a/lib/chili/eaterprises_feature/lib/eaterprises_feature.rb b/lib/chili/eaterprises_feature/lib/eaterprises_feature.rb deleted file mode 100644 index 72cd9d7d95..0000000000 --- a/lib/chili/eaterprises_feature/lib/eaterprises_feature.rb +++ /dev/null @@ -1,7 +0,0 @@ -require "chili" -require "eaterprises_feature/engine" - -module EaterprisesFeature - extend Chili::Base - active_if { OpenFoodNetwork::FeatureToggle.enabled? :eaterprises } -end diff --git a/lib/chili/eaterprises_feature/lib/eaterprises_feature/engine.rb b/lib/chili/eaterprises_feature/lib/eaterprises_feature/engine.rb deleted file mode 100644 index 25965c0559..0000000000 --- a/lib/chili/eaterprises_feature/lib/eaterprises_feature/engine.rb +++ /dev/null @@ -1,17 +0,0 @@ -require_relative '../../../../open_food_network/feature_toggle' - -module EaterprisesFeature - class Engine < ::Rails::Engine - isolate_namespace EaterprisesFeature - - if OpenFoodNetwork::FeatureToggle.enabled? :eaterprises - initializer 'eaterprises_feature.sass', :after => :load_config_initializers do |app| - app.config.sass.load_paths += [self.root.join('app', 'assets', 'stylesheets', 'eaterprises_feature')] if Rails.application.config.respond_to? :sass - end - - initializer :assets do |app| - app.config.assets.precompile += ['eaterprises_feature/*'] - end - end - end -end diff --git a/lib/chili/eaterprises_feature/lib/eaterprises_feature/version.rb b/lib/chili/eaterprises_feature/lib/eaterprises_feature/version.rb deleted file mode 100644 index 5424d0cb17..0000000000 --- a/lib/chili/eaterprises_feature/lib/eaterprises_feature/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module EaterprisesFeature - VERSION = "0.0.1" -end diff --git a/lib/chili/eaterprises_feature/lib/generators/eaterprises_feature_generator.rb b/lib/chili/eaterprises_feature/lib/generators/eaterprises_feature_generator.rb deleted file mode 100644 index b0b6f7f010..0000000000 --- a/lib/chili/eaterprises_feature/lib/generators/eaterprises_feature_generator.rb +++ /dev/null @@ -1,3 +0,0 @@ -class EaterprisesFeatureGenerator < Rails::Generators::Base - include Chili::GeneratorProxy -end diff --git a/lib/chili/local_organics_feature/.gitignore b/lib/chili/local_organics_feature/.gitignore deleted file mode 100644 index 8619e09c5a..0000000000 --- a/lib/chili/local_organics_feature/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.bundle/ -log/*.log -pkg/ diff --git a/lib/chili/local_organics_feature/README.rdoc b/lib/chili/local_organics_feature/README.rdoc deleted file mode 100644 index 5f394c59cb..0000000000 --- a/lib/chili/local_organics_feature/README.rdoc +++ /dev/null @@ -1,3 +0,0 @@ -= Local Organics Feature - -This feature is released under the AGPL licence. diff --git a/lib/chili/local_organics_feature/app/assets/images/local_organics_feature/.gitkeep b/lib/chili/local_organics_feature/app/assets/images/local_organics_feature/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/chili/local_organics_feature/app/assets/images/local_organics_feature/logo.png b/lib/chili/local_organics_feature/app/assets/images/local_organics_feature/logo.png deleted file mode 100644 index 92750bb69882dcfcda536b40d9086076a2f62626..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9507 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 -<%= stylesheet_link_tag 'local_organics_feature/admin' %> -<%= javascript_include_tag 'local_organics_feature/admin' %> diff --git a/lib/chili/local_organics_feature/app/overrides/spree/layouts/admin/logo.html.erb.deface b/lib/chili/local_organics_feature/app/overrides/spree/layouts/admin/logo.html.erb.deface deleted file mode 100644 index 6b8250dead..0000000000 --- a/lib/chili/local_organics_feature/app/overrides/spree/layouts/admin/logo.html.erb.deface +++ /dev/null @@ -1,5 +0,0 @@ - -
-<%= link_to image_tag('local_organics_feature/logo.png', :id => 'logo'), spree.admin_path %> -

<%= link_to t(:administration), spree.admin_path %>

-
<%= image_tag 'admin/progress.gif' %> <%= t(:loading) %>...
diff --git a/lib/chili/local_organics_feature/app/overrides/spree/layouts/spree_application/assets.html.erb.deface b/lib/chili/local_organics_feature/app/overrides/spree/layouts/spree_application/assets.html.erb.deface deleted file mode 100644 index c1fe8ec1e0..0000000000 --- a/lib/chili/local_organics_feature/app/overrides/spree/layouts/spree_application/assets.html.erb.deface +++ /dev/null @@ -1,3 +0,0 @@ - -<%= stylesheet_link_tag 'local_organics_feature/application' %> -<%= javascript_include_tag 'local_organics_feature/application' %> diff --git a/lib/chili/local_organics_feature/app/overrides/spree/layouts/spree_application/footer.html.erb.deface b/lib/chili/local_organics_feature/app/overrides/spree/layouts/spree_application/footer.html.erb.deface deleted file mode 100644 index d9b0ac9441..0000000000 --- a/lib/chili/local_organics_feature/app/overrides/spree/layouts/spree_application/footer.html.erb.deface +++ /dev/null @@ -1,3 +0,0 @@ - -| <%= link_to 'Terms and Conditions', "http://www.localorg.com.au/contactterms-and-conditions.html" %> -| <%= link_to "http://openfoodweb.org/foundation" do %><%= image_tag 'ofw.png', alt: 'Open Food Foundation' %><% end %> \ No newline at end of file diff --git a/lib/chili/local_organics_feature/app/overrides/spree/layouts/spree_application/logo.html.erb.deface b/lib/chili/local_organics_feature/app/overrides/spree/layouts/spree_application/logo.html.erb.deface deleted file mode 100644 index 1f4b4fe5dd..0000000000 --- a/lib/chili/local_organics_feature/app/overrides/spree/layouts/spree_application/logo.html.erb.deface +++ /dev/null @@ -1,2 +0,0 @@ - -<%= logo 'local_organics_feature/logo.png' %> diff --git a/lib/chili/local_organics_feature/app/overrides/spree/shared/_products_by_distributor/local.html.haml.deface b/lib/chili/local_organics_feature/app/overrides/spree/shared/_products_by_distributor/local.html.haml.deface deleted file mode 100644 index f63276ec91..0000000000 --- a/lib/chili/local_organics_feature/app/overrides/spree/shared/_products_by_distributor/local.html.haml.deface +++ /dev/null @@ -1,3 +0,0 @@ -/ replace_contents '#products-local' -%h5= "Products at #{current_distributor.name}" -= render 'spree/shared/products', :products => @products_local, :taxon => @taxon diff --git a/lib/chili/local_organics_feature/app/overrides/spree/shared/_products_by_distributor/remote.html.haml.deface b/lib/chili/local_organics_feature/app/overrides/spree/shared/_products_by_distributor/remote.html.haml.deface deleted file mode 100644 index fa27ef4f1a..0000000000 --- a/lib/chili/local_organics_feature/app/overrides/spree/shared/_products_by_distributor/remote.html.haml.deface +++ /dev/null @@ -1,3 +0,0 @@ -/ replace_contents '#products-remote' -%h5 Products found elsewhere -= render 'spree/shared/products', :products => @products_remote, :taxon => @taxon diff --git a/lib/chili/local_organics_feature/config/routes.rb b/lib/chili/local_organics_feature/config/routes.rb deleted file mode 100644 index 7ee7f3fd58..0000000000 --- a/lib/chili/local_organics_feature/config/routes.rb +++ /dev/null @@ -1,3 +0,0 @@ -LocalOrganicsFeature::Engine.automount! -LocalOrganicsFeature::Engine.routes.draw do -end diff --git a/lib/chili/local_organics_feature/lib/generators/local_organics_feature_generator.rb b/lib/chili/local_organics_feature/lib/generators/local_organics_feature_generator.rb deleted file mode 100644 index 23cf22c4eb..0000000000 --- a/lib/chili/local_organics_feature/lib/generators/local_organics_feature_generator.rb +++ /dev/null @@ -1,3 +0,0 @@ -class LocalOrganicsFeatureGenerator < Rails::Generators::Base - include Chili::GeneratorProxy -end diff --git a/lib/chili/local_organics_feature/lib/local_organics_feature.rb b/lib/chili/local_organics_feature/lib/local_organics_feature.rb deleted file mode 100644 index 148abe7761..0000000000 --- a/lib/chili/local_organics_feature/lib/local_organics_feature.rb +++ /dev/null @@ -1,7 +0,0 @@ -require "chili" -require "local_organics_feature/engine" - -module LocalOrganicsFeature - extend Chili::Base - active_if { OpenFoodNetwork::FeatureToggle.enabled? :local_organics } -end diff --git a/lib/chili/local_organics_feature/lib/local_organics_feature/engine.rb b/lib/chili/local_organics_feature/lib/local_organics_feature/engine.rb deleted file mode 100644 index aaba6a8e8c..0000000000 --- a/lib/chili/local_organics_feature/lib/local_organics_feature/engine.rb +++ /dev/null @@ -1,17 +0,0 @@ -require_relative '../../../../open_food_network/feature_toggle' - -module LocalOrganicsFeature - class Engine < ::Rails::Engine - isolate_namespace LocalOrganicsFeature - - if OpenFoodNetwork::FeatureToggle.enabled? :local_organics - initializer 'local_organics_feature.sass', :after => :load_config_initializers do |app| - app.config.sass.load_paths += [self.root.join('app', 'assets', 'stylesheets', 'local_organics_feature')] if Rails.application.config.respond_to? :sass - end - - initializer :assets do |app| - app.config.assets.precompile += ['local_organics_feature/*'] - end - end - end -end diff --git a/lib/chili/local_organics_feature/lib/local_organics_feature/version.rb b/lib/chili/local_organics_feature/lib/local_organics_feature/version.rb deleted file mode 100644 index ef7867a4d6..0000000000 --- a/lib/chili/local_organics_feature/lib/local_organics_feature/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module LocalOrganicsFeature - VERSION = "0.0.1" -end diff --git a/lib/chili/local_organics_feature/local_organics_feature.gemspec b/lib/chili/local_organics_feature/local_organics_feature.gemspec deleted file mode 100644 index 8f9619b4a4..0000000000 --- a/lib/chili/local_organics_feature/local_organics_feature.gemspec +++ /dev/null @@ -1,22 +0,0 @@ -$:.push File.expand_path("../lib", __FILE__) - -# Maintain your gem's version: -require "local_organics_feature/version" - -# Describe your gem and declare its dependencies: -Gem::Specification.new do |s| - s.name = "local_organics_feature" - s.version = LocalOrganicsFeature::VERSION - s.authors = ["Rohan Mitchell"] - s.email = ["rohan@rohanmitchell.com"] - s.homepage = "" - s.summary = "Summary of LocalOrganicsFeature." - s.description = "Description of LocalOrganicsFeature." - - s.files = Dir["{app,config,db,lib}/**/*"] + ["README.rdoc"] - - s.add_dependency "rails", "~> 3.2.11" - s.add_dependency 'chili', '~> 3.1' - - s.add_development_dependency "sqlite3" -end diff --git a/spec/features/admin/enterprises_spec.rb b/spec/features/admin/enterprises_spec.rb index 88c6dc8cb4..3bcce92be2 100644 --- a/spec/features/admin/enterprises_spec.rb +++ b/spec/features/admin/enterprises_spec.rb @@ -64,6 +64,7 @@ feature %q{ fill_in 'enterprise_name', :with => 'Eaterprises' fill_in 'enterprise_description', :with => 'Connecting farmers and eaters' fill_in 'enterprise_long_description', :with => 'Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro.' + fill_in 'enterprise_distributor_info', :with => 'Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro.' uncheck 'enterprise_is_primary_producer' check 'enterprise_is_distributor' diff --git a/spec/features/consumer/shopping/checkout_spec.rb b/spec/features/consumer/shopping/checkout_spec.rb index a780e9fd4e..0f956816a2 100644 --- a/spec/features/consumer/shopping/checkout_spec.rb +++ b/spec/features/consumer/shopping/checkout_spec.rb @@ -7,7 +7,7 @@ feature "As a consumer I want to check out my cart", js: true do include WebHelper include UIComponentHelper - let(:distributor) { create(:distributor_enterprise) } + let(:distributor) { create(:distributor_enterprise, distributor_info: 'distributor info') } let(:supplier) { create(:supplier_enterprise) } let(:order_cycle) { create(:order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise)) } let(:product) { create(:simple_product, supplier: supplier) } @@ -97,6 +97,22 @@ feature "As a consumer I want to check out my cart", js: true do click_button "Purchase" sleep 10 page.should have_content "Your order has been processed successfully" + + # It sends a confirmation email containing the distributor info, pickup time and pickup instructions + distributor_info = distributor.distributor_info + pickup_time = order_cycle.pickup_time_for(distributor) + pickup_instructions = order_cycle.pickup_instructions_for(distributor) + + distributor_info.should_not be_blank + pickup_time.should_not be_blank + pickup_instructions.should_not be_blank + + wait_until { ActionMailer::Base.deliveries.length == 1 } + email = ActionMailer::Base.deliveries.last + + email.body.should include distributor_info + email.body.should include pickup_time + email.body.should include pickup_instructions end it "takes us to the order confirmation page when submitted with 'same as billing address' checked" do From 4480c75494e118e319f81ec6672cea0376e87347 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 1 May 2014 17:13:07 +1000 Subject: [PATCH 22/49] Fix "undefined method 'association_class' for nil:NilClass" error when creating Migs payment gateway --- app/models/spree/gateway_decorator.rb | 10 ++++++++++ app/models/spree/payment_method_decorator.rb | 1 + 2 files changed, 11 insertions(+) create mode 100644 app/models/spree/gateway_decorator.rb diff --git a/app/models/spree/gateway_decorator.rb b/app/models/spree/gateway_decorator.rb new file mode 100644 index 0000000000..e40b260ae8 --- /dev/null +++ b/app/models/spree/gateway_decorator.rb @@ -0,0 +1,10 @@ +Spree::Gateway.class_eval do + + # Due to class load order, when config.cache_classes is enabled (ie. staging and production + # environments), this association isn't inherited from PaymentMethod. As a result, creating + # payment methods using payment gateways results in: + # undefined method `association_class' for nil:NilClass + # To avoid that, we redefine this association here. + + has_and_belongs_to_many :distributors, join_table: 'distributors_payment_methods', :class_name => 'Enterprise', foreign_key: 'payment_method_id', association_foreign_key: 'distributor_id' +end diff --git a/app/models/spree/payment_method_decorator.rb b/app/models/spree/payment_method_decorator.rb index 8e696989a4..ddbc0251a9 100644 --- a/app/models/spree/payment_method_decorator.rb +++ b/app/models/spree/payment_method_decorator.rb @@ -1,4 +1,5 @@ Spree::PaymentMethod.class_eval do + # See gateway_decorator.rb when modifying this association has_and_belongs_to_many :distributors, join_table: 'distributors_payment_methods', :class_name => 'Enterprise', association_foreign_key: 'distributor_id' attr_accessible :distributor_ids From 930bc2b7cebed359263e0c443e600f4cd8383027 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 2 May 2014 14:09:42 +1000 Subject: [PATCH 23/49] Set increased Capybara.default_wait_time globally --- .../features/consumer/checkout_spec.rb | 9 ------- .../admin/bulk_order_management_spec.rb | 9 ------- .../admin/bulk_product_update_spec.rb | 25 ++++++------------- spec/features/admin/enterprise_fees_spec.rb | 9 ------- spec/features/admin/enterprises_spec.rb | 9 ------- spec/features/admin/order_cycles_spec.rb | 10 -------- spec/spec_helper.rb | 2 ++ 7 files changed, 10 insertions(+), 63 deletions(-) diff --git a/spec/archive/features/consumer/checkout_spec.rb b/spec/archive/features/consumer/checkout_spec.rb index 525805eee5..9641085c39 100644 --- a/spec/archive/features/consumer/checkout_spec.rb +++ b/spec/archive/features/consumer/checkout_spec.rb @@ -8,15 +8,6 @@ feature %q{ include AuthenticationWorkflow include WebHelper - before :all do - @default_wait_time = Capybara.default_wait_time - Capybara.default_wait_time = 5 - end - - after :all do - Capybara.default_wait_time = @default_wait_time - end - background do set_feature_toggle :order_cycles, true diff --git a/spec/features/admin/bulk_order_management_spec.rb b/spec/features/admin/bulk_order_management_spec.rb index a56f669756..0039dfd3e1 100644 --- a/spec/features/admin/bulk_order_management_spec.rb +++ b/spec/features/admin/bulk_order_management_spec.rb @@ -7,15 +7,6 @@ feature %q{ include AuthenticationWorkflow include WebHelper - before :all do - @default_wait_time = Capybara.default_wait_time - Capybara.default_wait_time = 10 - end - - after :all do - Capybara.default_wait_time = @default_wait_time - end - context "listing orders" do before :each do login_to_admin_section diff --git a/spec/features/admin/bulk_product_update_spec.rb b/spec/features/admin/bulk_product_update_spec.rb index 0c8d81bd5c..8006b311a5 100644 --- a/spec/features/admin/bulk_product_update_spec.rb +++ b/spec/features/admin/bulk_product_update_spec.rb @@ -7,15 +7,6 @@ feature %q{ include AuthenticationWorkflow include WebHelper - before :all do - @default_wait_time = Capybara.default_wait_time - Capybara.default_wait_time = 5 - end - - after :all do - Capybara.default_wait_time = @default_wait_time - end - describe "listing products" do before :each do login_to_admin_section @@ -534,16 +525,16 @@ feature %q{ end scenario "updating when no changes have been made" do - Capybara.default_wait_time = 2 - FactoryGirl.create(:product, :name => "product 1") - FactoryGirl.create(:product, :name => "product 2") - login_to_admin_section + Capybara.using_wait_time(2) do + FactoryGirl.create(:product, :name => "product 1") + FactoryGirl.create(:product, :name => "product 2") + login_to_admin_section - visit '/admin/products/bulk_edit' + visit '/admin/products/bulk_edit' - click_button 'Update' - page.find("span#update-status-message").should have_content "No changes to update." - Capybara.default_wait_time = 5 + click_button 'Update' + page.find("span#update-status-message").should have_content "No changes to update." + end end scenario "updating when a filter has been applied" do diff --git a/spec/features/admin/enterprise_fees_spec.rb b/spec/features/admin/enterprise_fees_spec.rb index 958aeea419..44f26deddd 100644 --- a/spec/features/admin/enterprise_fees_spec.rb +++ b/spec/features/admin/enterprise_fees_spec.rb @@ -7,15 +7,6 @@ feature %q{ include AuthenticationWorkflow include WebHelper - before :all do - @default_wait_time = Capybara.default_wait_time - Capybara.default_wait_time = 5 - end - - after :all do - Capybara.default_wait_time = @default_wait_time - end - scenario "listing enterprise fees" do fee = create(:enterprise_fee, name: '$0.50 / kg', fee_type: 'packing') amount = fee.calculator.preferred_amount diff --git a/spec/features/admin/enterprises_spec.rb b/spec/features/admin/enterprises_spec.rb index 3bcce92be2..4fac8b4ba5 100644 --- a/spec/features/admin/enterprises_spec.rb +++ b/spec/features/admin/enterprises_spec.rb @@ -7,15 +7,6 @@ feature %q{ include AuthenticationWorkflow include WebHelper - before :all do - @default_wait_time = Capybara.default_wait_time - Capybara.default_wait_time = 5 - end - - after :all do - Capybara.default_wait_time = @default_wait_time - end - scenario "listing enterprises" do s = create(:supplier_enterprise) d = create(:distributor_enterprise) diff --git a/spec/features/admin/order_cycles_spec.rb b/spec/features/admin/order_cycles_spec.rb index 2eff8508c7..9ee0ff5ff0 100644 --- a/spec/features/admin/order_cycles_spec.rb +++ b/spec/features/admin/order_cycles_spec.rb @@ -7,16 +7,6 @@ feature %q{ include AuthenticationWorkflow include WebHelper - before :all do - @orig_default_wait_time = Capybara.default_wait_time - Capybara.default_wait_time = 10 - end - - after :all do - Capybara.default_wait_time = @orig_default_wait_time - end - - scenario "listing order cycles" do # Given some order cycles (created in an arbitrary order) oc4 = create(:simple_order_cycle, name: '4', diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6cf9229252..eff1867c4f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -45,6 +45,8 @@ Capybara.register_driver :poltergeist do |app| Capybara::Poltergeist::Driver.new(app, options) end +Capybara.default_wait_time = 30 + require "paperclip/matchers" From 1d5f0042d4f3ebae34e093a7eb8957befb93a34d Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 2 May 2014 14:25:06 +1000 Subject: [PATCH 24/49] Remove sleeps - these should be covered by increased capybara wait time now --- spec/features/admin/bulk_product_update_spec.rb | 2 -- spec/features/consumer/shopping/checkout_spec.rb | 2 -- 2 files changed, 4 deletions(-) diff --git a/spec/features/admin/bulk_product_update_spec.rb b/spec/features/admin/bulk_product_update_spec.rb index 8006b311a5..7174da9758 100644 --- a/spec/features/admin/bulk_product_update_spec.rb +++ b/spec/features/admin/bulk_product_update_spec.rb @@ -584,7 +584,6 @@ feature %q{ first("a.delete-product").click - sleep(0.5) if page.has_selector? "a.delete-product", :count => 3 # Wait for product to be removed from page page.should have_selector "a.delete-product", :count => 2 visit '/admin/products/bulk_edit' @@ -606,7 +605,6 @@ feature %q{ first("a.delete-variant").click - sleep(0.5) if page.has_selector? "a.delete-variant", :count => 3 # Wait for variant to be removed from page page.should have_selector "a.delete-variant", :count => 2 visit '/admin/products/bulk_edit' diff --git a/spec/features/consumer/shopping/checkout_spec.rb b/spec/features/consumer/shopping/checkout_spec.rb index 0f956816a2..fc64fbed29 100644 --- a/spec/features/consumer/shopping/checkout_spec.rb +++ b/spec/features/consumer/shopping/checkout_spec.rb @@ -95,7 +95,6 @@ feature "As a consumer I want to check out my cart", js: true do fill_in "Postcode", with: "3066" end click_button "Purchase" - sleep 10 page.should have_content "Your order has been processed successfully" # It sends a confirmation email containing the distributor info, pickup time and pickup instructions @@ -138,7 +137,6 @@ feature "As a consumer I want to check out my cart", js: true do toggle_accordion "Shipping" check "Shipping address same as billing address?" click_button "Purchase" - sleep 10 page.should have_content "Your order has been processed successfully" end end From db653682b18db1c5862e26691dec8b9e1293800b Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 2 May 2014 14:25:19 +1000 Subject: [PATCH 25/49] Add capybara-screenshot - automatic screenshots for test fails --- Gemfile | 1 + Gemfile.lock | 4 ++++ spec/spec_helper.rb | 1 + 3 files changed, 6 insertions(+) diff --git a/Gemfile b/Gemfile index af4108c9eb..45a78d9dc9 100644 --- a/Gemfile +++ b/Gemfile @@ -69,6 +69,7 @@ group :test, :development do gem 'shoulda-matchers' gem 'factory_girl_rails', :require => false gem 'capybara' + gem 'capybara-screenshot' gem 'database_cleaner', '0.7.1', :require => false gem 'simplecov', :require => false gem 'awesome_print' diff --git a/Gemfile.lock b/Gemfile.lock index adba98ff8a..e82e5e5ad8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -166,6 +166,9 @@ GEM rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) + capybara-screenshot (0.3.19) + capybara (>= 1.0, < 3) + launchy celluloid (0.15.2) timers (~> 1.1.0) chunky_png (1.3.0) @@ -488,6 +491,7 @@ DEPENDENCIES aws-sdk bugsnag capybara + capybara-screenshot coffee-rails (~> 3.2.1) comfortable_mexican_sofa compass-rails diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index eff1867c4f..66d1f681b4 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -11,6 +11,7 @@ ENV["RAILS_ENV"] ||= 'test' require File.expand_path("../../config/environment", __FILE__) require 'rspec/rails' require 'capybara' +require 'capybara-screenshot/rspec' require 'database_cleaner' # Allow connections to phantomjs/selenium whilst raising errors From b907616749660c03e5c06c80f2eb99e247383730 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Fri, 2 May 2014 14:47:12 +1000 Subject: [PATCH 26/49] Renaming our partials --- .../darkswarm/services/order.js.coffee | 2 +- app/controllers/application_controller.rb | 2 +- .../{shop => }/checkout_controller.rb | 2 +- app/controllers/{shop => }/shop_controller.rb | 6 +++--- app/helpers/shop/checkout_helper.rb | 2 -- .../checkout/_authentication.html.haml | 0 .../{shop => }/checkout/_billing.html.haml | 0 .../{shop => }/checkout/_details.html.haml | 0 app/views/checkout/_form.html.haml | 17 +++++++++++++++++ app/views/{shop => }/checkout/_order.rabl | 0 .../{shop => }/checkout/_payment.html.haml | 0 .../{shop => }/checkout/_shipping.html.haml | 0 .../{shop => }/checkout/_summary.html.haml | 0 app/views/{shop => }/checkout/edit.html.haml | 8 ++++---- app/views/{shop/shop => json}/_order_cycle.rabl | 0 app/views/shop/{shop => }/_products.html.haml | 2 +- app/views/shop/{shop => }/_variant.html.haml | 0 app/views/shop/checkout/_form.html.haml | 17 ----------------- app/views/shop/{shop => }/products.rabl | 0 app/views/shop/{shop => }/show.html.haml | 4 ++-- .../shop => shopping_shared}/_about.html.haml | 0 .../shop => shopping_shared}/_contact.html.haml | 0 .../_details.html.haml | 6 +++--- .../shop => shopping_shared}/_groups.html.haml | 0 .../_last_order_cycle.html.haml | 0 .../{shop => shopping_shared}/_modals.html.haml | 0 .../_next_order_cycle.html.haml | 0 .../_order_cycles.html.haml | 6 +++--- .../_producers.html.haml | 0 .../{shop => shopping_shared}/_tabs.html.haml | 2 +- app/views/spree/orders/edit.html.haml | 4 ++-- app/views/spree/orders/show.html.haml | 2 +- config/routes.rb | 10 ++++------ .../{shop => }/checkout_controller_spec.rb | 2 +- .../{shop => }/shop_controller_spec.rb | 2 +- .../consumer/shopping/checkout_auth_spec.rb | 4 ++-- .../features/consumer/shopping/checkout_spec.rb | 6 +++--- .../darkswarm/services/order_spec.js.coffee | 6 +++--- 38 files changed, 54 insertions(+), 58 deletions(-) rename app/controllers/{shop => }/checkout_controller.rb (98%) rename app/controllers/{shop => }/shop_controller.rb (87%) delete mode 100644 app/helpers/shop/checkout_helper.rb rename app/views/{shop => }/checkout/_authentication.html.haml (100%) rename app/views/{shop => }/checkout/_billing.html.haml (100%) rename app/views/{shop => }/checkout/_details.html.haml (100%) create mode 100644 app/views/checkout/_form.html.haml rename app/views/{shop => }/checkout/_order.rabl (100%) rename app/views/{shop => }/checkout/_payment.html.haml (100%) rename app/views/{shop => }/checkout/_shipping.html.haml (100%) rename app/views/{shop => }/checkout/_summary.html.haml (100%) rename app/views/{shop => }/checkout/edit.html.haml (62%) rename app/views/{shop/shop => json}/_order_cycle.rabl (100%) rename app/views/shop/{shop => }/_products.html.haml (98%) rename app/views/shop/{shop => }/_variant.html.haml (100%) delete mode 100644 app/views/shop/checkout/_form.html.haml rename app/views/shop/{shop => }/products.rabl (100%) rename app/views/shop/{shop => }/show.html.haml (88%) rename app/views/{shop/shop => shopping_shared}/_about.html.haml (100%) rename app/views/{shop/shop => shopping_shared}/_contact.html.haml (100%) rename app/views/{shop => shopping_shared}/_details.html.haml (66%) rename app/views/{shop/shop => shopping_shared}/_groups.html.haml (100%) rename app/views/{shop/shop => shopping_shared}/_last_order_cycle.html.haml (100%) rename app/views/{shop => shopping_shared}/_modals.html.haml (100%) rename app/views/{shop/shop => shopping_shared}/_next_order_cycle.html.haml (100%) rename app/views/{shop/shop => shopping_shared}/_order_cycles.html.haml (74%) rename app/views/{shop/shop => shopping_shared}/_producers.html.haml (100%) rename app/views/{shop => shopping_shared}/_tabs.html.haml (88%) rename spec/controllers/{shop => }/checkout_controller_spec.rb (99%) rename spec/controllers/{shop => }/shop_controller_spec.rb (99%) diff --git a/app/assets/javascripts/darkswarm/services/order.js.coffee b/app/assets/javascripts/darkswarm/services/order.js.coffee index 3c86afac9f..63ea6ee6c7 100644 --- a/app/assets/javascripts/darkswarm/services/order.js.coffee +++ b/app/assets/javascripts/darkswarm/services/order.js.coffee @@ -8,7 +8,7 @@ Darkswarm.factory 'Order', ($resource, Product, order, $http, CheckoutFormState, @order.shipping_method_id ||= parseInt(Object.keys(@order.shipping_methods)[0]) submit: -> - $http.put('/shop/checkout', {order: @preprocess()}).success (data, status)=> + $http.put('/checkout', {order: @preprocess()}).success (data, status)=> Navigation.go data.path .error (response, status)=> @errors = response.errors diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d9cb36a3e9..3a4de9aaf6 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -6,7 +6,7 @@ class ApplicationController < ActionController::Base def after_sign_in_path_for(resource) if request.referer and referer_path = URI(request.referer).path - [main_app.shop_checkout_path].include?(referer_path) ? referer_path : root_path + [main_app.checkout_path].include?(referer_path) ? referer_path : root_path else root_path end diff --git a/app/controllers/shop/checkout_controller.rb b/app/controllers/checkout_controller.rb similarity index 98% rename from app/controllers/shop/checkout_controller.rb rename to app/controllers/checkout_controller.rb index f2d79e503a..95cee2fd39 100644 --- a/app/controllers/shop/checkout_controller.rb +++ b/app/controllers/checkout_controller.rb @@ -1,4 +1,4 @@ -class Shop::CheckoutController < Spree::CheckoutController +class CheckoutController < Spree::CheckoutController layout 'darkswarm' prepend_before_filter :require_order_cycle prepend_before_filter :require_distributor_chosen diff --git a/app/controllers/shop/shop_controller.rb b/app/controllers/shop_controller.rb similarity index 87% rename from app/controllers/shop/shop_controller.rb rename to app/controllers/shop_controller.rb index 95d18a0e2e..8406a15951 100644 --- a/app/controllers/shop/shop_controller.rb +++ b/app/controllers/shop_controller.rb @@ -1,4 +1,4 @@ -class Shop::ShopController < BaseController +class ShopController < BaseController layout "darkswarm" before_filter :require_distributor_chosen before_filter :set_order_cycles @@ -19,12 +19,12 @@ class Shop::ShopController < BaseController if request.post? if oc = OrderCycle.with_distributor(@distributor).active.find_by_id(params[:order_cycle_id]) current_order(true).set_order_cycle! oc - render partial: "shop/shop/order_cycle" + render partial: "json/order_cycle" else render status: 404, json: "" end else - render partial: "shop/shop/order_cycle" + render partial: "json/order_cycle" end end diff --git a/app/helpers/shop/checkout_helper.rb b/app/helpers/shop/checkout_helper.rb deleted file mode 100644 index 263dcc8321..0000000000 --- a/app/helpers/shop/checkout_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module Shop::CheckoutHelper -end diff --git a/app/views/shop/checkout/_authentication.html.haml b/app/views/checkout/_authentication.html.haml similarity index 100% rename from app/views/shop/checkout/_authentication.html.haml rename to app/views/checkout/_authentication.html.haml diff --git a/app/views/shop/checkout/_billing.html.haml b/app/views/checkout/_billing.html.haml similarity index 100% rename from app/views/shop/checkout/_billing.html.haml rename to app/views/checkout/_billing.html.haml diff --git a/app/views/shop/checkout/_details.html.haml b/app/views/checkout/_details.html.haml similarity index 100% rename from app/views/shop/checkout/_details.html.haml rename to app/views/checkout/_details.html.haml diff --git a/app/views/checkout/_form.html.haml b/app/views/checkout/_form.html.haml new file mode 100644 index 0000000000..ec759f73a4 --- /dev/null +++ b/app/views/checkout/_form.html.haml @@ -0,0 +1,17 @@ += f_form_for current_order, url: main_app.update_checkout_path, + html: {name: "checkout", + id: "checkout_form", + novalidate: true, + name: "checkout"} do |f| + + :javascript + angular.module('Darkswarm').value('order', #{render "checkout/order"}) + + -#%pre + -#{{ Order.order == order }} + + .large-12.columns + = render partial: "checkout/details", locals: {f: f} + = render partial: "checkout/billing", locals: {f: f} + = render partial: "checkout/shipping", locals: {f: f} + = render partial: "checkout/payment", locals: {f: f} diff --git a/app/views/shop/checkout/_order.rabl b/app/views/checkout/_order.rabl similarity index 100% rename from app/views/shop/checkout/_order.rabl rename to app/views/checkout/_order.rabl diff --git a/app/views/shop/checkout/_payment.html.haml b/app/views/checkout/_payment.html.haml similarity index 100% rename from app/views/shop/checkout/_payment.html.haml rename to app/views/checkout/_payment.html.haml diff --git a/app/views/shop/checkout/_shipping.html.haml b/app/views/checkout/_shipping.html.haml similarity index 100% rename from app/views/shop/checkout/_shipping.html.haml rename to app/views/checkout/_shipping.html.haml diff --git a/app/views/shop/checkout/_summary.html.haml b/app/views/checkout/_summary.html.haml similarity index 100% rename from app/views/shop/checkout/_summary.html.haml rename to app/views/checkout/_summary.html.haml diff --git a/app/views/shop/checkout/edit.html.haml b/app/views/checkout/edit.html.haml similarity index 62% rename from app/views/shop/checkout/edit.html.haml rename to app/views/checkout/edit.html.haml index c3db3fddf6..e43d4f282d 100644 --- a/app/views/shop/checkout/edit.html.haml +++ b/app/views/checkout/edit.html.haml @@ -4,15 +4,15 @@ Order ready on = pickup_time current_order_cycle - = render partial: "shop/details" + = render partial: "shopping_shared/details" %accordion.row{"close-others" => "true"} %checkout{"ng-controller" => "CheckoutCtrl"} .large-9.columns - unless spree_current_user - = render partial: "shop/checkout/authentication" + = render partial: "checkout/authentication" .row - = render partial: "shop/checkout/form" + = render partial: "checkout/form" .large-3.columns - = render partial: "shop/checkout/summary" + = render partial: "checkout/summary" diff --git a/app/views/shop/shop/_order_cycle.rabl b/app/views/json/_order_cycle.rabl similarity index 100% rename from app/views/shop/shop/_order_cycle.rabl rename to app/views/json/_order_cycle.rabl diff --git a/app/views/shop/shop/_products.html.haml b/app/views/shop/_products.html.haml similarity index 98% rename from app/views/shop/shop/_products.html.haml rename to app/views/shop/_products.html.haml index 57f03632fa..7ed6606717 100644 --- a/app/views/shop/shop/_products.html.haml +++ b/app/views/shop/_products.html.haml @@ -72,7 +72,7 @@ %td{colspan: 2}{{ product.notes | truncate:80 }} %tr.variant{"ng-repeat" => "variant in product.variants", "ng-if" => "product.show_variants"} - = render partial: "shop/shop/variant" + = render partial: "shop/variant" %input.button.right{type: :submit, value: "Add to Cart"} diff --git a/app/views/shop/shop/_variant.html.haml b/app/views/shop/_variant.html.haml similarity index 100% rename from app/views/shop/shop/_variant.html.haml rename to app/views/shop/_variant.html.haml diff --git a/app/views/shop/checkout/_form.html.haml b/app/views/shop/checkout/_form.html.haml deleted file mode 100644 index a198213397..0000000000 --- a/app/views/shop/checkout/_form.html.haml +++ /dev/null @@ -1,17 +0,0 @@ -= f_form_for current_order, url: main_app.shop_update_checkout_path, - html: {name: "checkout", - id: "checkout_form", - novalidate: true, - name: "checkout"} do |f| - - :javascript - angular.module('Darkswarm').value('order', #{render "shop/checkout/order"}) - - -#%pre - -#{{ Order.order == order }} - - .large-12.columns - = render partial: "shop/checkout/details", locals: {f: f} - = render partial: "shop/checkout/billing", locals: {f: f} - = render partial: "shop/checkout/shipping", locals: {f: f} - = render partial: "shop/checkout/payment", locals: {f: f} diff --git a/app/views/shop/shop/products.rabl b/app/views/shop/products.rabl similarity index 100% rename from app/views/shop/shop/products.rabl rename to app/views/shop/products.rabl diff --git a/app/views/shop/shop/show.html.haml b/app/views/shop/show.html.haml similarity index 88% rename from app/views/shop/shop/show.html.haml rename to app/views/shop/show.html.haml index 1ec4da7b2e..ecfcc8e4e3 100644 --- a/app/views/shop/shop/show.html.haml +++ b/app/views/shop/show.html.haml @@ -11,7 +11,7 @@ Orders close %strong {{ OrderCycle.orders_close_at() | date_in_words }} - = render partial: "shop/details" + = render partial: "shopping_shared/details" %products.row - = render partial: "shop/shop/products" + = render partial: "shop/products" diff --git a/app/views/shop/shop/_about.html.haml b/app/views/shopping_shared/_about.html.haml similarity index 100% rename from app/views/shop/shop/_about.html.haml rename to app/views/shopping_shared/_about.html.haml diff --git a/app/views/shop/shop/_contact.html.haml b/app/views/shopping_shared/_contact.html.haml similarity index 100% rename from app/views/shop/shop/_contact.html.haml rename to app/views/shopping_shared/_contact.html.haml diff --git a/app/views/shop/_details.html.haml b/app/views/shopping_shared/_details.html.haml similarity index 66% rename from app/views/shop/_details.html.haml rename to app/views/shopping_shared/_details.html.haml index 73a83fec5a..37edfa3c16 100644 --- a/app/views/shop/_details.html.haml +++ b/app/views/shopping_shared/_details.html.haml @@ -1,4 +1,4 @@ -= render partial: "shop/modals" += render partial: "shopping_shared/modals" %navigation %distributor.details.row @@ -10,6 +10,6 @@ %small %a{href: "/"} Change location - = render partial: "shop/shop/order_cycles" + = render partial: "shopping_shared/order_cycles" -= render partial: "shop/tabs" += render partial: "shopping_shared/tabs" diff --git a/app/views/shop/shop/_groups.html.haml b/app/views/shopping_shared/_groups.html.haml similarity index 100% rename from app/views/shop/shop/_groups.html.haml rename to app/views/shopping_shared/_groups.html.haml diff --git a/app/views/shop/shop/_last_order_cycle.html.haml b/app/views/shopping_shared/_last_order_cycle.html.haml similarity index 100% rename from app/views/shop/shop/_last_order_cycle.html.haml rename to app/views/shopping_shared/_last_order_cycle.html.haml diff --git a/app/views/shop/_modals.html.haml b/app/views/shopping_shared/_modals.html.haml similarity index 100% rename from app/views/shop/_modals.html.haml rename to app/views/shopping_shared/_modals.html.haml diff --git a/app/views/shop/shop/_next_order_cycle.html.haml b/app/views/shopping_shared/_next_order_cycle.html.haml similarity index 100% rename from app/views/shop/shop/_next_order_cycle.html.haml rename to app/views/shopping_shared/_next_order_cycle.html.haml diff --git a/app/views/shop/shop/_order_cycles.html.haml b/app/views/shopping_shared/_order_cycles.html.haml similarity index 74% rename from app/views/shop/shop/_order_cycles.html.haml rename to app/views/shopping_shared/_order_cycles.html.haml index 1ec978dce2..91517e0c1c 100644 --- a/app/views/shop/shop/_order_cycles.html.haml +++ b/app/views/shopping_shared/_order_cycles.html.haml @@ -1,6 +1,6 @@ %ordercycle{"ng-controller" => "OrderCycleCtrl"} :javascript - angular.module('Darkswarm').value('orderCycleData', #{render "shop/shop/order_cycle"}) + angular.module('Darkswarm').value('orderCycleData', #{render "json/order_cycle"}) - if @order_cycles and @order_cycles.empty? Orders are currently closed for this hub @@ -8,8 +8,8 @@ Please contact your hub directly to see if they accept late orders, or wait until the next cycle opens. - = render partial: "shop/shop/next_order_cycle" - = render partial: "shop/shop/last_order_cycle" + = render partial: "shopping_shared/next_order_cycle" + = render partial: "shopping_shared/last_order_cycle" - else %form.custom diff --git a/app/views/shop/shop/_producers.html.haml b/app/views/shopping_shared/_producers.html.haml similarity index 100% rename from app/views/shop/shop/_producers.html.haml rename to app/views/shopping_shared/_producers.html.haml diff --git a/app/views/shop/_tabs.html.haml b/app/views/shopping_shared/_tabs.html.haml similarity index 88% rename from app/views/shop/_tabs.html.haml rename to app/views/shopping_shared/_tabs.html.haml index a548a6710e..3a29a12e6c 100644 --- a/app/views/shop/_tabs.html.haml +++ b/app/views/shopping_shared/_tabs.html.haml @@ -10,4 +10,4 @@ id: "tab_#{name}", active: "active(#{name}.path)", select: "select(#{name})"} - = render "shop/shop/#{name}" + = render "shopping_shared/#{name}" diff --git a/app/views/spree/orders/edit.html.haml b/app/views/spree/orders/edit.html.haml index d732c5fc59..06b82d5169 100644 --- a/app/views/spree/orders/edit.html.haml +++ b/app/views/spree/orders/edit.html.haml @@ -8,7 +8,7 @@ - else = @order.distributor.next_collection_at - = render partial: "shop/details" + = render partial: "shopping_shared/details" %fieldset - if @order.line_items.empty? @@ -54,5 +54,5 @@ = button_tag :class => 'secondary', :id => 'update-button' do = t(:update) = t(:or) - = link_to "Checkout", main_app.shop_checkout_path, class: "button checkout primary", id: "checkout-link" + = link_to "Checkout", main_app.checkout_path, class: "button checkout primary", id: "checkout-link" diff --git a/app/views/spree/orders/show.html.haml b/app/views/spree/orders/show.html.haml index 32177157e7..f0fe766696 100644 --- a/app/views/spree/orders/show.html.haml +++ b/app/views/spree/orders/show.html.haml @@ -7,7 +7,7 @@ - else = @order.distributor.next_collection_at - = render partial: "shop/details" + = render partial: "shopping_shared/details" .row %fieldset#order_summary{"data-hook" => ""} diff --git a/config/routes.rb b/config/routes.rb index 2352b832d6..e4868d777c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,7 +1,7 @@ Openfoodnetwork::Application.routes.draw do root :to => 'home#index' - resource :shop, controller: "shop/shop" do + resource :shop, controller: "shop" do get :products post :order_cycle get :order_cycle @@ -9,11 +9,9 @@ Openfoodnetwork::Application.routes.draw do resources :producers - namespace :shop do - get '/checkout', :to => 'checkout#edit' , :as => :checkout - put '/checkout', :to => 'checkout#update' , :as => :update_checkout - get "/checkout/paypal_payment", to: 'checkout#paypal_payment', as: :paypal_payment - end + get '/checkout', :to => 'checkout#edit' , :as => :checkout + put '/checkout', :to => 'checkout#update' , :as => :update_checkout + get "/checkout/paypal_payment", to: 'checkout#paypal_payment', as: :paypal_payment resources :enterprises do collection do diff --git a/spec/controllers/shop/checkout_controller_spec.rb b/spec/controllers/checkout_controller_spec.rb similarity index 99% rename from spec/controllers/shop/checkout_controller_spec.rb rename to spec/controllers/checkout_controller_spec.rb index bdefa65ec2..1f3b1cb9fc 100644 --- a/spec/controllers/shop/checkout_controller_spec.rb +++ b/spec/controllers/checkout_controller_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Shop::CheckoutController do +describe CheckoutController do let(:distributor) { double(:distributor) } let(:order_cycle) { create(:order_cycle) } let(:order) { create(:order) } diff --git a/spec/controllers/shop/shop_controller_spec.rb b/spec/controllers/shop_controller_spec.rb similarity index 99% rename from spec/controllers/shop/shop_controller_spec.rb rename to spec/controllers/shop_controller_spec.rb index e94e785573..88cde0e6d9 100644 --- a/spec/controllers/shop/shop_controller_spec.rb +++ b/spec/controllers/shop_controller_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Shop::ShopController do +describe ShopController do let(:d) { create(:distributor_enterprise) } it "redirects to the home page if no distributor is selected" do diff --git a/spec/features/consumer/shopping/checkout_auth_spec.rb b/spec/features/consumer/shopping/checkout_auth_spec.rb index f1650109ca..5574aedc57 100644 --- a/spec/features/consumer/shopping/checkout_auth_spec.rb +++ b/spec/features/consumer/shopping/checkout_auth_spec.rb @@ -20,14 +20,14 @@ feature "As a consumer I want to check out my cart", js: true do it "does not not render the login form when logged in" do quick_login_as user - visit shop_checkout_path + visit checkout_path within "section[role='main']" do page.should_not have_content "USER" end end it "renders the login form when logged out" do - visit shop_checkout_path + visit checkout_path toggle_accordion "User" within "section[role='main']" do page.should have_content "User" diff --git a/spec/features/consumer/shopping/checkout_spec.rb b/spec/features/consumer/shopping/checkout_spec.rb index 309148b100..b2e476b092 100644 --- a/spec/features/consumer/shopping/checkout_spec.rb +++ b/spec/features/consumer/shopping/checkout_spec.rb @@ -19,7 +19,7 @@ feature "As a consumer I want to check out my cart", js: true do end it "shows the current distributor oncheckout" do - visit shop_checkout_path + visit checkout_path page.should have_content distributor.name end @@ -33,7 +33,7 @@ feature "As a consumer I want to check out my cart", js: true do context "on the checkout page" do before do - visit shop_checkout_path + visit checkout_path end it "shows all shipping methods, but doesn't show ship address when not needed" do @@ -60,7 +60,7 @@ feature "As a consumer I want to check out my cart", js: true do let!(:pm3) { create(:payment_method, distributors: [distributor], name: "Paypal", type: "Spree::BillingIntegration::PaypalExpress") } before do - visit shop_checkout_path + visit checkout_path toggle_accordion "Payment Details" end diff --git a/spec/javascripts/unit/darkswarm/services/order_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/order_spec.js.coffee index a6e3ab9642..fa06ead17f 100644 --- a/spec/javascripts/unit/darkswarm/services/order_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/order_spec.js.coffee @@ -58,18 +58,18 @@ describe 'Order service', -> expect(Order.paymentMethod()).toEqual {test: "foo"} it "Posts the Order to the server", -> - $httpBackend.expectPUT("/shop/checkout", {order: Order.preprocess()}).respond 200, {path: "test"} + $httpBackend.expectPUT("/checkout", {order: Order.preprocess()}).respond 200, {path: "test"} Order.submit() $httpBackend.flush() it "sends flash messages to the flash service", -> - $httpBackend.expectPUT("/shop/checkout").respond 400, {flash: {error: "frogs"}} + $httpBackend.expectPUT("/checkout").respond 400, {flash: {error: "frogs"}} Order.submit() $httpBackend.flush() expect(flash.error).toEqual "frogs" it "puts errors into the scope", -> - $httpBackend.expectPUT("/shop/checkout").respond 400, {errors: {error: "frogs"}} + $httpBackend.expectPUT("/checkout").respond 400, {errors: {error: "frogs"}} Order.submit() $httpBackend.flush() expect(Order.errors).toEqual {error: "frogs"} From 23fa1c7b7b080126bd3fd7e2a7aa0fa6675c6895 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Fri, 2 May 2014 15:17:44 +1000 Subject: [PATCH 27/49] Patching a couple more issues --- app/controllers/checkout_controller.rb | 2 +- spec/controllers/checkout_controller_spec.rb | 2 +- spec/features/consumer/home_spec.rb | 7 +++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/controllers/checkout_controller.rb b/app/controllers/checkout_controller.rb index 95cee2fd39..43930818ca 100644 --- a/app/controllers/checkout_controller.rb +++ b/app/controllers/checkout_controller.rb @@ -120,7 +120,7 @@ class CheckoutController < Spree::CheckoutController # Overriding to customize the cancel url def order_opts_with_new_cancel_return_url(order, payment_method_id, stage) opts = order_opts_without_new_cancel_return_url(order, payment_method_id, stage) - opts[:cancel_return_url] = main_app.shop_checkout_url + opts[:cancel_return_url] = main_app.checkout_url opts end alias_method_chain :order_opts, :new_cancel_return_url diff --git a/spec/controllers/checkout_controller_spec.rb b/spec/controllers/checkout_controller_spec.rb index 1f3b1cb9fc..d8c6ee738c 100644 --- a/spec/controllers/checkout_controller_spec.rb +++ b/spec/controllers/checkout_controller_spec.rb @@ -125,7 +125,7 @@ describe CheckoutController do it "should override the cancel return url" do controller.stub(:params).and_return({payment_method_id: payment_method.id}) - controller.send(:order_opts, order, payment_method.id, 'payment')[:cancel_return_url].should == shop_checkout_url + controller.send(:order_opts, order, payment_method.id, 'payment')[:cancel_return_url].should == checkout_url end end end diff --git a/spec/features/consumer/home_spec.rb b/spec/features/consumer/home_spec.rb index 67599d97a0..ae60766f30 100644 --- a/spec/features/consumer/home_spec.rb +++ b/spec/features/consumer/home_spec.rb @@ -4,13 +4,12 @@ feature 'Home', js: true do include AuthenticationWorkflow include UIComponentHelper - let(:distributor) { create(:distributor_enterprise) } + let!(:distributor) { create(:distributor_enterprise) } let(:d1) { create(:distributor_enterprise) } let(:d2) { create(:distributor_enterprise) } - let(:order_cycle) { create(:order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise)) } + let!(:order_cycle) { create(:order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise)) } + before do - distributor - order_cycle visit "/" end From 901c9abe381a7331f1d5791cb0a7db8338455373 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 2 May 2014 15:39:17 +1000 Subject: [PATCH 28/49] Increase wait time for failing spec --- spec/features/consumer/shopping/checkout_spec.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/spec/features/consumer/shopping/checkout_spec.rb b/spec/features/consumer/shopping/checkout_spec.rb index fc64fbed29..ae0b9760da 100644 --- a/spec/features/consumer/shopping/checkout_spec.rb +++ b/spec/features/consumer/shopping/checkout_spec.rb @@ -106,12 +106,14 @@ feature "As a consumer I want to check out my cart", js: true do pickup_time.should_not be_blank pickup_instructions.should_not be_blank - wait_until { ActionMailer::Base.deliveries.length == 1 } - email = ActionMailer::Base.deliveries.last + Capybara.using_wait_time(60) do + wait_until { ActionMailer::Base.deliveries.length == 1 } + email = ActionMailer::Base.deliveries.last - email.body.should include distributor_info - email.body.should include pickup_time - email.body.should include pickup_instructions + email.body.should include distributor_info + email.body.should include pickup_time + email.body.should include pickup_instructions + end end it "takes us to the order confirmation page when submitted with 'same as billing address' checked" do From 27728d6f0ea1f17d39ccc2fa0a2b4f2d3257ffff Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Mon, 5 May 2014 12:08:45 +1000 Subject: [PATCH 29/49] Adding our first request spec --- spec/requests/shop_spec.rb | 79 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 spec/requests/shop_spec.rb diff --git a/spec/requests/shop_spec.rb b/spec/requests/shop_spec.rb new file mode 100644 index 0000000000..7f4f4395e6 --- /dev/null +++ b/spec/requests/shop_spec.rb @@ -0,0 +1,79 @@ +require 'spec_helper' + +describe "Shop API" do + include ShopWorkflow + + describe "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: oc1) } + + before do + set_order order + + 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 + get products_shop_path + end + + it "filters products based on availability" do + # It shows on hand products + response.body.should include p1.name + response.body.should include p4.name + # It shows on demand products + response.body.should include p2.name + # It does not show products that are neither on hand or on demand + response.body.should_not include p3.name + # It shows on demand variants + response.body.should include v3.options_text + # It does not show variants that are neither on hand or on demand + response.body.should_not include v2.options_text + # It does not show products that have no available variants in this distribution + response.body.should_not include p5.name + # It does not show deleted products + response.body.should_not include p6.name + # It does not show deleted variants + response.body.should_not include v6.name + response.body.should_not include p7.name + end + end +end From 1774bc1e197241777b58830382e0198fed0cfc12 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Mon, 5 May 2014 15:43:11 +1000 Subject: [PATCH 30/49] Adding producers filtering and more Angular magic --- .../account_sidebar_controller.js.coffee | 0 .../forgot_sidebar_controller.js.coffee | 0 .../login_sidebar_controller.js.coffee | 0 .../sidebar_controller.js.coffee | 0 .../signup_sidebar_controller.js.coffee | 0 .../darkswarm/filters/filter_hubs.js.coffee | 10 +++---- .../filters/filter_producers.js.coffee | 6 ++++ .../darkswarm/services/matcher.js.coffee | 5 ++++ app/views/home/_hubs.html.haml | 2 +- app/views/producers/index.haml | 12 ++++++-- app/views/shared/{ => menu}/_menu.html.haml | 0 .../filters/filter_hubs_spec.js.coffee | 4 +-- .../filters/filter_producers_spec.js.coffee | 28 +++++++++++++++++++ 13 files changed, 57 insertions(+), 10 deletions(-) rename app/assets/javascripts/darkswarm/controllers/{ => sidebar}/account_sidebar_controller.js.coffee (100%) rename app/assets/javascripts/darkswarm/controllers/{ => sidebar}/forgot_sidebar_controller.js.coffee (100%) rename app/assets/javascripts/darkswarm/controllers/{ => sidebar}/login_sidebar_controller.js.coffee (100%) rename app/assets/javascripts/darkswarm/controllers/{ => sidebar}/sidebar_controller.js.coffee (100%) rename app/assets/javascripts/darkswarm/controllers/{ => sidebar}/signup_sidebar_controller.js.coffee (100%) create mode 100644 app/assets/javascripts/darkswarm/filters/filter_producers.js.coffee create mode 100644 app/assets/javascripts/darkswarm/services/matcher.js.coffee rename app/views/shared/{ => menu}/_menu.html.haml (100%) create mode 100644 spec/javascripts/unit/darkswarm/filters/filter_producers_spec.js.coffee diff --git a/app/assets/javascripts/darkswarm/controllers/account_sidebar_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/sidebar/account_sidebar_controller.js.coffee similarity index 100% rename from app/assets/javascripts/darkswarm/controllers/account_sidebar_controller.js.coffee rename to app/assets/javascripts/darkswarm/controllers/sidebar/account_sidebar_controller.js.coffee diff --git a/app/assets/javascripts/darkswarm/controllers/forgot_sidebar_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/sidebar/forgot_sidebar_controller.js.coffee similarity index 100% rename from app/assets/javascripts/darkswarm/controllers/forgot_sidebar_controller.js.coffee rename to app/assets/javascripts/darkswarm/controllers/sidebar/forgot_sidebar_controller.js.coffee diff --git a/app/assets/javascripts/darkswarm/controllers/login_sidebar_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/sidebar/login_sidebar_controller.js.coffee similarity index 100% rename from app/assets/javascripts/darkswarm/controllers/login_sidebar_controller.js.coffee rename to app/assets/javascripts/darkswarm/controllers/sidebar/login_sidebar_controller.js.coffee diff --git a/app/assets/javascripts/darkswarm/controllers/sidebar_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/sidebar/sidebar_controller.js.coffee similarity index 100% rename from app/assets/javascripts/darkswarm/controllers/sidebar_controller.js.coffee rename to app/assets/javascripts/darkswarm/controllers/sidebar/sidebar_controller.js.coffee diff --git a/app/assets/javascripts/darkswarm/controllers/signup_sidebar_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/sidebar/signup_sidebar_controller.js.coffee similarity index 100% rename from app/assets/javascripts/darkswarm/controllers/signup_sidebar_controller.js.coffee rename to app/assets/javascripts/darkswarm/controllers/sidebar/signup_sidebar_controller.js.coffee diff --git a/app/assets/javascripts/darkswarm/filters/filter_hubs.js.coffee b/app/assets/javascripts/darkswarm/filters/filter_hubs.js.coffee index 29f0b993d1..b6adb84508 100644 --- a/app/assets/javascripts/darkswarm/filters/filter_hubs.js.coffee +++ b/app/assets/javascripts/darkswarm/filters/filter_hubs.js.coffee @@ -1,9 +1,9 @@ -Darkswarm.filter 'filterHubs', -> +Darkswarm.filter 'hubs', (Matcher)-> (hubs, text) -> hubs ||= [] text ?= "" - match = (matched)-> - matched.toLowerCase().indexOf(text.toLowerCase()) != -1 - hubs.filter (hub)-> - match(hub.name) or match(hub.address.zipcode) or match(hub.address.city) or match(hub.address.state) + hubs.filter (hub)=> + Matcher.match [ + hub.name, hub.address.zipcode, hub.address.city, hub.address.state + ], text diff --git a/app/assets/javascripts/darkswarm/filters/filter_producers.js.coffee b/app/assets/javascripts/darkswarm/filters/filter_producers.js.coffee new file mode 100644 index 0000000000..bbbb82fa30 --- /dev/null +++ b/app/assets/javascripts/darkswarm/filters/filter_producers.js.coffee @@ -0,0 +1,6 @@ +Darkswarm.filter 'filterProducers', (hubsFilter)-> + (producers, text) -> + producers ||= [] + text ?= "" + + hubsFilter(producers, text) diff --git a/app/assets/javascripts/darkswarm/services/matcher.js.coffee b/app/assets/javascripts/darkswarm/services/matcher.js.coffee new file mode 100644 index 0000000000..679c30f4c7 --- /dev/null +++ b/app/assets/javascripts/darkswarm/services/matcher.js.coffee @@ -0,0 +1,5 @@ +Darkswarm.factory "Matcher", -> + new class Matcher + match: (properties, text)-> + properties.some (prop)-> + prop.toLowerCase().indexOf(text.toLowerCase()) != -1 diff --git a/app/views/home/_hubs.html.haml b/app/views/home/_hubs.html.haml index a1d821e721..d3eead785b 100644 --- a/app/views/home/_hubs.html.haml +++ b/app/views/home/_hubs.html.haml @@ -23,7 +23,7 @@ .row{bindonce: true} .small-12.columns .active_table - %hub.active_table_node.row{"ng-repeat" => "hub in filteredHubs = (hubs | filterHubs:query)", + %hub.active_table_node.row{"ng-repeat" => "hub in filteredHubs = (hubs | hubs:query)", "ng-class" => "{'closed' : !open(), 'open' : open(), 'inactive' : !hub.active, 'current' : current()}", "ng-controller" => "HubNodeCtrl", id: "{{hub.path}}"} diff --git a/app/views/producers/index.haml b/app/views/producers/index.haml index c368de6011..307014fad6 100644 --- a/app/views/producers/index.haml +++ b/app/views/producers/index.haml @@ -1,14 +1,22 @@ .producers{"ng-controller" => "ProducersCtrl"} :javascript angular.module('Darkswarm').value('producers', #{render partial: "json/producers", object: @producers}) - -#%pre -#{{ Producers.producers | json }} + + .row + .small-12.columns + %input{type: :text, + "ng-model" => "query", + placeholder: "Search postcode, suburb or hub name...", + "ng-debounce" => "150", + "ofn-disable-enter" => true} + .row{bindonce: true} .small-12.columns .active_table %producer.active_table_node.row{id: "{{producer.path}}", - "ng-repeat" => "producer in Producers.producers", + "ng-repeat" => "producer in filteredProducers = (Producers.producers | filterProducers:query)", "ng-controller" => "ProducerNodeCtrl", "ng-class" => "{'closed' : !open(), 'open' : open(), 'inactive' : !producer.active}"} diff --git a/app/views/shared/_menu.html.haml b/app/views/shared/menu/_menu.html.haml similarity index 100% rename from app/views/shared/_menu.html.haml rename to app/views/shared/menu/_menu.html.haml diff --git a/spec/javascripts/unit/darkswarm/filters/filter_hubs_spec.js.coffee b/spec/javascripts/unit/darkswarm/filters/filter_hubs_spec.js.coffee index 8ef281d598..fc2702a72b 100644 --- a/spec/javascripts/unit/darkswarm/filters/filter_hubs_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/filters/filter_hubs_spec.js.coffee @@ -21,10 +21,10 @@ describe 'filtering Hubs', -> module 'Darkswarm' inject ($filter) -> filter = $filter - filterHubs = $filter('filterHubs') + filterHubs = $filter('hubs') it 'has a hub filter', -> - expect(filter('filterHubs')).not.toBeNull() + expect(filter('hubs')).not.toBeNull() it "filters by name", -> expect(filterHubs(hubs, 'donkeys').length).toEqual 1 diff --git a/spec/javascripts/unit/darkswarm/filters/filter_producers_spec.js.coffee b/spec/javascripts/unit/darkswarm/filters/filter_producers_spec.js.coffee new file mode 100644 index 0000000000..29d8986b56 --- /dev/null +++ b/spec/javascripts/unit/darkswarm/filters/filter_producers_spec.js.coffee @@ -0,0 +1,28 @@ +describe 'filtering producers', -> + filter = null + filterProducers = null + producers = [{ + name: "frogs" + other: "roger" + address: + zipcode: "cats" + city: "cambridge" + state: "kansas" + }, { + name: "donkeys" + other: "roger" + address: + zipcode: "" + city: "Wellington" + state: "uzbekistan" + }] + + beforeEach -> + module 'Darkswarm' + inject ($filter) -> + filter = $filter + filterProducers = $filter('filterProducers') + + + it 'has a producer filter', -> + expect(filter('filterProducers')).not.toBeNull() From dd25bfd3453b91d1e6012e66498860c5db5476a0 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Mon, 5 May 2014 15:43:33 +1000 Subject: [PATCH 31/49] Starting to rework menu --- app/views/layouts/darkswarm.html.haml | 24 ++++++++-------- app/views/shared/_sidebar.html.haml | 2 +- app/views/shared/_signed_in.html.haml | 2 +- app/views/shared/_signed_out.html.haml | 11 ++++---- app/views/shared/menu/_large_menu.html.haml | 29 ++++++++++++++++++++ app/views/shared/menu/_menu.html.haml | 27 ++---------------- app/views/shared/menu/_mobile_menu.html.haml | 23 ++++++++++++++++ 7 files changed, 75 insertions(+), 43 deletions(-) create mode 100644 app/views/shared/menu/_large_menu.html.haml create mode 100644 app/views/shared/menu/_mobile_menu.html.haml diff --git a/app/views/layouts/darkswarm.html.haml b/app/views/layouts/darkswarm.html.haml index e44c0600af..52d0b74601 100644 --- a/app/views/layouts/darkswarm.html.haml +++ b/app/views/layouts/darkswarm.html.haml @@ -14,16 +14,18 @@ = csrf_meta_tags %body.off-canvas{"ng-app" => "Darkswarm"} - = render partial: "shared/current_hub" - = render partial: "shared/current_user" - = render partial: "shared/menu" - = display_flash_messages - %ofn-flash + .off-canvas-wrap + .inner-wrap + = render partial: "shared/current_hub" + = render partial: "shared/current_user" + = render partial: "shared/menu/menu" + = display_flash_messages + %ofn-flash - = render "shared/sidebar" + = render "shared/sidebar" - %section{ role: "main" } - = yield - - #footer - = yield :scripts + %section{ role: "main" } + = yield + + #footer + = yield :scripts diff --git a/app/views/shared/_sidebar.html.haml b/app/views/shared/_sidebar.html.haml index 158083d584..c7d69781ea 100644 --- a/app/views/shared/_sidebar.html.haml +++ b/app/views/shared/_sidebar.html.haml @@ -1,4 +1,4 @@ -%section#sidebar{ role: "complementary", "ng-controller" => "SidebarCtrl", +%aside#sidebar.right-off-canvas-menu{ role: "complementary", "ng-controller" => "SidebarCtrl", "ng-class" => "{'active' : Sidebar.active()}"} - if spree_current_user.nil? diff --git a/app/views/shared/_signed_in.html.haml b/app/views/shared/_signed_in.html.haml index f3236cfa73..357391406b 100644 --- a/app/views/shared/_signed_in.html.haml +++ b/app/views/shared/_signed_in.html.haml @@ -1,5 +1,5 @@ %li#login-name - %a.sidebar-button{"ng-click" => "toggle('/account')"} + %a{"ng-click" => "toggle('/account')"} = spree_current_user.email %li.divider %li#sign-out-link diff --git a/app/views/shared/_signed_out.html.haml b/app/views/shared/_signed_out.html.haml index 1ea02cc4ea..67031ceb8c 100644 --- a/app/views/shared/_signed_out.html.haml +++ b/app/views/shared/_signed_out.html.haml @@ -1,5 +1,6 @@ --#%li#login-link - -#%a.sidebar-button{"ng-click" => "toggle('/login')"} Login --#%li.divider --#%li#sign-up-link - -#%a.sidebar-button{"ng-click" => "toggle('/signup')"} Sign Up +%li#login-link + %a{"ng-click" => "toggle('/login')"} Login +%li.divider +%li#sign-up-link + %a{"ng-click" => "toggle('/signup')"} Sign Up + diff --git a/app/views/shared/menu/_large_menu.html.haml b/app/views/shared/menu/_large_menu.html.haml new file mode 100644 index 0000000000..a775a1e64d --- /dev/null +++ b/app/views/shared/menu/_large_menu.html.haml @@ -0,0 +1,29 @@ +%nav.top-bar.hide-for-small + %section.top-bar-section + %ul.left + -#%li + -#%a.icon{"ng-click" => "Sidebar.toggle()"} + -#%i.fi-list + %li= link_to image_tag("ofn_logo_small.png"), root_path + %li.divider + %li + %a{href: producers_path} Producers + + %section.top-bar-section + %ul.right{"ng-controller" => "AuthenticationActionsCtrl"} + %li.divider + - if spree_current_user.nil? + = render 'shared/signed_out' + - else + = render 'shared/signed_in' + %li.divider + %li.current_hub{"ng-controller" => "CurrentHubCtrl", "ng-show" => "CurrentHub.id"} + %a{href: main_app.shop_path} + {{ CurrentHub.name }} + %li.cart + %a.icon{href: cart_url} + %i.fi-shopping-cart + %span + = cart_count + items + diff --git a/app/views/shared/menu/_menu.html.haml b/app/views/shared/menu/_menu.html.haml index dcd3897195..115af32134 100644 --- a/app/views/shared/menu/_menu.html.haml +++ b/app/views/shared/menu/_menu.html.haml @@ -1,25 +1,2 @@ -%nav.top-bar - %section.top-bar-section - %ul.left{"ng-controller" => "AuthenticationActionsCtrl"} - %li - %a.icon{"ng-click" => "Sidebar.toggle()"} - %i.fi-list - - %li= link_to image_tag("ofn_logo_small.png"), root_path - %li.divider - - if spree_current_user.nil? - = render 'shared/signed_out' - - else - = render 'shared/signed_in' - - %section.top-bar-section - %ul.right - %li.current_hub{"ng-controller" => "CurrentHubCtrl", "ng-show" => "CurrentHub.id"} - %a{href: main_app.shop_path} - {{ CurrentHub.name }} - %li.cart - %a.icon{href: cart_url} - %i.fi-shopping-cart - %span - = cart_count - items += render partial: "shared/menu/large_menu" += render partial: "shared/menu/mobile_menu" diff --git a/app/views/shared/menu/_mobile_menu.html.haml b/app/views/shared/menu/_mobile_menu.html.haml new file mode 100644 index 0000000000..8e581c6504 --- /dev/null +++ b/app/views/shared/menu/_mobile_menu.html.haml @@ -0,0 +1,23 @@ +%nav.tab-bar.show-for-small + %section.left-small + %a.left-off-canvas-toggle.menu-icon + %span + %section.right-small + %a.icon{href: cart_url} + %i.fi-shopping-cart + %span + = cart_count + items + %a{href: main_app.shop_path} + {{ CurrentHub.name }} + +%aside.left-off-canvas-menu.show-for-small + %ul.off-canvas-list + %li= link_to image_tag("ofn_logo_small.png"), root_path + %li + %a{href: producers_path} Producers + %li + - if spree_current_user.nil? + = render 'shared/signed_out' + - else + = render 'shared/signed_in' From dcd2e39f2cf5192d982b4a2cc5362205226cb790 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Mon, 5 May 2014 15:57:16 +1000 Subject: [PATCH 32/49] Tweaking for a moved partial --- app/views/layouts/darkswarm.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/darkswarm.html.haml b/app/views/layouts/darkswarm.html.haml index e44c0600af..30910a52a8 100644 --- a/app/views/layouts/darkswarm.html.haml +++ b/app/views/layouts/darkswarm.html.haml @@ -16,7 +16,7 @@ %body.off-canvas{"ng-app" => "Darkswarm"} = render partial: "shared/current_hub" = render partial: "shared/current_user" - = render partial: "shared/menu" + = render partial: "shared/menu/menu" = display_flash_messages %ofn-flash From 9db602f0313726d57c0db4ff521c60849358058f Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Mon, 5 May 2014 16:26:03 +1000 Subject: [PATCH 33/49] Patching the visible flag in admin --- app/views/admin/enterprises/_form.html.haml | 8 ++++---- app/views/admin/enterprises/index.html.erb | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/views/admin/enterprises/_form.html.haml b/app/views/admin/enterprises/_form.html.haml index 3158f464eb..ff5b995af0 100644 --- a/app/views/admin/enterprises/_form.html.haml +++ b/app/views/admin/enterprises/_form.html.haml @@ -25,18 +25,18 @@ = f.collection_select :group_ids, EnterpriseGroup.all, :id, :name, {}, {class: "select2 fullwidth", multiple: true} .row .alpha.two.columns   - .omega.ten.columns + .six.columns = f.check_box :is_primary_producer = f.label :is_primary_producer, 'Producer'   = f.check_box :is_distributor = f.label :is_distributor, 'Hub' -   - = f.check_box :visible - = f.label :visible, 'Visible in search?' .with-tip{'data-powertip' => "Select 'Producer' if you are a primary producer of food. Select 'Hub' if you want a shop-front. You can choose either or both."} %a What's this? + .omega.four.columns + = f.check_box :visible + = f.label :visible, 'Visible in search?' = f.fields_for :address do |af| %fieldset.no-border-bottom diff --git a/app/views/admin/enterprises/index.html.erb b/app/views/admin/enterprises/index.html.erb index f5f6727e56..07c1fa4c46 100644 --- a/app/views/admin/enterprises/index.html.erb +++ b/app/views/admin/enterprises/index.html.erb @@ -24,7 +24,7 @@ Name Role - Active? + Visible? Next Collection Date/Time Description From 010025798d88080ab526c6f3f3d6f6050f61bfae Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Mon, 5 May 2014 16:29:33 +1000 Subject: [PATCH 34/49] Removing a redundant 'in' --- app/assets/javascripts/darkswarm/filters/dates.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/darkswarm/filters/dates.js.coffee b/app/assets/javascripts/darkswarm/filters/dates.js.coffee index 9091c80c7c..d223411e99 100644 --- a/app/assets/javascripts/darkswarm/filters/dates.js.coffee +++ b/app/assets/javascripts/darkswarm/filters/dates.js.coffee @@ -7,4 +7,4 @@ Darkswarm.filter "sensible_timeframe", (date_in_wordsFilter)-> if moment().add('days', 2) < moment(date) "Orders open" else - "Closing in #{date_in_wordsFilter(date)}" + "Closing #{date_in_wordsFilter(date)}" From 1a396429fea588ae03cb189fae2febc4b1442078 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Tue, 6 May 2014 12:27:21 +1000 Subject: [PATCH 35/49] Re-ordering stuff for Laura --- app/views/shared/_signed_out.html.haml | 8 ++++---- app/views/shared/menu/_large_menu.html.haml | 15 ++++++++++++--- app/views/shared/menu/_menu.html.haml | 5 +++-- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/app/views/shared/_signed_out.html.haml b/app/views/shared/_signed_out.html.haml index 67031ceb8c..5c333d8b5f 100644 --- a/app/views/shared/_signed_out.html.haml +++ b/app/views/shared/_signed_out.html.haml @@ -1,6 +1,6 @@ %li#login-link - %a{"ng-click" => "toggle('/login')"} Login -%li.divider -%li#sign-up-link - %a{"ng-click" => "toggle('/signup')"} Sign Up + %a{"ng-click" => "toggle('/login')"} Sign in +-#%li.divider +-#%li#sign-up-link + -#%a{"ng-click" => "toggle('/signup')"} Sign Up diff --git a/app/views/shared/menu/_large_menu.html.haml b/app/views/shared/menu/_large_menu.html.haml index a775a1e64d..fb8916c67c 100644 --- a/app/views/shared/menu/_large_menu.html.haml +++ b/app/views/shared/menu/_large_menu.html.haml @@ -6,8 +6,20 @@ -#%i.fi-list %li= link_to image_tag("ofn_logo_small.png"), root_path %li.divider + %li.current_hub{"ng-controller" => "CurrentHubCtrl", "ng-show" => "CurrentHub.id"} + %a{href: main_app.shop_path} + Selected hub: + {{ CurrentHub.name }} + %li.divider + %li + %a{href: ""} Map + %li.divider %li %a{href: producers_path} Producers + %li.divider + %li + %a{href: ""} Groups & Regions + %li.divider %section.top-bar-section %ul.right{"ng-controller" => "AuthenticationActionsCtrl"} @@ -17,9 +29,6 @@ - else = render 'shared/signed_in' %li.divider - %li.current_hub{"ng-controller" => "CurrentHubCtrl", "ng-show" => "CurrentHub.id"} - %a{href: main_app.shop_path} - {{ CurrentHub.name }} %li.cart %a.icon{href: cart_url} %i.fi-shopping-cart diff --git a/app/views/shared/menu/_menu.html.haml b/app/views/shared/menu/_menu.html.haml index 115af32134..d8f721d71b 100644 --- a/app/views/shared/menu/_menu.html.haml +++ b/app/views/shared/menu/_menu.html.haml @@ -1,2 +1,3 @@ -= render partial: "shared/menu/large_menu" -= render partial: "shared/menu/mobile_menu" +.fixed + = render partial: "shared/menu/large_menu" + = render partial: "shared/menu/mobile_menu" From 93f095d976b621b379ea21b5b291012fd99de426 Mon Sep 17 00:00:00 2001 From: summerscope Date: Tue, 6 May 2014 16:10:02 +1000 Subject: [PATCH 36/49] Adding a menu style and styling around the new top nav --- .../foundation4/foundation/_variables.scss | 2 +- app/assets/stylesheets/darkswarm/all.scss | 1 + .../stylesheets/darkswarm/branding.css.sass | 1 + .../stylesheets/darkswarm/menu.css.sass | 23 +++++++++++++ app/assets/stylesheets/darkswarm/mixins.sass | 7 ++++ .../stylesheets/darkswarm/sidebar.css.sass | 2 -- .../stylesheets/darkswarm/typography.css.sass | 3 +- app/assets/stylesheets/darkswarm/ui.css.sass | 5 +++ app/views/shared/_signed_in.html.haml | 2 +- app/views/shared/_signed_out.html.haml | 4 ++- app/views/shared/menu/_large_menu.html.haml | 33 +++++++++++-------- 11 files changed, 62 insertions(+), 21 deletions(-) create mode 100644 app/assets/stylesheets/darkswarm/menu.css.sass diff --git a/app/assets/javascripts/foundation4/foundation/_variables.scss b/app/assets/javascripts/foundation4/foundation/_variables.scss index 797474c676..fe0b092147 100755 --- a/app/assets/javascripts/foundation4/foundation/_variables.scss +++ b/app/assets/javascripts/foundation4/foundation/_variables.scss @@ -1260,7 +1260,7 @@ $default-float: left; // Height and margin -// $topbar-height: 45px; +// $topbar-height: 85px; // $topbar-margin-bottom: 0; // Control Input height for top bar diff --git a/app/assets/stylesheets/darkswarm/all.scss b/app/assets/stylesheets/darkswarm/all.scss index bbcdb15a3b..a3ee62ec56 100644 --- a/app/assets/stylesheets/darkswarm/all.scss +++ b/app/assets/stylesheets/darkswarm/all.scss @@ -12,3 +12,4 @@ ofn-modal { display: block; } + diff --git a/app/assets/stylesheets/darkswarm/branding.css.sass b/app/assets/stylesheets/darkswarm/branding.css.sass index 5fb026cec4..cb2bf151d6 100644 --- a/app/assets/stylesheets/darkswarm/branding.css.sass +++ b/app/assets/stylesheets/darkswarm/branding.css.sass @@ -2,6 +2,7 @@ $clr-brick: #8f301d $clr-brick-light: #f5e4e1 $clr-brick-ultra-light: #f7f4ef $clr-brick-bright: #db583d +$clr-brick-light-bright: #f4bbb0 $clr-turquoise: #097563 $clr-turquoise-light: #cef2ec diff --git a/app/assets/stylesheets/darkswarm/menu.css.sass b/app/assets/stylesheets/darkswarm/menu.css.sass new file mode 100644 index 0000000000..d675b1684d --- /dev/null +++ b/app/assets/stylesheets/darkswarm/menu.css.sass @@ -0,0 +1,23 @@ +@import branding +@import mixins + +.inner-wrap + padding-top: 45px + +nav + @include textpress + .top-bar-section ul li > a + font-size: 0.75rem + height: 45px + @include csstrans + opacity: 0.8 + &:hover, &:focus, &:active + opacity: 1 + .nav-branded + color: $clr-brick-light-bright + .nav-primary + @include avenir + font-size: 0.875rem + +nav.top-bar a.icon i + font-size: 22px \ No newline at end of file diff --git a/app/assets/stylesheets/darkswarm/mixins.sass b/app/assets/stylesheets/darkswarm/mixins.sass index 1a3c81c478..7c29d476c3 100644 --- a/app/assets/stylesheets/darkswarm/mixins.sass +++ b/app/assets/stylesheets/darkswarm/mixins.sass @@ -66,3 +66,10 @@ -o-transition: all 100ms ease-in-out transition: all 100ms ease-in-out -webkit-transform-style: preserve-3d + +@mixin avenir + font-family: "AvenirBla_IE", "AvenirBla" + +@mixin textpress + text-shadow: 0 -1px 1px #111111, 0 1px 2px #222222 + diff --git a/app/assets/stylesheets/darkswarm/sidebar.css.sass b/app/assets/stylesheets/darkswarm/sidebar.css.sass index e2c3b06d40..4addd035dc 100644 --- a/app/assets/stylesheets/darkswarm/sidebar.css.sass +++ b/app/assets/stylesheets/darkswarm/sidebar.css.sass @@ -2,8 +2,6 @@ // We can't import foundation components? // See https://github.com/zurb/foundation/issues/3855#issuecomment-30372252 - -@import "foundation" @import "variables" @import "components/global" @import "components/buttons" diff --git a/app/assets/stylesheets/darkswarm/typography.css.sass b/app/assets/stylesheets/darkswarm/typography.css.sass index a75e4c29fd..13d0ab1753 100644 --- a/app/assets/stylesheets/darkswarm/typography.css.sass +++ b/app/assets/stylesheets/darkswarm/typography.css.sass @@ -24,9 +24,8 @@ a &:hover text-decoration: none color: $clr-brick-bright - + @mixin avenir - color: #333333 font-family: "AvenirBla_IE", "AvenirBla" h1, h2, h3, h4, h5, h6, .avenir diff --git a/app/assets/stylesheets/darkswarm/ui.css.sass b/app/assets/stylesheets/darkswarm/ui.css.sass index 29a0ee02b5..8c3d986811 100644 --- a/app/assets/stylesheets/darkswarm/ui.css.sass +++ b/app/assets/stylesheets/darkswarm/ui.css.sass @@ -38,3 +38,8 @@ background-color: rgba(0, 0, 0, 0.1) text-shadow: 0 1px 0 #fff + +// Responsive +@media screen and (min-width: 768px) + [role="main"] + padding: 0 \ No newline at end of file diff --git a/app/views/shared/_signed_in.html.haml b/app/views/shared/_signed_in.html.haml index 357391406b..1ac376879b 100644 --- a/app/views/shared/_signed_in.html.haml +++ b/app/views/shared/_signed_in.html.haml @@ -3,4 +3,4 @@ = spree_current_user.email %li.divider %li#sign-out-link - = link_to "Sign Out", "/logout" + = link_to "Sign Out", "/logout" \ No newline at end of file diff --git a/app/views/shared/_signed_out.html.haml b/app/views/shared/_signed_out.html.haml index 5c333d8b5f..25578b01de 100644 --- a/app/views/shared/_signed_out.html.haml +++ b/app/views/shared/_signed_out.html.haml @@ -1,5 +1,7 @@ %li#login-link - %a{"ng-click" => "toggle('/login')"} Sign in + %a{"ng-click" => "toggle('/login')"} + %i.fi-lock + LOGIN -#%li.divider -#%li#sign-up-link -#%a{"ng-click" => "toggle('/signup')"} Sign Up diff --git a/app/views/shared/menu/_large_menu.html.haml b/app/views/shared/menu/_large_menu.html.haml index fb8916c67c..38177b20ba 100644 --- a/app/views/shared/menu/_large_menu.html.haml +++ b/app/views/shared/menu/_large_menu.html.haml @@ -1,26 +1,27 @@ -%nav.top-bar.hide-for-small +%nav.top-bar.hide-for-small{'data' => 'topbar'} %section.top-bar-section %ul.left -#%li -#%a.icon{"ng-click" => "Sidebar.toggle()"} -#%i.fi-list - %li= link_to image_tag("ofn_logo_small.png"), root_path - %li.divider - %li.current_hub{"ng-controller" => "CurrentHubCtrl", "ng-show" => "CurrentHub.id"} - %a{href: main_app.shop_path} - Selected hub: - {{ CurrentHub.name }} + %li= link_to image_tag("ofn_logo_small.png"), root_path %li.divider %li - %a{href: ""} Map + %a + %span.nav-primary{href: ""} Shop %li.divider %li - %a{href: producers_path} Producers + %a + %span.nav-primary{href: ""} Map %li.divider %li - %a{href: ""} Groups & Regions + %a + %span.nav-primary{href: producers_path} Producers + %li.divider + %li + %a + %span.nav-primary{href: ""} Groups %li.divider - %section.top-bar-section %ul.right{"ng-controller" => "AuthenticationActionsCtrl"} %li.divider @@ -29,10 +30,14 @@ - else = render 'shared/signed_in' %li.divider + %li.current_hub{"ng-controller" => "CurrentHubCtrl", "ng-show" => "CurrentHub.id"} + %a{href: main_app.shop_path} + %em Shopping at: + %span.nav-primary.nav-branded {{ CurrentHub.name }} + %li.divider %li.cart %a.icon{href: cart_url} - %i.fi-shopping-cart + %i.fi-shopping-cart.nav-branded %span = cart_count - items - + items \ No newline at end of file From 6cb186ffe3fedeca5e8d4d18cdc607fce88c432a Mon Sep 17 00:00:00 2001 From: summerscope Date: Tue, 6 May 2014 17:32:22 +1000 Subject: [PATCH 37/49] Styling for footer and further work for top nav --- app/assets/stylesheets/darkswarm/footer.sass | 10 ++++ .../darkswarm/home_tagline.css.sass | 5 +- .../stylesheets/darkswarm/menu.css.sass | 3 ++ app/assets/stylesheets/darkswarm/mixins.sass | 9 ++++ .../stylesheets/darkswarm/typography.css.sass | 19 ++++++-- app/assets/stylesheets/darkswarm/ui.css.sass | 1 + app/views/shared/_footer.html.haml | 48 ++++++++++++++----- app/views/shared/menu/_large_menu.html.haml | 2 +- 8 files changed, 80 insertions(+), 17 deletions(-) diff --git a/app/assets/stylesheets/darkswarm/footer.sass b/app/assets/stylesheets/darkswarm/footer.sass index 3041817073..973538c147 100644 --- a/app/assets/stylesheets/darkswarm/footer.sass +++ b/app/assets/stylesheets/darkswarm/footer.sass @@ -3,10 +3,20 @@ footer background: $dark-grey + border-top: 1px dotted white @include panepadding .row &, & * color: white + a, a > i + @include csstrans + a, a * + color: $clr-brick-light-bright + &:hover, &:active, &:focus + color: $clr-brick-bright + @include textsoftpress + small + font-size: 0.75rem span.email direction: rtl unicode-bidi: bidi-override diff --git a/app/assets/stylesheets/darkswarm/home_tagline.css.sass b/app/assets/stylesheets/darkswarm/home_tagline.css.sass index 950a3c216d..aa369723ea 100644 --- a/app/assets/stylesheets/darkswarm/home_tagline.css.sass +++ b/app/assets/stylesheets/darkswarm/home_tagline.css.sass @@ -14,4 +14,7 @@ h2 font-size: 1.6875rem a - color: $clr-brick-bright \ No newline at end of file + color: $clr-brick-bright + &:hover, &:active, &:focus + color: $clr-brick-light-bright + @include textsoftpress \ No newline at end of file diff --git a/app/assets/stylesheets/darkswarm/menu.css.sass b/app/assets/stylesheets/darkswarm/menu.css.sass index d675b1684d..7020a52e47 100644 --- a/app/assets/stylesheets/darkswarm/menu.css.sass +++ b/app/assets/stylesheets/darkswarm/menu.css.sass @@ -4,6 +4,9 @@ .inner-wrap padding-top: 45px +.top-bar + @include box-shadow(0 2px 3px 0 rgba(0,0,0,0.25)) + nav @include textpress .top-bar-section ul li > a diff --git a/app/assets/stylesheets/darkswarm/mixins.sass b/app/assets/stylesheets/darkswarm/mixins.sass index 7c29d476c3..193bf003c9 100644 --- a/app/assets/stylesheets/darkswarm/mixins.sass +++ b/app/assets/stylesheets/darkswarm/mixins.sass @@ -67,9 +67,18 @@ transition: all 100ms ease-in-out -webkit-transform-style: preserve-3d +@mixin box-shadow($box-shadow) + -moz-box-shadow: $box-shadow + -webkit-box-shadow: $box-shadow + box-shadow: $box-shadow + @mixin avenir font-family: "AvenirBla_IE", "AvenirBla" @mixin textpress text-shadow: 0 -1px 1px #111111, 0 1px 2px #222222 +@mixin textsoftpress + text-shadow: 0 0 3px rgba(0,0,0,0.35) + + diff --git a/app/assets/stylesheets/darkswarm/typography.css.sass b/app/assets/stylesheets/darkswarm/typography.css.sass index 13d0ab1753..f16ea80bee 100644 --- a/app/assets/stylesheets/darkswarm/typography.css.sass +++ b/app/assets/stylesheets/darkswarm/typography.css.sass @@ -16,9 +16,9 @@ font-family: 'AvenirMed' src: url("/AvenirLTStd-Medium.otf") format("opentype") -//body - //font-family: "AvenirBla_IE", "AvenirBla" - +body + font-family: Calibri, Candara, Segoe, "Segoe UI", Optima, Arial, sans-serif + a color: $clr-brick &:hover @@ -32,6 +32,19 @@ h1, h2, h3, h4, h5, h6, .avenir @include avenir padding: 0px +ul.ofn-list + margin-left: 0.5em + li + list-style: none + li:before + content: "\f112" + font-family: "foundation-icons" + display: inline-block + font-weight: normal + font-style: normal + font-variant: normal + text-transform: none + font-size: 80% .light-grey color: #666666 diff --git a/app/assets/stylesheets/darkswarm/ui.css.sass b/app/assets/stylesheets/darkswarm/ui.css.sass index 8c3d986811..2370b856f3 100644 --- a/app/assets/stylesheets/darkswarm/ui.css.sass +++ b/app/assets/stylesheets/darkswarm/ui.css.sass @@ -4,6 +4,7 @@ .neutral-btn @include button + font-family: Calibri, Candara, Segoe, "Segoe UI", Optima, Arial, sans-serif background-color: transparent border: 2px solid rgba(200, 200, 200, 1) color: #999 diff --git a/app/views/shared/_footer.html.haml b/app/views/shared/_footer.html.haml index eb655b7c37..c436e00bc2 100644 --- a/app/views/shared/_footer.html.haml +++ b/app/views/shared/_footer.html.haml @@ -1,7 +1,12 @@ %footer .row.landing-page-row - .small-5.columns.text-left - %h3 Follow us + .small-4.columns.text-left + %h4 Email us + %p + %a{href: "hello@openfoodnetwork.org".reverse, target: '_blank', mailto: true} + %span.email + = "hello@openfoodnetwork.org".reverse + %h4 Follow us %p %a{title:'Follow us on Facebook', href: 'https://www.facebook.com/OpenFoodNet', target: '_blank'} %i.fi-social-facebook @@ -11,17 +16,36 @@ Twitter    %a{title:'Join our group on LinkedIn', href: 'http://www.linkedin.com/groups/Open-Food-Foundation-4743336', target: '_blank'} %i.fi-social-linkedin - LinkedIn    - %p - %a{href: "hello@openfoodnetwork.org".reverse, target: '_blank', mailto: true} - %span.email - = "hello@openfoodnetwork.org".reverse - .small-2.columns - .small-5.columns.text-right - %h3 About us + LinkedIn + .small-4.columns.text-left + %h4 Getting around + %ul.ofn-list + %li + %a{href: ""} Shop + %li + %a{href: ""} Map + %li + %a{href: ""} Producers + %li + %a{href: ""} Groups + .small-4.columns.text-left + %h4 About us %p OFN is a network of independent online food stores that connect farmers and food hubs with individuals and local businesses. It gives farmers and food hubs an easier and fairer way to distribute their food. .row.landing-page-row .small-12.columns.text-center %p - %p © Copyright 2014 Open Food Foundation - %small Content | Terms of Service | Code - Opensource on Github | Creative Commons / IP | OFN.org + %p + %hr + %h5 + %a{title: 'Open Food Network', href:'http://www.openfoodnetwork.org', target: '_blank' } openfoodnetwork.org + %br + %p + © Copyright 2014 Open Food Foundation + %small + %a{href:'' } Terms & conditions + | + %a{href:'' } Creative Commons + | + %a{href:'' } Github + | + %a{href:'' } Developers diff --git a/app/views/shared/menu/_large_menu.html.haml b/app/views/shared/menu/_large_menu.html.haml index 38177b20ba..2dfcda5211 100644 --- a/app/views/shared/menu/_large_menu.html.haml +++ b/app/views/shared/menu/_large_menu.html.haml @@ -32,7 +32,7 @@ %li.divider %li.current_hub{"ng-controller" => "CurrentHubCtrl", "ng-show" => "CurrentHub.id"} %a{href: main_app.shop_path} - %em Shopping at: + %em Shopping @ %span.nav-primary.nav-branded {{ CurrentHub.name }} %li.divider %li.cart From c4cd15423c995b0b5fc94dcbfa67d19f887bcfbc Mon Sep 17 00:00:00 2001 From: summerscope Date: Tue, 6 May 2014 17:40:02 +1000 Subject: [PATCH 38/49] Add email link with reverse --- app/views/home/_beta.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/home/_beta.html.haml b/app/views/home/_beta.html.haml index 318608edb4..ba6993cb68 100644 --- a/app/views/home/_beta.html.haml +++ b/app/views/home/_beta.html.haml @@ -8,6 +8,6 @@ %p Want to help? Or find out when OFN is coming to you? %strong We’d love to hear from you: %p - %a{title:'Food buyers', href: '/food-buyers'} Food buyers + %a{href: "hello@openfoodnetwork.org".reverse, target: '_blank', mailto: true} Food buyers | - %a{title:'Food producers & farmers', href: '/food-producers'} Food producers & farmers \ No newline at end of file + %a{href: "hello@openfoodnetwork.org".reverse, target: '_blank', mailto: true} Food producers & farmers \ No newline at end of file From 779bf6b096976ac662093bf37b1f3958b3c455d0 Mon Sep 17 00:00:00 2001 From: summerscope Date: Tue, 6 May 2014 17:55:38 +1000 Subject: [PATCH 39/49] Renaming ID to make it more generic to table search rather than Hub --- ...earch.css.sass => active_table_search.css.sass} | 2 +- app/views/home/_hubs.html.haml | 2 +- app/views/modals/_producers.html.haml | 4 ++++ app/views/producers/index.haml | 14 ++++++++++++-- 4 files changed, 18 insertions(+), 4 deletions(-) rename app/assets/stylesheets/darkswarm/{hub_search.css.sass => active_table_search.css.sass} (50%) create mode 100644 app/views/modals/_producers.html.haml diff --git a/app/assets/stylesheets/darkswarm/hub_search.css.sass b/app/assets/stylesheets/darkswarm/active_table_search.css.sass similarity index 50% rename from app/assets/stylesheets/darkswarm/hub_search.css.sass rename to app/assets/stylesheets/darkswarm/active_table_search.css.sass index 6c608171ac..5b70800bab 100644 --- a/app/assets/stylesheets/darkswarm/hub_search.css.sass +++ b/app/assets/stylesheets/darkswarm/active_table_search.css.sass @@ -1,6 +1,6 @@ @import mixins -#hub-search +#active-table-search input font-size: 2em @include big-input \ No newline at end of file diff --git a/app/views/home/_hubs.html.haml b/app/views/home/_hubs.html.haml index d3eead785b..010fae5ec6 100644 --- a/app/views/home/_hubs.html.haml +++ b/app/views/home/_hubs.html.haml @@ -12,7 +12,7 @@ from the list below: %p - #hub-search.row + #active-table-search.row .small-12.columns %input{type: :text, "ng-model" => "query", diff --git a/app/views/modals/_producers.html.haml b/app/views/modals/_producers.html.haml new file mode 100644 index 0000000000..153e4dcae3 --- /dev/null +++ b/app/views/modals/_producers.html.haml @@ -0,0 +1,4 @@ +%h2 Producers +%h5 Our producers make the food! All the delicious! +%p More text goes here. +%a.close-reveal-modal{"ng-click" => "cancel()"} × \ No newline at end of file diff --git a/app/views/producers/index.haml b/app/views/producers/index.haml index 307014fad6..b55628c7c1 100644 --- a/app/views/producers/index.haml +++ b/app/views/producers/index.haml @@ -4,8 +4,16 @@ -#%pre -#{{ Producers.producers | json }} - .row - .small-12.columns + #active-table-search.row + .small-12.columns.text-center + %h1 Producers + %div + Select a + %ofn-modal{title: "producer"} + = render partial: "modals/producers" + from the list below: + %p + %input{type: :text, "ng-model" => "query", placeholder: "Search postcode, suburb or hub name...", @@ -23,3 +31,5 @@ .small-12.columns = render partial: 'producers/skinny' = render partial: 'producers/fat' + += render partial: "shared/footer" \ No newline at end of file From 1d9a1aa8ce66aa65a7035a16f96505e0076ad9e0 Mon Sep 17 00:00:00 2001 From: summerscope Date: Tue, 6 May 2014 18:04:17 +1000 Subject: [PATCH 40/49] Add stylesheet for producers --- .../darkswarm/producer_node.css.sass | 36 +++++++++++++++++++ app/views/producers/index.haml | 1 + 2 files changed, 37 insertions(+) create mode 100644 app/assets/stylesheets/darkswarm/producer_node.css.sass diff --git a/app/assets/stylesheets/darkswarm/producer_node.css.sass b/app/assets/stylesheets/darkswarm/producer_node.css.sass new file mode 100644 index 0000000000..25be5e16e9 --- /dev/null +++ b/app/assets/stylesheets/darkswarm/producer_node.css.sass @@ -0,0 +1,36 @@ +@import branding + +.active_table .active_table_node + + &.open + .active_table_row:first-child + border-top: 1px solid $clr-turquoise + border-left: 1px solid $clr-turquoise + border-right: 1px solid $clr-turquoise + &:hover, &:active, &:focus + color: $clr-turquoise + + .active_table_row:nth-child(2) + border-left: 1px solid $clr-turquoise + border-right: 1px solid $clr-turquoise + border-bottom: 1px solid $clr-turquoise + + .active_table_row.link + background-color: $clr-turquoise + &:hover + background-color: $clr-turquoise-bright + + &.closed + &:hover, &:active, &:focus + border: 1px solid $clr-turquoise + color: $clr-turquoise + + &.current + &.closed + &, & * + color: $clr-turquoise + &.open + .active_table_row:first-child + &, & * + color: $clr-turquoise + diff --git a/app/views/producers/index.haml b/app/views/producers/index.haml index b55628c7c1..7a6925c3aa 100644 --- a/app/views/producers/index.haml +++ b/app/views/producers/index.haml @@ -6,6 +6,7 @@ #active-table-search.row .small-12.columns.text-center + %p %h1 Producers %div Select a From e84ee91184284adec28d5f16d72a7bf768a90ca3 Mon Sep 17 00:00:00 2001 From: summerscope Date: Tue, 6 May 2014 18:24:30 +1000 Subject: [PATCH 41/49] Styling for producers page and new pretty bg picture --- .../images/producers/producers-pg-bg.jpg | Bin 0 -> 146346 bytes app/assets/stylesheets/darkswarm/mixins.sass | 2 +- .../stylesheets/darkswarm/producers.css.sass | 8 ++++++++ 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 app/assets/images/producers/producers-pg-bg.jpg create mode 100644 app/assets/stylesheets/darkswarm/producers.css.sass diff --git a/app/assets/images/producers/producers-pg-bg.jpg b/app/assets/images/producers/producers-pg-bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..916f47408436d21bde7cbe33fc2dfedff5f5ef59 GIT binary patch literal 146346 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
$7@2=7l<9PB9@wQ(iT1i-zZr=_TG`N?Xd% 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 Date: Tue, 6 May 2014 18:27:17 +1000 Subject: [PATCH 42/49] Styling for producer node + add link for producers into footer --- app/assets/stylesheets/darkswarm/producer_node.css.sass | 2 +- app/views/shared/_footer.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/darkswarm/producer_node.css.sass b/app/assets/stylesheets/darkswarm/producer_node.css.sass index 25be5e16e9..ca8b88e35f 100644 --- a/app/assets/stylesheets/darkswarm/producer_node.css.sass +++ b/app/assets/stylesheets/darkswarm/producer_node.css.sass @@ -28,7 +28,7 @@ &.current &.closed &, & * - color: $clr-turquoise + color: $clr-turquoise-bright &.open .active_table_row:first-child &, & * diff --git a/app/views/shared/_footer.html.haml b/app/views/shared/_footer.html.haml index c436e00bc2..46a02da534 100644 --- a/app/views/shared/_footer.html.haml +++ b/app/views/shared/_footer.html.haml @@ -25,7 +25,7 @@ %li %a{href: ""} Map %li - %a{href: ""} Producers + %a{href: producers_path} Producers %li %a{href: ""} Groups .small-4.columns.text-left From 3542799349b4213bb3075b079724814e26bd83f3 Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Tue, 6 May 2014 17:26:10 +1000 Subject: [PATCH 43/49] Removing pointless foundation crud, reworking the login --- Gemfile.lock | 5 +- .../javascripts/darkswarm/all.js.coffee | 5 +- .../forgot_controller.js.coffee} | 10 +- .../authentication/login_controller.js.coffee | 8 + .../signup_controller.js.coffee} | 10 +- ...uthentication_actions_controller.js.coffee | 5 - .../authentication_controller.js.coffee | 6 + .../controllers/hub_node_controller.js.coffee | 6 +- .../producer_node_controller.js.coffee | 4 +- .../login_sidebar_controller.js.coffee | 17 - .../controllers/tmp_controller.js.coffee | 2 + .../javascripts/darkswarm/darkswarm.js.coffee | 2 +- .../services/authentication_service.js.coffee | 21 + .../services/hash_navigation.js.coffee | 17 + .../darkswarm/services/navigation.js.coffee | 14 +- .../javascripts/foundation4/foundation.scss | 43 - .../foundation4/foundation/_variables.scss | 1325 ----------------- .../foundation/components/_alert-boxes.scss | 107 -- .../foundation/components/_block-grid.scss | 71 - .../foundation/components/_breadcrumbs.scss | 124 -- .../foundation/components/_button-groups.scss | 89 -- .../foundation/components/_buttons.scss | 230 --- .../foundation/components/_clearing.scss | 227 --- .../foundation/components/_custom-forms.scss | 278 ---- .../components/_dropdown-buttons.scss | 115 -- .../foundation/components/_dropdown.scss | 151 -- .../foundation/components/_flex-video.scss | 46 - .../foundation/components/_forms.scss | 409 ----- .../foundation/components/_global.scss | 363 ----- .../foundation/components/_grid-5.scss | 214 --- .../foundation/components/_grid.scss | 188 --- .../foundation/components/_inline-lists.scss | 53 - .../foundation/components/_joyride.scss | 217 --- .../foundation/components/_keystrokes.scss | 57 - .../foundation/components/_labels.scss | 85 -- .../foundation/components/_magellan.scss | 23 - .../foundation/components/_orbit.scss | 340 ----- .../foundation/components/_pagination.scss | 140 -- .../foundation/components/_panels.scss | 83 -- .../components/_pricing-tables.scss | 131 -- .../foundation/components/_progress-bars.scss | 71 - .../foundation/components/_reveal.scss | 136 -- .../foundation/components/_section.scss | 391 ----- .../foundation/components/_side-nav.scss | 69 - .../foundation/components/_split-buttons.scss | 167 --- .../foundation/components/_sub-nav.scss | 84 -- .../foundation/components/_switch.scss | 266 ---- .../foundation/components/_tables.scss | 84 -- .../foundation/components/_thumbs.scss | 53 - .../foundation/components/_tooltips.scss | 117 -- .../foundation/components/_top-bar.scss | 570 ------- .../foundation/components/_type.scss | 435 ------ .../foundation/components/_visibility.scss | 322 ---- .../javascripts/foundation4/normalize.scss | 410 ----- .../templates/authentication.html.haml | 6 + .../javascripts/templates/forgot.html.haml} | 6 +- .../javascripts/templates/login.html.haml} | 6 +- .../javascripts/templates/signup.html.haml} | 6 +- .../{ => javascripts}/templates/test.nghaml | 0 app/views/json/_hubs.rabl | 4 + app/views/shared/_sidebar.html.haml | 20 +- app/views/shared/_signed_out.html.haml | 5 +- app/views/shared/menu/_large_menu.html.haml | 9 +- app/views/shared/menu/_mobile_menu.html.haml | 26 +- config/initializers/angular_assets.rb | 1 - .../unit/darkswarm/navigation.js.coffee | 5 - 66 files changed, 128 insertions(+), 8382 deletions(-) rename app/assets/javascripts/darkswarm/controllers/{sidebar/forgot_sidebar_controller.js.coffee => authentication/forgot_controller.js.coffee} (56%) create mode 100644 app/assets/javascripts/darkswarm/controllers/authentication/login_controller.js.coffee rename app/assets/javascripts/darkswarm/controllers/{sidebar/signup_sidebar_controller.js.coffee => authentication/signup_controller.js.coffee} (52%) delete mode 100644 app/assets/javascripts/darkswarm/controllers/authentication_actions_controller.js.coffee create mode 100644 app/assets/javascripts/darkswarm/controllers/authentication_controller.js.coffee delete mode 100644 app/assets/javascripts/darkswarm/controllers/sidebar/login_sidebar_controller.js.coffee create mode 100644 app/assets/javascripts/darkswarm/controllers/tmp_controller.js.coffee create mode 100644 app/assets/javascripts/darkswarm/services/authentication_service.js.coffee create mode 100644 app/assets/javascripts/darkswarm/services/hash_navigation.js.coffee delete mode 100755 app/assets/javascripts/foundation4/foundation.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/_variables.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_alert-boxes.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_block-grid.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_breadcrumbs.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_button-groups.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_buttons.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_clearing.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_custom-forms.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_dropdown-buttons.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_dropdown.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_flex-video.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_forms.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_global.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_grid-5.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_grid.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_inline-lists.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_joyride.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_keystrokes.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_labels.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_magellan.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_orbit.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_pagination.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_panels.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_pricing-tables.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_progress-bars.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_reveal.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_section.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_side-nav.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_split-buttons.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_sub-nav.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_switch.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_tables.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_thumbs.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_tooltips.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_top-bar.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_type.scss delete mode 100755 app/assets/javascripts/foundation4/foundation/components/_visibility.scss delete mode 100755 app/assets/javascripts/foundation4/normalize.scss create mode 100644 app/assets/javascripts/templates/authentication.html.haml rename app/{views/shared/_forgot_sidebar.html.haml => assets/javascripts/templates/forgot.html.haml} (88%) rename app/{views/shared/_login_sidebar.html.haml => assets/javascripts/templates/login.html.haml} (90%) rename app/{views/shared/_signup_sidebar.html.haml => assets/javascripts/templates/signup.html.haml} (91%) rename app/assets/{ => javascripts}/templates/test.nghaml (100%) delete mode 100644 config/initializers/angular_assets.rb diff --git a/Gemfile.lock b/Gemfile.lock index e82e5e5ad8..1b031569f7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -140,9 +140,10 @@ GEM acts_as_list (0.1.4) addressable (2.3.3) andand (1.3.3) - angular-rails-templates (0.0.7) + angular-rails-templates (0.1.1) railties (>= 3.1) sprockets + tilt angularjs-rails (1.2.13) ansi (1.4.2) arel (3.0.3) @@ -319,7 +320,7 @@ GEM money (5.0.0) i18n (~> 0.4) json - multi_json (1.9.3) + multi_json (1.10.0) multi_xml (0.5.5) net-scp (1.1.2) net-ssh (>= 2.6.5) diff --git a/app/assets/javascripts/darkswarm/all.js.coffee b/app/assets/javascripts/darkswarm/all.js.coffee index cc9a1bbc56..484bb56492 100644 --- a/app/assets/javascripts/darkswarm/all.js.coffee +++ b/app/assets/javascripts/darkswarm/all.js.coffee @@ -10,7 +10,10 @@ #= require ../shared/bindonce.min.js #= require ../shared/ng-infinite-scroll.min.js #= require ../shared/angular-local-storage.js -#= require_tree ../../templates + +#= require angular-rails-templates +#= require_tree ../templates +# #= require angular-backstretch.js #= require angular-flash.min.js #= require moment diff --git a/app/assets/javascripts/darkswarm/controllers/sidebar/forgot_sidebar_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/authentication/forgot_controller.js.coffee similarity index 56% rename from app/assets/javascripts/darkswarm/controllers/sidebar/forgot_sidebar_controller.js.coffee rename to app/assets/javascripts/darkswarm/controllers/authentication/forgot_controller.js.coffee index 4300461a0d..175e18d2a2 100644 --- a/app/assets/javascripts/darkswarm/controllers/sidebar/forgot_sidebar_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/authentication/forgot_controller.js.coffee @@ -1,14 +1,6 @@ -Darkswarm.controller "ForgotSidebarCtrl", ($scope, $http, $location, SpreeUser, Navigation) -> - $scope.spree_user = SpreeUser.spree_user +Darkswarm.controller "ForgotCtrl", ($scope, $http, $location, AuthenticationService) -> $scope.path = "/forgot" $scope.sent = false - Navigation.paths.push $scope.path - - $scope.active = -> - $location.path() == $scope.path - - $scope.select = -> - Navigation.navigate($scope.path) $scope.submit = -> if $scope.spree_user.email != null diff --git a/app/assets/javascripts/darkswarm/controllers/authentication/login_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/authentication/login_controller.js.coffee new file mode 100644 index 0000000000..c2211bc033 --- /dev/null +++ b/app/assets/javascripts/darkswarm/controllers/authentication/login_controller.js.coffee @@ -0,0 +1,8 @@ +Darkswarm.controller "LoginCtrl", ($scope, $http, $location, AuthenticationService) -> + $scope.path = "/login" + + $scope.submit = -> + $http.post("/user/spree_user/sign_in", {spree_user: $scope.spree_user}).success (data)-> + location.href = location.origin + location.pathname # Strips out hash fragments + .error (data) -> + $scope.errors = data.message diff --git a/app/assets/javascripts/darkswarm/controllers/sidebar/signup_sidebar_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/authentication/signup_controller.js.coffee similarity index 52% rename from app/assets/javascripts/darkswarm/controllers/sidebar/signup_sidebar_controller.js.coffee rename to app/assets/javascripts/darkswarm/controllers/authentication/signup_controller.js.coffee index ef6ded77fd..d15ef4141d 100644 --- a/app/assets/javascripts/darkswarm/controllers/sidebar/signup_sidebar_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/authentication/signup_controller.js.coffee @@ -1,17 +1,9 @@ -Darkswarm.controller "SignupSidebarCtrl", ($scope, $http, $location, SpreeUser, Navigation) -> - $scope.spree_user = SpreeUser.spree_user +Darkswarm.controller "SignupCtrl", ($scope, $http, $location, AuthenticationService) -> $scope.path = "/signup" - Navigation.paths.push $scope.path $scope.errors = email: null password: null - $scope.active = -> - $location.path() == $scope.path - - $scope.select = -> - Navigation.navigate($scope.path) - $scope.submit = -> $http.post("/user/spree_user", {spree_user: $scope.spree_user}).success (data)-> location.href = location.origin + location.pathname # Strips out hash fragments diff --git a/app/assets/javascripts/darkswarm/controllers/authentication_actions_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/authentication_actions_controller.js.coffee deleted file mode 100644 index e8716e750b..0000000000 --- a/app/assets/javascripts/darkswarm/controllers/authentication_actions_controller.js.coffee +++ /dev/null @@ -1,5 +0,0 @@ -Darkswarm.controller "AuthenticationActionsCtrl", ($scope, Navigation, storage, Sidebar) -> - $scope.Sidebar = Sidebar - - $scope.toggle = (path)-> - Navigation.navigate(path) diff --git a/app/assets/javascripts/darkswarm/controllers/authentication_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/authentication_controller.js.coffee new file mode 100644 index 0000000000..be960145af --- /dev/null +++ b/app/assets/javascripts/darkswarm/controllers/authentication_controller.js.coffee @@ -0,0 +1,6 @@ +Darkswarm.controller "AuthenticationCtrl", ($scope, AuthenticationService, SpreeUser)-> + $scope.open = AuthenticationService.open + + $scope.spree_user = SpreeUser.spree_user + $scope.active = AuthenticationService.active + $scope.select = AuthenticationService.select diff --git a/app/assets/javascripts/darkswarm/controllers/hub_node_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/hub_node_controller.js.coffee index f17d985434..ea2503efbe 100644 --- a/app/assets/javascripts/darkswarm/controllers/hub_node_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/hub_node_controller.js.coffee @@ -1,9 +1,9 @@ -Darkswarm.controller "HubNodeCtrl", ($scope, Navigation, $location, $anchorScroll, $templateCache, CurrentHub) -> +Darkswarm.controller "HubNodeCtrl", ($scope, HashNavigation, $location, $anchorScroll, $templateCache, CurrentHub) -> $scope.toggle = -> - Navigation.navigate $scope.hub.path + HashNavigation.toggle $scope.hub.hash $scope.open = -> - $location.path() == $scope.hub.path + HashNavigation.active $scope.hub.hash $scope.current = -> $scope.hub.id is CurrentHub.id diff --git a/app/assets/javascripts/darkswarm/controllers/producer_node_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/producer_node_controller.js.coffee index 03b99d7ebb..733e0d6798 100644 --- a/app/assets/javascripts/darkswarm/controllers/producer_node_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/producer_node_controller.js.coffee @@ -1,9 +1,9 @@ -Darkswarm.controller "ProducerNodeCtrl", ($scope, Navigation, $location, $anchorScroll) -> +Darkswarm.controller "ProducerNodeCtrl", ($scope, Navigation, $anchorScroll) -> $scope.toggle = -> Navigation.navigate $scope.producer.path $scope.open = -> - $location.path() == $scope.producer.path + Navigation.active($scope.producer.path) if $scope.open() $anchorScroll() diff --git a/app/assets/javascripts/darkswarm/controllers/sidebar/login_sidebar_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/sidebar/login_sidebar_controller.js.coffee deleted file mode 100644 index 63d31a8f3c..0000000000 --- a/app/assets/javascripts/darkswarm/controllers/sidebar/login_sidebar_controller.js.coffee +++ /dev/null @@ -1,17 +0,0 @@ -Darkswarm.controller "LoginSidebarCtrl", ($scope, $http, $location, SpreeUser, Navigation) -> - $scope.spree_user = SpreeUser.spree_user - $scope.path = "/login" - Navigation.paths.push $scope.path - - $scope.active = -> - $location.path() == $scope.path - - $scope.select = -> - Navigation.navigate($scope.path) - - - $scope.submit = -> - $http.post("/user/spree_user/sign_in", {spree_user: $scope.spree_user}).success (data)-> - location.href = location.origin + location.pathname # Strips out hash fragments - .error (data) -> - $scope.errors = data.message diff --git a/app/assets/javascripts/darkswarm/controllers/tmp_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/tmp_controller.js.coffee new file mode 100644 index 0000000000..8f173df154 --- /dev/null +++ b/app/assets/javascripts/darkswarm/controllers/tmp_controller.js.coffee @@ -0,0 +1,2 @@ +Darkswarm.controller "TmpCtrl", ($scope)-> + $scope.test = {foo: "bar"} diff --git a/app/assets/javascripts/darkswarm/darkswarm.js.coffee b/app/assets/javascripts/darkswarm/darkswarm.js.coffee index 9382f70d46..9abbfb01a5 100644 --- a/app/assets/javascripts/darkswarm/darkswarm.js.coffee +++ b/app/assets/javascripts/darkswarm/darkswarm.js.coffee @@ -5,7 +5,7 @@ window.Darkswarm = angular.module("Darkswarm", ["ngResource", 'infinite-scroll', 'angular-flash.service', 'templates', - 'backstretch']).config ($httpProvider, $tooltipProvider) -> + 'backstretch']).config ($httpProvider, $tooltipProvider, $locationProvider) -> $httpProvider.defaults.headers.post['X-CSRF-Token'] = $('meta[name="csrf-token"]').attr('content') $httpProvider.defaults.headers.put['X-CSRF-Token'] = $('meta[name="csrf-token"]').attr('content') $httpProvider.defaults.headers['common']['X-Requested-With'] = 'XMLHttpRequest' diff --git a/app/assets/javascripts/darkswarm/services/authentication_service.js.coffee b/app/assets/javascripts/darkswarm/services/authentication_service.js.coffee new file mode 100644 index 0000000000..cdcb21c027 --- /dev/null +++ b/app/assets/javascripts/darkswarm/services/authentication_service.js.coffee @@ -0,0 +1,21 @@ +Darkswarm.factory "AuthenticationService", (Navigation, $modal, $location)-> + new class AuthenticationService + selectedPath: "/login" + constructor: -> + if $location.path() in ["/login", "/signup", "/forgot"] + @open() + open: => + @modalInstance = $modal.open + templateUrl: 'authentication.html' + + @modalInstance.result.then @close, @close + Navigation.navigate @selectedPath + + select: (path)=> + @selectedPath = path + Navigation.navigate @selectedPath + + active: Navigation.active + + close: -> + Navigation.navigate "/" diff --git a/app/assets/javascripts/darkswarm/services/hash_navigation.js.coffee b/app/assets/javascripts/darkswarm/services/hash_navigation.js.coffee new file mode 100644 index 0000000000..d6fd3525ee --- /dev/null +++ b/app/assets/javascripts/darkswarm/services/hash_navigation.js.coffee @@ -0,0 +1,17 @@ +Darkswarm.factory 'HashNavigation', ($location) -> + new class HashNavigation + hash: null + + active: (hash)-> + $location.hash() == hash + + navigate: (hash)-> + @hash = hash + $location.hash(@hash) + + toggle: (hash = false)-> + @hash = hash || @hash + if $location.hash() == @hash + $location.hash("") + else + @navigate(hash) diff --git a/app/assets/javascripts/darkswarm/services/navigation.js.coffee b/app/assets/javascripts/darkswarm/services/navigation.js.coffee index 923aa9cf0d..25a4ce577b 100644 --- a/app/assets/javascripts/darkswarm/services/navigation.js.coffee +++ b/app/assets/javascripts/darkswarm/services/navigation.js.coffee @@ -1,14 +1,20 @@ Darkswarm.factory 'Navigation', ($location) -> new class Navigation - paths: [] path: null - navigate: (path = false)-> - @path = path || @path || @paths[0] + active: (path)-> + $location.path() == path + + navigate: (path)-> + @path = path + $location.path(@path) + + toggle: (path = false)-> + @path = path || @path if $location.path() == @path $location.path("/") else - $location.path(@path) + @navigate(path) go: (path)-> window.location.pathname = path diff --git a/app/assets/javascripts/foundation4/foundation.scss b/app/assets/javascripts/foundation4/foundation.scss deleted file mode 100755 index d9a6e98582..0000000000 --- a/app/assets/javascripts/foundation4/foundation.scss +++ /dev/null @@ -1,43 +0,0 @@ -// Make sure the charset is set appropriately -@charset "UTF-8"; - -// This includes all of the foundation global elements that are needed to work with any of the other files. -@import "foundation4/foundation/variables"; - -// Foundation Components -@import - "foundation4/foundation/components/global", - "foundation4/foundation/components/grid", - "foundation4/foundation/components/visibility", - "foundation4/foundation/components/block-grid", - "foundation4/foundation/components/type", - "foundation4/foundation/components/buttons", - "foundation4/foundation/components/forms", - "foundation4/foundation/components/button-groups", - "foundation4/foundation/components/dropdown-buttons", - "foundation4/foundation/components/split-buttons", - "foundation4/foundation/components/flex-video", - "foundation4/foundation/components/section", - "foundation4/foundation/components/top-bar", - "foundation4/foundation/components/orbit", - "foundation4/foundation/components/reveal", - "foundation4/foundation/components/joyride", - "foundation4/foundation/components/clearing", - "foundation4/foundation/components/alert-boxes", - "foundation4/foundation/components/breadcrumbs", - "foundation4/foundation/components/custom-forms", - "foundation4/foundation/components/keystrokes", - "foundation4/foundation/components/labels", - "foundation4/foundation/components/inline-lists", - "foundation4/foundation/components/pagination", - "foundation4/foundation/components/panels", - "foundation4/foundation/components/pricing-tables", - "foundation4/foundation/components/progress-bars", - "foundation4/foundation/components/side-nav", - "foundation4/foundation/components/sub-nav", - "foundation4/foundation/components/switch", - "foundation4/foundation/components/magellan", - "foundation4/foundation/components/tables", - "foundation4/foundation/components/thumbs", - "foundation4/foundation/components/tooltips", - "foundation4/foundation/components/dropdown"; diff --git a/app/assets/javascripts/foundation4/foundation/_variables.scss b/app/assets/javascripts/foundation4/foundation/_variables.scss deleted file mode 100755 index fe0b092147..0000000000 --- a/app/assets/javascripts/foundation4/foundation/_variables.scss +++ /dev/null @@ -1,1325 +0,0 @@ -// -// Foundation Variables -// - -// The default font-size is set to 100% of the browser style sheet (usually 16px) -// for compatibility with browser-based text zoom or user-set defaults. -$base-font-size: 100% !default; - -// $base-line-height is 24px while $base-font-size is 16px -// $base-line-height: 150%; - -// This is the default html and body font-size for the base em value. - -// Since the typical default browser font-size is 16px, that makes the calculation for grid size. -// If you want your base font-size to be a different size and not have it effect grid size too, -// set the value of $em-base to $base-font-size ($em-base: $base-font-size;) -$em-base: 16px !default; - -// It strips the unit of measure and returns it -@function strip-unit($num) { - @return $num / ($num * 0 + 1); -} - -// Converts "px" to "em" using the ($)em-base -@function convert-to-em($value, $base-value: $em-base) { - $value: strip-unit($value) / strip-unit($base-value) * 1em; - @if ($value == 0em) { $value: 0; } // Turn 0em into 0 - @return $value; -} - -// Working in ems is annoying. Think in pixels by using this handy function, em-calc(#) -// Just enter the number, no need to mention "px" -@function em-calc($values, $base-value: $em-base) { - $max: length($values); // Get the total number of parameters passed - - // If there is only 1 parameter, then return it as an integer. - // This is done because a list can't be multiplied or divided even if it contains a single value - @if $max == 1 { @return convert-to-em(nth($values, 1), $base-value); } - - $emValues: (); // This will eventually store the converted $values in a list - @for $i from 1 through $max { - $emValues: append($emValues, convert-to-em(nth($values, $i), $base-value)); - } - @return $emValues; -} - -//Retaining this for backward compatability - -@function emCalc($pxWidth) { - @return $pxWidth / $em-base * 1em; -} - -// Maybe you want to create rems with pixels -// $rem-base: 0.625 !default; //Set the value corresponding to body font size. In this case, you should set as: body {font-size: 62.5%;} -// @function rem-calc($pxWidth) { -// @return $pxWidth / $rem-base * 1rem; -// } - -// Change whether or not you include browser prefixes -// $experimental: true; - -// Various global styles - -$default-float: left; - -// $body-bg: #fff; -// $body-font-color: #222; -// $body-font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; -// $body-font-weight: normal; -// $body-font-style: normal; - -// Font-smoothing - -// $font-smoothing: antialiased; - -// Text direction settings - -// $text-direction: ltr; - -// Colors - -// $primary-color: #2ba6cb; -// $secondary-color: #e9e9e9; -// $alert-color: #c60f13; -// $success-color: #5da423; - -// Make sure border radius matches unless we want it different. - -// $global-radius: 3px; -// $global-rounded: 1000px; - -// Inset shadow shiny edges and depressions. - -// $shiny-edge-size: 0 1px 0; -// $shiny-edge-color: rgba(#fff, .5); -// $shiny-edge-active-color: rgba(#000, .2); - -// Control whether or not CSS classes come through in the CSS files. - -// $include-html-classes: true; -// $include-print-styles: true; -// $include-html-global-classes: $include-html-classes; -// $include-html-inline-list-classes: $include-html-classes; -// $include-html-type-classes: $include-html-classes; -// $include-html-grid-classes: $include-html-classes; -// $include-html-visibility-classes: $include-html-classes; -// $include-html-button-classes: $include-html-classes; -// $include-html-form-classes: $include-html-classes; -// $include-html-custom-form-classes: $include-html-classes; -// $include-html-media-classes: $include-html-classes; -// $include-html-section-classes: $include-html-classes; -// $include-html-orbit-classes: $include-html-classes; -// $include-html-reveal-classes: $include-html-classes; -// $include-html-joyride-classes: $include-html-classes; -// $include-html-clearing-classes: $include-html-classes; -// $include-html-alert-classes: $include-html-classes; -// $include-html-nav-classes: $include-html-classes; -// $include-html-top-bar-classes: $include-html-classes; -// $include-html-label-classes: $include-html-classes; -// $include-html-panel-classes: $include-html-classes; -// $include-html-pricing-classes: $include-html-classes; -// $include-html-progress-classes: $include-html-classes; -// $include-html-magellan-classes: $include-html-classes; -// $include-html-tooltip-classes: $include-html-classes; - -// Media Queries - -// $small-screen: 768px; -// $medium-screen: 1280px; -// $large-screen: 1440px; - -// $screen: "only screen"; -// $small: "only screen and (min-width: #{$small-screen})"; -// $medium: "only screen and (min-width: #{$medium-screen})"; -// $large: "only screen and (min-width: #{$large-screen})"; -// $landscape: "only screen and (orientation: landscape)"; -// $portrait: "only screen and (orientation: portrait)"; - -//// Cursors - -//Custom use example -> $cursor-default-value: url(http://cursors-site.net/path/to/custom/cursor/default.cur),progress; - -// $cursor-crosshair-value: "crosshair"; -// $cursor-default-value: "default"; -// $cursor-pointer-value: "pointer"; -// $cursor-help-value: "help"; - -// -// Grid Variables -// - -// $row-width: em-calc(1000); -// $column-gutter: em-calc(30); -// $total-columns: 12; - -// -// Block Grid Variables -// - -// We use this to control the maximum number of block grid elements per row - -// $block-grid-elements: 12; -// $block-grid-default-spacing: em-calc(20); - -// Enables media queries for block-grid classes. Set to false if writing semantic HTML. - -// $block-grid-media-queries: true; - -// -// Typography Variables -// - -// Control header font styles - -// $header-font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; -// $header-font-weight: bold; -// $header-font-style: normal; -// $header-font-color: #222; -// $header-line-height: 1.4; -// $header-top-margin: .2em; -// $header-bottom-margin: .5em; -// $header-text-rendering: optimizeLegibility; - -// Control header font sizes - -// $h1-font-size: em-calc(44); -// $h2-font-size: em-calc(37); -// $h3-font-size: em-calc(27); -// $h4-font-size: em-calc(23); -// $h5-font-size: em-calc(18); -// $h6-font-size: 1em; - -// Control how subheaders are styled. - -// $subheader-line-height: 1.4; -// $subheader-font-color: lighten($header-font-color, 30%); -// $subheader-font-weight: 300; -// $subheader-top-margin: .2em; -// $subheader-bottom-margin: .5em; - -// A general styling - -// $small-font-size: 60%; -// $small-font-color: lighten($header-font-color, 30%); - -// Style paragraphs - -// $paragraph-font-family: inherit; -// $paragraph-font-weight: normal; -// $paragraph-font-size: 1em; -// $paragraph-line-height: 1.6; -// $paragraph-margin-bottom: em-calc(20); -// $paragraph-aside-font-size: em-calc(14); -// $paragraph-aside-line-height: 1.35; -// $paragraph-aside-font-style: italic; -// $paragraph-text-rendering: optimizeLegibility; - -// Style tags - -// $code-color: darken($alert-color, 15%); -// $code-font-family: Consolas, 'Liberation Mono', Courier, monospace; -// $code-font-weight: bold; - -// Style anchors - -// $anchor-text-decoration: none; -// $anchor-font-color: $primary-color; -// $anchor-font-color-hover: darken($primary-color, 5%); - -// Style the
element - -// $hr-border-width: 1px; -// $hr-border-style: solid; -// $hr-border-color: #ddd; -// $hr-margin: em-calc(20); - -// Style lists - -// $list-style-position: outside; -// $list-side-margin: 0; -// $list-nested-margin: em-calc(20); -// $definition-list-header-weight: bold; -// $definition-list-header-margin-bottom: .3em; -// $definition-list-margin-bottom: em-calc(12); - -// Style blockquotes - -// $blockquote-font-color: lighten($header-font-color, 30%); -// $blockquote-padding: em-calc(9, 20, 0, 19); -// $blockquote-border: 1px solid #ddd; -// $blockquote-cite-font-size: em-calc(13); -// $blockquote-cite-font-color: lighten($header-font-color, 20%); -// $blockquote-cite-link-color: $blockquote-cite-font-color; - -// Acronym styles - -// $acronym-underline: 1px dotted #ddd; - -// Control padding and margin - -// $microformat-padding: em-calc(10 12); -// $microformat-margin: em-calc(0 0 20 0); - -// Control the border styles - -// $microformat-border-width: 1px; -// $microformat-border-style: solid; -// $microformat-border-color: #ddd; - -// Control full name font styles - -// $microformat-fullname-font-weight: bold; -// $microformat-fullname-font-size: em-calc(15); - -// Control the summary font styles - -// $microformat-summary-font-weight: bold; - -// Control abbr padding -// $microformat-abbr-padding: em-calc(0 1); - -// Control abbr font styles - -// $microformat-abbr-font-weight: bold; -// $microformat-abbr-font-decoration: none; - -// -// Form Variables -// - -// We use this to set the base for lots of form spacing and positioning styles - -// $form-spacing: em-calc(16); - -// We use these to style the labels in different ways - -// $form-label-pointer: pointer; -// $form-label-font-size: em-calc(14); -// $form-label-font-weight: 500; -// $form-label-font-color: lighten(#000, 30%); -// $form-label-bottom-margin: em-calc(3); -// $input-font-family: inherit; -// $input-font-color: rgba(0,0,0,0.75); -// $input-font-size: em-calc(14); -// $input-bg-color: #fff; -// $input-focus-bg-color: darken(#fff, 2%); -// $input-border-color: darken(#fff, 20%); -// $input-focus-border-color: darken(#fff, 40%); -// $input-border-style: solid; -// $input-border-width: 1px; -// $input-disabled-bg: #ddd; -// $input-box-shadow: inset 0 1px 2px rgba(0,0,0,0.1); -// $input-include-glowing-effect: true; - -// We use these to style the fieldset border and spacing. - -// $fieldset-border-style: solid; -// $fieldset-border-width: 1px; -// $fieldset-border-color: #ddd; -// $fieldset-padding: em-calc(20); -// $fieldset-margin: em-calc(18 0); - -// We use these to style the legends when you use them - -// $legend-bg: #fff; -// $legend-font-weight: bold; -// $legend-padding: em-calc(0 3); - -// We use these to style the prefix and postfix input elements - -// $input-prefix-bg: darken(#fff, 5%); -// $input-prefix-border-color: darken(#fff, 20%); -// $input-prefix-border-size: 1px; -// $input-prefix-border-type: solid; -// $input-prefix-overflow: hidden; -// $input-prefix-font-color: #333; -// $input-prefix-font-color-alt: #fff; - -// We use these to style the error states for inputs and labels - -// $input-error-message-padding: em-calc(6 4); -// $input-error-message-top: 0; -// $input-error-message-font-size: em-calc(12); -// $input-error-message-font-weight: bold; -// $input-error-message-font-color: #fff; -// $input-error-message-font-color-alt: #333; - -// We use this to style the glowing effect of inputs when focused - -// $glowing-effect-fade-time: 0.45s; -// $glowing-effect-color: $input-focus-border-color; - -// -// Button Variables -// - -// We use these to build padding for buttons. - -// $button-med: em-calc(12); -// $button-tny: em-calc(7); -// $button-sml: em-calc(9); -// $button-lrg: em-calc(16); - -// We use this to control the display property. - -// $button-display: inline-block; -// $button-margin-bottom: em-calc(20); - -// We use these to control button text styles. - -// $button-font-family: inherit; -// $button-font-color: #fff; -// $button-font-color-alt: #333; -// $button-font-med: em-calc(16); -// $button-font-tny: em-calc(11); -// $button-font-sml: em-calc(13); -// $button-font-lrg: em-calc(20); -// $button-font-weight: bold; -// $button-font-align: center; - -// We use these to control various hover effects. - -// $button-function-factor: 10%; - -// We use these to control button border styles. - -// $button-border-width: 1px; -// $button-border-style: solid; - -// We use this to set the default radius used throughout the core. - -// $button-radius: $global-radius; -// $button-round: $global-rounded; - -// We use this to set default opacity for disabled buttons. - -// $button-disabled-opacity: 0.6; - -// -// Button Groups -// - -// Sets the margin for the right side by default, and the left margin if right-to-left direction is used - -// $button-bar-margin-opposite: em-calc(10); - -// -// Dropdown Button Variables -// - -// We use these to set the color of the pip in dropdown buttons - -// $dropdown-button-pip-color: #fff; -// $dropdown-button-pip-color-alt: #333; - -// We use these to style tiny dropdown buttons - -// $dropdown-button-padding-tny: $button-tny * 5; -// $dropdown-button-pip-size-tny: $button-tny; -// $dropdown-button-pip-opposite-tny: $button-tny * 2; -// $dropdown-button-pip-top-tny: -$button-tny / 2 + em-calc(1); - -// We use these to style small dropdown buttons - -// $dropdown-button-padding-sml: $button-sml * 5; -// $dropdown-button-pip-size-sml: $button-sml; -// $dropdown-button-pip-opposite-sml: $button-sml * 2; -// $dropdown-button-pip-top-sml: -$button-sml / 2 + em-calc(1); - -// We use these to style medium dropdown buttons - -// $dropdown-button-padding-med: $button-med * 4 + em-calc(3); -// $dropdown-button-pip-size-med: $button-med - em-calc(3); -// $dropdown-button-pip-opposite-med: $button-med * 2; -// $dropdown-button-pip-top-med: -$button-med / 2 + em-calc(2); - -// We use these to style large dropdown buttons - -// $dropdown-button-padding-lrg: $button-lrg * 4; -// $dropdown-button-pip-size-lrg: $button-lrg - em-calc(6); -// $dropdown-button-pip-opposite-lrg: $button-lrg + em-calc(12); -// $dropdown-button-pip-top-lrg: -$button-lrg / 2 + em-calc(3); - -// -// Split Button Variables -// - -// We use these to control different shared styles for Split Buttons - -// $split-button-function-factor: 15%; -// $split-button-pip-color: #fff; -// $split-button-pip-color-alt: #333; -// $split-button-active-bg-tint: rgba(0,0,0,0.1); - -// We use these to control tiny split buttons - -// $split-button-padding-tny: $button-tny * 9; -// $split-button-span-width-tny: $button-tny * 6.5; -// $split-button-pip-size-tny: $button-tny; -// $split-button-pip-top-tny: $button-tny * 2; -// $split-button-pip-default-float-tny: em-calc(-5); - -// We use these to control small split buttons - -// $split-button-padding-sml: $button-sml * 7; -// $split-button-span-width-sml: $button-sml * 5; -// $split-button-pip-size-sml: $button-sml; -// $split-button-pip-top-sml: $button-sml * 1.5; -// $split-button-pip-default-float-sml: em-calc(-9); - -// We use these to control medium split buttons - -// $split-button-padding-med: $button-med * 6.4; -// $split-button-span-width-med: $button-med * 4; -// $split-button-pip-size-med: $button-med - em-calc(3); -// $split-button-pip-top-med: $button-med * 1.5; -// $split-button-pip-default-float-med: em-calc(-9); - -// We use these to control large split buttons - -// $split-button-padding-lrg: $button-lrg * 6; -// $split-button-span-width-lrg: $button-lrg * 3.75; -// $split-button-pip-size-lrg: $button-lrg - em-calc(6); -// $split-button-pip-top-lrg: $button-lrg + em-calc(5); -// $split-button-pip-default-float-lrg: em-calc(-9); - -// -// Alert Box Variables -// - -// We use this to control alert padding. - -// $alert-padding-top: em-calc(11); -// $alert-padding-default-float: $alert-padding-top; -// $alert-padding-opposite-direction: $alert-padding-top + em-calc(10); -// $alert-padding-bottom: $alert-padding-top + em-calc(1); - -// We use these to control text style. - -// $alert-font-weight: bold; -// $alert-font-size: em-calc(14); -// $alert-font-color: #fff; -// $alert-font-color-alt: darken($secondary-color, 60%); - -// We use this for close hover effect. - -// $alert-function-factor: 10%; - -// We use these to control border styles. - -// $alert-border-style: solid; -// $alert-border-width: 1px; -// $alert-border-color: darken($primary-color, $alert-function-factor); -// $alert-bottom-margin: em-calc(20); - -// We use these to style the close buttons - -// $alert-close-color: #333; -// $alert-close-position: em-calc(5); -// $alert-close-font-size: em-calc(22); -// $alert-close-opacity: 0.3; -// $alert-close-opacity-hover: 0.5; -// $alert-close-padding: 5px 4px 4px; - -// We use this to control border radius - -// $alert-radius: $global-radius; - - -// -// Breadcrumb Variables -// - -// We use this to set the background color for the breadcrumb container. - -// $crumb-bg: lighten($secondary-color, 5%); - -// We use these to set the padding around the breadcrumbs. - -// $crumb-padding: em-calc(9 14 9); -// $crumb-side-padding: em-calc(12); - -// We use these to control border styles. - -// $crumb-function-factor: 10%; -// $crumb-border-size: 1px; -// $crumb-border-style: solid; -// $crumb-border-color: darken($crumb-bg, $crumb-function-factor); -// $crumb-radius: $global-radius; - -// We use these to set various text styles for breadcrumbs. - -// $crumb-font-size: em-calc(11); -// $crumb-font-color: $primary-color; -// $crumb-font-color-current: #333; -// $crumb-font-color-unavailable: #999; -// $crumb-font-transform: uppercase; -// $crumb-link-decor: underline; - -// We use these to control the slash between breadcrumbs - -// $crumb-slash-color: #aaa; -// $crumb-slash: "/"; - -// -// Clearing Variables -// - -// We use these to set the background colors for parts of Clearing. - -// $clearing-bg: #111; -// $clearing-caption-bg: $clearing-bg; -// $clearing-carousel-bg: #111; -// $clearing-img-bg: $clearing-bg; - -// We use these to style the close button - -// $clearing-close-color: #fff; -// $clearing-close-size: 40px; - -// We use these to style the arrows - -// $clearing-arrow-size: 16px; -// $clearing-arrow-color: $clearing-close-color; - -// We use these to style captions - -// $clearing-caption-font-color: #fff; -// $clearing-caption-padding: 10px 30px; - -// We use these to make the image and carousel height and style - -// $clearing-active-img-height: 75%; -// $clearing-carousel-height: 150px; -// $clearing-carousel-thumb-width: 175px; -// $clearing-carousel-thumb-active-border: 4px solid rgb(255,255,255); - -// -// Custom Form Variables -// - -// We use these to control the basic form styles input styles - -// $custom-form-border-color: #ccc; -// $custom-form-border-size: 1px; -// $custom-form-bg: #fff; -// $custom-form-bg-disabled: #ddd; -// $custom-form-input-size: 16px; -// $custom-form-check-color: #222; -// $custom-form-check-size: 16px; -// $custom-form-radio-size: 8px; -// $custom-form-checkbox-radius: 0; - -// We use these to style the custom select form element. - -// $custom-select-bg: #fff; -// $custom-select-fade-to-color: #f3f3f3; -// $custom-select-border-color: #ddd; -// $custom-select-triangle-color: #aaa; -// $custom-select-triangle-color-open: #222; -// $custom-select-height: em-calc(13) + ($form-spacing * 1.5); -// $custom-select-margin-bottom: em-calc(20); -// $custom-select-font-color-selected: #141414; -// $custom-select-disabled-color: #888; - -// We use these to control the style of the custom select dropdown element. - -// $custom-dropdown-height: 200px; -// $custom-dropdown-bg: #fff; -// $custom-dropdown-border-color: darken(#fff, 20%); -// $custom-dropdown-border-width: 1px; -// $custom-dropdown-border-style: solid; -// $custom-dropdown-font-color: #555; -// $custom-dropdown-font-size: em-calc(14); -// $custom-dropdown-color-selected: #eeeeee; -// $custom-dropdown-font-color-selected: #000; -// $custom-dropdown-shadow: 0 2px 2px 0 rgba(0,0,0,0.1); -// $custom-dropdown-offset-top: auto; -// $custom-dropdown-list-padding: em-calc(4); -// $custom-dropdown-default-float-padding: em-calc(6); -// $custom-dropdown-opposite-padding: em-calc(38); -// $custom-dropdown-list-item-min-height: em-calc(24); -// $custom-dropdown-width-small: 134px; -// $custom-dropdown-width-medium: 254px; -// $custom-dropdown-width-large: 434px; - -// -// Dropdown Variables -// - -// We use these to controls height and width styles. - -// $f-dropdown-max-width: 200px; -// $f-dropdown-height: auto; -// $f-dropdown-max-height: none; -// $f-dropdown-margin-top: 2px; - -// We use this to control the background color - -// $f-dropdown-bg: #fff; - -// We use this to set the border styles for dropdowns. - -// $f-dropdown-border-style: solid; -// $f-dropdown-border-width: 1px; -// $f-dropdown-border-color: darken(#fff, 20%); - -// We use these to style the triangle pip. - -// $f-dropdown-triangle-size: 6px; -// $f-dropdown-triangle-color: #fff; -// $f-dropdown-triangle-side-offset: 10px; - -// We use these to control styles for the list elements. - -// $f-dropdown-list-style: none; -// $f-dropdown-font-color: #555; -// $f-dropdown-font-size: em-calc(14); -// $f-dropdown-list-padding: em-calc(5 10); -// $f-dropdown-line-height: em-calc(18); -// $f-dropdown-list-hover-bg: #eeeeee; -// $dropdown-mobile-default-float: 0; - -// We use this to control the styles for when the dropdown has custom content. - -// $f-dropdown-content-padding: em-calc(20); - -// -// Flex Video Variables -// - -// We use these to control video container padding and margins - -// $flex-video-padding-top: em-calc(25); -// $flex-video-padding-bottom: 67.5%; -// $flex-video-margin-bottom: em-calc(16); - -// We use this to control widescreen bottom padding - -// $flex-video-widescreen-padding-bottom: 57.25%; - -// -// Inline List Variables -// - -// We use this to control the margins and padding of the inline list. - -// $inline-list-top-margin: 0; -// $inline-list-opposite-margin: 0; -// $inline-list-bottom-margin: em-calc(17); -// $inline-list-default-float-margin: em-calc(-22); - -// $inline-list-padding: 0; - -// We use this to control the overflow of the inline list. - -// $inline-list-overflow: hidden; - -// We use this to control the list items - -// $inline-list-display: block; - -// We use this to control any elments within list items - -// $inline-list-children-display: block; - -// -// Joyride Variables -// - -// Controlling default Joyride styles - -// $joyride-tip-bg: rgb(0,0,0); -// $joyride-tip-default-width: 300px; -// $joyride-tip-padding: em-calc(18 20 24); -// $joyride-tip-border: solid 1px #555; -// $joyride-tip-radius: 4px; -// $joyride-tip-position-offset: 22px; - -// Here, we're setting the tip dont styles - -// $joyride-tip-font-color: #fff; -// $joyride-tip-font-size: em-calc(14); -// $joyride-tip-header-weight: bold; - -// This changes the nub size - -// $joyride-tip-nub-size: 14px; - -// This adjusts the styles for the timer when its enabled - -// $joyride-tip-timer-width: 50px; -// $joyride-tip-timer-height: 3px; -// $joyride-tip-timer-color: #666; - -// This changes up the styles for the close button - -// $joyride-tip-close-color: #777; -// $joyride-tip-close-size: 30px; -// $joyride-tip-close-weight: normal; - -// When Joyride is filling the screen, we use this style for the bg - -// $joyride-screenfill: rgba(0,0,0,0.5); - -// -// Keystroke Variables -// - -// We use these to control text styles. - -// $keystroke-font: "Consolas", "Menlo", "Courier", monospace; -// $keystroke-font-size: em-calc(14); -// $keystroke-font-color: #222; -// $keystroke-font-color-alt: #fff; -// $keystroke-function-factor: 7%; - -// We use this to control keystroke padding. - -// $keystroke-padding: em-calc(2 4 0); - -// We use these to control background and border styles. - -// $keystroke-bg: darken(#fff, $keystroke-function-factor); -// $keystroke-border-style: solid; -// $keystroke-border-width: 1px; -// $keystroke-border-color: darken($keystroke-bg, $keystroke-function-factor); -// $keystroke-radius: $global-radius; - -// -// Label Variables -// - -// We use these to style the labels - -// $label-padding: em-calc(3 10 4); -// $label-radius: $global-radius; - -// We use these to style the label text - -// $label-font-sizing: em-calc(14); -// $label-font-weight: bold; -// $label-font-color: #333; -// $label-font-color-alt: #fff; - -// -// Magellan Variables -// - -// $magellan-bg: #fff; -// $magellan-padding: 10px; - -// -// Orbit Settings -// - -// We use these to control the caption styles - -// $orbit-container-bg: #f5f5f5; -// $orbit-caption-bg: rgba(0,0,0,0.6); -// $orbit-caption-font-color: #fff; -// $orbit-caption-font-size: emCalc(14); -// $orbit-caption-position: "bottom"; // Supported values: "bottom", "under" -// $orbit-caption-padding: emCalc(10,14); -// $orbit-caption-height: auto; - -// We use these to control the left/right nav styles - -// $orbit-nav-bg: rgba(0,0,0,0.6); -// $orbit-nav-bg-hover: rgba(0,0,0,0.6); -// $orbit-nav-arrow-color: #fff; -// $orbit-nav-arrow-color-hover: #ccc; - -// We use these to control the timer styles - -// $orbit-timer-bg: rgba(0,0,0,0.6); -// $orbit-timer-show-progress-bar: true; - -// We use these to control the bullet nav styles - -// $orbit-bullet-nav-color: #999; -// $orbit-bullet-nav-color-active: #555; -// $orbit-bullet-radius: emCalc(18); - -// We use these to controls the style of slide numbers - -// $orbit-slide-number-bg: rgba(0,0,0,0); -// $orbit-slide-number-font-color: #fff; -// $orbit-slide-number-padding: em-calc(5); - -// Graceful Loading Wrapper and preloader - -// $wrapper-class: "slideshow-wrapper"; -// $preloader-class: "preloader"; - -// -// Pagination Variables -// - -// We use these to control the pagination container - -// $pagination-height: em-calc(24); -// $pagination-margin: em-calc(-5); - -// We use these to set the list-item properties - -// $pagination-li-float: $default-float; -// $pagination-li-height: em-calc(24); -// $pagination-li-font-color: #222; -// $pagination-li-font-size: em-calc(14); -// $pagination-li-margin: em-calc(5); - -// We use these for the pagination anchor links - -// $pagination-link-pad: em-calc(1 7 1); -// $pagination-link-font-color: #999; -// $pagination-link-active-bg: darken(#fff, 10%); - -// We use these for disabled anchor links - -// $pagination-link-unavailable-cursor: default; -// $pagination-link-unavailable-font-color: #999; -// $pagination-link-unavailable-bg-active: transparent; - -// We use these for currently selected anchor links - -// $pagination-link-current-background: $primary-color; -// $pagination-link-current-font-color: #fff; -// $pagination-link-current-font-weight: bold; -// $pagination-link-current-cursor: default; -// $pagination-link-current-active-bg: $primary-color; - -// -// Panel Variables -// - -// We use these to control the background and border styles - -// $panel-bg: darken(#fff, 5%); -// $panel-border-style: solid; -// $panel-border-size: 1px; - -// We use this % to control how much we darken things on hover - -// $panel-function-factor: 10%; -// $panel-border-color: darken($panel-bg, $panel-function-factor); - -// We use these to set default inner padding and bottom margin - -// $panel-margin-bottom: em-calc(20); -// $panel-padding: em-calc(20); - -// We use these to set default font colors - -// $panel-font-color: #333; -// $panel-font-color-alt: #fff; - -// $panel-header-adjust: true; - -// -// Pricing Table Variables -// - -// We use this to control the border color - -// $price-table-border: solid 1px #ddd; - -// We use this to control the bottom margin of the pricing table - -// $price-table-margin-bottom: em-calc(20); - -// We use these to control the title styles - -// $price-title-bg: #ddd; -// $price-title-padding: em-calc(15 20); -// $price-title-align: center; -// $price-title-color: #333; -// $price-title-weight: bold; -// $price-title-size: em-calc(16); - -// We use these to control the price styles - -// $price-money-bg: #eee; -// $price-money-padding: em-calc(15, 20); -// $price-money-align: center; -// $price-money-color: #333; -// $price-money-weight: normal; -// $price-money-size: em-calc(20); - -// We use these to control the description styles - -// $price-bg: #fff; -// $price-desc-color: #777; -// $price-desc-padding: em-calc(15); -// $price-desc-align: center; -// $price-desc-font-size: em-calc(12); -// $price-desc-weight: normal; -// $price-desc-line-height: 1.4; -// $price-desc-bottom-border: dotted 1px #ddd; - -// We use these to control the list item styles - -// $price-item-color: #333; -// $price-item-padding: em-calc(15); -// $price-item-align: center; -// $price-item-font-size: em-calc(14); -// $price-item-weight: normal; -// $price-item-bottom-border: dotted 1px #ddd; - -// We use these to control the CTA area styles - -// $price-cta-bg: #f5f5f5; -// $price-cta-align: center; -// $price-cta-padding: em-calc(20 20 0); - -// -// Progress Bar Variables -// - -// We use this to se the prog bar height - -// $progress-bar-height: em-calc(25); -// $progress-bar-color: transparent; - -// We use these to control the border styles - -// $progress-bar-border-color: darken(#fff, 20%); -// $progress-bar-border-size: 1px; -// $progress-bar-border-style: solid; -// $progress-bar-border-radius: $global-radius; - -// We use these to control the margin & padding - -// $progress-bar-pad: em-calc(2); -// $progress-bar-margin-bottom: em-calc(10); - -// We use these to set the meter colors - -// $progress-meter-color: $primary-color; -// $progress-meter-secondary-color: $secondary-color; -// $progress-meter-success-color: $success-color; -// $progress-meter-alert-color: $alert-color; - -// -// Reveal Variables -// - -// We use these to control the style of the reveal overlay. - -// $reveal-overlay-bg: rgba(#000, .45); -// $reveal-overlay-bg-old: #000; - -// We use these to control the style of the modal itself. - -// $reveal-modal-bg: #fff; -// $reveal-position-top: 50px; -// $reveal-default-width: 80%; -// $reveal-modal-padding: em-calc(20); -// $reveal-box-shadow: 0 0 10px rgba(#000,.4); - -// We use these to style the reveal close button - -// $reveal-close-font-size: em-calc(22); -// $reveal-close-top: em-calc(8); -// $reveal-close-side: em-calc(11); -// $reveal-close-color: #aaa; -// $reveal-close-weight: bold; - -// We use these to control the modal border - -// $reveal-border-style: solid; -// $reveal-border-width: 1px; -// $reveal-border-color: #666; - -// $reveal-modal-class: "reveal-modal"; -// $close-reveal-modal-class: "close-reveal-modal"; - -// -// Section Variables -// - -// We use these to set padding and hover factor - -// $section-title-padding: em-calc(15); -// $section-content-padding: em-calc(15); -// $section-function-factor: 10%; - -// These style the titles - -// $section-title-color: #333; -// $section-title-color-active: #333; -// $section-title-bg: #efefef; -// $section-title-bg-active: darken($section-title-bg, $section-function-factor); -// $section-title-bg-active-tabs: #fff; -// $section-title-bg-hover: darken($section-title-bg, $section-function-factor / 2); - -// Want to control border size, here ya go! - -// $section-border-size: 1px; -// $section-border-style: solid; -// $section-border-color: #ccc; - -// Font controls - -// $section-font-size: em-calc(14); - -// Control the color of the background and some size options - -// $section-content-bg: #fff; -// $section-vertical-nav-min-width: em-calc(200); -// $section-vertical-tabs-title-width: em-calc(200); -// $section-bottom-margin: em-calc(20); - -// $title-selector: ".title"; -// $content-selector: ".content"; -// $active-region-selector: ".active"; - -// -// Side Nav Variables -// - -// We use this to control padding. - -// $side-nav-padding: em-calc(14 0); - -// We use these to control list styles. - -// $side-nav-list-type: none; -// $side-nav-list-position: inside; -// $side-nav-list-margin: em-calc(0 0 7 0); - -// We use these to control link styles. - -// $side-nav-link-color: $primary-color; -// $side-nav-link-color-active: lighten(#000, 30%); -// $side-nav-font-size: em-calc(14); -// $side-nav-font-weight: bold; - -// We use these to control border styles - -// $side-nav-divider-size: 1px; -// $side-nav-divider-style: solid; -// $side-nav-divider-color: darken(#fff, 10%); - -// -// Sub Nav Variables -// - -// We use these to control margin and padding - -// $sub-nav-list-margin: em-calc(-4 0 18); -// $sub-nav-list-padding-top: em-calc(4); - -// We use this to control the definition - -// $sub-nav-font-size: em-calc(14); -// $sub-nav-font-color: #999; -// $sub-nav-font-weight: normal; -// $sub-nav-text-decoration: none; -// $sub-nav-border-radius: 1000px; - -// We use these to control the active item styles - -// $sub-nav-active-font-weight: bold; -// $sub-nav-active-bg: $primary-color; -// $sub-nav-active-color: #fff; -// $sub-nav-active-padding: em-calc(3 9); -// $sub-nav-active-cursor: default; - -// $sub-nav-item-divider: "" !default; -// $sub-nav-item-divider-margin: emCalc(12) !default; - -// -// Switch Variables -// - -// Controlling border styles and background colors for the switch container - -// $switch-border-color: darken(#fff, 20%); -// $switch-border-style: solid; -// $switch-border-width: 1px; -// $switch-bg: #fff; - -// We use these to control the switch heights for our default classes - -// $switch-height-tny: 22px; -// $switch-height-sml: 28px; -// $switch-height-med: 36px; -// $switch-height-lrg: 44px; -// $switch-bottom-margin: em-calc(20); - -// We use these to control default font sizes for our classes. - -// $switch-font-size-tny: 11px; -// $switch-font-size-sml: 12px; -// $switch-font-size-med: 14px; -// $switch-font-size-lrg: 17px; -// $switch-label-side-padding: 6px; - -// We use these to style the switch-paddle - -// $switch-paddle-bg: #fff; -// $switch-paddle-fade-to-color: darken($switch-paddle-bg, 10%); -// $switch-paddle-border-color: darken($switch-paddle-bg, 35%); -// $switch-paddle-border-width: 1px; -// $switch-paddle-border-style: solid; -// $switch-paddle-transition-speed: .1s; -// $switch-paddle-transition-ease: ease-out; -// $switch-positive-color: lighten($success-color, 50%); -// $switch-negative-color: #f5f5f5; - -// Outline Style for tabbing through switches - -// $switch-label-outline: 1px dotted #888; - -// -// Table Variables -// - -// These control the background color for the table and even rows - -// $table-bg: #fff; -// $table-even-row-bg: #f9f9f9; - -// These control the table cell border style - -// $table-border-style: solid; -// $table-border-size: 1px; -// $table-border-color: #ddd; - -// These control the table head styles - -// $table-head-bg: #f5f5f5; -// $table-head-font-size: em-calc(14); -// $table-head-font-color: #222; -// $table-head-font-weight: bold; -// $table-head-padding: em-calc(8 10 10); - -// These control the row padding and font styles - -// $table-row-padding: em-calc(9 10); -// $table-row-font-size: em-calc(14); -// $table-row-font-color: #222; -// $table-line-height: em-calc(18); - -// These are for controlling the display and margin of tables - -// $table-display: table-cell; -// $table-margin-bottom: em-calc(20); - -// -// Image Thumbnail Variables -// - -// We use these to control border styles - -// $thumb-border-style: solid; -// $thumb-border-width: 4px; -// $thumb-border-color: #fff; -// $thumb-box-shadow: 0 0 0 1px rgba(#000,.2); -// $thumb-box-shadow-hover: 0 0 6px 1px rgba($primary-color,0.5); - -// Radius and transition speed for thumbs - -// $thumb-radius: $global-radius; -// $thumb-transition-speed: 200ms; - -// -// Tooltip Variables -// - -// $has-tip-border-bottom: dotted 1px #ccc; -// $has-tip-font-weight: bold; -// $has-tip-font-color: #333; -// $has-tip-border-bottom-hover: dotted 1px darken($primary-color, 20%); -// $has-tip-font-color-hover: $primary-color; -// $has-tip-cursor-type: help; - -// $tooltip-padding: em-calc(8); -// $tooltip-bg: #000; -// $tooltip-font-size: em-calc(15); -// $tooltip-font-weight: bold; -// $tooltip-font-color: #fff; -// $tooltip-line-height: 1.3; -// $tooltip-close-font-size: em-calc(10); -// $tooltip-close-font-weight: normal; -// $tooltip-close-font-color: #888; -// $tooltip-font-size-sml: em-calc(14); -// $tooltip-radius: $global-radius; -// $tooltip-pip-size: 5px; - -// -// Top Bar Variables -// - -// Background color for the top bar - -// $topbar-bg-color: #111; -// $topbar-bg: $topbar-bg-color; - -// Height and margin - -// $topbar-height: 85px; -// $topbar-margin-bottom: 0; - -// Control Input height for top bar - -// $topbar-input-height: 2.45em; - -// Controlling the styles for the title in the top bar - -// $topbar-title-weight: bold; -// $topbar-title-font-size: em-calc(17); - -// Style the top bar dropdown elements - -// $topbar-dropdown-bg: #222; -// $topbar-dropdown-link-color: #fff; -// // $topbar-dropdown-link-bg: lighten($topbar-bg-color, 5%); -// $topbar-dropdown-toggle-size: 5px; -// $topbar-dropdown-toggle-color: #fff; -// $topbar-dropdown-toggle-alpha: 0.5; - -// Set the link colors and styles for top-level nav - -// $topbar-link-color: #fff; -// $topbar-link-color-hover: #fff; -// $topbar-link-color-active: #fff; -// $topbar-link-weight: bold; -// $topbar-link-font-size: em-calc(13); -// $topbar-link-hover-lightness: -30%; // Darken by 30% -// $topbar-link-bg-hover: darken($topbar-bg-color, 3%); -// $topbar-link-bg-active: darken($topbar-bg-color, 3%); - -// $topbar-dropdown-label-color: #555; -// $topbar-dropdown-label-text-transform: uppercase; -// $topbar-dropdown-label-font-weight: bold; -// $topbar-dropdown-label-font-size: em-calc(10); -// $topbar-dropdown-label-bg: lighten($topbar-bg-color, 5%); - -// Top menu icon styles - -// $topbar-menu-link-transform: uppercase; -// $topbar-menu-link-font-size: em-calc(13); -// $topbar-menu-link-weight: bold; -// $topbar-menu-link-color: #fff; -// $topbar-menu-icon-color: #fff; -// $topbar-menu-link-color-toggled: #888; -// $topbar-menu-icon-color-toggled: #888; - -// Transitions and breakpoint styles - -// $topbar-transition-speed: 300ms; -// $topbar-breakpoint: 940 !default; // Change to 9999px for always mobile layout -// $topbar-media-query: "only screen and (min-width: #{$topbar-breakpoint})"; - -// Divider Styles - -// $topbar-divider-border-bottom: solid 1px lighten($topbar-bg-color, 10%); -// $topbar-divider-border-top: solid 1px darken($topbar-bg-color, 10%); - -// Sticky Class - -// $topbar-sticky-class: ".sticky"; -// $topbar-arrows: true; //Set false to remove the triangle icon from the menu item diff --git a/app/assets/javascripts/foundation4/foundation/components/_alert-boxes.scss b/app/assets/javascripts/foundation4/foundation/components/_alert-boxes.scss deleted file mode 100755 index 01c5360250..0000000000 --- a/app/assets/javascripts/foundation4/foundation/components/_alert-boxes.scss +++ /dev/null @@ -1,107 +0,0 @@ -// -// Alert Box Variables -// -$include-html-alert-classes: $include-html-classes !default; - -// We use this to control alert padding. -$alert-padding-top: em-calc(11) !default; -$alert-padding-default-float: $alert-padding-top !default; -$alert-padding-opposite-direction: $alert-padding-top + em-calc(10) !default; -$alert-padding-bottom: $alert-padding-top + em-calc(1) !default; - -// We use these to control text style. -$alert-font-weight: bold !default; -$alert-font-size: em-calc(14) !default; -$alert-font-color: #fff !default; -$alert-font-color-alt: darken($secondary-color, 60%) !default; - -// We use this for close hover effect. -$alert-function-factor: 10% !default; - -// We use these to control border styles. -$alert-border-style: solid !default; -$alert-border-width: 1px !default; -$alert-border-color: darken($primary-color, $alert-function-factor) !default; -$alert-bottom-margin: em-calc(20) !default; - -// We use these to style the close buttons -$alert-close-color: #333 !default; -$alert-close-position: em-calc(5) !default; -$alert-close-font-size: em-calc(22) !default; -$alert-close-opacity: 0.3 !default; -$alert-close-opacity-hover: 0.5 !default; -$alert-close-padding: 5px 4px 4px !default; - -// We use this to control border radius -$alert-radius: $global-radius !default; - -// -// Alert Mixins -// - -// We use this mixin to create a default alert base. -@mixin alert-base { - border-style: $alert-border-style; - border-width: $alert-border-width; - display: block; - font-weight: $alert-font-weight; - margin-bottom: $alert-bottom-margin; - position: relative; - padding: $alert-padding-top $alert-padding-opposite-direction $alert-padding-bottom $alert-padding-default-float; - font-size: $alert-font-size; -} - -// We use this mixin to add alert styles -@mixin alert-style($bg:$primary-color) { - - // This find the lightness percentage of the background color. - $bg-lightness: lightness($bg); - - // We control which background color and border come through. - background-color: $bg; - border-color: darken($bg, $alert-function-factor); - - // We control the text color for you based on the background color. - @if $bg-lightness > 70% { color: $alert-font-color-alt; } - @else { color: $alert-font-color; } - -} - -// We use this to create the close button. -@mixin alert-close { - font-size: $alert-close-font-size; - padding: $alert-close-padding; - line-height: 0; - position: absolute; - top: $alert-close-position + em-calc(2); - #{$opposite-direction}: $alert-close-position; - color: $alert-close-color; - opacity: $alert-close-opacity; - &:hover, - &:focus { opacity: $alert-close-opacity-hover; } -} - -// We use this to quickly create alerts with a single mixin. -@mixin alert($bg:$primary-color, $radius:false) { - @include alert-base; - @include alert-style($bg); - @include radius($radius); -} - -@if $include-html-alert-classes != false { - - /* Foundation Alerts */ - .alert-box { - @include alert; - - .close { @include alert-close; } - - &.radius { @include radius($alert-radius); } - &.round { @include radius($global-rounded); } - - &.success { @include alert-style($success-color); } - &.alert { @include alert-style($alert-color); } - &.secondary { @include alert-style($secondary-color); } - } - -} diff --git a/app/assets/javascripts/foundation4/foundation/components/_block-grid.scss b/app/assets/javascripts/foundation4/foundation/components/_block-grid.scss deleted file mode 100755 index 4b1474ab98..0000000000 --- a/app/assets/javascripts/foundation4/foundation/components/_block-grid.scss +++ /dev/null @@ -1,71 +0,0 @@ -// -// Block Grid Variables -// -$include-html-grid-classes: $include-html-classes !default; - -// We use this to control the maximum number of block grid elements per row -$block-grid-elements: 12 !default; -$block-grid-default-spacing: em-calc(20) !default; - -// Enables media queries for block-grid classes. Set to false if writing semantic HTML. -$block-grid-media-queries: true !default; - -// -// Block Grid Mixins -// - -// We use this mixin to create different block-grids. You can apply per-row and spacing options. -// Setting $base-style to false will ommit default styles. -@mixin block-grid($per-row:false, $spacing:$block-grid-default-spacing, $base-style:true) { - - @if $base-style { - display: block; - padding: 0; - margin: 0 (-$spacing/2); - @include clearfix; - - &>li { - display: inline; - height: auto; - float: $default-float; - padding: 0 ($spacing/2) $spacing; - } - } - - @if $per-row { - &>li { - width: 100%/$per-row; - padding: 0 ($spacing/2) $spacing; - - &:nth-of-type(n) { clear: none; } - &:nth-of-type(#{$per-row}n+1) { clear: both; } - } - } - -} - -@if $include-html-grid-classes { - /* Foundation Block Grids for below small breakpoint */ - @media only screen { - [class*="block-grid-"] { @include block-grid; } - - @for $i from 1 through $block-grid-elements { - .small-block-grid-#{($i)} { - @include block-grid($i,$block-grid-default-spacing,false); - } - } - } - - /* Foundation Block Grids for above small breakpoint */ - @media #{$small} { - /* Remove small grid clearing */ - @for $i from 1 through $block-grid-elements { - .small-block-grid-#{($i)} > li:nth-of-type(#{$i}n+1) { clear: none; } - } - @for $i from 1 through $block-grid-elements { - .large-block-grid-#{($i)} { - @include block-grid($i,$block-grid-default-spacing,false); - } - } - } -} diff --git a/app/assets/javascripts/foundation4/foundation/components/_breadcrumbs.scss b/app/assets/javascripts/foundation4/foundation/components/_breadcrumbs.scss deleted file mode 100755 index 24b42246a1..0000000000 --- a/app/assets/javascripts/foundation4/foundation/components/_breadcrumbs.scss +++ /dev/null @@ -1,124 +0,0 @@ -// -// Breadcrumb Variables -// -$include-html-nav-classes: $include-html-classes !default; - -// We use this to set the background color for the breadcrumb container. -$crumb-bg: lighten($secondary-color, 5%) !default; - -// We use these to set the padding around the breadcrumbs. -$crumb-padding: em-calc(9 14 9) !default; -$crumb-side-padding: em-calc(12) !default; - -// We use these to control border styles. -$crumb-function-factor: 10% !default; -$crumb-border-size: 1px !default; -$crumb-border-style: solid !default; -$crumb-border-color: darken($crumb-bg, $crumb-function-factor) !default; -$crumb-radius: $global-radius !default; - -// We use these to set various text styles for breadcrumbs. -$crumb-font-size: em-calc(11) !default; -$crumb-font-color: $primary-color !default; -$crumb-font-color-current: #333 !default; -$crumb-font-color-unavailable: #999 !default; -$crumb-font-transform: uppercase !default; -$crumb-link-decor: underline !default; - -// We use these to control the slash between breadcrumbs -$crumb-slash-color: #aaa !default; -$crumb-slash: "/" !default; - -// -// Breakcrumb Mixins -// - -// We use this mixin to create a container around our breadcrumbs -@mixin crumb-container { - display: block; - padding: $crumb-padding; - overflow: hidden; - margin-#{$default-float}: 0; - list-style: none; - border-style: $crumb-border-style; - border-width: $crumb-border-size; - - // We control which background color and border come through. - background-color: $crumb-bg; - border-color: $crumb-border-color; -} - -// We use this mixin to create breadcrumb styles from list items. -@mixin crumbs { - - // A normal state will make the links look and act like clickable breadcrumbs. - margin: 0; - float: $default-float; - font-size: $crumb-font-size; - text-transform: $crumb-font-transform; - - &:hover a, &:focus a { text-decoration: $crumb-link-decor; } - - a, - span { - text-transform: $crumb-font-transform; - color: $crumb-font-color; - } - - // Current is for the link of the current page - &.current { - cursor: $cursor-default-value; - color: $crumb-font-color-current; - a { - cursor: $cursor-default-value; - color: $crumb-font-color-current; - } - - &:hover, &:hover a, - &:focus, &:focus a { text-decoration: none; } - } - - // Unavailable removed color and link styles so it looks inactive. - &.unavailable { - color: $crumb-font-color-unavailable; - a { color: $crumb-font-color-unavailable; } - - &:hover, - &:hover a, - &:focus, - a:focus { - text-decoration: none; - color: $crumb-font-color-unavailable; - cursor: $cursor-default-value; - } - } - - &:before { - content: "#{$crumb-slash}"; - color: $crumb-slash-color; - margin: 0 $crumb-side-padding; - position: relative; - top: 1px; - } - - &:first-child:before { - content: " "; - margin: 0; - } - -} - - -@if $include-html-nav-classes != false { - - /* Breadcrumbs */ - .breadcrumbs { - @include crumb-container; - @include radius($crumb-radius); - - &>* { - @include crumbs; - } - } - -} diff --git a/app/assets/javascripts/foundation4/foundation/components/_button-groups.scss b/app/assets/javascripts/foundation4/foundation/components/_button-groups.scss deleted file mode 100755 index d35e05ad9a..0000000000 --- a/app/assets/javascripts/foundation4/foundation/components/_button-groups.scss +++ /dev/null @@ -1,89 +0,0 @@ -// -// Button Group Variables -// -$include-html-button-classes: $include-html-classes !default; - -// Sets the margin for the right side by default, and the left margin if right-to-left direction is used -$button-bar-margin-opposite: em-calc(10) !default; - -// -// Button Group Mixins -// - -// We use this to add styles for a button group container -@mixin button-group-container($styles:true, $float:false) { - @if $styles { - list-style: none; - margin: 0; - @include clearfix(); - } - @if $float { - float: #{$default-float}; - margin-#{$opposite-direction}: $button-bar-margin-opposite; - & div { overflow: hidden; } - } -} - -// We use this to control styles for button groups -@mixin button-group-style($radius:false, $even:false, $float:$default-float) { - - // We use this to control the flow, or remove those styles completely. - @if $float { - margin: 0 0 0 (-$button-border-width); - float: $float; - // Make sure the first child doesn't get the negative margin. - &:first-child { margin-#{$default-float}: 0; } - } - - // We use these to control left and right radius on first/last buttons in the group. - @if $radius == true { - &:first-child, - &:first-child > a, - &:first-child > button, - &:first-child > .button { @include side-radius($default-float, $button-radius); } - &:last-child, - &:last-child > a, - &:last-child > button, - &:last-child > .button { @include side-radius($opposite-direction, $button-radius); } - } - @else if $radius { - &:first-child, - &:first-child > a, - &:first-child > button, - &:first-child > .button { @include side-radius($default-float, $radius); } - &:last-child, - &:last-child > a, - &:last-child > button, - &:last-child > .button { @include side-radius($opposite-direction, $radius); } - } - - // We use this to make the buttons even width across their container - @if $even { - width: percentage((100/$even) / 100); - button, .button { width: 100%; } - } - -} - -// Only include these CSS classes if $include-html-classes: true -@if $include-html-button-classes != false { - - /* Button Groups */ - .button-group { @include button-group-container; - - &> * { @include button-group-style(); } - - &.radius > * { @include button-group-style($radius:$button-radius, $float:null); } - &.round > * { @include button-group-style($radius:$button-round, $float:null); } - - @for $i from 2 through 8 { - &.even#{-$i} li { @include button-group-style($even:$i, $float:null); } - } - } - - .button-bar { - @include clearfix; - .button-group { @include button-group-container($styles:false,$float:true); } - } - -} diff --git a/app/assets/javascripts/foundation4/foundation/components/_buttons.scss b/app/assets/javascripts/foundation4/foundation/components/_buttons.scss deleted file mode 100755 index c5954ad821..0000000000 --- a/app/assets/javascripts/foundation4/foundation/components/_buttons.scss +++ /dev/null @@ -1,230 +0,0 @@ -// -// Button Variables -// -$include-html-button-classes: $include-html-classes !default; - -// We use these to build padding for buttons. -$button-med: em-calc(12) !default; -$button-tny: em-calc(7) !default; -$button-sml: em-calc(9) !default; -$button-lrg: em-calc(16) !default; - -// We use this to control the display property. -$button-display: inline-block !default; -$button-margin-bottom: em-calc(20) !default; - -// We use these to control button text styles. -$button-font-family: inherit !default; -$button-font-color: #fff !default; -$button-font-color-alt: #333 !default; -$button-font-med: em-calc(16) !default; -$button-font-tny: em-calc(11) !default; -$button-font-sml: em-calc(13) !default; -$button-font-lrg: em-calc(20) !default; -$button-font-weight: bold !default; -$button-font-align: center !default; - -// We use these to control various hover effects. -$button-function-factor: 10% !default; - -// We use these to control button border styles. -$button-border-width: 1px !default; -$button-border-style: solid !default; - -// We use this to set the default radius used throughout the core. -$button-radius: $global-radius !default; -$button-round: $global-rounded !default; - -// We use this to set default opacity for disabled buttons. -$button-disabled-opacity: 0.6 !default; - - -// -// Button Mixins -// - -// We use this mixin to create a default button base. -@mixin button-base($style:true, $display:$button-display) { - @if $style { - border-style: $button-border-style; - border-width: $button-border-width; - cursor: $cursor-pointer-value; - font-family: $button-font-family; - font-weight: $button-font-weight; - line-height: normal; - margin: 0 0 $button-margin-bottom; - position: relative; - text-decoration: none; - text-align: $button-font-align; - } - @if $display { display: $display; } -} - -// We use this mixin to add button size styles -@mixin button-size($padding:$button-med, $full-width:false, $is-input:false) { - - // We control which padding styles come through, - // these can be turned off by setting $padding:false - @if $padding { - padding-top: $padding; - padding-#{$opposite-direction}: $padding * 2; - padding-bottom: $padding + em-calc(1); - padding-#{$default-float}: $padding * 2; - - // We control the font-size based on mixin input. - @if $padding == $button-med { font-size: $button-font-med; } - @else if $padding == $button-tny { font-size: $button-font-tny; } - @else if $padding == $button-sml { font-size: $button-font-sml; } - @else if $padding == $button-lrg { font-size: $button-font-lrg; } - @else { font-size: $padding - em-calc(2); } - } - - // We can set $full-width:true to remove side padding extend width. - @if $full-width { - // We still need to check if $padding is set. - @if $padding { - padding-top: $padding; - padding-bottom: $padding + em-calc(1); - } @else if $padding == false { - padding-top:0; - padding-bottom:0; - } - padding-right: 0; - padding-left: 0; - width: 100%; - } - - // 's and