diff --git a/app/assets/images/map-icon-both.svg b/app/assets/images/map-icon-both.svg deleted file mode 100644 index a51867f841..0000000000 --- a/app/assets/images/map-icon-both.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/assets/images/map-icon-hub.svg b/app/assets/images/map-icon-hub.svg deleted file mode 100644 index fcd6a4913e..0000000000 --- a/app/assets/images/map-icon-hub.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/app/assets/images/map-icon-producer.svg b/app/assets/images/map-icon-producer.svg deleted file mode 100644 index 50ec792e91..0000000000 --- a/app/assets/images/map-icon-producer.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/app/assets/images/map_001-producer-only.svg b/app/assets/images/map_001-producer-only.svg new file mode 100644 index 0000000000..b34c01f1ed --- /dev/null +++ b/app/assets/images/map_001-producer-only.svg @@ -0,0 +1,63 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/map_002-producer-only-profile.svg b/app/assets/images/map_002-producer-only-profile.svg new file mode 100644 index 0000000000..0522f91257 --- /dev/null +++ b/app/assets/images/map_002-producer-only-profile.svg @@ -0,0 +1,65 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/map_003-producer-shop.svg b/app/assets/images/map_003-producer-shop.svg new file mode 100644 index 0000000000..84c324ac4e --- /dev/null +++ b/app/assets/images/map_003-producer-shop.svg @@ -0,0 +1,63 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/map_004-producer-shop-profile.svg b/app/assets/images/map_004-producer-shop-profile.svg new file mode 100644 index 0000000000..4d35236813 --- /dev/null +++ b/app/assets/images/map_004-producer-shop-profile.svg @@ -0,0 +1,65 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/map_005-hub.svg b/app/assets/images/map_005-hub.svg new file mode 100644 index 0000000000..be2d292c20 --- /dev/null +++ b/app/assets/images/map_005-hub.svg @@ -0,0 +1,46 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/map_006-hub-profile.svg b/app/assets/images/map_006-hub-profile.svg new file mode 100644 index 0000000000..b284ea34f3 --- /dev/null +++ b/app/assets/images/map_006-hub-profile.svg @@ -0,0 +1,48 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + diff --git a/app/assets/images/map_007-shop.svg b/app/assets/images/map_007-shop.svg new file mode 100644 index 0000000000..e2ebe118ce --- /dev/null +++ b/app/assets/images/map_007-shop.svg @@ -0,0 +1,47 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + diff --git a/app/assets/images/map_008-shop-profile.svg b/app/assets/images/map_008-shop-profile.svg new file mode 100644 index 0000000000..635602b7bf --- /dev/null +++ b/app/assets/images/map_008-shop-profile.svg @@ -0,0 +1,68 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/javascripts/admin/services/enterprise_relationships.js.coffee b/app/assets/javascripts/admin/services/enterprise_relationships.js.coffee index cad556efd8..16c9c38fea 100644 --- a/app/assets/javascripts/admin/services/enterprise_relationships.js.coffee +++ b/app/assets/javascripts/admin/services/enterprise_relationships.js.coffee @@ -24,5 +24,5 @@ angular.module("ofn.admin").factory 'EnterpriseRelationships', ($http, enterpris permission_presentation: (permission) -> switch permission - when "add_to_order_cycle" then "can add to order cycle" - when "manage_products" then "can manage the products of" + when "add_to_order_cycle" then "to add to order cycle" + when "manage_products" then "to manage products" diff --git a/app/assets/javascripts/darkswarm/controllers/checkout/checkout_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/checkout/checkout_controller.js.coffee index e77712eae6..9c953c4f4a 100644 --- a/app/assets/javascripts/darkswarm/controllers/checkout/checkout_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/checkout/checkout_controller.js.coffee @@ -6,9 +6,9 @@ Darkswarm.controller "CheckoutCtrl", ($scope, storage, Checkout, CurrentUser, Cu prefix = "order_#{Checkout.order.id}#{CurrentUser?.id}#{CurrentHub.hub.id}" for field in $scope.fieldsToBind - storage.bind $scope, "Checkout.order.#{field}", + storage.bind $scope, "Checkout.order.#{field}", storeName: "#{prefix}_#{field}" - storage.bind $scope, "Checkout.ship_address_same_as_billing", + storage.bind $scope, "Checkout.ship_address_same_as_billing", storeName: "#{prefix}_sameasbilling" defaultValue: true diff --git a/app/assets/javascripts/darkswarm/services/checkout.js.coffee b/app/assets/javascripts/darkswarm/services/checkout.js.coffee index cafd4d6718..a12ed1ae45 100644 --- a/app/assets/javascripts/darkswarm/services/checkout.js.coffee +++ b/app/assets/javascripts/darkswarm/services/checkout.js.coffee @@ -13,7 +13,7 @@ Darkswarm.factory 'Checkout', (CurrentOrder, ShippingMethods, PaymentMethods, $h Loading.clear() @errors = response.errors RailsFlashLoader.loadFlash(response.flash) - + # Rails wants our Spree::Address data to be provided with _attributes preprocess: -> munged_order = {} @@ -25,7 +25,7 @@ Darkswarm.factory 'Checkout', (CurrentOrder, ShippingMethods, PaymentMethods, $h munged_order["ship_address_attributes"] = value when "payment_method_id" munged_order["payments_attributes"] = [{payment_method_id: value}] - when "shipping_method_id", "payment_method_id", "email" + when "shipping_method_id", "payment_method_id", "email", "special_instructions" munged_order[name] = value else # Ignore everything else @@ -58,7 +58,7 @@ Darkswarm.factory 'Checkout', (CurrentOrder, ShippingMethods, PaymentMethods, $h shippingPrice: -> @shippingMethod()?.price || 0.0 - + paymentMethod: -> PaymentMethods.payment_methods_by_id[@order.payment_method_id] diff --git a/app/assets/javascripts/darkswarm/services/hubs.js.coffee b/app/assets/javascripts/darkswarm/services/hubs.js.coffee index ac7dc3a0eb..de9900866f 100644 --- a/app/assets/javascripts/darkswarm/services/hubs.js.coffee +++ b/app/assets/javascripts/darkswarm/services/hubs.js.coffee @@ -2,7 +2,7 @@ Darkswarm.factory 'Hubs', ($filter, Enterprises, visibleFilter) -> new class Hubs constructor: -> @hubs = @order Enterprises.enterprises.filter (hub)-> - hub.is_distributor + hub.is_distributor && hub.has_shopfront @visible = visibleFilter @hubs order: (hubs)-> diff --git a/app/assets/javascripts/templates/partials/hub_actions.html.haml b/app/assets/javascripts/templates/partials/hub_actions.html.haml index 54b8ee98b1..fa9ff4e183 100644 --- a/app/assets/javascripts/templates/partials/hub_actions.html.haml +++ b/app/assets/javascripts/templates/partials/hub_actions.html.haml @@ -1,16 +1,16 @@ -.row.pad-top{bindonce: true, "ng-if" => "enterprise.hubs.length > 0"} +.row.pad-top{bindonce: true, "ng-if" => "enterprise.hubs.length > 0 && enterprise.has_shopfront"} .cta-container.small-12.columns %label Shop for %strong {{enterprise.name}} products at: - %a.button.hub{"ng-repeat" => "hub in enterprise.hubs", + %a.cta-hub{"ng-repeat" => "hub in enterprise.hubs", "bo-href" => "hub.path", "bo-class" => "{primary: hub.active, secondary: !hub.active}", "ofn-empties-cart" => "hub"} %i.ofn-i_033-open-sign{"bo-if" => "hub.active"} %i.ofn-i_032-closed-sign{"bo-if" => "!hub.active"} - {{hub.name}} + .hub-name {{hub.name}} .button-address {{ hub.address.city }} , {{hub.address.state_name}} - %i.ofn-i_007-caret-right + / %i.ofn-i_007-caret-right diff --git a/app/assets/javascripts/templates/partials/hub_details.html.haml b/app/assets/javascripts/templates/partials/hub_details.html.haml index 8de1039f10..27933cefcb 100644 --- a/app/assets/javascripts/templates/partials/hub_details.html.haml +++ b/app/assets/javascripts/templates/partials/hub_details.html.haml @@ -1,8 +1,8 @@ -.row.pad-top{bindonce: true} +.row.pad-top{bindonce: true, ng: { if: 'enterprise.has_shopfront' } } .cta-container.small-12.columns .row .small-4.columns - %label{"active-table-hub-link" => "enterprise", change: "Change hub to:", shop: "Shop now at:"} + %label{"active-table-hub-link" => "enterprise", change: "Change shop to:", shop: "Shop now at:"} .small-8.columns.right %label.right{"bo-if" => "enterprise.pickup || enterprise.delivery"} Delivery options: @@ -14,11 +14,11 @@ Delivery .row .columns.small-12 - %a.button.hub.expand{"bo-href" => "enterprise.path", + %a.cta-hub{"bo-href" => "enterprise.path", "ng-class" => "{primary: enterprise.active, secondary: !enterprise.active}", "ofn-empties-cart" => "enterprise"} %i.ofn-i_033-open-sign{"bo-if" => "enterprise.active"} %i.ofn-i_032-closed-sign{"bo-if" => "!enterprise.active"} - {{enterprise.name}} + .hub-name {{enterprise.name}} .button-address {{ enterprise.address.city }} , {{enterprise.address.state_name}} - %i.ofn-i_007-caret-right + / %i.ofn-i_007-caret-right diff --git a/app/assets/stylesheets/darkswarm/active_table.css.sass b/app/assets/stylesheets/darkswarm/active_table.css.sass index 131836da4e..695ee3039a 100644 --- a/app/assets/stylesheets/darkswarm/active_table.css.sass +++ b/app/assets/stylesheets/darkswarm/active_table.css.sass @@ -16,6 +16,7 @@ padding: 1rem 0 .active_table .active_table_node + margin-top: 0.25rem display: block border: 0 @@ -28,11 +29,17 @@ span text-decoration: underline + span.margin-top + margin-top: 0.5rem + display: inline-block + // Generic text resize @media all and (max-width: 640px) - font-size: 0.875rem &, & * font-size: 0.875rem + fat > div label + &, & * + font-size: 0.75rem .active_table_row // Inherits from active_table @@ -68,7 +75,7 @@ //Open row sections .fat > div - border-top: 1px solid $disabled-bright + border-top: 1px solid #aaa ul, ol font-size: 0.875rem @@ -81,7 +88,7 @@ font-size: 0.75rem margin-top: 0.25rem margin-bottom: 0.25rem - color: $disabled-dark + color: #777 p.trans-sentence text-transform: capitalize diff --git a/app/assets/stylesheets/darkswarm/angular.css.sass b/app/assets/stylesheets/darkswarm/angular.css.sass new file mode 100644 index 0000000000..0430dd1390 --- /dev/null +++ b/app/assets/stylesheets/darkswarm/angular.css.sass @@ -0,0 +1,3 @@ +// https://docs.angularjs.org/api/ng/directive/ngCloak +[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak + display: none !important diff --git a/app/assets/stylesheets/darkswarm/hub_node.css.sass b/app/assets/stylesheets/darkswarm/hub_node.css.sass index d0b5dcc0ef..322da9b375 100644 --- a/app/assets/stylesheets/darkswarm/hub_node.css.sass +++ b/app/assets/stylesheets/darkswarm/hub_node.css.sass @@ -10,23 +10,30 @@ overflow-x: hidden overflow-y: visible - //Hub icon styline - i.ofn-i_040-hub - @include border-radius(99999rem) - font-size: 1.15rem - display: inline-block - padding: 0.2rem - margin-top: 0.1rem - margin-bottom: 0.1rem - background-color: transparent - @media all and (max-width: 768px) - font-size: 1rem - //Generic text link style a:hover, a:active, a:focus color: $clr-brick-bright - @media all and (max-width: 640px) + //Hub and Producer icons + // i.ofn-i_040-hub + i.ofn-i_063-hub, i.ofn-i_064-hub-reversed, i.ofn-i_059-producer, i.ofn-i_060-producer-reversed + font-size: 2rem + display: inline-block + margin-right: 0.25rem + float: left + + //Closed & Open column + .open_closed + i + font-size: 2rem + float: right + margin-left: 0.5rem + + //Hub Name + span.hub-name-listing + font-weight: 700 + + @media all and (max-width: 640px) &.closed, &.open .active_table_row:first-child .skinny-head background-color: $clr-brick-light @@ -38,38 +45,35 @@ &.closed, &.open .active_table_row:first-child .skinny-head background-color: white - + &.current + &.closed, &.open + .active_table_row:first-child .skinny-head + background-color: $clr-brick-bright + &.current + &.inactive + &.closed, &.open + .active_table_row:first-child .skinny-head + background-color: #555 + //Inactive row &.inactive, &.inactive strong color: $disabled-dark - &, & * color: $disabled-dark a i.ofn-i_040-hub color: $disabled-dark - - &.current + &.current + &.inactive &.closed, &.open - - a, a strong, a span, a i - color: $disabled-dark - &:hover, &:focus, &:active - color: $disabled-dark - - a i.ofn-i_040-hub - color: white + .active_table_row:first-child background-color: $disabled-dark - a:hover, a:focus, a:active - color: $disabled-dark - i.ofn-i_040-hub - background-color: $disabled-dark - + &, & * + color: white &.closed &:hover, &:active, &:focus border: none color: $disabled-dark - &.open .active_table_row:first-child color: $disabled-dark @@ -82,31 +86,27 @@ .active_table_row:nth-child(2) background-color: rgba(255, 255, 255, 0) - //Open row + //Padding second row &.open .active_table_row:nth-child(2) padding-bottom: 0.75rem - + //Current selected row &.current //overwrites active_table - &.closed - a, a i, a span, a strong - color: $clr-brick - &.closed, &.open - a i.ofn-i_040-hub - color: white + .active_table_row:first-child background-color: $clr-brick - - - a:hover, a:focus, a:active - strong, span - color: $clr-brick-bright - i.ofn-i_040-hub - background-color: $clr-brick-bright - - - - + opacity: 1 + &:hover, &:focus, &:active + opacity: 0.9 + &, & * + color: white + &.open, &.closed + .active_table_row + border-color: $clr-brick + &.inactive + &.open, &.closed + .active_table_row + border-color: $disabled-dark diff --git a/app/assets/stylesheets/darkswarm/modal-enterprises.css.sass b/app/assets/stylesheets/darkswarm/modal-enterprises.css.sass index 4883aa3572..9f08b38790 100644 --- a/app/assets/stylesheets/darkswarm/modal-enterprises.css.sass +++ b/app/assets/stylesheets/darkswarm/modal-enterprises.css.sass @@ -2,6 +2,23 @@ @import mixins +// Generic styles for use + +.modal-centered + text-align: center + p + margin-bottom: 0 + +.modal-header, p.modal-header + text-align: center + text-transform: uppercase + font-size: 1rem + font-weight: 400 + color: $disabled-dark + border-bottom: 1px solid $disabled-dark + margin-top: 0.75rem + margin-bottom: 0.5rem + // Enterprise promo image and text .highlight @@ -53,7 +70,7 @@ // FOLLOW Enterprise .follow-icons - text-align: center + // text-align: center span display: inline-block margin: 0 0.25rem 0.75rem 0.25rem @@ -74,7 +91,7 @@ label text-transform: uppercase font-size: 0.875rem - margin-bottom: 0 + margin-bottom: 0.75rem 5rem color: $dark-grey @@ -82,51 +99,53 @@ color: $disabled-dark span text-transform: capitalize + + .cta-hub + margin-right: 2rem + margin-top: 0rem + margin-bottom: 0.75rem + display: inline-block - .button.secondary - background-color: #999 - .button.hub - margin-right: 1rem - margin-top: 0.25rem - margin-bottom: 1rem - padding-left: 1rem - padding-right: 1rem - font-weight: bold + &.secondary + color: $disabled-dark + + &.primary + color: $clr-brick + i.ofn-i_033-open-sign, i.ofn-i_032-closed-sign - margin-right: 0.15rem - font-size: 1.25rem - i.ofn-i_007-caret-right - margin-left: 1rem + margin-right: 0.1rem + font-size: 2rem + padding: 0.15rem 0.25rem 0.35rem 0.25rem + float: left + + .hub-name + margin-top: 0.75rem + margin-bottom: 0.2rem + font-weight: 400 + display: inline-block + border-bottom: 1px solid transparent .button-address + margin-top: 0.5rem + margin-bottom: 0.2rem + margin-left: 0.1rem + text-transform: uppercase font-weight: 300 font-style: italic font-size: 0.75rem - display: inline + display: inline-block + border-bottom: 1px solid transparent @media all and (max-width: 640px) display: none - .button.hub.expand - text-align: left - i.ofn-i_007-caret-right - float: right - i.ofn-i_033-open-sign, i.ofn-i_032-closed-sign - float: left - margin-right: 0.5rem + + &:hover, &:focus, &:active + &.secondary + color: #666 + .hub-name, .button-address + border-bottom: 1px solid #999 + &.primary + color: $clr-brick-bright + .hub-name, .button-address + border-bottom: 1px solid $clr-brick-bright -// Generic styles for use - -.modal-centered - text-align: center - p - margin-bottom: 0 - -.modal-header, p.modal-header - text-align: center - text-transform: uppercase - font-size: 1rem - font-weight: 400 - color: $disabled-dark - border-bottom: 1px solid $disabled-dark - margin-top: 0.75rem - margin-bottom: 0.5rem diff --git a/app/assets/stylesheets/darkswarm/producer_node.css.sass b/app/assets/stylesheets/darkswarm/producer_node.css.sass index 1dcb49b528..25759d30e5 100644 --- a/app/assets/stylesheets/darkswarm/producer_node.css.sass +++ b/app/assets/stylesheets/darkswarm/producer_node.css.sass @@ -11,6 +11,42 @@ margin-bottom: 1rem padding-top: 1rem padding-bottom: 1rem + .follow-icons + &, & * + font-size: 1.5rem + + // Producer icons + i.ofn-i_059-producer, i.ofn-i_060-producer-reversed + font-size: 2rem + display: inline-block + margin-right: 0.25rem + float: left + color: $clr-turquoise + + a + &:hover, &:active, &:focus + color: $clr-turquoise-bright + span + text-decoration: underline + + a.cta-hub + &:hover, &:focus, &:active + &.secondary + color: #666 + .hub-name, .button-address + border-bottom: 1px solid #999 + &.primary + color: $clr-brick-bright + .hub-name, .button-address + border-bottom: 1px solid $clr-brick-bright + + p.word-wrap + margin-bottom: 0 + &:last-child + margin-bottom: 1rem + + .fat-taxons + background-color: $clr-turquoise-light //Open row &.open @@ -18,13 +54,17 @@ .active_table_row border-left: 1px solid $clr-turquoise-bright border-right: 1px solid $clr-turquoise-bright - background-color: rgba(255,255,255,0.4) + background-color: rgba(206,239,228,0.4) .cta-container background: none .columns img padding: 1rem 0 max-height: 160px width: auto + &.left + padding: 0.25rem 1rem 0.25rem 0 + &.right + padding: 0.25rem 0.5rem 0.25rem 2rem .active_table_row:first-child border-top: 1px solid $clr-turquoise-bright @@ -37,4 +77,7 @@ &.closed &:hover, &:active, &:focus .active_table_row.closed - border: 1px solid $clr-turquoise \ No newline at end of file + border: 1px solid $clr-turquoise + + + diff --git a/app/assets/stylesheets/darkswarm/style.css b/app/assets/stylesheets/darkswarm/style.css index 843d362510..3d2a98276b 100755 --- a/app/assets/stylesheets/darkswarm/style.css +++ b/app/assets/stylesheets/darkswarm/style.css @@ -1,10 +1,10 @@ @font-face { font-family: 'OFN'; - src:url('/OFN.eot?-4w617y'); - src:url('/OFN.eot?#iefix-4w617y') format('embedded-opentype'), - url('/OFN.woff?-4w617y') format('woff'), - url('/OFN.ttf?-4w617y') format('truetype'), - url('/OFN.svg?-4w617y#OFN') format('svg'); + src:url('/OFN.eot?eslsji'); + src:url('/OFN.eot?#iefixeslsji') format('embedded-opentype'), + url('/OFN.woff?eslsji') format('woff'), + url('/OFN.ttf?eslsji') format('truetype'), + url('/OFN.svg?eslsji#OFN') format('svg'); font-weight: normal; font-style: normal; } @@ -194,6 +194,42 @@ .ofn-i_057-expand:before { content: "\e638"; } -.ofn-i-058-graph:before { +.ofn-i_058-graph:before { content: "\e639"; } +.ofn-i_059-producer:before { + content: "\e63a"; +} +.ofn-i_060-producer-reversed:before { + content: "\e63b"; +} +.ofn-i_061-producer-map:before { + content: "\e63c"; +} +.ofn-i_062-producer-map-reversed:before { + content: "\e63d"; +} +.ofn-i_063-hub:before { + content: "\e63e"; +} +.ofn-i_064-hub-reversed:before { + content: "\e63f"; +} +.ofn-i_065-hub-map:before { + content: "\e640"; +} +.ofn-i_066-hub-map-reversed:before { + content: "\e641"; +} +.ofn-i_067-shop:before { + content: "\e642"; +} +.ofn-i_068-shop-reversed:before { + content: "\e643"; +} +.ofn-i_069-shop-map:before { + content: "\e644"; +} +.ofn-i_070-shop-map-reversed:before { + content: "\e645"; +} diff --git a/app/assets/stylesheets/darkswarm/ui.css.sass b/app/assets/stylesheets/darkswarm/ui.css.sass index a4d70392bb..3bbce61552 100644 --- a/app/assets/stylesheets/darkswarm/ui.css.sass +++ b/app/assets/stylesheets/darkswarm/ui.css.sass @@ -63,6 +63,20 @@ button.success, .button.success .button.success:hover, .button.success:active, .button.success:focus, button.success:hover, button.success:active, button.success:focus background: #14b6cc +.button.help-btn + @include border-radius(999999px) + &.tiny + padding: 0rem + margin: 0 + float: right + i + font-size: 1.25rem + +.profile-checkbox + display: inline-block + input[type="checkbox"] + label + margin: 0 0.2rem + // Responsive @media screen and (min-width: 768px) [role="main"] diff --git a/app/controllers/admin/enterprises_controller.rb b/app/controllers/admin/enterprises_controller.rb index 85fe6831fb..ceeb26abfc 100644 --- a/app/controllers/admin/enterprises_controller.rb +++ b/app/controllers/admin/enterprises_controller.rb @@ -4,6 +4,8 @@ module Admin before_filter :load_countries, :except => :index before_filter :load_methods_and_fees, :only => [:new, :edit, :update, :create] create.after :grant_management + before_filter :check_type, only: :update + before_filter :check_bulk_type, only: :bulk_update helper 'spree/products' include OrderCyclesHelper @@ -67,6 +69,18 @@ module Admin @enterprise_fees = EnterpriseFee.managed_by(spree_current_user).for_enterprise(@enterprise).order(:fee_type, :name).all end + def check_bulk_type + unless spree_current_user.admin? + params[:enterprise_set][:collection_attributes].each do |i, enterprise_params| + enterprise_params.delete :type + end + end + end + + def check_type + params[:enterprise].delete :type unless spree_current_user.admin? + end + # Overriding method on Spree's resource controller def location_after_save if params[:enterprise].key? :producer_properties_attributes diff --git a/app/controllers/checkout_controller.rb b/app/controllers/checkout_controller.rb index 8e2a33bd56..7e8b04afda 100644 --- a/app/controllers/checkout_controller.rb +++ b/app/controllers/checkout_controller.rb @@ -9,7 +9,7 @@ class CheckoutController < Spree::CheckoutController include OrderCyclesHelper include EnterprisesHelper - + def edit # Because this controller doesn't inherit from our BaseController # We need to duplicate the code here @@ -56,7 +56,7 @@ class CheckoutController < Spree::CheckoutController private - + # Copied and modified from spree. Remove check for order state, since the state machine is # progressed all the way in one go with the one page checkout. def object_params @@ -94,7 +94,7 @@ class CheckoutController < Spree::CheckoutController def skip_state_validation? true end - + def load_order @order = current_order redirect_to main_app.shop_path and return unless @order and @order.checkout_allowed? @@ -112,6 +112,14 @@ class CheckoutController < Spree::CheckoutController @order.ship_address ||= preferred_ship_address || last_used_ship_address || Spree::Address.default end + def after_payment + # object_params sets the payment amount to the order total, but it does this before + # the shipping method is set. This results in the customer not being charged for their + # order's shipping. To fix this, we refresh the payment amount here. + @order.update_totals + @order.payments.first.update_attribute :amount, @order.total + end + # Overriding Spree's methods def raise_insufficient_quantity flash[:error] = t(:spree_inventory_error_flash_for_insufficient_quantity) diff --git a/app/helpers/spree/admin/navigation_helper_decorator.rb b/app/helpers/spree/admin/navigation_helper_decorator.rb index 024f467154..eb210ef482 100644 --- a/app/helpers/spree/admin/navigation_helper_decorator.rb +++ b/app/helpers/spree/admin/navigation_helper_decorator.rb @@ -8,6 +8,7 @@ module Spree klass = klass_for_without_sym_fallback(name) klass ||= name.singularize.to_sym klass = :overview if klass == :dashboard + klass = Spree::Order if klass == :bulk_order_management klass end alias_method_chain :klass_for, :sym_fallback diff --git a/app/models/enterprise_relationship.rb b/app/models/enterprise_relationship.rb index dba99cc7b3..ff2c1fe3fa 100644 --- a/app/models/enterprise_relationship.rb +++ b/app/models/enterprise_relationship.rb @@ -1,7 +1,7 @@ class EnterpriseRelationship < ActiveRecord::Base belongs_to :parent, class_name: 'Enterprise', touch: true belongs_to :child, class_name: 'Enterprise', touch: true - has_many :permissions, class_name: 'EnterpriseRelationshipPermission' + has_many :permissions, class_name: 'EnterpriseRelationshipPermission', dependent: :destroy validates_presence_of :parent_id, :child_id validates_uniqueness_of :child_id, scope: :parent_id, message: "^That relationship is already established." diff --git a/app/models/spree/ability_decorator.rb b/app/models/spree/ability_decorator.rb index 9f9c96cb15..79019f3e8a 100644 --- a/app/models/spree/ability_decorator.rb +++ b/app/models/spree/ability_decorator.rb @@ -59,12 +59,12 @@ class AbilityDecorator # Enterprise User can only access orders that they are a distributor for can [:index, :create], Spree::Order - can [:read, :update, :bulk_management, :fire, :resend], Spree::Order do |order| + can [:read, :update, :fire, :resend], Spree::Order do |order| # We allow editing orders with a nil distributor as this state occurs # during the order creation process from the admin backend order.distributor.nil? || user.enterprises.include?(order.distributor) end - can [:admin], Spree::Order if user.admin? || user.enterprises.any?(&:is_distributor?) + can [:admin, :bulk_management], Spree::Order if user.admin? || user.enterprises.any?(&:is_distributor?) can [:admin, :create], Spree::LineItem can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Payment diff --git a/app/serializers/api/enterprise_serializer.rb b/app/serializers/api/enterprise_serializer.rb index 850c88ad15..c76cffd7d1 100644 --- a/app/serializers/api/enterprise_serializer.rb +++ b/app/serializers/api/enterprise_serializer.rb @@ -17,6 +17,9 @@ end class Api::UncachedEnterpriseSerializer < ActiveModel::Serializer attributes :orders_close_at, :active + #TODO: Remove these later + attributes :icon, :has_shopfront, :can_aggregate + def orders_close_at OrderCycle.first_closing_for(object).andand.orders_close_at end @@ -24,16 +27,52 @@ class Api::UncachedEnterpriseSerializer < ActiveModel::Serializer def active @options[:active_distributors].andand.include? object end + + # TODO: Move this back to uncached section when relavant properties are defined on the Enterprise model + def icon + # TODO: Replace with object.has_shopfront when this property exists + if has_shopfront + if can_aggregate + "/assets/map_005-hub.svg" + else + if object.is_distributor + "/assets/map_003-producer-shop.svg" + else + "/assets/map_001-producer-only.svg" + end + end + else + if can_aggregate + "/assets/map_006-hub-profile.svg" + else + if object.is_distributor + "/assets/map_004-producer-shop-profile.svg" + else + "/assets/map_002-producer-only-profile.svg" + end + end + end + end + + # TODO: Remove this when flags on enterprises are switched over + def has_shopfront + object.type != 'profile' + end + + # TODO: Remove this when flags on enterprises are switched over + def can_aggregate + object.is_distributor && object.suppliers != [object] + end end class Api::CachedEnterpriseSerializer < ActiveModel::Serializer cached delegate :cache_key, to: :object - attributes :name, :id, :description, :latitude, :longitude, - :long_description, :website, :instagram, :linkedin, :twitter, + attributes :name, :id, :description, :latitude, :longitude, + :long_description, :website, :instagram, :linkedin, :twitter, :facebook, :is_primary_producer, :is_distributor, :phone, :visible, - :email, :hash, :logo, :promo_image, :icon, :path, + :email, :hash, :logo, :promo_image, :path, :pickup, :delivery has_many :distributed_taxons, key: :taxons, serializer: Api::IdSerializer @@ -67,16 +106,6 @@ class Api::CachedEnterpriseSerializer < ActiveModel::Serializer object.promo_image(:large) if object.promo_image.exists? end - def icon - if object.is_primary_producer? and object.is_distributor? - "/assets/map-icon-both.svg" - elsif object.is_primary_producer? - "/assets/map-icon-producer.svg" - else - "/assets/map-icon-hub.svg" - end - end - # TODO when ActiveSerializers supports URL helpers # Then refactor. See readme https://github.com/rails-api/active_model_serializers def path diff --git a/app/views/admin/enterprise_relationships/_enterprise_relationship.html.haml b/app/views/admin/enterprise_relationships/_enterprise_relationship.html.haml index 6a7dcdc7f4..45e79b1877 100644 --- a/app/views/admin/enterprise_relationships/_enterprise_relationship.html.haml +++ b/app/views/admin/enterprise_relationships/_enterprise_relationship.html.haml @@ -1,8 +1,10 @@ -%td {{ enterprise_relationship.child_name }} -%td - %ul - %li{"ng-repeat" => "permission in enterprise_relationship.permissions"} - {{ EnterpriseRelationships.permission_presentation(permission.name) }} -%td {{ enterprise_relationship.parent_name }} -%td.actions - %a.delete-enterprise-relationship.icon-trash.no-text{'ng-click' => 'delete(enterprise_relationship)'} +%tr{"ng-repeat" => "enterprise_relationship in EnterpriseRelationships.enterprise_relationships | filter:query"} + %td {{ enterprise_relationship.parent_name }} + %td permits + %td {{ enterprise_relationship.child_name }} + %td + %ul + %li{"ng-repeat" => "permission in enterprise_relationship.permissions"} + {{ EnterpriseRelationships.permission_presentation(permission.name) }} + %td.actions + %a.delete-enterprise-relationship.icon-trash.no-text{'ng-click' => 'delete(enterprise_relationship)'} diff --git a/app/views/admin/enterprise_relationships/_form.html.haml b/app/views/admin/enterprise_relationships/_form.html.haml index 86086c8781..9d031a57c5 100644 --- a/app/views/admin/enterprise_relationships/_form.html.haml +++ b/app/views/admin/enterprise_relationships/_form.html.haml @@ -1,4 +1,9 @@ %tr + %td + %select{name: "enterprise_relationship_parent_id", "ng-model" => "parent_id", "ng-options" => "e.id as e.name for e in Enterprises.my_enterprises"} + + %td + permits %td %select{name: "enterprise_relationship_child_id", "ng-model" => "child_id", "ng-options" => "e.id as e.name for e in Enterprises.all_enterprises"} %td @@ -6,8 +11,6 @@ %label %input{type: "checkbox", "ng-model" => "permissions[permission]"} {{ EnterpriseRelationships.permission_presentation(permission) }} - %td - %select{name: "enterprise_relationship_parent_id", "ng-model" => "parent_id", "ng-options" => "e.id as e.name for e in Enterprises.my_enterprises"} %td.actions %input{type: "button", value: "Create", "ng-click" => "create()"} .errors {{ EnterpriseRelationships.create_errors }} diff --git a/app/views/admin/enterprise_relationships/index.html.haml b/app/views/admin/enterprise_relationships/index.html.haml index e0e289efcf..0807a37825 100644 --- a/app/views/admin/enterprise_relationships/index.html.haml +++ b/app/views/admin/enterprise_relationships/index.html.haml @@ -11,5 +11,4 @@ %table#enterprise-relationships %tbody = render 'form' - %tr{"ng-repeat" => "enterprise_relationship in EnterpriseRelationships.enterprise_relationships | filter:query"} - = render 'enterprise_relationship' + = render 'enterprise_relationship' diff --git a/app/views/admin/enterprises/_form.html.haml b/app/views/admin/enterprises/_form.html.haml index 07be41dd6e..dbf986c7aa 100644 --- a/app/views/admin/enterprises/_form.html.haml +++ b/app/views/admin/enterprises/_form.html.haml @@ -36,24 +36,25 @@ = f.check_box :is_primary_producer, 'ng-model' => 'Enterprise.is_primary_producer'   = f.label :is_primary_producer, 'Producer' - .row - .alpha.eleven.columns - .three.columns.alpha - = f.label :type, 'Profile type' - .with-tip{'data-powertip' => "Full - enterprise may have products and relationships.
Single - enterprise may have products but no relationships.
Profile - enterprise has a profile but no products or relationships.
"} - %a What's this? - .two.columns - = f.radio_button :type, "full" -   - = f.label :type, "Full", value: "full" - .two.columns - = f.radio_button :type, "single" -   - = f.label :type, "Single", value: "single" - .four.columns.omega - = f.radio_button :type, "profile" -   - = f.label :type, "Profile", value: "profile" + - if spree_current_user.admin? + .row + .alpha.eleven.columns + .three.columns.alpha + = f.label :type, 'Profile type' + .with-tip{'data-powertip' => "Full - enterprise may have products and relationships.
Single - enterprise may have products but no relationships.
Profile - enterprise has a profile but no products or relationships.
"} + %a What's this? + .two.columns + = f.radio_button :type, "full" +   + = f.label :type, "Full", value: "full" + .two.columns + = f.radio_button :type, "single" +   + = f.label :type, "Single", value: "single" + .four.columns.omega + = f.radio_button :type, "profile" +   + = f.label :type, "Profile", value: "profile" .row .three.columns.alpha %label Visible in search? diff --git a/app/views/admin/enterprises/index.html.haml b/app/views/admin/enterprises/index.html.haml index 7ab6ea4d0e..c8b3cce3d4 100644 --- a/app/views/admin/enterprises/index.html.haml +++ b/app/views/admin/enterprises/index.html.haml @@ -10,17 +10,17 @@ = form_for @enterprise_set, :url => main_app.bulk_update_admin_enterprises_path do |f| %table#listing_enterprises.index %colgroup - %col{style: "width: 20%;"}/ + %col{style: "width: 25%;"}/ %col{style: "width: 10%;"}/ %col{style: "width: 5%;"}/ - %col/ + %col{style: "width: 10%;"}/ %col{style: "width: 20%;"}/ %thead %tr{"data-hook" => "enterprises_header"} %th Name %th Role %th Visible? - %th Description + %th Type %th %tbody = f.fields_for :collection do |enterprise_form| @@ -28,16 +28,13 @@ %tr{class: "enterprise-#{enterprise.id}"} %td= link_to enterprise.name, main_app.edit_admin_enterprise_path(enterprise) %td - - if enterprise.is_primary_producer && enterprise.is_distributor - Producer & Distributor - - elsif enterprise.is_distributor - Distributor - - elsif enterprise.is_primary_producer - Producer - - else - %h1.icon-exclamation-sign.with-tip{"data-powertip" => "This enterprise does not have any roles", style: "text-align: center;color: #DA5354"} + = enterprise_form.check_box :is_primary_producer + Producer + %br/ + = enterprise_form.check_box :is_distributor + Hub %td= enterprise_form.check_box :visible - %td= enterprise.description + %td= enterprise_form.select :type, Enterprise::TYPES, {}, class: 'select2 fullwidth' %td{"data-hook" => "admin_users_index_row_actions"} = render 'actions', enterprise: enterprise - if @enterprises.empty? diff --git a/app/views/checkout/_form.html.haml b/app/views/checkout/_form.html.haml index a64be0ac44..52f6f983cc 100644 --- a/app/views/checkout/_form.html.haml +++ b/app/views/checkout/_form.html.haml @@ -1,8 +1,8 @@ -= f_form_for current_order, url: main_app.update_checkout_path, += f_form_for current_order, html: {name: "checkout", id: "checkout_form", novalidate: true, - name: "checkout"} do |f| + "ng-submit" => "purchase($event)"} do |f| = inject_available_shipping_methods = inject_available_payment_methods @@ -20,7 +20,6 @@ = render partial: "checkout/payment", locals: {f: f} %p %button.button.primary{type: :submit, - "ng-click" => "purchase($event)", "ng-disabled" => "checkout.$invalid"} Place order now / {{ checkout.$valid }} diff --git a/app/views/home/_fat.html.haml b/app/views/home/_fat.html.haml index f3f74cb282..406431b9b7 100644 --- a/app/views/home/_fat.html.haml +++ b/app/views/home/_fat.html.haml @@ -6,7 +6,7 @@ %span.fat-taxons{"ng-repeat" => "taxon in hub.taxons"} %render-svg{path: "{{taxon.icon}}"} {{taxon.name}} - %div{"bo-if" => "!hub.taxons"} + %div.show-for-medium-up{"bo-if" => "hub.taxons.length==0"}   .columns.small-12.medium-3.large-2.fat %div{"bo-if" => "hub.pickup || hub.delivery"} @@ -27,5 +27,5 @@ %i.ofn-i_036-producers %span {{ enterprise.name }} - %div{"bo-if" => "!hub.producers"} + %div.show-for-medium-up{"bo-if" => "hub.producers.length==0"}   diff --git a/app/views/home/_hubs.html.haml b/app/views/home/_hubs.html.haml index 5669014bcf..e93e312fb7 100644 --- a/app/views/home/_hubs.html.haml +++ b/app/views/home/_hubs.html.haml @@ -2,7 +2,7 @@ #hubs.hubs{"ng-controller" => "HubsCtrl"} .row .small-12.columns - %h1 Find hubs in your area... + %h1 Shop your local area / %div / Shop a / %ofn-modal{title: "food hub"} @@ -14,7 +14,7 @@ / %i.ofn-i_020-search %input{type: :text, "ng-model" => "query", - placeholder: "Search by Hub or Suburb name", + placeholder: "Search by Shop or Suburb...", "ng-debounce" => "150", "ofn-disable-enter" => true} diff --git a/app/views/home/_skinny.html.haml b/app/views/home/_skinny.html.haml index 2b59132999..3c5654437c 100644 --- a/app/views/home/_skinny.html.haml +++ b/app/views/home/_skinny.html.haml @@ -1,23 +1,26 @@ .row.active_table_row{"ng-click" => "toggle()", "ng-class" => "{'closed' : !open()}", bindonce: true} .columns.small-12.medium-6.large-5.skinny-head %a.hub{"bo-href" => "hub.path", "ng-class" => "{primary: hub.active, secondary: !hub.active}", "ofn-empties-cart" => "hub"} - %i.ofn-i_040-hub - %span - %strong {{ hub.name | truncate:40}} + %i{ ng: { class: "{ 'ofn-i_063-hub': hub.can_aggregate && hub.has_shopfront, + 'ofn-i_059-producer': !hub.can_aggregate && hub.has_shopfront, + 'ofn-i_060-producer-reversed': !hub.can_aggregate && !hub.has_shopfront, + 'ofn-i_064-hub-reversed': hub.can_aggregate && !hub.has_shopfront }" } } + / %i.ofn-i_063-hub + %span.margin-top.hub-name-listing {{ hub.name | truncate:40}} .columns.small-4.medium-2.large-2 - {{ hub.address.city }} + %span.margin-top {{ hub.address.city }} .columns.small-2.medium-1.large-1 - {{ hub.address.state_name | uppercase }} + %span.margin-top {{ hub.address.state_name | uppercase }} .columns.small-6.medium-3.large-4.text-right{"bo-if" => "hub.active"} - %a.hub{"bo-href" => "hub.path", "ng-class" => "{primary: hub.active, secondary: !hub.active}", "ofn-empties-cart" => "hub"} + %a.hub.open_closed{"bo-href" => "hub.path", "ng-class" => "{primary: hub.active, secondary: !hub.active}", "ofn-empties-cart" => "hub"} %i.ofn-i_033-open-sign - %span {{ hub.orders_close_at | sensible_timeframe }} + %span.margin-top {{ hub.orders_close_at | sensible_timeframe }} .columns.small-6.medium-3.large-4.text-right{"bo-if" => "!hub.active"} - %a.hub{"bo-href" => "hub.path", "ng-class" => "{primary: hub.active, secondary: !hub.active}", "ofn-empties-cart" => "hub"} + %a.hub.open_closed{"bo-href" => "hub.path", "ng-class" => "{primary: hub.active, secondary: !hub.active}", "ofn-empties-cart" => "hub"} %i.ofn-i_032-closed-sign - %span Orders closed + %span.margin-top Orders closed diff --git a/app/views/home/index.html.haml b/app/views/home/index.html.haml index 63d2216052..36ee67998f 100644 --- a/app/views/home/index.html.haml +++ b/app/views/home/index.html.haml @@ -4,16 +4,17 @@ %h1= image_tag "ofn_logo_beta.png", title: "Open Food Network (beta)" %h2 An open marketplace that makes it easy to find, buy, sell and move sustainable local food. - %ofn-modal{title: "Learn more"} + %ofn-modal{title: "Learn more", "ng-cloak" => true} = render partial: "modals/learn_more" -= render partial: "home/hubs" +.ng-cloak + = render partial: "home/hubs" -/ = render partial: "home/map" + / = render partial: "home/map" -/ = render partial: "home/producers" + / = render partial: "home/producers" -/ = render partial: "home/groups" + / = render partial: "home/groups" = render partial: "home/beta" diff --git a/app/views/json/partials/_enterprise.rabl b/app/views/json/partials/_enterprise.rabl index d9fa11f529..5b52898482 100644 --- a/app/views/json/partials/_enterprise.rabl +++ b/app/views/json/partials/_enterprise.rabl @@ -22,10 +22,10 @@ end node :icon do |e| if e.is_primary_producer? and e.is_distributor? - image_path "map-icon-both.svg" + image_path "map_003-producer-shop.svg" elsif e.is_primary_producer? - image_path "map-icon-producer.svg" + image_path "map_001-producer-only.svg" else - image_path "map-icon-hub.svg" + image_path "map_005-hub.svg" end end diff --git a/app/views/producers/_fat.html.haml b/app/views/producers/_fat.html.haml index 042e39dba9..a8512c9a22 100644 --- a/app/views/producers/_fat.html.haml +++ b/app/views/producers/_fat.html.haml @@ -1,23 +1,61 @@ .row.active_table_row{"ng-show" => "open()", "ng-click" => "toggle()", "ng-class" => "{'open' : !ofn-i_032-closed-sign()}"} - .columns.small-12.medium-4.large-4.fat + + .columns.small-12.medium-7.large-7.fat + / No long description available because it spits out HTML formatting producer.long_description + %div{"bo-if" => "producer.long_description"} + %label About us + %img.right.show-for-medium-up{src: "{{ producer.logo }}" } + %p.text-small + {{ producer.long_description }} + %div.show-for-medium-up{"bo-if" => "producer.long_description.length==0"} + %label   + + .columns.small-12.medium-5.large-5.fat + %div{"ng-if" => "producer.supplied_taxons"} %label Shop for %p.trans-sentence %span.fat-taxons{"ng-repeat" => "taxon in producer.supplied_taxons"} %render-svg{path: "{{taxon.icon}}"} {{taxon.name}} + + %div.show-for-medium-up{"ng-if" => "producer.supplied_taxons.length==0"} +   - .columns.small-12.medium-3.large-3.fat - %div{"bo-if" => "producer.logo"} - %img{src: "{{ producer.logo }}" } + %div{"ng-if" => "producer.email || producer.website || producer.phone"} + %label Contact + + %p.word-wrap{"ng-if" => "producer.phone"} + Call {{ producer.phone }} - .columns.small-12.medium-5.large-5.fat - %div{"bo-if" => "producer.description"} - %label About us - %p.text-small - {{ producer.description }} + %p.word-wrap{"ng-if" => "producer.email"} + %a{"ng-href" => "{{producer.email | stripUrl}}", target: "_blank", mailto: true} + %span.email {{ producer.email | stripUrl }} -.row.active_table_row{"ng-show" => "open()", "bo-if" => "producer.hubs"} + %p.word-wrap{"ng-if" => "producer.website"} + %a{"ng-href" => "http://{{producer.website | stripUrl}}", target: "_blank" } + %span {{ producer.website | stripUrl }} + + %div{"ng-if" => "producer.twitter || producer.facebook || producer.linkedin || producer.instagram"} + %label Follow + .follow-icons{bindonce: true} + %span{"ng-if" => "producer.twitter"} + %a{"ng-href" => "http://twitter.com/{{producer.twitter}}", target: "_blank"} + %i.ofn-i_041-twitter + + %span{"ng-if" => "producer.facebook"} + %a{"ng-href" => "http://{{producer.facebook | stripUrl}}", target: "_blank"} + %i.ofn-i_044-facebook + + %span{"ng-if" => "producer.linkedin"} + %a{"ng-href" => "http://{{producer.linkedin | stripUrl}}", target: "_blank"} + %i.ofn-i_042-linkedin + + %span{"ng-if" => "producer.instagram"} + %a{"ng-href" => "http://instagram.com/{{producer.instagram}}", target: "_blank"} + %i.ofn-i_043-instagram + +.row.active_table_row.pad-top{"ng-show" => "open()", "bo-if" => "producer.hubs"} .columns.small-12 .row .columns.small-12.fat @@ -26,13 +64,15 @@ Shop for %span.turquoise {{ producer.name }} products at: + %div.show-for-medium-up{"bo-if" => "!producer.name"} +   .row.cta-container .columns.small-12 - %a.button.hub{"ng-repeat" => "hub in producer.hubs | orderBy:'-active'", + %a.cta-hub{"ng-repeat" => "hub in producer.hubs | orderBy:'-active'", "bo-href" => "hub.path", "ofn-empties-cart" => "hub", "bo-class" => "{primary: hub.active, secondary: !hub.active}"} %i.ofn-i_033-open-sign{"bo-if" => "hub.active"} %i.ofn-i_032-closed-sign{"bo-if" => "!hub.active"} - {{hub.name}} + .hub-name {{hub.name}} .button-address {{ [hub.address.city, hub.address.state_name] | printArray }} - %i.ofn-i_007-caret-right + diff --git a/app/views/producers/_skinny.html.haml b/app/views/producers/_skinny.html.haml index e1f26f0304..a5d6b790fc 100644 --- a/app/views/producers/_skinny.html.haml +++ b/app/views/producers/_skinny.html.haml @@ -1,12 +1,13 @@ .row.active_table_row{"ng-click" => "toggle()", "ng-class" => "{'closed' : !open()}"} .columns.small-12.medium-4.large-4.skinny-head - %i.ofn-i_036-producers - %strong {{ producer.name }} + / This needs logic to show profile only icon when available %i.ofn-i_060-producer-reversed + %i.ofn-i_059-producer + %span.margin-top + %strong {{ producer.name }} .columns.small-6.medium-3.large-3 - {{ producer.address.city }} + %span.margin-top {{ producer.address.city }} .columns.small-4.medium-3.large-4 - {{ producer.address.state_name | uppercase }} + %span.margin-top {{ producer.address.state_name | uppercase }} .columns.small-2.medium-2.large-1.text-right - / This forces line-height to be triggered - %span   - %i{"ng-class" => "{'ofn-i_005-caret-down' : !open(), 'ofn-i_006-caret-up' : open()}"} + %span.margin-top + %i{"ng-class" => "{'ofn-i_005-caret-down' : !open(), 'ofn-i_006-caret-up' : open()}"} diff --git a/app/views/producers/index.html.haml b/app/views/producers/index.html.haml index 1a2c827068..b8645f936a 100644 --- a/app/views/producers/index.html.haml +++ b/app/views/producers/index.html.haml @@ -13,7 +13,7 @@ .small-12.columns %input.animate-show{type: :text, "ng-model" => "query", - placeholder: "Search by Producer or Suburb name", + placeholder: "Search by Producer or Suburb...", "ng-debounce" => "150", "ofn-disable-enter" => true} diff --git a/app/views/shared/components/_filter_controls.html.haml b/app/views/shared/components/_filter_controls.html.haml index 55b7ef1adb..d35727c087 100644 --- a/app/views/shared/components/_filter_controls.html.haml +++ b/app/views/shared/components/_filter_controls.html.haml @@ -1,5 +1,5 @@ .row - .small-12.columns + .small-12.medium-6.columns %a.button.success.tiny.filterbtn{"ng-click" => "filtersActive = !filtersActive", "ng-show" => "FilterSelectorsService.selectors.length > 0"} {{ filterText(filtersActive) }} @@ -8,3 +8,12 @@ %a.button.secondary.tiny.filterbtn.disabled{"ng-show" => "FilterSelectorsService.selectors.length == 0"} No filters + .small-12.medium-6.columns.text-right + .profile-checkbox + + / Hide until we're ready to work on this: + + / %input{type: "checkbox", name: "profile"}>< + / %label Show profiles + / %button.button.secondary.tiny.help-btn.ng-scope{:popover => "Profiles do not have a shopfront on the Open Food Network, but they may have their own physical or online shop elsewhere", "popover-placement" => "left"}>< + / %i.ofn-i_013-help diff --git a/app/views/shared/menu/_large_menu.html.haml b/app/views/shared/menu/_large_menu.html.haml index 22618b50c4..71f297dede 100644 --- a/app/views/shared/menu/_large_menu.html.haml +++ b/app/views/shared/menu/_large_menu.html.haml @@ -32,10 +32,10 @@ - else = render 'shared/signed_in' %li.divider - %li.current_hub{"ng-controller" => "CurrentHubCtrl", "ng-show" => "CurrentHub.hub.id"} + %li.current_hub{"ng-controller" => "CurrentHubCtrl", "ng-show" => "CurrentHub.hub.id", "ng-cloak" => true} %a{href: main_app.shop_path} %em Shopping @ %span.nav-primary.nav-branded {{ CurrentHub.hub.name }} %li.divider - %li.cart + %li.cart{"ng-cloak" => true} = render partial: "shared/menu/cart" diff --git a/db/schema.rb b/db/schema.rb index dbb50d6b33..462e89c952 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -563,9 +563,9 @@ ActiveRecord::Schema.define(:version => 20140826043521) do t.string "email" t.text "special_instructions" t.integer "distributor_id" - t.integer "order_cycle_id" t.string "currency" t.string "last_ip_address" + t.integer "order_cycle_id" t.integer "cart_id" end diff --git a/public/OFN.eot b/public/OFN.eot index 5839e08963..0329e7ac1e 100755 Binary files a/public/OFN.eot and b/public/OFN.eot differ diff --git a/public/OFN.svg b/public/OFN.svg index f92225f1cd..a50fcc7687 100755 --- a/public/OFN.svg +++ b/public/OFN.svg @@ -4,65 +4,77 @@ Generated by IcoMoon - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/OFN.ttf b/public/OFN.ttf index cac7377e06..51423d3860 100755 Binary files a/public/OFN.ttf and b/public/OFN.ttf differ diff --git a/public/OFN.woff b/public/OFN.woff index 4ccf9c6192..e58fda0e07 100755 Binary files a/public/OFN.woff and b/public/OFN.woff differ diff --git a/spec/archive/features/consumer/checkout_spec.rb b/spec/archive/features/consumer/checkout_spec.rb index 9641085c39..74a2443b36 100644 --- a/spec/archive/features/consumer/checkout_spec.rb +++ b/spec/archive/features/consumer/checkout_spec.rb @@ -7,7 +7,7 @@ feature %q{ }, skip: true do include AuthenticationWorkflow include WebHelper - + background do set_feature_toggle :order_cycles, true @@ -24,8 +24,8 @@ feature %q{ :state => Spree::State.find_by_name('Victoria'), :country => Spree::Country.find_by_name('Australia')), :pickup_times => 'Tuesday, 4 PM') - - + + @distributor_alternative = create(:distributor_enterprise, :name => 'Alternative Distributor', :address => create(:address, :address1 => '1600 Rathdowne St', @@ -33,7 +33,7 @@ feature %q{ :zipcode => 3054, :state => Spree::State.find_by_name('Victoria'), :country => Spree::Country.find_by_name('Australia')), - :pickup_times => 'Tuesday, 4 PM') + :pickup_times => 'Tuesday, 4 PM') @enterprise_fee_1 = create(:enterprise_fee, :name => 'Enterprise Fee One', :calculator => Spree::Calculator::PerItem.new) @enterprise_fee_1.calculator.set_preference :amount, 1 @@ -347,16 +347,16 @@ feature %q{ login_to_consumer_section click_link 'FruitAndVeg' - visit enterprise_path @distributor1 + visit enterprise_path @distributor1 click_link 'Bananas' click_button 'Add To Cart' - visit enterprise_path @distributor1 + visit enterprise_path @distributor1 click_link 'Zucchini' click_button 'Add To Cart' find('#checkout-link').click - + # And manually visit the old checkout visit "/checkout" @@ -389,7 +389,7 @@ feature %q{ # -- Checkout: Delivery page.should have_content "DELIVERY METHOD" order_charges = page.all("tbody#summary-order-charges tr").map {|row| row.all('td').map(&:text)}.take(2) - order_charges.should == [["Distribution:", "$51.00"]] + order_charges.should == [["Distribution:", "$51.00"]] click_checkout_continue_button @@ -403,7 +403,7 @@ feature %q{ # -- Checkout: Order complete page.should have_content 'Your order has been processed successfully' page.should have_content @payment_method_distributor_oc.description - page.should have_content @distributor_oc.name + page.should have_content @distributor_oc.name page.should have_selector 'tfoot#order-charges tr.total td', text: 'Distribution' page.should have_selector 'tfoot#order-charges tr.total td', text: '51.00' diff --git a/spec/controllers/admin/enterprises_controller_spec.rb b/spec/controllers/admin/enterprises_controller_spec.rb index 20482bef09..14faf26287 100644 --- a/spec/controllers/admin/enterprises_controller_spec.rb +++ b/spec/controllers/admin/enterprises_controller_spec.rb @@ -36,5 +36,67 @@ module Admin admin_user.enterprise_roles.where(enterprise_id: enterprise).should be_empty end end + + describe "updating an enterprise" do + let(:profile_enterprise) { create(:enterprise, type: 'profile') } + + context "as manager" do + it "does not allow 'type' to be changed" do + profile_enterprise.enterprise_roles.build(user: user).save + controller.stub spree_current_user: user + enterprise_params = { id: profile_enterprise.id, enterprise: { type: 'full' } } + + spree_put :update, enterprise_params + profile_enterprise.reload + expect(profile_enterprise.type).to eq 'profile' + end + end + + context "as super admin" do + it "allows 'type' to be changed" do + controller.stub spree_current_user: admin_user + enterprise_params = { id: profile_enterprise.id, enterprise: { type: 'full' } } + + spree_put :update, enterprise_params + profile_enterprise.reload + expect(profile_enterprise.type).to eq 'full' + end + end + end + + describe "bulk updating enterprises" do + let(:profile_enterprise1) { create(:enterprise, type: 'profile') } + let(:profile_enterprise2) { create(:enterprise, type: 'profile') } + + context "as manager" do + it "does not allow 'type' to be changed" do + profile_enterprise1.enterprise_roles.build(user: user).save + profile_enterprise2.enterprise_roles.build(user: user).save + controller.stub spree_current_user: user + bulk_enterprise_params = { enterprise_set: { collection_attributes: { '0' => { id: profile_enterprise1.id, type: 'full' }, '1' => { id: profile_enterprise2.id, type: 'full' } } } } + + spree_put :bulk_update, bulk_enterprise_params + profile_enterprise1.reload + profile_enterprise2.reload + expect(profile_enterprise1.type).to eq 'profile' + expect(profile_enterprise2.type).to eq 'profile' + end + end + + context "as super admin" do + it "allows 'type' to be changed" do + profile_enterprise1.enterprise_roles.build(user: user).save + profile_enterprise2.enterprise_roles.build(user: user).save + controller.stub spree_current_user: admin_user + bulk_enterprise_params = { enterprise_set: { collection_attributes: { '0' => { id: profile_enterprise1.id, type: 'full' }, '1' => { id: profile_enterprise2.id, type: 'full' } } } } + + spree_put :bulk_update, bulk_enterprise_params + profile_enterprise1.reload + profile_enterprise2.reload + expect(profile_enterprise1.type).to eq 'full' + expect(profile_enterprise2.type).to eq 'full' + end + end + end end end diff --git a/spec/features/admin/bulk_order_management_spec.rb b/spec/features/admin/bulk_order_management_spec.rb index a8fe6cbda7..fe18f1a9bf 100644 --- a/spec/features/admin/bulk_order_management_spec.rb +++ b/spec/features/admin/bulk_order_management_spec.rb @@ -15,13 +15,6 @@ feature %q{ admin_user = quick_login_as_admin 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" - end - it "displays a message when number of line items is zero" do visit '/admin/orders/bulk_management' page.should have_text "No orders found." @@ -586,6 +579,13 @@ feature %q{ quick_login_as @enterprise_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" + end + it "shows only line item from orders that I distribute, and not those that I supply" do visit '/admin/orders/bulk_management' diff --git a/spec/features/admin/enterprise_relationships_spec.rb b/spec/features/admin/enterprise_relationships_spec.rb index 7317f44066..bfc624bce5 100644 --- a/spec/features/admin/enterprise_relationships_spec.rb +++ b/spec/features/admin/enterprise_relationships_spec.rb @@ -24,10 +24,10 @@ feature %q{ # Then I should see the relationships within('table#enterprise-relationships') do - page.should have_relationship e1, e2, ['can add to order cycle'] - page.should have_relationship e2, e3, ['can manage the products of'] + page.should have_relationship e1, e2, ['to add to order cycle'] + page.should have_relationship e2, e3, ['to manage products'] page.should have_relationship e3, e4, - ['can add to order cycle', 'can manage the products of'] + ['to add to order cycle', 'to manage products'] end end @@ -39,13 +39,13 @@ feature %q{ visit admin_enterprise_relationships_path select 'One', from: 'enterprise_relationship_parent_id' - check 'can add to order cycle' - check 'can manage the products of' - uncheck 'can manage the products of' + check 'to add to order cycle' + check 'to manage products' + uncheck 'to manage products' select 'Two', from: 'enterprise_relationship_child_id' click_button 'Create' - page.should have_relationship e1, e2, ['can add to order cycle'] + page.should have_relationship e1, e2, ['to add to order cycle'] er = EnterpriseRelationship.where(parent_id: e1, child_id: e2).first er.should be_present er.permissions.map(&:name).should == ['add_to_order_cycle'] @@ -69,14 +69,13 @@ feature %q{ end.to change(EnterpriseRelationship, :count).by(0) end - scenario "deleting a relationship" do e1 = create(:enterprise, name: 'One') e2 = create(:enterprise, name: 'Two') - er = create(:enterprise_relationship, parent: e1, child: e2) + er = create(:enterprise_relationship, parent: e1, child: e2, permissions_list: [:add_to_order_cycle]) visit admin_enterprise_relationships_path - page.should have_relationship e1, e2 + page.should have_relationship e1, e2, ['to add to order cycle'] first("a.delete-enterprise-relationship").click @@ -118,8 +117,8 @@ feature %q{ private def have_relationship(parent, child, perms=[]) - perms = perms.join(' ') || 'permits' + perms = perms.join(' ') - have_table_row [child.name, perms, parent.name, ''] + have_table_row [parent.name, 'permits', child.name, perms, ''] end end diff --git a/spec/features/admin/enterprises_spec.rb b/spec/features/admin/enterprises_spec.rb index da32f92681..a824716d95 100644 --- a/spec/features/admin/enterprises_spec.rb +++ b/spec/features/admin/enterprises_spec.rb @@ -15,39 +15,43 @@ feature %q{ click_link 'Enterprises' within("tr.enterprise-#{s.id}") do - page.should have_content s.name - page.should have_content "Edit Profile" - page.should have_content "Delete" - page.should_not have_content "Payment Methods" - page.should_not have_content "Shipping Methods" - page.should have_content "Enterprise Fees" + expect(page).to have_content s.name + expect(page).to have_select "enterprise_set_collection_attributes_1_type" + expect(page).to have_content "Edit Profile" + expect(page).to have_content "Delete" + expect(page).to_not have_content "Payment Methods" + expect(page).to_not have_content "Shipping Methods" + expect(page).to have_content "Enterprise Fees" end within("tr.enterprise-#{d.id}") do - page.should have_content d.name - page.should have_content "Edit Profile" - page.should have_content "Delete" - page.should have_content "Payment Methods" - page.should have_content "Shipping Methods" - page.should have_content "Enterprise Fees" + expect(page).to have_content d.name + expect(page).to have_select "enterprise_set_collection_attributes_0_type" + expect(page).to have_content "Edit Profile" + expect(page).to have_content "Delete" + expect(page).to have_content "Payment Methods" + expect(page).to have_content "Shipping Methods" + expect(page).to have_content "Enterprise Fees" end end scenario "editing enterprises in bulk" do s = create(:supplier_enterprise) - d = create(:distributor_enterprise) + d = create(:distributor_enterprise, type: 'profile') login_to_admin_section click_link 'Enterprises' within("tr.enterprise-#{d.id}") do - page.should have_checked_field "enterprise_set_collection_attributes_0_visible" + expect(page).to have_checked_field "enterprise_set_collection_attributes_0_visible" uncheck "enterprise_set_collection_attributes_0_visible" + select 'full', from: "enterprise_set_collection_attributes_0_type" end click_button "Update" flash_message.should == 'Enterprises updated successfully' distributor = Enterprise.find(d.id) - distributor.visible.should == false + expect(distributor.visible).to eq false + expect(distributor.type).to eq 'full' end scenario "viewing an enterprise" do @@ -127,7 +131,7 @@ feature %q{ choose 'Single' 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.' - + # Check Angularjs switching of sidebar elements uncheck 'enterprise_is_primary_producer' uncheck 'enterprise_is_distributor' @@ -259,10 +263,22 @@ feature %q{ click_link "Enterprises" - page.should have_content supplier1.name - page.should have_content distributor1.name - page.should_not have_content supplier2.name - page.should_not have_content distributor2.name + within("tr.enterprise-#{distributor1.id}") do + expect(page).to have_content distributor1.name + expect(page).to have_checked_field "enterprise_set_collection_attributes_0_is_distributor" + expect(page).to have_unchecked_field "enterprise_set_collection_attributes_0_is_primary_producer" + expect(page).to have_select "enterprise_set_collection_attributes_0_type" + end + + within("tr.enterprise-#{supplier1.id}") do + expect(page).to have_content supplier1.name + expect(page).to have_unchecked_field "enterprise_set_collection_attributes_1_is_distributor" + expect(page).to have_checked_field "enterprise_set_collection_attributes_1_is_primary_producer" + expect(page).to have_select "enterprise_set_collection_attributes_1_type" + end + + expect(page).to_not have_content "supplier2.name" + expect(page).to_not have_content "distributor2.name" end scenario "creating an enterprise" do diff --git a/spec/features/consumer/shopping/checkout_spec.rb b/spec/features/consumer/shopping/checkout_spec.rb index b26e924495..ab53befda5 100644 --- a/spec/features/consumer/shopping/checkout_spec.rb +++ b/spec/features/consumer/shopping/checkout_spec.rb @@ -94,10 +94,6 @@ feature "As a consumer I want to check out my cart", js: true do describe "purchasing" do it "takes us to the order confirmation page when we submit a complete form" do - toggle_shipping - choose sm2.name - toggle_payment - choose pm1.name toggle_details within "#details" do fill_in "First Name", with: "Will" @@ -112,14 +108,25 @@ feature "As a consumer I want to check out my cart", js: true do select "Victoria", from: "State" fill_in "City", with: "Melbourne" fill_in "Postcode", with: "3066" - end + toggle_shipping + within "#shipping" do + choose sm2.name + fill_in 'Any notes or custom delivery instructions?', with: "SpEcIaL NoTeS" + end + toggle_payment + within "#payment" do + choose pm1.name + end + place_order page.should have_content "Your order has been processed successfully" ActionMailer::Base.deliveries.length.should == 2 email = ActionMailer::Base.deliveries.last site_name = Spree::Config[:site_name] email.subject.should include "#{site_name} Order Confirmation" + o = Spree::Order.complete.first + expect(o.special_instructions).to eq "SpEcIaL NoTeS" end context "with basic details filled" do @@ -152,6 +159,20 @@ feature "As a consumer I want to check out my cart", js: true do page.should have_content "Your order has been processed successfully" end + context "when we are charged a shipping fee" do + before { choose sm2.name } + + it "creates a payment for the full amount inclusive of shipping" do + place_order + page.should have_content "Your order has been processed successfully" + + # There are two orders - our order and our new cart + o = Spree::Order.complete.first + o.adjustments.shipping.first.amount.should == 4.56 + o.payments.first.amount.should == 10 + 1.23 + 4.56 # items + fees + shipping + end + end + context "with a credit card payment method" do let!(:pm1) { create(:payment_method, distributors: [distributor], name: "Roger rabbit", type: "Spree::Gateway::Bogus") } @@ -167,7 +188,7 @@ feature "As a consumer I want to check out my cart", js: true do # Order should have a payment with the correct amount o = Spree::Order.complete.first - o.payments.first.amount.should == 11.23 + o.payments.first.amount.should == 15.79 end it "shows the payment processing failed message when submitted with an invalid credit card" do diff --git a/spec/helpers/navigation_helper_spec.rb b/spec/helpers/navigation_helper_spec.rb index 41decd6e5a..76fe9573f2 100644 --- a/spec/helpers/navigation_helper_spec.rb +++ b/spec/helpers/navigation_helper_spec.rb @@ -15,6 +15,10 @@ module Spree it "returns :overview for the dashboard" do helper.klass_for('dashboard').should == :overview end + + it "returns Spree::Order for bulk_order_management" do + helper.klass_for('bulk_order_management').should == Spree::Order + end end end end diff --git a/spec/lib/spree/product_filters_spec.rb b/spec/lib/spree/product_filters_spec.rb index 0e240a5479..5573ef0407 100644 --- a/spec/lib/spree/product_filters_spec.rb +++ b/spec/lib/spree/product_filters_spec.rb @@ -4,7 +4,9 @@ describe Spree::ProductFilters do context "distributor filter" do it "provides filtering for all distributors" do 3.times { create(:distributor_enterprise) } - Spree::ProductFilters.distributor_filter[:labels].should == Enterprise.is_distributor.sort.map { |d| [d.name, d.name] } + Enterprise.is_distributor.sort.map { |d| [d.name, d.name] }.each do |distributor| + expect(Spree::ProductFilters.distributor_filter[:labels]).to include distributor + end end end end diff --git a/spec/serializers/enterprise_serializer_spec.rb b/spec/serializers/enterprise_serializer_spec.rb index 8072862e72..5fe57a99e2 100644 --- a/spec/serializers/enterprise_serializer_spec.rb +++ b/spec/serializers/enterprise_serializer_spec.rb @@ -16,6 +16,6 @@ describe Api::EnterpriseSerializer do it "will render urls" do serializer = Api::EnterpriseSerializer.new enterprise - serializer.to_json.should match "map-icon-hub.svg" + serializer.to_json.should match "map_005-hub.svg" end end