diff --git a/app/assets/javascripts/admin/enterprises/controllers/enterprise_index_row_controller.js.coffee b/app/assets/javascripts/admin/enterprises/controllers/enterprise_index_row_controller.js.coffee index 226438c434..63b8daf07c 100644 --- a/app/assets/javascripts/admin/enterprises/controllers/enterprise_index_row_controller.js.coffee +++ b/app/assets/javascripts/admin/enterprises/controllers/enterprise_index_row_controller.js.coffee @@ -1,14 +1,11 @@ angular.module("admin.enterprises").controller "EnterpriseIndexRowCtrl", ($scope) -> - $scope.statusText = -> - issueCount = (issue for issue in $scope.enterprise.issues when !issue.resolved).length - if issueCount > 0 - $scope.statusClass = "issue" + $scope.status = -> + if $scope.enterprise.issues.length > 0 + "issue" + else if $scope.enterprise.warnings.length > 0 + "warning" else - warningCount = (warning for warning in $scope.enterprise.warnings when !warning.resolved).length - if warningCount > 0 - $scope.statusClass = "warning" - else - $scope.statusClass = "ok" + "ok" $scope.producerText = -> @@ -42,7 +39,6 @@ angular.module("admin.enterprises").controller "EnterpriseIndexRowCtrl", ($scope $scope.updateRowText = -> $scope.producer = $scope.producerText() $scope.package = $scope.packageText() - $scope.status = $scope.statusText() $scope.producerError = ($scope.producer == "Choose") $scope.packageError = ($scope.package == "Choose") diff --git a/app/assets/javascripts/admin/enterprises/controllers/index_status_panel_controller.js.coffee b/app/assets/javascripts/admin/enterprises/controllers/index_status_panel_controller.js.coffee index 7a0765e29b..987a206bd0 100644 --- a/app/assets/javascripts/admin/enterprises/controllers/index_status_panel_controller.js.coffee +++ b/app/assets/javascripts/admin/enterprises/controllers/index_status_panel_controller.js.coffee @@ -1,3 +1,3 @@ angular.module("admin.enterprises").controller 'indexStatusPanelCtrl', ($scope, $filter) -> - $scope.issues = $filter('filter')($scope.object.issues, {resolved: false }) - $scope.warnings = $filter('filter')($scope.object.warnings, {resolved: false}) + $scope.issues = $scope.object.issues + $scope.warnings = $scope.object.warnings diff --git a/app/assets/javascripts/admin/index_utils/directives/panel_toggle.js.coffee b/app/assets/javascripts/admin/index_utils/directives/panel_toggle.js.coffee index 3641e43870..df81328905 100644 --- a/app/assets/javascripts/admin/index_utils/directives/panel_toggle.js.coffee +++ b/app/assets/javascripts/admin/index_utils/directives/panel_toggle.js.coffee @@ -1,7 +1,7 @@ angular.module("admin.indexUtils").directive "panelToggle", -> restrict: "C" transclude: true - template: '
' + template: '' require: "^panelToggleRow" scope: name: "@" diff --git a/app/assets/javascripts/darkswarm/directives/filter_selector.js.coffee b/app/assets/javascripts/darkswarm/directives/filter_selector.js.coffee index 95aee1b413..818af3b785 100644 --- a/app/assets/javascripts/darkswarm/directives/filter_selector.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/filter_selector.js.coffee @@ -22,17 +22,11 @@ Darkswarm.directive "filterSelector", (FilterSelectorsService)-> .map (selector)-> selector.object.id - # This can be called from a parent scope - # when data has been loaded, in order to pass - # selectors up - scope.$on 'loadFilterSelectors', -> - scope.allSelectors = scope.selectors() if attr.allSelectors? - - scope.$watchCollection "selectors()", (newValue, oldValue) -> - scope.allSelectors = scope.selectors() if attr.allSelectors? + scope.$watchCollection "objects()", (newValue, oldValue) -> + scope.allSelectors = scope.buildSelectors() # Build a list of selectors - scope.selectors = -> + scope.buildSelectors = -> # Generate a selector for each object. # NOTE: THESE ARE MEMOIZED to stop new selectors from being created constantly, otherwise function always returns non-identical results # This means the $digest cycle can never close and times out diff --git a/app/assets/javascripts/templates/admin/panels/enterprise_status.html.haml b/app/assets/javascripts/templates/admin/panels/enterprise_status.html.haml index 63f416f091..39392a497d 100644 --- a/app/assets/javascripts/templates/admin/panels/enterprise_status.html.haml +++ b/app/assets/javascripts/templates/admin/panels/enterprise_status.html.haml @@ -1,5 +1,5 @@ .row.enterprise_status_panel{ ng: { controller: 'indexStatusPanelCtrl' } } - .alpha.sixteen.columns + .alpha.omega.sixteen.columns %h4.status-ok.text-center{ ng: { show: "issues.length == 0 && warnings.length == 0" } } %i.icon-ok-sign @@ -21,7 +21,7 @@ %td.resolve %div{ ng: { bind: { html: "issue.link" } } } %tr{ ng: { repeat: "warning in warnings"} } - %td.severity.text-center + %td.severity %i.icon-warning-sign.warning %td.description %span{ bo: { bind: "warning.description" } } diff --git a/app/assets/javascripts/templates/filter_selector.html.haml b/app/assets/javascripts/templates/filter_selector.html.haml index c6990c369f..a53c4f44db 100644 --- a/app/assets/javascripts/templates/filter_selector.html.haml +++ b/app/assets/javascripts/templates/filter_selector.html.haml @@ -1,4 +1,4 @@ -%div{bindonce:true, style: "display: inline-block" } +%ul{ bindonce: true } %active-selector{ ng: { repeat: "selector in allSelectors", show: "ifDefined(selector.fits, true)" } } %render-svg{path: "{{selector.object.icon}}", ng: { if: "selector.object.icon"} } %span{"bo-text" => "selector.object.name"} diff --git a/app/assets/javascripts/templates/product_modal.html.haml b/app/assets/javascripts/templates/product_modal.html.haml index 915bf3ea5e..481fa67c20 100644 --- a/app/assets/javascripts/templates/product_modal.html.haml +++ b/app/assets/javascripts/templates/product_modal.html.haml @@ -9,12 +9,10 @@ %br .filter-shopfront.taxon-selectors.inline-block - %ul - %filter-selector{ objects: "[product] | taxonsOf" } + %filter-selector{ objects: "[product] | taxonsOf" } .filter-shopfront.property-selectors.inline-block - %ul - %filter-selector{ objects: "[product] | propertiesWithValuesOf" } + %filter-selector{ objects: "[product] | propertiesWithValuesOf" } %div{"ng-if" => "product.description"} %hr diff --git a/app/assets/javascripts/templates/single_line_selectors.html.haml b/app/assets/javascripts/templates/single_line_selectors.html.haml index d54ce57bbb..d8d5ae6f3a 100644 --- a/app/assets/javascripts/templates/single_line_selectors.html.haml +++ b/app/assets/javascripts/templates/single_line_selectors.html.haml @@ -1,8 +1,8 @@ -%ul - -# In order for the single-line-selector scope to have access to the available selectors, - %filter-selector{objects: "objects()", "active-selectors" => "activeSelectors", "all-selectors" => "allSelectors" } +-# In order for the single-line-selector scope to have access to the available selectors, +%filter-selector{objects: "objects()", "active-selectors" => "activeSelectors", "all-selectors" => "allSelectors" } - %li.more{ ng: { show: "overFlowSelectors().length > 0 || fitting" } } +%ul{ ng: { if: "overFlowSelectors().length > 0 || fitting" } } + %li.more %a.dropdown{ data: { dropdown: "{{ 'show-more-' + selectorName }}" }, ng: { class: "{active: selectedOverFlowSelectors().length > 0}" } } %span + {{ overFlowSelectors().length }} more diff --git a/app/assets/stylesheets/admin/enterprise_index_panels.css.scss b/app/assets/stylesheets/admin/enterprise_index_panels.css.scss index 665a806ce8..2ce2916497 100644 --- a/app/assets/stylesheets/admin/enterprise_index_panels.css.scss +++ b/app/assets/stylesheets/admin/enterprise_index_panels.css.scss @@ -96,6 +96,8 @@ } td.severity { + text-align: center; + i { font-size: 1.5rem; diff --git a/app/assets/stylesheets/admin/index_panels.css.scss b/app/assets/stylesheets/admin/index_panels.css.scss index 8694c96dd6..a910e41d14 100644 --- a/app/assets/stylesheets/admin/index_panels.css.scss +++ b/app/assets/stylesheets/admin/index_panels.css.scss @@ -9,11 +9,12 @@ tr.panel-toggle-row { position: relative; - i { + i.icon-chevron::before { font-size: 1.2rem; + content: "\f078"; } - &::before { + &.error::before { font-family: FontAwesome; font-weight: normal; font-style: normal; @@ -24,23 +25,14 @@ tr.panel-toggle-row { right: 5px; font-size: 2rem; -webkit-font-smoothing: antialiased; - } - - &.error::before { content: "\f071"; color: #da5354; } &.status { - i.status::before { - font-family: FontAwesome; - font-weight: normal; - font-style: normal; - display: inline-block; - text-decoration: inherit; + i.icon-status::before { font-size: 1.5rem; opacity: 0.5; - -webkit-font-smoothing: antialiased; } i.issue::before { @@ -59,16 +51,6 @@ tr.panel-toggle-row { } } - &.selected { - background-color: #ffffff; - border-left: 2px solid #444444; - border-right: 2px solid #444444; - border-top: 2px solid #444444; - * { - color: #1b3c56; - } - } - &:hover { cursor: pointer; background-color: #d0e2f6; @@ -76,7 +58,7 @@ tr.panel-toggle-row { color: #1b3c56; } - i.status::before { + i.icon-status::before { opacity: 1.0; } } @@ -87,10 +69,27 @@ tr.panel-toggle-row { border-bottom: 2px solid #444444; &.selected { + background-color: #ffffff; + border-left: 2px solid #444444; + border-right: 2px solid #444444; + border-top: 2px solid #444444; border-bottom: none; + &:hover { background-color: #ffffff; } + + * { + color: #1b3c56; + } + + i.icon-status::before { + opacity: 1.0; + } + + i.icon-chevron::before { + content: "\f077"; + } } } } @@ -120,10 +119,6 @@ tr.panel-row { .column.alpha, .columns.alpha { padding-left: 20px; - - &.sixteen { - padding-right: 20px; - } } .column.omega, .columns.omega { diff --git a/app/assets/stylesheets/darkswarm/_shop-filters.css.sass b/app/assets/stylesheets/darkswarm/_shop-filters.css.sass index 3b31481ee1..cf80c63035 100644 --- a/app/assets/stylesheets/darkswarm/_shop-filters.css.sass +++ b/app/assets/stylesheets/darkswarm/_shop-filters.css.sass @@ -92,24 +92,23 @@ span.filter-label opacity: 0.75 -.filter-shopfront.taxon-selectors, .filter-shopfront.property-selectors - background: transparent - - single-line-selectors - overflow-x: hidden - white-space: nowrap - - .f-dropdown - overflow-x: auto - white-space: normal - - ul - margin: 0 - ul, ul li - list-style: none - - .filter-shopfront + &.taxon-selectors, &.property-selectors + background: transparent + + single-line-selectors + overflow-x: hidden + white-space: nowrap + + .f-dropdown + overflow-x: auto + white-space: normal + + ul + margin: 0 + display: inline-block + ul, ul li + list-style: none // Shopfront taxons &.taxon-selectors diff --git a/app/models/enterprise_relationship.rb b/app/models/enterprise_relationship.rb index de06a0578e..e6acc13332 100644 --- a/app/models/enterprise_relationship.rb +++ b/app/models/enterprise_relationship.rb @@ -32,6 +32,12 @@ class EnterpriseRelationship < ActiveRecord::Base relationships = EnterpriseRelationship.includes(:child, :parent) relatives = {} + Enterprise.all.each do |e| + relatives[e.id] ||= { distributors: Set.new, producers: Set.new } + relatives[e.id][:producers] << e.id if e.is_primary_producer + relatives[e.id][:distributors] << e.id if e.is_distributor + end + relationships.each do |r| relatives[r.parent_id] ||= {distributors: Set.new, producers: Set.new} relatives[r.child_id] ||= {distributors: Set.new, producers: Set.new} diff --git a/app/serializers/api/admin/index_enterprise_serializer.rb b/app/serializers/api/admin/index_enterprise_serializer.rb index a252557208..0f9166f4f8 100644 --- a/app/serializers/api/admin/index_enterprise_serializer.rb +++ b/app/serializers/api/admin/index_enterprise_serializer.rb @@ -23,32 +23,34 @@ class Api::Admin::IndexEnterpriseSerializer < ActiveModel::Serializer end def issues - [ - { - resolved: shipping_methods_ok?, - description: "#{object.name} currently has no shipping methods.", - link: "Create New" - }, - { - resolved: payment_methods_ok?, - description: "#{object.name} currently has no payment methods.", - link: "Create New" - }, - { - resolved: object.confirmed?, - description: "Email confirmation is pending. We've sent a confirmation email to #{object.email}.", - link: "Resend Email" - } - ] + issues = [] + + issues << { + description: "#{object.name} currently has no shipping methods.", + link: "Create New" + } unless shipping_methods_ok? + + issues << { + description: "#{object.name} currently has no payment methods.", + link: "Create New" + } unless payment_methods_ok? + + issues << { + description: "Email confirmation is pending. We've sent a confirmation email to #{object.email}.", + link: "Resend Email" + } unless object.confirmed? + + issues end def warnings - [ - { - resolved: object.visible, - description: "#{object.name} is not visible and so cannot be found on the map or in searches", - link: "Edit" - } - ] + warnings = [] + + warnings << { + description: "#{object.name} is not visible and so cannot be found on the map or in searches", + link: "Edit" + } unless object.visible + + warnings end end diff --git a/app/serializers/api/enterprise_serializer.rb b/app/serializers/api/enterprise_serializer.rb index 44364c4dbc..201757314f 100644 --- a/app/serializers/api/enterprise_serializer.rb +++ b/app/serializers/api/enterprise_serializer.rb @@ -89,12 +89,12 @@ class Api::CachedEnterpriseSerializer < ActiveModel::Serializer def producers relatives = options[:data].relatives[object.id] - relatives ? ids_to_objs(relatives[:producers]) : [] + ids_to_objs(relatives.andand[:producers]) end def hubs relatives = options[:data].relatives[object.id] - relatives ? ids_to_objs(relatives[:distributors]) : [] + ids_to_objs(relatives.andand[:distributors]) end # Map svg icons. @@ -139,6 +139,7 @@ class Api::CachedEnterpriseSerializer < ActiveModel::Serializer private def ids_to_objs(ids) - ids.andand.map { |id| {id: id} } + return [] if ids.blank? + ids.map { |id| {id: id} } end end diff --git a/app/views/admin/enterprises/_enterprise_user_index.html.haml b/app/views/admin/enterprises/_enterprise_user_index.html.haml index 3eaff9dc13..5f4ad6cca9 100644 --- a/app/views/admin/enterprises/_enterprise_user_index.html.haml +++ b/app/views/admin/enterprises/_enterprise_user_index.html.haml @@ -50,8 +50,8 @@ %h5{ ng: { bind: "producer" } } %td.package.panel-toggle.text-center{ ng: { show: 'columns.package.visible', class: "{error: packageError}" }, name: "package" } %h5{ ng: { bind: "package" } } - %td.status.panel-toggle.text-center{ ng: { show: 'columns.status.visible' }, bo: { class: "statusClass" }, name: "status" } - %i.status{ bo: { class: "status" } } + %td.status.panel-toggle.text-center{ ng: { show: 'columns.status.visible' }, name: "status" } + %i.icon-status{ bo: { class: "status" } } %td.manage{ ng: { show: 'columns.manage.visible' } } %a.button.fullwidth{ bo: { href: 'enterprise.edit_path' } } Manage diff --git a/app/views/home/_filters.html.haml b/app/views/home/_filters.html.haml index 6b339c13c9..365d87d8c2 100644 --- a/app/views/home/_filters.html.haml +++ b/app/views/home/_filters.html.haml @@ -1,22 +1,21 @@ .row - -# = render partial: 'shared/components/filter_controls' - .small-12.medium-6.columns + = render partial: 'shared/components/filter_controls' + -# .small-12.medium-6.columns = render partial: 'shared/components/show_profiles' --# .row.animate-show{"ng-show" => "filtersActive"} --# .small-12.columns --# .row.filter-box --# .small-12.large-9.columns --# %h5.tdhead --# .light Filter by --# Type --# %ul.small-block-grid-2.medium-block-grid-4.large-block-grid-5 --# %filter-selector{objects: "Enterprises.hubs | searchEnterprises:query | taxonsOf", "active-selectors" => "activeTaxons"} --# .small-12.large-3.columns --# %h5.tdhead --# .light Filter by --# Delivery --# %ul.small-block-grid-2.medium-block-grid-4.large-block-grid-2 --# %shipping-type-selector{results: "shippingTypes"} --# --# = render partial: 'shared/components/filter_box' +.row.animate-show{"ng-show" => "filtersActive"} + .small-12.columns + .row.filter-box + .small-12.large-9.columns + %h5.tdhead + .light Filter by + Type + %filter-selector.small-block-grid-2.medium-block-grid-4.large-block-grid-5{ objects: "Enterprises.hubs | searchEnterprises:query | taxonsOf", "active-selectors" => "activeTaxons" } + .small-12.large-3.columns + %h5.tdhead + .light Filter by + Delivery + %ul.small-block-grid-2.medium-block-grid-4.large-block-grid-2 + %shipping-type-selector{results: "shippingTypes"} + += render partial: 'shared/components/filter_box' diff --git a/app/views/producers/_filters.html.haml b/app/views/producers/_filters.html.haml index ec23c05b92..103b31d531 100644 --- a/app/views/producers/_filters.html.haml +++ b/app/views/producers/_filters.html.haml @@ -1,15 +1,14 @@ --# .row --# = render partial: 'shared/components/filter_controls' --# .small-12.medium-6.columns.text-right --# --# --# .row.animate-show{"ng-show" => "filtersActive"} --# .small-12.columns --# .row.filter-box --# .small-12.columns --# %h5.tdhead --# .light Filter by --# Type --# %ul.small-block-grid-2.medium-block-grid-4.large-block-grid-6 --# %filter-selector{objects: "Enterprises.producers | searchEnterprises:query | taxonsOf", "active-selectors" => "activeTaxons"} --# = render partial: 'shared/components/filter_box' +.row + = render partial: 'shared/components/filter_controls' + .small-12.medium-6.columns.text-right + + +.row.animate-show{"ng-show" => "filtersActive"} + .small-12.columns + .row.filter-box + .small-12.columns + %h5.tdhead + .light Filter by + Type + %filter-selector.small-block-grid-2.medium-block-grid-4.large-block-grid-6{objects: "Enterprises.producers | searchEnterprises:query | taxonsOf", "active-selectors" => "activeTaxons"} + = render partial: 'shared/components/filter_box' diff --git a/spec/lib/open_food_network/enterprise_injection_data_spec.rb b/spec/lib/open_food_network/enterprise_injection_data_spec.rb index cb94f2374a..ded13c9a6b 100644 --- a/spec/lib/open_food_network/enterprise_injection_data_spec.rb +++ b/spec/lib/open_food_network/enterprise_injection_data_spec.rb @@ -12,6 +12,11 @@ module OpenFoodNetwork it "only loads activated relatives" do subject.relatives[enterprise.id][:producers].should_not include producer_inactive.id end + + it "loads self where appropiate" do + subject.relatives[producer.id][:producers].should include producer.id + subject.relatives[enterprise.id][:distributors].should include enterprise.id + end end end end diff --git a/spec/models/enterprise_relationship_spec.rb b/spec/models/enterprise_relationship_spec.rb index c732d50849..fcdfa8b250 100644 --- a/spec/models/enterprise_relationship_spec.rb +++ b/spec/models/enterprise_relationship_spec.rb @@ -72,14 +72,20 @@ describe EnterpriseRelationship do describe "finding relatives" do let(:e1) { create(:supplier_enterprise) } - let(:e2) { create(:supplier_enterprise, sells: 'any') } + let(:e2) { create(:distributor_enterprise) } let!(:er) { create(:enterprise_relationship, parent: e1, child: e2) } let(:er_reverse) { create(:enterprise_relationship, parent: e2, child: e1) } + it "includes self where appropriate" do + EnterpriseRelationship.relatives[e2.id][:distributors].should include e2.id + EnterpriseRelationship.relatives[e2.id][:producers].should_not include e2.id + end + it "categorises enterprises into distributors and producers" do + e2.update_attribute :is_primary_producer, true EnterpriseRelationship.relatives.should == - {e1.id => {distributors: Set.new([e2.id]), producers: Set.new([e2.id])}, - e2.id => {distributors: Set.new([]), producers: Set.new([e1.id])}} + {e1.id => {distributors: Set.new([e2.id]), producers: Set.new([e1.id, e2.id])}, + e2.id => {distributors: Set.new([e2.id]), producers: Set.new([e2.id, e1.id])}} end it "finds inactive enterprises by default" do