diff --git a/.codeclimate.yml b/.codeclimate.yml new file mode 100644 index 0000000000..d737c0b3c9 --- /dev/null +++ b/.codeclimate.yml @@ -0,0 +1,13 @@ +engines: + rubocop: + enabled: true + scss-lint: + enabled: true +ratings: + paths: + - app/** + - lib/** + - "**.rb" +exclude_paths: +- spec/**/* +- vendor/**/* diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000000..2e70cbc53b --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,29 @@ +AllCops: + Include: + - '**/Rakefile' + - '**/config.ru' + Exclude: + - 'db/**/*' + - 'config/**/*' + - 'script/**/*' + - 'spec/**/*' + - !ruby/regexp /old_and_unused\.rb$/ + +Documentation: + Enabled: false + +Style/EmptyLinesAroundClassBody: + Enabled: false + +Style/BracesAroundHashParameters: + Enabled: false + +Metrics/LineLength: + Enabled: false + Max: 120 + +MethodLength: + Enabled: false + +StringLiterals: + Enabled: false diff --git a/.scss-lint.yml b/.scss-lint.yml new file mode 100644 index 0000000000..d90daf1407 --- /dev/null +++ b/.scss-lint.yml @@ -0,0 +1,3 @@ +scss_files: 'app/assets/stylesheets/**/*.css.scss' + +exclude: 'app/assets/stylesheets/shared/**' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 31ccc06991..6a43ed5f48 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,7 @@ # Contributing We love pull requests from everyone. Here are some instructions for -contributing code to Open Food Network. +contributing code to Open Food Network. See the [developer wiki](https://github.com/openfoodfoundation/openfoodnetwork/wiki) for more information. Fork, then clone the repo: diff --git a/README.markdown b/README.md similarity index 78% rename from README.markdown rename to README.md index 122e49c946..c572aae193 100644 --- a/README.markdown +++ b/README.md @@ -1,3 +1,4 @@ +[![Build Status](https://travis-ci.org/openfoodfoundation/openfoodnetwork.svg?branch=master)](https://travis-ci.org/openfoodfoundation/openfoodnetwork) [![Code Climate](https://codeclimate.com/github/openfoodfoundation/openfoodnetwork.png)](https://codeclimate.com/github/openfoodfoundation/openfoodnetwork) # Open Food Network @@ -14,10 +15,12 @@ We're part of global movement - get involved! ## Getting started -Below are instructions for setting up a development environment for Open Food Network. If you're interested in provisioning a server, see [the project's Ansible playbooks](https://github.com/openfoodfoundation/ofn_deployment). +Below are instructions for setting up a development environment for Open Food Network. More information is in the [developer wiki](https://github.com/openfoodfoundation/openfoodnetwork/wiki). + +If you're interested in provisioning a server, see [the project's Ansible playbooks](https://github.com/openfoodfoundation/ofn_deployment). -## Dependencies +### Dependencies * Rails 3.2.x * Ruby 2.1.5 @@ -26,7 +29,7 @@ Below are instructions for setting up a development environment for Open Food Ne * See Gemfile for a list of gems required -## Get it +### Get it The source code is managed with Git (a version control system) and hosted at GitHub. @@ -40,7 +43,7 @@ You can download the source with the command: git clone https://github.com/openfoodfoundation/openfoodnetwork.git -## Get it running +### Get it running For those new to Rails, the following tutorial will help get you up to speed with configuring a Rails environment: http://guides.rubyonrails.org/getting_started.html . @@ -58,6 +61,15 @@ Configure the site: cp config/application.yml.example config/application.yml edit config/application.yml +Create a PostgreSQL user: + +* Login as your system postrgresql priviledged user: `sudo -i -u postgres` (this may vary on your OS). Now your prompt looks like: `[postgres@your_host ~]$` +* Create the `ofn` database superuser and give it the password `f00d`: + +``` +createuser -s -P ofn +``` + Create the development and test databases, using the settings specified in `config/database.yml`, and populate them with a schema and seed data: rake db:setup @@ -71,7 +83,7 @@ At long last, your dreams of spinning up a development server can be realised: rails server -## Testing +### Testing Tests, both unit and integration, are based on RSpec. To run the test suite, first prepare the test database: @@ -97,6 +109,10 @@ usage instructions. * Will Marshall (http://soundcloud.com/willmarshall) * Laura Summers (https://github.com/summerscope) * Maikel Linke (https://github.com/mkllnk) +* Lynne Davis (https://github.com/lin-d-hop) +* Paul Mackay (https://github.com/pmackay) +* Steve Petitt (https://github.com/stveep) + ## Licence diff --git a/app/assets/javascripts/darkswarm/controllers/enterprises_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/enterprises_controller.js.coffee index 3883eca8d5..db995170dd 100644 --- a/app/assets/javascripts/darkswarm/controllers/enterprises_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/enterprises_controller.js.coffee @@ -1,9 +1,7 @@ Darkswarm.controller "EnterprisesCtrl", ($scope, $rootScope, $timeout, Enterprises, Search, $document, HashNavigation, FilterSelectorsService, EnterpriseModal, enterpriseMatchesNameQueryFilter, distanceWithinKmFilter) -> $scope.Enterprises = Enterprises - $scope.totalActive = FilterSelectorsService.totalActive - $scope.clearAll = FilterSelectorsService.clearAll - $scope.filterText = FilterSelectorsService.filterText - $scope.FilterSelectorsService = FilterSelectorsService + $scope.producers_to_filter = Enterprises.producers + $scope.filterSelectors = FilterSelectorsService.createSelectors() $scope.query = Search.search() $scope.openModal = EnterpriseModal.open $scope.activeTaxons = [] diff --git a/app/assets/javascripts/darkswarm/controllers/group_enterprises_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/group_enterprises_controller.js.coffee index ea652b8105..13c1017386 100644 --- a/app/assets/javascripts/darkswarm/controllers/group_enterprises_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/group_enterprises_controller.js.coffee @@ -1,8 +1,5 @@ Darkswarm.controller "GroupEnterprisesCtrl", ($scope, Search, FilterSelectorsService, EnterpriseModal) -> - $scope.totalActive = FilterSelectorsService.totalActive - $scope.clearAll = FilterSelectorsService.clearAll - $scope.filterText = FilterSelectorsService.filterText - $scope.FilterSelectorsService = FilterSelectorsService + $scope.filterSelectors = FilterSelectorsService.createSelectors() $scope.query = Search.search() $scope.openModal = EnterpriseModal.open $scope.activeTaxons = [] diff --git a/app/assets/javascripts/darkswarm/controllers/group_page_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/group_page_controller.js.coffee index 4e16b4d062..ed52f46bb7 100644 --- a/app/assets/javascripts/darkswarm/controllers/group_page_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/group_page_controller.js.coffee @@ -15,6 +15,8 @@ Darkswarm.controller "GroupPageCtrl", ($scope, group_enterprises, Enterprises, M $scope.group_hubs = visible_enterprises.filter (enterprise) -> enterprise.category in ["hub", "hub_profile", "producer_hub", "producer_shop"] + $scope.producers_to_filter = $scope.group_producers + $scope.map = angular.copy MapConfiguration.options $scope.mapMarkers = OfnMap.enterprise_markers visible_enterprises diff --git a/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee index 8443301765..4f149db1e5 100644 --- a/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee @@ -1,10 +1,8 @@ Darkswarm.controller "ProductsCtrl", ($scope, $rootScope, Products, OrderCycle, FilterSelectorsService, Cart, Taxons, Properties) -> $scope.Products = Products $scope.Cart = Cart - $scope.totalActive = FilterSelectorsService.totalActive - $scope.clearAll = FilterSelectorsService.clearAll - $scope.filterText = FilterSelectorsService.filterText - $scope.FilterSelectorsService = FilterSelectorsService + $scope.taxonSelectors = FilterSelectorsService.createSelectors() + $scope.propertySelectors = FilterSelectorsService.createSelectors() $scope.filtersActive = true $scope.limit = 3 $scope.order_cycle = OrderCycle.order_cycle @@ -33,4 +31,5 @@ Darkswarm.controller "ProductsCtrl", ($scope, $rootScope, Products, OrderCycle, $scope.clearAll = -> $scope.query = "" - FilterSelectorsService.clearAll() + $scope.taxonSelectors.clearAll() + $scope.propertySelectors.clearAll() diff --git a/app/assets/javascripts/darkswarm/directives/filter_selector.js.coffee b/app/assets/javascripts/darkswarm/directives/filter_selector.js.coffee index 818af3b785..2090c481f7 100644 --- a/app/assets/javascripts/darkswarm/directives/filter_selector.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/filter_selector.js.coffee @@ -1,9 +1,10 @@ -Darkswarm.directive "filterSelector", (FilterSelectorsService)-> +Darkswarm.directive "filterSelector", -> # Automatically builds activeSelectors for taxons # Lots of magic here restrict: 'E' replace: true scope: + selectorSet: '=' objects: "&" activeSelectors: "=?" allSelectors: "=?" # Optional @@ -36,7 +37,7 @@ Darkswarm.directive "filterSelector", (FilterSelectorsService)-> if selector = selectors_by_id[id] selectors.push selector else - selector = selectors_by_id[id] = FilterSelectorsService.new + selector = selectors_by_id[id] = scope.selectorSet.new object: object selectors.push selector selectors diff --git a/app/assets/javascripts/darkswarm/directives/shipping_type_selector.js.coffee b/app/assets/javascripts/darkswarm/directives/shipping_type_selector.js.coffee index 07656d84b7..15fda75820 100644 --- a/app/assets/javascripts/darkswarm/directives/shipping_type_selector.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/shipping_type_selector.js.coffee @@ -1,4 +1,4 @@ -Darkswarm.directive "shippingTypeSelector", (FilterSelectorsService)-> +Darkswarm.directive "shippingTypeSelector", -> # Builds selector for shipping types restrict: 'E' replace: true @@ -8,10 +8,10 @@ Darkswarm.directive "shippingTypeSelector", (FilterSelectorsService)-> pickup: false delivery: false - scope.selectors = - delivery: FilterSelectorsService.new + scope.selectors = + delivery: scope.filterSelectors.new icon: "ofn-i_039-delivery" - pickup: FilterSelectorsService.new + pickup: scope.filterSelectors.new icon: "ofn-i_038-takeaway" scope.emit = -> diff --git a/app/assets/javascripts/darkswarm/directives/single_line_selectors.coffee b/app/assets/javascripts/darkswarm/directives/single_line_selectors.coffee index 93896a41f9..ea5d8568d2 100644 --- a/app/assets/javascripts/darkswarm/directives/single_line_selectors.coffee +++ b/app/assets/javascripts/darkswarm/directives/single_line_selectors.coffee @@ -2,6 +2,7 @@ Darkswarm.directive 'singleLineSelectors', ($timeout, $filter) -> restrict: 'E' templateUrl: "single_line_selectors.html" scope: + selectors: "=" objects: "&" activeSelectors: "=" selectorName: "@activeSelectors" diff --git a/app/assets/javascripts/darkswarm/services/filter_selectors.js.coffee b/app/assets/javascripts/darkswarm/services/filter_selectors.js.coffee index ca80ae344c..e94a098b3a 100644 --- a/app/assets/javascripts/darkswarm/services/filter_selectors.js.coffee +++ b/app/assets/javascripts/darkswarm/services/filter_selectors.js.coffee @@ -1,8 +1,11 @@ +# Returns a factory with the only function `createSelectors()`. +# That function creates objects managing a list of filter selectors. Darkswarm.factory "FilterSelectorsService", -> # This stores all filters so we can access in-use counts etc - # Accessed via activeSelector Directive - new class FilterSelectorsService - selectors: [] + class FilterSelectors + constructor: -> + @selectors = [] + new: (obj = {})-> obj.active = false @selectors.push obj @@ -26,3 +29,8 @@ Darkswarm.factory "FilterSelectorsService", -> for selector in @selectors selector.active = false selector.emit() + + # Creates instances of `FilterSelectors` + new class FilterSelectorsService + createSelectors: -> + new FilterSelectors diff --git a/app/assets/javascripts/templates/shipping_type_selector.html.haml b/app/assets/javascripts/templates/shipping_type_selector.html.haml index 8feb23e59f..7774ab62c0 100644 --- a/app/assets/javascripts/templates/shipping_type_selector.html.haml +++ b/app/assets/javascripts/templates/shipping_type_selector.html.haml @@ -1,3 +1,4 @@ -%active-selector{"ng-repeat" => "(name, selector) in selectors"} - %i{"ng-class" => "selector.icon"} - {{ name | capitalize }} +%ul.small-block-grid-2.medium-block-grid-4.large-block-grid-2 + %active-selector{"ng-repeat" => "(name, selector) in selectors"} + %i{"ng-class" => "selector.icon"} + {{ name | capitalize }} diff --git a/app/assets/javascripts/templates/single_line_selectors.html.haml b/app/assets/javascripts/templates/single_line_selectors.html.haml index d8d5ae6f3a..0f5cdf0fa6 100644 --- a/app/assets/javascripts/templates/single_line_selectors.html.haml +++ b/app/assets/javascripts/templates/single_line_selectors.html.haml @@ -1,5 +1,5 @@ -# 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" } +%filter-selector{"selector-set" => "selectors", objects: "objects()", "active-selectors" => "activeSelectors", "all-selectors" => "allSelectors" } %ul{ ng: { if: "overFlowSelectors().length > 0 || fitting" } } %li.more diff --git a/app/assets/stylesheets/darkswarm/groups.css.sass b/app/assets/stylesheets/darkswarm/groups.css.sass index 97b984eb34..765689049d 100644 --- a/app/assets/stylesheets/darkswarm/groups.css.sass +++ b/app/assets/stylesheets/darkswarm/groups.css.sass @@ -11,6 +11,10 @@ background-size: 922px 922px @include sidepaddingSm @include panepadding + h1, p.text + font-weight: 300 + h1 + font-size: 350% a > .group-name &:hover, &:focus, &:active text-decoration: underline @@ -97,11 +101,13 @@ // Producers tab .producers background-image: none + background-color: initial .active_table .active_table_node a.is_distributor, .active_table .active_table_node a.is_distributor i.ofn-i_059-producer color: $clr-turquoise + padding: 0 // Hubs tab .hubs background-image: none padding-top: 0 padding-bottom: 0 - \ No newline at end of file + diff --git a/app/assets/stylesheets/darkswarm/modals.css.sass b/app/assets/stylesheets/darkswarm/modals.css.sass index 560153c5b1..5844a8b600 100644 --- a/app/assets/stylesheets/darkswarm/modals.css.sass +++ b/app/assets/stylesheets/darkswarm/modals.css.sass @@ -48,3 +48,7 @@ dialog .close-reveal-modal, .reveal-modal .close-reveal-modal &:hover, &:active, &:focus background-color: rgba(205,205,205,1) color: #333 + +// Prevent body from scrolling when a modal is open +body.modal-open + overflow: hidden diff --git a/app/helpers/injection_helper.rb b/app/helpers/injection_helper.rb index b3fa374607..6c35bc775f 100644 --- a/app/helpers/injection_helper.rb +++ b/app/helpers/injection_helper.rb @@ -6,7 +6,7 @@ module InjectionHelper end def inject_group_enterprises - inject_json_ams "group_enterprises", @group.enterprises, Api::EnterpriseSerializer, enterprise_injection_data + inject_json_ams "group_enterprises", @group.enterprises.activated.all, Api::EnterpriseSerializer, enterprise_injection_data end def inject_current_hub diff --git a/app/models/order_cycle.rb b/app/models/order_cycle.rb index 33851cfd65..03979220d6 100644 --- a/app/models/order_cycle.rb +++ b/app/models/order_cycle.rb @@ -16,7 +16,7 @@ class OrderCycle < ActiveRecord::Base scope :inactive, lambda { where('order_cycles.orders_open_at > ? OR order_cycles.orders_close_at < ?', Time.zone.now, Time.zone.now) } scope :upcoming, lambda { where('order_cycles.orders_open_at > ?', Time.zone.now) } scope :closed, lambda { where('order_cycles.orders_close_at < ?', Time.zone.now).order("order_cycles.orders_close_at DESC") } - scope :undated, where(orders_open_at: nil, orders_close_at: nil) + scope :undated, where('order_cycles.orders_open_at IS NULL OR orders_close_at IS NULL') scope :soonest_closing, lambda { active.order('order_cycles.orders_close_at ASC') } # TODO This method returns all the closed orders. So maybe we can replace it with :recently_closed. @@ -182,7 +182,7 @@ class OrderCycle < ActiveRecord::Base end def undated? - self.orders_open_at.nil? && self.orders_close_at.nil? + self.orders_open_at.nil? || self.orders_close_at.nil? end def upcoming? diff --git a/app/views/groups/_hub_filters.html.haml b/app/views/groups/_hub_filters.html.haml new file mode 100644 index 0000000000..71924d5e85 --- /dev/null +++ b/app/views/groups/_hub_filters.html.haml @@ -0,0 +1,21 @@ +.row + = render partial: 'shared/components/filter_controls' + = 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 + = t :hubs_filter_by + = t :hubs_filter_type + %filter-selector.small-block-grid-2.medium-block-grid-4.large-block-grid-5{"selector-set" => "filterSelectors", objects: "group_hubs | searchEnterprises:query | shipping:shippingTypes | showHubProfiles:show_profiles | taxonsOf", "active-selectors" => "activeTaxons"} + .small-12.large-3.columns + %h5.tdhead + .light + = t :hubs_filter_by + = t :hubs_filter_delivery + %shipping-type-selector + += render partial: 'shared/components/filter_box' diff --git a/app/views/groups/index.html.haml b/app/views/groups/index.html.haml index 19159bc63f..afb19e1b91 100644 --- a/app/views/groups/index.html.haml +++ b/app/views/groups/index.html.haml @@ -7,10 +7,14 @@ angular.module('Darkswarm').value('groups', #{render partial: "json/groups", object: @groups}) #groups.pad-top.footer-pad{"ng-controller" => "GroupsCtrl"} - #active-table-search.row.pad-top - .small-12.columns + .row + .small-12.medium-6.medium-offset-3.columns.text-center %h1 = t :groups_headline + %p.text + = t :groups_text + #active-table-search.row.pad-top + .small-12.columns %p %input{type: :text, "ng-model" => "query", diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index 4831a911a6..74588176b9 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -59,14 +59,13 @@ %h1 = t :groups_producers = render partial: "shared/components/enterprise_search" - -# TODO: find out why this is not working - -#= render partial: "producers/filters" + = render partial: "producers/filters" .row{bindonce: true} .small-12.columns .active_table %producer.active_table_node.row.animate-repeat{id: "{{producer.path}}", - "ng-repeat" => "producer in filteredEnterprises = (group_producers | visible | searchEnterprises:query | taxons:activeTaxons)", + "ng-repeat" => "producer in filteredEnterprises = (group_producers | searchEnterprises:query | taxons:activeTaxons)", "ng-controller" => "GroupEnterpriseNodeCtrl", "ng-class" => "{'closed' : !open(), 'open' : open(), 'inactive' : !producer.active}", id: "{{producer.hash}}"} @@ -87,17 +86,13 @@ = t :groups_hubs = render partial: "shared/components/enterprise_search" - -# TODO: find out why this is not working - -#= render partial: "home/filters" - .small-12.medium-6.columns - %span   - = render partial: 'shared/components/show_profiles' + = render partial: "hub_filters" .row{bindonce: true} .small-12.columns .active_table %hub.active_table_node.row.animate-repeat{id: "{{hub.hash}}", - "ng-repeat" => "hub in filteredEnterprises = (group_hubs | visible | searchEnterprises:query | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles | orderBy:['-active', '+orders_close_at'])", + "ng-repeat" => "hub in filteredEnterprises = (group_hubs | searchEnterprises:query | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles | orderBy:['-active', '+orders_close_at'])", "ng-class" => "{'is_profile' : hub.category == 'hub_profile', 'closed' : !open(), 'open' : open(), 'inactive' : !hub.active, 'current' : current()}", "ng-controller" => "GroupEnterpriseNodeCtrl"} .small-12.columns diff --git a/app/views/home/_filters.html.haml b/app/views/home/_filters.html.haml index bf4b1f8266..bfd13fdf54 100644 --- a/app/views/home/_filters.html.haml +++ b/app/views/home/_filters.html.haml @@ -11,13 +11,12 @@ .light = t :hubs_filter_by = t :hubs_filter_type - %filter-selector.small-block-grid-2.medium-block-grid-4.large-block-grid-5{ objects: "visibleMatches | visible | taxonsOf", "active-selectors" => "activeTaxons" } + %filter-selector.small-block-grid-2.medium-block-grid-4.large-block-grid-5{ "selector-set" => "filterSelectors", objects: "visibleMatches | visible | taxonsOf", "active-selectors" => "activeTaxons" } .small-12.large-3.columns %h5.tdhead .light = t :hubs_filter_by = t :hubs_filter_delivery - %ul.small-block-grid-2.medium-block-grid-4.large-block-grid-2 - %shipping-type-selector{results: "shippingTypes"} + %shipping-type-selector = render partial: 'shared/components/filter_box' diff --git a/app/views/layouts/darkswarm.html.haml b/app/views/layouts/darkswarm.html.haml index 0788286394..c758e4836e 100644 --- a/app/views/layouts/darkswarm.html.haml +++ b/app/views/layouts/darkswarm.html.haml @@ -3,7 +3,7 @@ %meta{charset: 'utf-8'}/ %meta{name: 'viewport', content: "width=device-width,initial-scale=1.0"}/ %meta{property: "og:title", content: content_for?(:title) ? yield(:title) : t(:title)} - %meta{property: "og:description", content: content_for?(:description) ? yield(:description) : t(:description)} + %meta{property: "og:description", content: content_for?(:description) ? yield(:description) : t(:site_meta_description)} %meta{property: "og:image", content: content_for?(:image) ? yield(:image) : ContentConfig.logo.url} %title= content_for?(:title) ? "#{yield(:title)} - #{t(:title)}".html_safe : "#{t(:welcome_to)} #{t(:title)}" - if Rails.env.production? diff --git a/app/views/producers/_filters.html.haml b/app/views/producers/_filters.html.haml index 40cf519450..97cc204cab 100644 --- a/app/views/producers/_filters.html.haml +++ b/app/views/producers/_filters.html.haml @@ -11,5 +11,5 @@ .light = t :producers_filter = t :producers_filter_type - %filter-selector.small-block-grid-2.medium-block-grid-4.large-block-grid-6{objects: "Enterprises.producers | searchEnterprises:query | taxonsOf", "active-selectors" => "activeTaxons"} + %filter-selector.small-block-grid-2.medium-block-grid-4.large-block-grid-6{"selector-set" => "filterSelectors", objects: "producers_to_filter | searchEnterprises:query | taxonsOf", "active-selectors" => "activeTaxons"} = render partial: 'shared/components/filter_box' diff --git a/app/views/shared/_footer.html.haml b/app/views/shared/_footer.html.haml index 22f1d426cc..fd7f5faf4e 100644 --- a/app/views/shared/_footer.html.haml +++ b/app/views/shared/_footer.html.haml @@ -150,7 +150,7 @@ = t :footer_legal_tos | = t :footer_legal_visit - %a{href:"https://github.com/openfoodfoundation/openfoodnetwork", target: "_blank"} Github + %a{href:"https://github.com/openfoodfoundation/openfoodnetwork", target: "_blank"} GitHub %p.text-small = t :footer_legal_text_html, {content_license: link_to('CC BY-SA 3.0', 'https://creativecommons.org/licenses/by-sa/3.0/'), code_license: link_to('AGPL 3', 'https://tldrlegal.com/license/gnu-affero-general-public-license-v3-(agpl-3.0)')} diff --git a/app/views/shared/components/_filter_box.html.haml b/app/views/shared/components/_filter_box.html.haml index e36d754fbd..564edd4150 100644 --- a/app/views/shared/components/_filter_box.html.haml +++ b/app/views/shared/components/_filter_box.html.haml @@ -1,5 +1,5 @@ -.row.filter-box.clear-filters.animate-show{"ng-show" => "filtersActive && totalActive() > 0"} +.row.filter-box.clear-filters.animate-show{"ng-show" => "filtersActive && filterSelectors.totalActive() > 0"} .small-12.columns - %a.button.secondary.small.expand{"ng-click" => "clearAll()"} + %a.button.secondary.small.expand{"ng-click" => "filterSelectors.clearAll()"} %i.ofn-i_009-close = t :components_filters_clearfilters diff --git a/app/views/shared/components/_filter_box_shopfront.html.haml b/app/views/shared/components/_filter_box_shopfront.html.haml deleted file mode 100644 index faf5930019..0000000000 --- a/app/views/shared/components/_filter_box_shopfront.html.haml +++ /dev/null @@ -1,4 +0,0 @@ -%span.animate-show{"ng-show" => "filtersActive && totalActive() > 0"} - %a.button.secondary.tiny{"ng-click" => "clearAll()"} - %i.ofn-i_009-close - = t :components_filters_clearfilters diff --git a/app/views/shared/components/_filter_controls.html.haml b/app/views/shared/components/_filter_controls.html.haml index 813c4920b6..d3141a3ea0 100644 --- a/app/views/shared/components/_filter_controls.html.haml +++ b/app/views/shared/components/_filter_controls.html.haml @@ -1,9 +1,9 @@ .small-12.medium-6.columns %a.button.success.tiny.filterbtn{"ng-click" => "filtersActive = !filtersActive", - "ng-show" => "FilterSelectorsService.selectors.length > 0"} - {{ filterText(filtersActive) }} + "ng-show" => "filterSelectors.selectors.length > 0"} + {{ filterSelectors.filterText(filtersActive) }} %i.ofn-i_005-caret-down{"ng-show" => "!filtersActive"} %i.ofn-i_006-caret-up{"ng-show" => "filtersActive"} - %a.button.secondary.tiny.filterbtn.disabled{"ng-show" => "FilterSelectorsService.selectors.length == 0"} + %a.button.secondary.tiny.filterbtn.disabled{"ng-show" => "filterSelectors.selectors.length == 0"} = t :components_filters_nofilters diff --git a/app/views/shared/components/_filter_controls_shopfront.html.haml b/app/views/shared/components/_filter_controls_shopfront.html.haml deleted file mode 100644 index 4bf7766a5c..0000000000 --- a/app/views/shared/components/_filter_controls_shopfront.html.haml +++ /dev/null @@ -1,8 +0,0 @@ -%a.button.success.tiny.filterbtn{"ng-click" => "filtersActive = !filtersActive", -"ng-show" => "FilterSelectorsService.selectors.length > 0"} - {{ filterText(filtersActive) }} - %i.ofn-i_005-caret-down{"ng-show" => "!filtersActive"} - %i.ofn-i_006-caret-up{"ng-show" => "filtersActive"} - -%a.button.secondary.tiny.filterbtn.disabled{"ng-show" => "FilterSelectorsService.selectors.length == 0"} - = t :components_filters_nofilters diff --git a/app/views/shared/mailers/_social_and_contact.html.haml b/app/views/shared/mailers/_social_and_contact.html.haml index a0f8e125e5..4f5222f77d 100644 --- a/app/views/shared/mailers/_social_and_contact.html.haml +++ b/app/views/shared/mailers/_social_and_contact.html.haml @@ -7,20 +7,23 @@ %td %h5 = t :email_social - %p - %a.soc-btn.fb{:href => "https://www.facebook.com/OpenFoodNet", :target => "_blank"} - Facebook - %a.soc-btn.tw{:href => "https://twitter.com/OpenFoodNet", :target => "_blank"} - Twitter - %a.soc-btn.li{:href => "http://www.linkedin.com/groups/Open-Food-Foundation-4743336", :target => "_blank"} - LinkedIn + %p.social-icons + - if ContentConfig.footer_facebook_url.present? + %a.soc-btn.fb{href: ContentConfig.footer_facebook_url} + Facebook + - if ContentConfig.footer_twitter_url.present? + %a.soc-btn.tw{href: ContentConfig.footer_twitter_url} + Twitter + - if ContentConfig.footer_linkedin_url.present? + %a.soc-btn.li{href: ContentConfig.footer_linkedin_url} + LinkedIn %table.column{:align => "left"} %tr %td - %h5 - = t :email_contact - %p + - if ContentConfig.footer_email.present? + %h5 + = t :email_contact %strong - %a{:href => "mailto:hello@openfoodnetwork.org"} - hello@openfoodnetwork.org + %a{href: ContentConfig.footer_email.reverse, mailto: true, target: '_blank'} + #{ContentConfig.footer_email} %span.clear diff --git a/app/views/shop/products/_filters.html.haml b/app/views/shop/products/_filters.html.haml index 786cd48662..7efaba6cc9 100644 --- a/app/views/shop/products/_filters.html.haml +++ b/app/views/shop/products/_filters.html.haml @@ -1,5 +1,5 @@ .filter-shopfront.taxon-selectors.text-right - %single-line-selectors{ objects: "Products.products | products:query | properties: activeProperties | taxonsOf", "active-selectors" => "activeTaxons"} + %single-line-selectors{ selectors: "taxonSelectors", objects: "Products.products | products:query | properties: activeProperties | taxonsOf", "active-selectors" => "activeTaxons"} .filter-shopfront.property-selectors.text-right - %single-line-selectors{ objects: "Products.products | products:query | taxons:activeTaxons | propertiesOf", "active-selectors" => "activeProperties"} + %single-line-selectors{ selectors: "propertySelectors", objects: "Products.products | products:query | taxons:activeTaxons | propertiesOf", "active-selectors" => "activeProperties"} diff --git a/app/views/spree/order_mailer/_shipping.html.haml b/app/views/spree/order_mailer/_shipping.html.haml index ba4829b171..4b73f9c970 100644 --- a/app/views/spree/order_mailer/_shipping.html.haml +++ b/app/views/spree/order_mailer/_shipping.html.haml @@ -18,7 +18,7 @@ - if @order.ship_address %h4 - = t :email_shipping_delivery_time + = t :email_shipping_delivery_address %p #{@order.ship_address.full_name} %br diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index b2e1d8d96c..7301ef4f2c 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -129,7 +129,7 @@ en-GB: footer_join_partners: "Food systems partners" footer_legal_call: "Read our" - footer_legal_tos: "Terms & conditions" + footer_legal_tos: "Terms and conditions" footer_legal_visit: "Find us on" footer_legal_text_html: "Open Food Network is a free and open source software platform. Our content is licensed with %{content_license} and our code with %{code_license}." @@ -355,7 +355,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using modal_how: "How it works" modal_how_shop: Shop the Open Food Network modal_how_shop_explained: 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.) - modal_how_pickup: Pick-ups, delivery & shipping costs + modal_how_pickup: Pick-ups, delivery and shipping costs modal_how_pickup_explained: 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. modal_how_more: Learn more modal_how_more_explained: "If you want to learn more about the Open Food Network, how it works, and get involved, check out:" @@ -432,7 +432,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using orders_edit_checkout: Checkout orders_form_empty_cart: "Empty cart" orders_form_subtotal: Produce subtotal - orders_form_admin: Admin & handling + orders_form_admin: Admin and handling orders_form_total: Total orders_oc_expired_headline: Orders have closed for this order cycle orders_oc_expired_text: "Sorry, orders for this order cycle closed %{time} ago! Please contact your hub directly to see if they can accept late orders." diff --git a/config/locales/en.yml b/config/locales/en.yml index 5b7f2ed5cd..4fb740cde6 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -29,7 +29,7 @@ en: home: "OFN" title: Open Food Network welcome_to: 'Welcome to ' - description: "We begin from the ground up. With farmers and growers ready to tell their stories proudly and truly. With distributors ready to connect people with products fairly and honestly. With buyers who believe that better weekly shopping decisions can…" + site_meta_description: "We begin from the ground up. With farmers and growers ready to tell their stories proudly and truly. With distributors ready to connect people with products fairly and honestly. With buyers who believe that better weekly shopping decisions can…" search_by_name: Search by name or suburb... producers: Aussie Producers producers_join: Australian producers are now welcome to join the Open Food Network. @@ -168,7 +168,7 @@ en: footer_join_partners: "Food systems partners" footer_legal_call: "Read our" - footer_legal_tos: "Terms & conditions" + footer_legal_tos: "Terms and conditions" footer_legal_visit: "Find us on" footer_legal_text_html: "Open Food Network is a free and open source software platform. Our content is licensed with %{content_license} and our code with %{code_license}." @@ -351,6 +351,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using groups_title: Groups groups_headline: Groups / regions + groups_text: "Every producer is unique. Every business has something different to offer. Our groups are collectives of producers, hubs and distributors who share something in common like location, farmers market or philosophy. This makes your shopping experience easier. So explore our groups and have the curating done for you." groups_search: "Search name or keyword" groups_no_groups: "No groups found" groups_about: "About Us" @@ -395,7 +396,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using modal_how: "How it works" modal_how_shop: Shop the Open Food Network modal_how_shop_explained: 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.) - modal_how_pickup: Pick-ups, delivery & shipping costs + modal_how_pickup: Pick-ups, delivery and shipping costs modal_how_pickup_explained: 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. modal_how_more: Learn more modal_how_more_explained: "If you want to learn more about the Open Food Network, how it works, and get involved, check out:" @@ -472,7 +473,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using orders_edit_checkout: Checkout orders_form_empty_cart: "Empty cart" orders_form_subtotal: Produce subtotal - orders_form_admin: Admin & handling + orders_form_admin: Admin and handling orders_form_total: Total orders_oc_expired_headline: Orders have closed for this order cycle orders_oc_expired_text: "Sorry, orders for this order cycle closed %{time} ago! Please contact your hub directly to see if they can accept late orders." @@ -630,7 +631,7 @@ Please follow the instructions there to make your enterprise visible on the Open registration_type_producer: "Yes, I'm a producer" registration_type_no_producer: "No, I'm not a producer" registration_type_error: "Please choose one. Are you are producer?" - registration_type_producer_help: "Producers make yummy things to eat &/or drink. You're a producer if you grow it, raise it, brew it, bake it, ferment it, milk it or mould it." + registration_type_producer_help: "Producers make yummy things to eat and/or drink. You're a producer if you grow it, raise it, brew it, bake it, ferment it, milk it or mould it." registration_type_no_producer_help: "If you’re not a producer, you’re probably someone who sells and distributes food. You might be a hub, coop, buying group, retailer, wholesaler or other." create_profile: "Create Profile" registration_images_headline: "Thanks!" diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 7ddd01655a..c4d0939e18 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -14,10 +14,33 @@ fr: title: Open Food France welcome_to: 'Bienvenue sur ' search_by_name: Recherche pas nom ou région... - producers: Producteurs & hubs + producers: Producteurs et hubs producers_join: Les producteurs et autres hubs basés en France sont invités à rejoindre Open Food France. charges_sales_tax: Soumis à la TVA? - print: "Imprimer" + print_invoice: "Imprimer la facture" + send_invoice: "Envoyer la facture" + resend_confirmation: "Renvoyer la confirmation" + view_order: "Voir la commande" + edit_order: "Editer la commande" + ship_order: "Envoyer la commande" + cancel_order: "Annuler la commande" + confirm_send_invoice: "La facture de cette commande va être transmise au client. Etes-vous sûr de vouloir continuer ?" + confirm_resend_order_confirmation: "Etes-vous sûr de vouloir renvoyer le mail de confirmation de commande ?" + must_have_valid_business_number: "%{enterprise_name} doit avoir un SIRET valide avant que les factures puissent être envoyées." + invoice: "Facture" + percentage_of_sales: "%{percentage} des ventes" + percentage_of_turnover: "Pourcentage du chiffre d'affaire" + monthly_cap_excl_tax: "Cumul mensuel (sans TVA)" + capped_at_cap: "plafonné à %{cap}" + per_month: "par mois" + free: "gratuit" + plus_tax: "plus TVA" + total_monthly_bill_incl_tax: "Facture mensuelle totale (taxes incluses)" + sort_order_cycles_on_shopfront_by: "Trier les cycles de vente par" + invoice_column_item: "Produit" + invoice_column_qty: "Qté" + invoice_column_tax: "TVA" + invoice_column_price: "Prix" logo: "Logo (640x130)" logo_mobile: "Logo smartphone (75x26)" logo_mobile_svg: "Logo smartphone (SVG)" @@ -34,7 +57,6 @@ fr: footer_links_md: "Liens" footer_about_url: "A propos URL" footer_tos_url: "Conditions d'utilisation URL" - invoice: "Facture" name: Nom first_name: Prénom last_name: Nom de famille @@ -111,7 +133,7 @@ fr: footer_join_groups: "Inscription groupes" footer_join_partners: "Partenaires" footer_legal_call: "Lire nos" - footer_legal_tos: "Termes & conditions" + footer_legal_tos: "Termes et conditions" footer_legal_visit: "Nous trouver sur" footer_legal_text_html: "Open Food Network est une plateforme logicielle open source, libre et gratuite. Nos données sont protégées sous licence %{content_license} et notre code sous %{code_license}." home_shop: Faire mes courses @@ -210,7 +232,7 @@ fr: email_payment_paid: RÉGLÉ email_payment_not_paid: NON RÉGLÉ email_payment_summary: Résumé du paiement - email_payment_method: "Payé via:" + email_payment_method: "Payer via :" email_shipping_delivery_details: Détails de livraison email_shipping_delivery_time: "Livré le:" email_shipping_delivery_address: "Adresse de livraison:" @@ -379,7 +401,7 @@ fr: orders_edit_checkout: Régler ma commande orders_form_empty_cart: "Vider le panier" orders_form_subtotal: Sous-total - orders_form_admin: Admin & opérations + orders_form_admin: Admin et opérations orders_form_total: Total orders_oc_expired_headline: Les commandes ne sont plus possibles pour ce cycle de vente. orders_oc_expired_text: "Désolé, les commandes pour ce cycle de vente ont été clôturées il y a %{time}! Veuillez contacter directement le hub pour voir s'il accepte les commandes tardives." @@ -576,4 +598,4 @@ fr: fundraising_fee: "Frais recherche de financement" price_graph: "Légende détail du prix" included_tax: "Inclut TVA" - remove_tax: "Afficher prix HT" + remove_tax: "Retirer TVA" diff --git a/config/locales/nb.yml b/config/locales/nb.yml index 079ef67eb9..59fa27ffa8 100644 --- a/config/locales/nb.yml +++ b/config/locales/nb.yml @@ -17,7 +17,30 @@ nb: producers: Norske Produsenter producers_join: Norske produsenter er nå velkommen til å bli med i Open Food Network. charges_sales_tax: MVA-pliktig? - print: "Print" + print_invoice: "Skriv ut Faktura" + send_invoice: "Send Faktura" + resend_confirmation: "Send Bekreftelse på nytt" + view_order: "Se Bestilling" + edit_order: "Rediger Bestilling" + ship_order: "Send Bestilling" + cancel_order: "Avbryt Bestilling" + confirm_send_invoice: "En faktura for denne bestillingen vil bli sendt til kunden. Er du sikker på at du vil fortsette?" + confirm_resend_order_confirmation: "Er du sikker på at du vil sende ordrebekreftelse via epost på nytt?" + must_have_valid_business_number: "%{enterprise_name} må ha et gyldig ORG nr. før fakturaer kan sendes." + invoice: "Faktura" + percentage_of_sales: "%{percentage} av handel" + percentage_of_turnover: "Prosent av omsetning" + monthly_cap_excl_tax: "månedlig tak (eks. MVA)" + capped_at_cap: "tak på %{cap}" + per_month: "pr. måned" + free: "gratis" + plus_tax: "pluss MVA" + total_monthly_bill_incl_tax: "Total månedlig regning (Inkl. Avgift)" + sort_order_cycles_on_shopfront_by: "Sorter Bestillingsrunder i Nettbutikk etter" + invoice_column_item: "Vare" + invoice_column_qty: "Mengde" + invoice_column_tax: "MVA" + invoice_column_price: "Pris" logo: "Logo (640x130)" logo_mobile: "Mobil logo (75x26)" logo_mobile_svg: "Mobil logo (SVG)" @@ -34,7 +57,6 @@ nb: footer_links_md: "Linker" footer_about_url: "Om URL" footer_tos_url: "Vilkår URL" - invoice: "Faktura" name: Navn first_name: Fornavn last_name: Etternavn @@ -111,7 +133,7 @@ nb: footer_join_groups: "Bli med som Gruppe" footer_join_partners: "Samarbeidspartnere" footer_legal_call: "Les våre" - footer_legal_tos: "Vilkår & betingelser" + footer_legal_tos: "Vilkår og betingelser" footer_legal_visit: "Finn oss på" footer_legal_text_html: "Open Food Network er en plattform med fri og åpen kildekode. Vårt innhold er lisensiert med %{content_license} og vår kode med %{code_license}." home_shop: Handle nå @@ -575,4 +597,4 @@ nb: fundraising_fee: "Pengeinnsamlingsgebyr" price_graph: "Prisgraf" included_tax: "inkludert avgift" - remove_tax: "Fjern MVA" + remove_tax: "Fjern avgift" diff --git a/script/ci/check_github_status.sh b/script/ci/check_github_status.sh index c4ce47c6fa..0a4775d268 100755 --- a/script/ci/check_github_status.sh +++ b/script/ci/check_github_status.sh @@ -15,5 +15,11 @@ echo "--- Checking environment variables" require_env_vars OFN_COMMIT BUILDKITE_REPO echo "--- Checking GitHub status" +if [ -n "$1" ]; then + REQUIRED_STATUS="$1" +else + REQUIRED_STATUS="success" +fi +echo "Require status '$REQUIRED_STATUS'" echo "Visiting $GITHUB_API_URL" -curl -s "$GITHUB_API_URL" | head -n 2 | grep '^ *"state": "success",$' +curl -s "$GITHUB_API_URL" | head -n 2 | grep '^ *"state":' | egrep "\"$REQUIRED_STATUS\",\$" diff --git a/spec/models/order_cycle_spec.rb b/spec/models/order_cycle_spec.rb index 554d427377..90465fb80e 100644 --- a/spec/models/order_cycle_spec.rb +++ b/spec/models/order_cycle_spec.rb @@ -35,12 +35,14 @@ describe OrderCycle do oc_not_yet_open = create(:simple_order_cycle, orders_open_at: 1.week.from_now, orders_close_at: 2.weeks.from_now) oc_already_closed = create(:simple_order_cycle, orders_open_at: 2.weeks.ago, orders_close_at: 1.week.ago) oc_undated = create(:simple_order_cycle, orders_open_at: nil, orders_close_at: nil) + oc_undated_open = create(:simple_order_cycle, orders_open_at: 1.week.ago, orders_close_at: nil) + oc_undated_close = create(:simple_order_cycle, orders_open_at: nil, orders_close_at: 1.week.from_now) OrderCycle.active.should == [oc_active] OrderCycle.inactive.should match_array [oc_not_yet_open, oc_already_closed] OrderCycle.upcoming.should == [oc_not_yet_open] OrderCycle.closed.should == [oc_already_closed] - OrderCycle.undated.should == [oc_undated] + OrderCycle.undated.should == [oc_undated, oc_undated_open, oc_undated_close] end it "finds order cycles accessible by a user" do @@ -356,6 +358,24 @@ describe OrderCycle do oc.should_not be_open oc.should_not be_closed end + + it "reports status when an order cycle is partially dated - opening time only" do + oc.update_attributes!(orders_close_at: nil) + + oc.should be_undated + oc.should_not be_upcoming + oc.should_not be_open + oc.should_not be_closed + end + + it "reports status when an order cycle is partially dated - closing time only" do + oc.update_attributes!(orders_open_at: nil) + + oc.should be_undated + oc.should_not be_upcoming + oc.should_not be_open + oc.should_not be_closed + end end it "clones itself" do