Merge branch 'master' into reset-on-demand-on-absent-products

This commit is contained in:
Pau Pérez Fabregat
2020-10-28 17:28:53 +01:00
committed by GitHub
189 changed files with 3903 additions and 3566 deletions

View File

@@ -13,21 +13,11 @@ Provide context for others to understand it. -->
#### Release notes
<!-- Write a line or two to be included in the release notes.
Everything is worth mentioning, because you did it for a reason. -->
<!-- Write a one liner description of the change to be included in the release notes.
Every PR is worth mentioning, because you did it for a reason. -->
<!-- Please assign one category to your PR and delete the others.
The categories are based on https://keepachangelog.com/en/1.0.0/. -->
Changelog Category: Added | Changed | Deprecated | Removed | Fixed | Security
#### Discourse thread
<!-- Is there a discussion about this in Discourse?
Add the link or remove this section. -->
<!-- Please select one for your PR and delete the other. -->
Changelog Category: User facing changes | Technical changes

View File

@@ -167,7 +167,6 @@ Layout/LineLength:
- spec/features/admin/enterprises/index_spec.rb
- spec/features/admin/enterprises_spec.rb
- spec/features/admin/enterprise_user_spec.rb
- spec/features/admin/image_settings_spec.rb
- spec/features/admin/multilingual_spec.rb
- spec/features/admin/order_cycles/complex_creating_specific_time_spec.rb
- spec/features/admin/order_cycles/complex_editing_multiple_product_pages_spec.rb
@@ -345,7 +344,6 @@ Metrics/AbcSize:
- app/controllers/cart_controller.rb
- app/controllers/discourse_sso_controller.rb
- app/controllers/enterprises_controller.rb
- app/controllers/spree/admin/image_settings_controller.rb
- app/controllers/spree/admin/orders_controller.rb
- app/controllers/spree/admin/orders/customer_details_controller.rb
- app/controllers/spree/admin/overview_controller.rb
@@ -665,7 +663,6 @@ Metrics/MethodLength:
- app/controllers/api/variants_controller.rb
- app/controllers/cart_controller.rb
- app/controllers/shop_controller.rb
- app/controllers/spree/admin/image_settings_controller.rb
- app/controllers/spree/admin/orders_controller.rb
- app/controllers/spree/admin/orders/customer_details_controller.rb
- app/controllers/spree/admin/payment_methods_controller.rb
@@ -814,42 +811,17 @@ Metrics/ModuleLength:
- app/helpers/spree/admin/navigation_helper.rb
- app/models/spree/order/checkout.rb
- app/models/spree/payment/processing.rb
- engines/catalog/spec/services/catalog/product_import/products_reset_strategy_spec.rb
- engines/order_management/spec/services/order_management/order/updater_spec.rb
- engines/order_management/spec/services/order_management/stock/package_spec.rb
- engines/order_management/spec/services/order_management/subscriptions/estimator_spec.rb
- engines/order_management/spec/services/order_management/subscriptions/form_spec.rb
- engines/order_management/spec/services/order_management/subscriptions/proxy_order_syncer_spec.rb
- engines/order_management/spec/services/order_management/subscriptions/summarizer_spec.rb
- engines/order_management/spec/services/order_management/subscriptions/validator_spec.rb
- engines/order_management/spec/services/order_management/subscriptions/variants_list_spec.rb
- lib/open_food_network/column_preference_defaults.rb
- spec/controllers/admin/order_cycles_controller_spec.rb
- spec/controllers/api/order_cycles_controller_spec.rb
- spec/controllers/api/orders_controller_spec.rb
- spec/controllers/spree/admin/payment_methods_controller_spec.rb
- spec/lib/open_food_network/address_finder_spec.rb
- spec/lib/open_food_network/customers_report_spec.rb
- spec/lib/open_food_network/enterprise_fee_calculator_spec.rb
- spec/lib/open_food_network/order_cycle_form_applicator_spec.rb
- spec/lib/open_food_network/order_cycle_permissions_spec.rb
- spec/lib/open_food_network/order_grouper_spec.rb
- spec/lib/open_food_network/packing_report_spec.rb
- spec/lib/open_food_network/permissions_spec.rb
- spec/lib/open_food_network/products_and_inventory_report_spec.rb
- spec/lib/open_food_network/scope_variant_to_hub_spec.rb
- spec/lib/open_food_network/tag_rule_applicator_spec.rb
- spec/lib/open_food_network/user_balance_calculator_spec.rb
- spec/lib/open_food_network/users_and_enterprises_report_spec.rb
- spec/models/spree/adjustment_spec.rb
- spec/models/spree/credit_card_spec.rb
- spec/models/spree/line_item_spec.rb
- spec/models/spree/product_spec.rb
- spec/models/spree/shipping_method_spec.rb
- spec/models/spree/variant_spec.rb
- spec/services/permissions/order_spec.rb
- spec/services/variant_units/option_value_namer_spec.rb
- spec/support/request/stripe_helper.rb
Metrics/ParameterLists:
Max: 5

7
.rubocop_specs.yml Normal file
View File

@@ -0,0 +1,7 @@
inherit_from:
- .rubocop.yml
# This rubocop config file is only used for specs
# Here we allow specs to be 300 lines long
Metrics/ModuleLength:
Max: 300

View File

@@ -691,7 +691,6 @@ Style/FrozenStringLiteralComment:
- 'app/controllers/spree/admin/base_controller.rb'
- 'app/controllers/spree/admin/countries_controller.rb'
- 'app/controllers/spree/admin/general_settings_controller.rb'
- 'app/controllers/spree/admin/image_settings_controller.rb'
- 'app/controllers/spree/admin/images_controller.rb'
- 'app/controllers/spree/admin/invoices_controller.rb'
- 'app/controllers/spree/admin/mail_methods_controller.rb'
@@ -726,7 +725,6 @@ Style/FrozenStringLiteralComment:
- 'app/controllers/user_passwords_controller.rb'
- 'app/controllers/user_registrations_controller.rb'
- 'app/helpers/admin/enterprises_helper.rb'
- 'app/helpers/admin/image_settings_helper.rb'
- 'app/helpers/admin/injection_helper.rb'
- 'app/helpers/admin/orders_helper.rb'
- 'app/helpers/admin/subscriptions_helper.rb'
@@ -1123,7 +1121,6 @@ Style/FrozenStringLiteralComment:
- 'spec/controllers/shops_controller_spec.rb'
- 'spec/controllers/spree/admin/adjustments_controller_spec.rb'
- 'spec/controllers/spree/admin/base_controller_spec.rb'
- 'spec/controllers/spree/admin/image_settings_controller_spec.rb'
- 'spec/controllers/spree/admin/invoices_controller_spec.rb'
- 'spec/controllers/spree/admin/mail_methods_controller_spec.rb'
- 'spec/controllers/spree/admin/orders/customer_details_controller_spec.rb'
@@ -1168,7 +1165,6 @@ Style/FrozenStringLiteralComment:
- 'spec/features/admin/bulk_product_update_spec.rb'
- 'spec/features/admin/configuration/content_spec.rb'
- 'spec/features/admin/configuration/general_settings_spec.rb'
- 'spec/features/admin/configuration/image_settings_spec.rb'
- 'spec/features/admin/configuration/mail_methods_spec.rb'
- 'spec/features/admin/configuration/states_spec.rb'
- 'spec/features/admin/configuration/tax_categories_spec.rb'
@@ -1184,7 +1180,6 @@ Style/FrozenStringLiteralComment:
- 'spec/features/admin/enterprises/index_spec.rb'
- 'spec/features/admin/enterprises_spec.rb'
- 'spec/features/admin/external_services_spec.rb'
- 'spec/features/admin/image_settings_spec.rb'
- 'spec/features/admin/multilingual_spec.rb'
- 'spec/features/admin/overview_spec.rb'
- 'spec/features/admin/payment_method_spec.rb'

View File

@@ -1,65 +0,0 @@
### Docker
It is possible to setup the Open Food Network app easily with Docker and Docker Compose.
The objective is to spare configuration time, in order to help people testing the app and contribute to it.
It can also be used as documentation. It is not perfect but it is used in many other projects and many devs are used to it nowadays.
### Install Docker
Please check the documentation here, https://docs.docker.com/install/ to install Docker.
For Docker Compose, information are here: https://docs.docker.com/compose/install/.
Better to have at least 2GB free on your computer in order to download images and create containers for Open Food Network app.
### Use Docker with Open Food Network
Open a terminal with a shell.
Clone the repository. If you're planning on contributing code to the project (which we [LOVE](CONTRIBUTING.md)), it is a good idea to begin by forking this repo using the Fork button in the top-right corner of this screen. You should then be able to use git clone to copy your fork onto your local machine.
```sh
$ git clone https://github.com/YOUR_GITHUB_USERNAME_HERE/openfoodnetwork
```
Otherwise, if you just want to get things running, clone from the OFN main repo:
```sh
$ git clone git@github.com:openfoodfoundation/openfoodnetwork.git
```
Go at the root of the app:
```sh
$ cd openfoodnetwork
```
Download the Docker images and build the containers:
```sh
$ docker-compose build
```
Setup the database and seed it with sample data:
```sh
$ docker-compose run web bundle exec rake db:reset
$ docker-compose run web bundle exec rake db:test:prepare
$ docker-compose run web bundle exec rake ofn:sample_data
```
Finally, run the app with all the required containers:
```sh
$ docker-compose up
```
The default admin user is 'ofn@example.com' with 'ofn123' password.
Check the app in the browser at `http://localhost:3000`.
You will then get the trace of the containers in the terminal. You can stop the containers using Ctrl-C in the terminal.
You can find some useful tips and commands [here](https://github.com/openfoodfoundation/openfoodnetwork/wiki/Docker:-useful-tips-and-commands).
### Troubleshooting
If you are using Windows and having issues related to the ruby-build not finding a definition for the ruby version, you may need to follow these commands [here](https://stackoverflow.com/questions/2517190/how-do-i-force-git-to-use-lf-instead-of-crlf-under-windows/33424884#33424884) to fix your local git config related to line breaks.

View File

@@ -27,8 +27,11 @@ RUN sh -c "echo 'deb https://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main'
apt-get update && \
apt-get install -yqq --no-install-recommends postgresql-client-9.5 libpq-dev
# Install node
RUN apt-get install -y nodejs
# Install node & yarn
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update && \
apt-get install -y nodejs yarn
# Install Chrome
RUN wget --quiet -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
@@ -43,5 +46,9 @@ RUN wget https://chromedriver.storage.googleapis.com/2.41/chromedriver_linux64.z
# Copy code and install app dependencies
COPY . /usr/src/app/
# Install front-end dependencies
RUN yarn install
# Run bundler install in parallel with the amount of available CPUs
RUN bundle install --jobs="$(nproc)"

View File

@@ -3,7 +3,7 @@ ruby "2.3.7"
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
gem 'i18n', '~> 0.6.11'
gem 'i18n-js', '~> 3.7.1'
gem 'i18n-js', '~> 3.8.0'
gem 'rails', '~> 4.0.13'
gem 'rails-i18n', '~> 4.0'
gem 'rails_safe_tasks', '~> 1.0'

View File

@@ -109,7 +109,7 @@ GEM
activesupport (= 4.0.13)
arel (~> 4.0.0)
activerecord-deprecated_finders (1.0.4)
activerecord-import (1.0.6)
activerecord-import (1.0.7)
activerecord (>= 3.2)
activerecord-postgresql-adapter (0.0.1)
pg
@@ -204,7 +204,7 @@ GEM
activerecord (>= 3.2.0, < 5.0)
fog (~> 1.0)
rails (>= 3.2.0, < 5.0)
ddtrace (0.41.0)
ddtrace (0.42.0)
msgpack
debugger-linecache (1.2.0)
delayed_job (4.1.8)
@@ -421,7 +421,7 @@ GEM
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
i18n (0.6.11)
i18n-js (3.7.1)
i18n-js (3.8.0)
i18n (>= 0.6.6)
immigrant (0.3.6)
activerecord (>= 3.0)
@@ -685,7 +685,7 @@ GEM
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
selenium-webdriver (>= 3.0, < 4.0)
webmock (3.9.2)
webmock (3.9.3)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
@@ -754,7 +754,7 @@ DEPENDENCIES
highline (= 1.6.18)
httparty (~> 0.18)
i18n (~> 0.6.11)
i18n-js (~> 3.7.1)
i18n-js (~> 3.8.0)
immigrant
jquery-migrate-rails
jquery-rails (= 3.1.5)

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="15 13 34 38.4" enable-background="new 15 13 34 38.4" xml:space="preserve">
<g>
<polygon fill="#FFFFFF" points="15.5,13.5 48.5,13.5 48.5,50.7 31.6,45.5 15.5,50.7 "/>
<path fill="#999999" d="M48,14v36l-16.4-5L16,50V14H48 M49,13h-1H16h-1v1v36v1.4l1.3-0.4l15.3-5l16.1,5l1.3,0.4V50V14V13L49,13z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -27,14 +27,14 @@
//= require lodash.underscore.js
// spree
//= require spree
//= require admin/spree/spree
//= require admin/spree/spree-select2
//= require modernizr
//= require equalize
//= require css_browser_selector_dev
//= require responsive-tables
//= require admin/spree_paypal_express
//= require admin/handlebar_extensions
//= require handlebars
// OFN specific
//= require_tree ../templates/admin

View File

@@ -116,7 +116,8 @@ $.fn.radioControlsVisibilityOfElement = function(dependentElementSelector){
}
$(document).ready(function() {
if (typeof Spree !== 'undefined') {
if (typeof Spree !== 'undefined' &&
typeof Spree.translations !== 'undefined') {
handle_date_picker_fields = function(){
$('.datepicker').datepicker({
dateFormat: Spree.translations.date_picker,

View File

@@ -1,59 +0,0 @@
$(document).ready(function() {
if ($('input#preferences_use_s3[type="checkbox"]:checked').length > 0) {
$('#s3_settings, #s3_headers').show();
}
// Toggle display of S3 settings based on value of use_s3 checkbox
$('input#preferences_use_s3[type="checkbox"]').click(function() {
$('#s3_settings, #s3_headers').toggle();
});
$(document).on('click', '.destroy_style', function(e) {
e.preventDefault();
$(this).parent().remove();
});
$(document).on('click', '.destroy_new_attachment_styles', function(e) {
e.preventDefault();
$(this).closest('.new_attachment_styles').remove();
});
$(document).on('click', '.destroy_new_s3_headers', function(e) {
e.preventDefault();
$(this).closest('.new_s3_headers').remove();
});
// Handle adding new styles
var styles_hash_index = 1;
$(document).on('click', '.add_new_style', function(e) {
e.preventDefault();
$('#new-styles').append(generate_html_for_hash("new_attachment_styles", styles_hash_index));
});
// Handle adding new headers
var headers_hash_index = 1;
$(document).on('click', '.add_header', function(e) {
e.preventDefault();
$('#headers_list').append(generate_html_for_hash("new_s3_headers", headers_hash_index));
});
// Generates html for new paperclip styles form fields
generate_html_for_hash = function(hash_name, index) {
var html = '<div class="' + hash_name + ' row"><div class="field">';
html += '<div class="five columns">';
html += '<label for="' + hash_name + '_' + index + '_name">';
html += Spree.translations.name + '</label>';
html += '<input id="' + hash_name + '_' + index + '_name" name="' + hash_name + '[' + index + '][name]" type="text" class="fullwidth"><br>';
html += '</div><div class="five columns">'
html += '<label for="' + hash_name + '_' + index + '_value">';
html += Spree.translations.value + '</label>';
html += '<input id="' + hash_name + '_' + index + '_value" name="' + hash_name + '[' + index + '][value]" type="text" class="fullwidth">';
html += '</div><div class="two columns">'
html += '<a href="#" title="' + Spree.translations.destroy + '" class="destroy_' + hash_name + ' with-tip button" style="margin-top: 19px;"><i class="icon-trash"></i> &nbsp; ' + Spree.translations.destroy + '</a>';
html += '</div></div></div>';
index += 1;
return html;
};
});

View File

@@ -0,0 +1,13 @@
#= require jsuri
class window.Spree
# Helper function to take a URL and add query parameters to it
@url: (uri, query) ->
if uri.path == undefined
uri = new Uri(uri)
if query
$.each query, (key, value) ->
uri.addQueryParam(key, value)
if Spree.api_key
uri.addQueryParam('token', Spree.api_key)
return uri

View File

@@ -1,6 +1,6 @@
Darkswarm.controller "ProductNodeCtrl", ($scope, $modal, FilterSelectorsService) ->
$scope.enterprise = $scope.product.supplier # For the modal, so it's consistent
$scope.productPropertySelectors = FilterSelectorsService.createSelectors()
$scope.triggerProductModal = ->
$scope.productPropertySelectors = FilterSelectorsService.createSelectors()
$modal.open(templateUrl: "product_modal.html", scope: $scope)

View File

@@ -0,0 +1,39 @@
Darkswarm.controller "ShopVariantCtrl", ($scope, $modal, Cart) ->
$scope.$watchGroup [
'variant.line_item.quantity',
'variant.line_item.max_quantity'
], (new_value, old_value) ->
return if old_value[0] == null && new_value[0] == null
Cart.adjust($scope.variant.line_item)
$scope.add = (quantity) ->
item = $scope.variant.line_item
item.quantity += quantity
if $scope.variant.product.group_buy
if item.quantity < 1 || item.max_quantity < item.quantity
item.max_quantity = item.quantity
$scope.addMax = (quantity) ->
item = $scope.variant.line_item
item.max_quantity += quantity
if item.max_quantity < item.quantity
item.quantity = item.max_quantity
$scope.canAdd = (quantity) ->
wantedQuantity = $scope.variant.line_item.quantity + quantity
$scope.quantityValid(wantedQuantity)
$scope.canAddMax = (quantity) ->
variant = $scope.variant
wantedQuantity = variant.line_item.max_quantity + quantity
$scope.quantityValid(wantedQuantity) && variant.line_item.quantity > 0
$scope.quantityValid = (quantity) ->
variant = $scope.variant
minimum = 0
maximum = variant.on_demand && Infinity || variant.on_hand
quantity >= minimum && quantity <= maximum
$scope.addBulk = (quantity) ->
$scope.add(quantity)
$modal.open(templateUrl: "bulk_buy_modal.html", scope: $scope, windowClass: "product-bulk-modal")

View File

@@ -2,7 +2,7 @@ Darkswarm.directive "priceBreakdown", ($tooltip)->
# We use the $tooltip service from Angular foundation to give us boilerplate
# Subsequently we patch the scope, template and restrictions
tooltip = $tooltip 'priceBreakdown', 'priceBreakdown', 'click'
tooltip.scope =
tooltip.scope =
variant: "="
tooltip.templateUrl = "price_breakdown_button.html"
tooltip.replace = true
@@ -15,6 +15,3 @@ Darkswarm.directive 'priceBreakdownPopup', ->
replace: true
templateUrl: 'price_breakdown.html'
scope: false
link: (scope, elem, attrs) ->
scope.expanded = false unless scope.expanded?

View File

@@ -1,10 +0,0 @@
Darkswarm.directive "pricePercentage", ->
restrict: 'E'
replace: true
templateUrl: 'price_percentage.html'
scope:
percentage: '='
link: (scope, elem, attrs) ->
elem.find(".meter").css
width: "#{scope.percentage}%"

View File

@@ -4,10 +4,4 @@ Darkswarm.directive "shopVariant", ->
templateUrl: 'shop_variant.html'
scope:
variant: '='
controller: ($scope, Cart) ->
$scope.$watchGroup [
'variant.line_item.quantity',
'variant.line_item.max_quantity'
], (new_value, old_value) ->
return if old_value[0] == null && new_value[0] == null
Cart.adjust($scope.variant.line_item)
controller: 'ShopVariantCtrl'

View File

@@ -10,7 +10,6 @@ Darkswarm.factory 'Variants', ->
extend: (variant)->
variant.extended_name = @extendedVariantName(variant)
variant.base_price_percentage = Math.round(variant.price / variant.price_with_fees * 100)
variant.line_item ||= @lineItemFor(variant) # line_item may have been initialised in Cart#constructor
variant.line_item.total_price = variant.price_with_fees * variant.line_item.quantity
variant

View File

@@ -0,0 +1,37 @@
.row
.columns.small-12
%h3{"ng-bind" => "::variant.extended_name"}
.row.variant-bulk-buy-price-summary
.columns.small-6
.variant-unit {{ ::variant.unit_to_display }}
.columns.small-6
{{ variant.line_item.total_price | localizeCurrency }}
.row
.columns.small-6
.variant-bulk-buy-quantity-label
{{ "js.shopfront.bulk_buy_modal.min_quantity" | t }}
%div
%button.bulk-buy-add.variant-quantity{type: "button", ng: {click: "add(-1)", disabled: "!canAdd(-1)"}}>
-# U+FF0D Fullwidth Hyphen-Minus
%span.bulk-buy.variant-quantity>
{{ variant.line_item.quantity }}
%button.bulk-buy-add.variant-quantity{type: "button", ng: {click: "add(1)", disabled: "!canAdd(1)"}}
-# U+FF0B Fullwidth Plus Sign
.columns.small-6
.variant-bulk-buy-quantity-label
{{ "js.shopfront.bulk_buy_modal.max_quantity" | t }}
%div
%button.bulk-buy-add.variant-quantity{type: "button", ng: {click: "addMax(-1)", disabled: "!canAddMax(-1)"}}>
-# U+FF0D Fullwidth Hyphen-Minus
%span.bulk-buy.variant-quantity>
{{ variant.line_item.max_quantity }}
%button.bulk-buy-add.variant-quantity{type: "button", ng: {click: "addMax(1)", disabled: "!canAddMax(1)"}}
-# U+FF0B Fullwidth Plus Sign
%ng-include{src: "'partials/close.html'"}

View File

@@ -1,14 +1,16 @@
.small-5.medium-3.large-3.columns.text-right{"ng-if" => "::!variant.product.group_buy"}
%input{type: :number,
integer: true,
value: nil,
min: 0,
placeholder: "0",
"ofn-disable-scroll" => true,
"ng-debounce" => "500",
onwheel: "this.blur()",
"ng-model" => "variant.line_item.quantity",
"ofn-on-hand" => "{{variant.on_demand && 9999 || variant.on_hand }}",
"ng-disabled" => "!variant.on_demand && variant.on_hand == 0",
name: "variants[{{::variant.id}}]", id: "variants_{{::variant.id}}"}
%button.add-variant{type: "button", ng: {if: "!variant.line_item.quantity", click: "add(1)", disabled: "!canAdd(1)"}}
{{ "js.shopfront.variant.add_to_cart" | t }}
%button.variant-quantity{type: "button", ng: {if: "variant.line_item.quantity", click: "add(-1)"}}>
-# U+FF0D Fullwidth Hyphen-Minus
%button.variant-quantity{type: "button", ng: {if: "variant.line_item.quantity", click: "add(1)", disabled: "!canAdd(1)"}}
-# U+FF0B Fullwidth Plus Sign
%br
.variant-quantity-display{ng: {class: "{visible: variant.line_item.quantity}"}}
{{ "js.shopfront.variant.quantity_in_cart" | t:{quantity: variant.line_item.quantity || 0} }}
%input{type: :hidden,
name: "variants[{{::variant.id}}]",
ng: {model: "variant.line_item.quantity"}}

View File

@@ -1,28 +1,17 @@
.small-5.medium-3.large-3.columns.text-right{"ng-if" => "::variant.product.group_buy"}
%span.bulk-input-container
%span.bulk-input
%input.bulk.first{type: :number,
value: nil,
integer: true,
min: 0,
"ng-model" => "variant.line_item.quantity",
placeholder: "{{::'shop_variant_quantity_min' | t}}",
"ofn-disable-scroll" => true,
"ng-debounce" => "500",
onwheel: "this.blur()",
"ofn-on-hand" => "{{variant.on_demand && 9999 || variant.on_hand }}",
name: "variants[{{::variant.id}}]", id: "variants_{{::variant.id}}"}
%span.bulk-input
%input.bulk.second{type: :number,
"ng-disabled" => "!variant.line_item.quantity",
integer: true,
min: 0,
"ng-model" => "variant.line_item.max_quantity",
placeholder: "{{::'shop_variant_quantity_max' | t}}",
"ofn-disable-scroll" => true,
"ng-debounce" => "500",
onwheel: "this.blur()",
min: "{{variant.line_item.quantity}}",
name: "variant_attributes[{{::variant.id}}][max_quantity]",
id: "variants_{{::variant.id}}_max"}
%button.add-variant{type: "button", ng: {if: "!variant.line_item.quantity", click: "addBulk(1)", disabled: "!canAdd(1)"}}
{{ "js.shopfront.variant.add_to_cart" | t }}
%button.bulk-buy.variant-quantity{type: "button", ng: {if: "variant.line_item.quantity", click: "addBulk(0)"}}>
{{ variant.line_item.quantity }}
%button.bulk-buy.variant-quantity{type: "button", ng: {if: "variant.line_item.quantity", click: "addBulk(0)"}}
{{ variant.line_item.max_quantity || "-" }}
%br
.variant-quantity-display{ng: {class: "{visible: variant.line_item.quantity}"}}
{{ "js.shopfront.variant.in_cart" | t }}
%input{type: :hidden,
name: "variants[{{::variant.id}}]",
ng: {model: "variant.line_item.quantity"}}
%input{type: :hidden,
name: "variants[{{::variant.id}}]",
ng: {model: "variant.line_item.max_quantity"}}

View File

@@ -1,37 +1,28 @@
.joyride-tip-guide.price_breakdown{"ng-class" => "{ in: tt_isOpen, fade: tt_animation }"}
%span.joyride-nub.right
.joyride-tip-guide.price_breakdown{ng: {class: "{ in: tt_isOpen, fade: tt_animation }", show: "tt_isOpen"}}
%span.joyride-nub.top
.background{ng: {click: "tt_isOpen = false"}}
.joyride-content-wrapper
.collapsed{"ng-show" => "!expanded"}
%price-percentage{percentage: 'variant.base_price_percentage'}
%a{"ng-click" => "expanded = !expanded"}
%span{"ng-bind" => "::'price_breakdown' | t"}
%i.ofn-i_005-caret-down
.expanded{"ng-show" => "expanded"}
%ul
%li.cost
.right {{ ::variant.price | localizeCurrency }}
%span{"ng-bind" => "::'item_cost' | t"}
%li.admin-fee{"ng-if" => "::variant.fees.admin"}
.right {{ ::variant.fees.admin | localizeCurrency }}
%span{"ng-bind" => "::'admin_fee' | t"}
%li.sales-fee{"ng-if" => "::variant.fees.sales"}
.right {{ ::variant.fees.sales | localizeCurrency }}
%span{"ng-bind" => "::'sales_fee' | t"}
%li.packing-fee{"ng-if" => "::variant.fees.packing"}
.right {{ ::variant.fees.packing | localizeCurrency }}
%span{"ng-bind" => "::'packing_fee' | t"}
%li.transport-fee{"ng-if" => "::variant.fees.transport"}
.right {{ ::variant.fees.transport | localizeCurrency }}
%span{"ng-bind" => "::'transport_fee' | t"}
%li.fundraising-fee{"ng-if" => "::variant.fees.fundraising"}
.right {{ ::variant.fees.fundraising | localizeCurrency }}
%span{"ng-bind" => "::'fundraising_fee' | t"}
%li.total
%strong
.right = {{ ::variant.price_with_fees | localizeCurrency }}
&nbsp;
%a{"ng-click" => "expanded = !expanded"}
%span{"ng-bind" => "::'price_graph' | t"}
%i.ofn-i_006-caret-up
%h6 {{ "js.shopfront.price_breakdown" | t }}
%ul
%li
.right {{ ::variant.price | localizeCurrency }}
%span{"ng-bind" => "::'item_cost' | t"}
%li{"ng-if" => "::variant.fees.admin"}
.right {{ ::variant.fees.admin | localizeCurrency }}
%span{"ng-bind" => "::'admin_fee' | t"}
%li{"ng-if" => "::variant.fees.sales"}
.right {{ ::variant.fees.sales | localizeCurrency }}
%span{"ng-bind" => "::'sales_fee' | t"}
%li{"ng-if" => "::variant.fees.packing"}
.right {{ ::variant.fees.packing | localizeCurrency }}
%span{"ng-bind" => "::'packing_fee' | t"}
%li{"ng-if" => "::variant.fees.transport"}
.right {{ ::variant.fees.transport | localizeCurrency }}
%span{"ng-bind" => "::'transport_fee' | t"}
%li{"ng-if" => "::variant.fees.fundraising"}
.right {{ ::variant.fees.fundraising | localizeCurrency }}
%span{"ng-bind" => "::'fundraising_fee' | t"}
%li
%strong
.right = {{ ::variant.price_with_fees | localizeCurrency }}
&nbsp;

View File

@@ -1,4 +0,0 @@
.progress
.right {{::'fees' | t}}
.meter
{{::'item_cost' | t}}

View File

@@ -1,31 +1,16 @@
.variants.row
.small-12.medium-4.large-4.columns.variant-name
.table-cell
.inline {{ ::variant.name_to_display }}
.bulk-buy.inline{"ng-if" => "::variant.product.group_buy"}
%i.ofn-i_056-bulk><
%em><
\ {{::'bulk' | t}}
.small-4.medium-4.large-6.columns.variant-name
.inline{"ng-if" => "::variant.display_name"} {{ ::variant.display_name }}
.variant-unit {{ ::variant.unit_to_display }}
.small-3.medium-3.large-2.columns.variant-price
%price-breakdown{"price-breakdown" => "_", variant: "variant",
"price-breakdown-append-to-body" => "true",
"price-breakdown-placement" => "bottom",
"price-breakdown-animation" => true}
{{ variant.price_with_fees | localizeCurrency }}
.medium-2.large-1.columns.total-price
%span{"ng-class" => "{filled: variant.line_item.total_price}"}
{{ variant.line_item.total_price | localizeCurrency }}
%ng-include{src: "'partials/shop_variant_no_group_buy.html'"}
%ng-include{src: "'partials/shop_variant_with_group_buy.html'"}
.small-3.medium-1.large-1.columns.variant-unit
.table-cell
%em {{ ::variant.unit_to_display }}
.small-4.medium-2.large-2.columns.variant-price
.table-cell.price
%i.ofn-i_009-close
{{ variant.price_with_fees | localizeCurrency }}
-# Now in a template in app/assets/javascripts/templates !
%price-breakdown{"price-breakdown" => "_", variant: "variant",
"price-breakdown-append-to-body" => "true",
"price-breakdown-placement" => "left",
"price-breakdown-animation" => true}
.small-12.medium-2.large-2.columns.total-price.text-right
.table-cell
%strong{"ng-class" => "{filled: variant.line_item.total_price}"}
{{ variant.line_item.total_price | localizeCurrency }}

View File

@@ -35,7 +35,6 @@
@import 'plugins/font-awesome';
@import 'plugins/select2';
@import 'sections/image_settings';
@import 'sections/orders';
@import 'sections/products';

View File

@@ -29,11 +29,6 @@ html.ie {
z-index: 0;
}
}
// Fix margin-top for destroy paperclip styles background
.destroy_new_attachment_styles {
margin-top: 17px !important;
}
}
// IE8 Hacks

View File

@@ -1,3 +0,0 @@
.destroy_style, .destroy_header {
float: right;
}

View File

@@ -71,12 +71,6 @@
display: none;
}
// For block grids
.frameless {
margin-left: -10px;
margin-right: -10px;
}
// Header
//---------------------------------------------------
#header {

View File

@@ -6,93 +6,110 @@
.darkswarm {
// #search
@include placeholder(rgba(0, 0, 0, 0.4), #777);
}
// ordering
product {
input {
@include border-radius(0);
.reveal-modal.product-bulk-modal {
width: 26em;
}
@include csstrans;
// Components to add variants to cart and change quantities
//
// They are not nested so that they can be used in modals.
button.add-variant, button.variant-quantity {
height: 2.5rem;
border-radius: 0;
background-color: $orange-500;
color: white;
// Override foundation button styles:
font-size: 1rem;
margin: 0;
padding: 0;
transition: none;
margin: 0;
width: 10rem;
display: inline;
@include box-shadow(none);
border-color: #b3b3b3;
text-align: right;
@include breakpoint(desktop) {
width: 8rem;
}
@include breakpoint(tablet) {
width: 7rem;
}
@include breakpoint(phablet) {
float: left !important;
font-size: 0.75rem;
padding-left: 0.25rem;
padding-right: 0.25rem;
}
@include breakpoint(mobile) {
width: 5.8rem;
}
&:hover {
@include box-shadow(none);
border-color: #888;
background-color: #fafafa;
}
&:active, &:focus, &.active {
@include box-shadow(none);
background-color: #f9f4b9;
border-color: #666;
}
&:hover {
background-color: $orange-600;
}
&[disabled] {
&:hover, &:focus {
background-color: $orange-500;
}
}
&:nth-of-type(1) {
border-bottom-left-radius: 0.25em;
border-top-left-radius: 0.25em;
}
&:nth-last-of-type(1) {
border-top-right-radius: 0.25em;
border-bottom-right-radius: 0.25em;
}
}
// BULK
button.add-variant {
min-width: 6rem;
padding: 0 1em;
input.bulk {
width: 5rem;
@include breakpoint(desktop) {
width: 4rem;
}
@include breakpoint(tablet) {
width: 3.5rem;
}
@include breakpoint(mobile) {
width: 2.8rem;
}
}
input.bulk.first {
border-right: 0;
}
input.bulk.second {
border-left: 0;
}
.bulk-input-container {
float: right;
@include breakpoint(phablet) {
float: left !important;
}
.bulk-input {
float: left;
}
&[disabled] {
&:hover, &:focus {
background-color: $orange-500;
}
}
}
button.variant-quantity {
width: 3rem;
&:nth-of-type(1):not(.bulk-buy):not(.bulk-buy-add) {
border-right: .1em solid $orange-400;
}
}
.variant-quantity-display {
display: inline-block;
font-size: 0.875em;
margin-top: 0.25em;
text-align: center;
width: 6rem;
visibility: hidden;
&.visible {
visibility: visible;
}
}
button.bulk-buy.variant-quantity {
background-color: transparent;
border: .1em solid $grey-200;
color: inherit;
}
button.bulk-buy-add.variant-quantity {
width: 2.5rem;
&[disabled] {
background-color: $grey-400;
&:hover, &:focus {
background-color: $grey-400;
}
}
}
span.bulk-buy.variant-quantity {
border: .1em solid $grey-200;
height: 2.5rem;
display: inline-block;
min-width: 3em;
padding: .5em;
text-align: center;
vertical-align: top;
}
.variant-bulk-buy-price-summary {
color: $disabled-med;
margin-bottom: 1em;
}
.variant-bulk-buy-quantity-label {
font-size: 0.875rem;
margin-bottom: .5em;
}

View File

@@ -178,7 +178,7 @@ shop ordercycle {
}
shop navigation ordercycle {
margin-top: 3em;
margin-top: 3.4em;
padding: 1em;
height: 7.6em;
position: absolute;

View File

@@ -4,86 +4,69 @@
// Pop over
// Foundation overrides
.joyride-tip-guide.price_breakdown {
width: 16rem;
max-width: 65%;
// JS needs to be tweaked to adjust for left alignment - this is dynamic can't rewrite in CSS
background-color: #999;
color: #1f1f1f;
margin-left: -8px;
margin-left: -7.4rem;
margin-top: 0.1rem;
@include box-shadow(0 1px 2px 0 rgba(0, 0, 0, 0.7));
@include box-shadow(0 2px 8px 0 rgba(0, 0, 0, 0.35));
.joyride-content-wrapper {
padding: 1.125rem 1.25rem 1.5rem;
padding: 1rem;
margin: 1%;
padding: .625rem;
width: 98%;
background-color: white;
}
h1, h2, h3, h4, h5, h6 {
color: #1f1f1f;
}
.joyride-nub.right {
top: 38px;
border-color: #999 !important;
border-top-color: transparent !important;
border-right-color: transparent !important;
border-bottom-color: transparent !important;
}
.progress {
background-color: #13bf85;
padding: 0;
border: none;
background-color: $grey-800;
color: white;
font-size: 0.75rem;
font-style: oblique;
line-height: 1;
height: auto;
.right {
padding: 0.5rem 0.25rem 0 0;
}
.meter {
background-color: #0b8c61;
padding: 0.5rem 0.25rem;
border-right: 1px solid #539f92;
}
}
.expanded {
ul, li {
list-style: none;
margin: 0;
font-size: 0.875rem;
}
h6 {
font-size: 0.937rem;
line-height: 1;
border-bottom: .1em solid $grey-700;
padding: 0 0 .625em 0;
margin-bottom: 2px;
}
li {
background-color: #13bf85;
padding: 0 0.25rem;
margin-bottom: 2px;
color: white;
}
.joyride-nub.top {
left: 7.4rem;
z-index: -1;
}
li.cost {
background-color: #0b8c61;
}
.background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
cursor: pointer;
}
li:last-child {
margin-bottom: 0.75rem;
}
ul, li {
list-style: none;
margin: 0;
font-size: 0.875rem;
}
li {
line-height: 1;
border-bottom: .1em solid $grey-700;
padding: 0.625rem 0;
margin-bottom: 2px;
}
li:last-child {
border-bottom: 0;
padding-bottom: 0;
}
}
button.graph-button {
// z-index: 9999999
border: 1px solid transparent;
padding: 0;
margin: 0;
display: inline;
display: inline-block;
background-color: rgba(255, 255, 255, 0.5);
padding: 4px;
@include box-shadow(none);
@@ -97,7 +80,6 @@ button.graph-button {
}
&:focus {
border: 1px solid #e0e0e0;
background-color: rgba(255, 255, 255, 1);
&:before {
@@ -107,22 +89,15 @@ button.graph-button {
&:hover, &:active {
background-color: rgba(255, 255, 255, 1);
border: 1px solid transparent;
&:before {
color: $clr-brick-bright;
color: $teal-500;
}
}
@include breakpoint(tablet) {
// Hide for small
display: none;
}
}
button.graph-button.open {
border: 1px solid transparent;
background-color: $clr-brick-bright;
background-color: $teal-500;
&:before {
content: "";

View File

@@ -10,91 +10,57 @@
.columns {
padding-top: 0em;
padding-bottom: 0em;
display: table;
line-height: 1.1;
// outline: 1px solid red
@include breakpoint(tablet) {
font-size: 0.875rem;
}
@include breakpoint(phablet) {
font-size: 0.75rem;
}
}
}
.table-cell {
display: table-cell;
vertical-align: middle;
height: 37px;
.shop-variants {
// product-thumb width + 1rem
padding-left: calc(22.222% + 1rem);
@include breakpoint(phablet) {
padding-left: 0;
clear: left;
}
}
// ROW VARIANTS
.row.variants {
margin-left: 0;
margin-right: 0;
background-color: #ECECEC;
&:hover, &:focus, &:active {
background-color: $clr-brick-light;
}
&:nth-of-type(even) {
background-color: #f9f9f9;
&:hover, &:focus, &:active {
background-color: $clr-brick-ultra-light;
}
}
margin: 0 0 1em 0;
&.out-of-stock {
opacity: 0.2;
}
.variant-name,
.total-price {
padding-top: .74em;
}
.variant-price {
padding-top: .65em;
}
// Variant name
.variant-name {
padding-left: 7.9375rem;
padding-left: 0;
padding-right: 0;
@include breakpoint(tablet) {
padding-left: 4.9375rem;
}
}
.variant-name {
@include breakpoint(phablet) {
background: #333;
color: white;
padding-left: 0.9375rem;
font-weight: bold;
.table-cell {
height: 27px;
}
padding-left: 0.5rem;
}
}
// Variant unit
.variant-unit {
padding-left: 0rem;
padding-right: 0rem;
color: #888;
font-size: 0.875rem;
overflow: hidden;
@include breakpoint(tablet) {
font-size: 0.75rem;
& > *:nth-child(n + 2) {
color: $grey-550;
font-size: 0.875rem;
font-style: italic;
line-height: normal;
}
}
// Variant price
.variant-price {
padding-left: 0.25rem;
padding-right: 0.25rem;
@include breakpoint(phablet) {
text-align: right;
padding-left: 1rem;
}
}
@@ -108,24 +74,16 @@
}
@include breakpoint(phablet) {
background: #777;
color: $disabled-med;
.filled {
color: white;
}
.table-cell {
height: 27px;
}
display: none;
}
}
}
// ROW SUMMARY
.row.summary {
.summary {
margin-left: 0;
margin-right: 0;
margin-bottom: 1.25em;
background: #fff;
.columns {
@@ -140,39 +98,77 @@
}
.summary-header {
padding-left: 7.9375rem;
@include breakpoint(tablet) {
padding-left: 4.9375rem;
}
// product-thumb width + 1rem
padding-left: calc(22.222% + 1rem);
padding-right: 1rem;
@include breakpoint(phablet) {
padding-left: 0.9375rem;
padding-left: calc(33.333% + 1rem);
}
small {
font-size: 80%;
.product-producer {
color: $grey-550;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-style: italic;
a {
color: $teal-500;
&:hover, &:focus, &:active {
color: $teal-600;
text-decoration: underline;
}
}
}
h3 {
font-size: 1.5rem;
margin: 0;
font-size: 1.3rem;
margin-top: 0.75rem;
margin-bottom: 0.6rem;
}
h3 a {
color: #222;
i {
@include csstrans;
font-size: 0.6em;
}
color: $orange-500;
&:hover, &:focus, &:active {
color: $clr-brick;
color: $orange-600;
text-decoration: underline;
}
}
i {
font-size: 0.8em;
.product-description {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: 0.75rem;
}
.product-properties {
margin: .5em 0;
li {
margin: 0 0.25rem 0.25rem 0;
a {
padding: 0.1em 0.625em;
cursor: auto;
&.has-tip {
cursor: pointer;
font-weight: normal;
}
&:hover, &:focus {
border-color: #ccc;
}
}
// Foundation doesn't show the nub on mobile.
// Repeating the style to show it here.
.nub {
border-color: transparent transparent #333333 transparent;
}
}
}

View File

@@ -1,80 +1,32 @@
@import "mixins";
@import "branding";
@import "animations";
.darkswarm {
products {
product {
.product-thumb {
@include csstrans;
position: absolute;
top: 2px;
left: 0px;
width: 7rem;
height: 7rem;
// Desktop: the product summary is nine columns wide. Use two
// for the image. 100% / 9 * 2 = 22.222% <= 192px
width: calc(22.222%);
float: left;
display: block;
z-index: 1;
background-color: white;
overflow: hidden;
i {
@include csstrans;
transition-delay: 150ms;
position: absolute;
left: 45%;
top: 45%;
z-index: 99999;
color: white;
font-size: 1rem;
opacity: 0;
}
img {
@include csstrans;
opacity: 1;
@include transform-scale(scale(1));
}
&:hover, &:focus, &:active {
background-color: $clr-brick;
i {
left: 32%;
top: 30%;
font-size: 3rem;
opacity: 1;
}
img {
opacity: 0.5;
@include transform-scale(scale(1.1));
}
}
@include breakpoint(tablet) {
top: 2px;
width: 4rem;
height: 4rem;
&:hover, &:focus, &:active {
i {
left: 30%;
top: 30%;
font-size: 2rem;
}
}
}
// Mobile: the summary has full twelve columns and the image
// should take four of them. 100% / 12 * 4 = 33.333% <= 227px
@include breakpoint(phablet) {
display: none;
width: 0rem;
height: 0rem;
width: calc(33.333%);
}
// Make this an anchor for the bulk label.
position: relative;
.product-thumb__bulk-label {
background-color: $grey-700;
color: white;
position: absolute;
right: 0;
top: .8em;
padding: .25em .5em;
}
&:hover {
filter: brightness(96%);
}
}
}

View File

@@ -1,47 +0,0 @@
@import "mixins";
.darkswarm {
products {
product {
.taxon-flag {
background: transparent image-url("flag.svg") top center no-repeat;
background-size: 34px 39px;
min-height: 40px;
width: 34px;
margin-top: -1.1rem;
padding-top: 0.25rem;
z-index: 999999;
@include breakpoint(mobile) {
background-size: 28px 32px;
min-height: 32px;
width: 28px;
}
render-svg {
svg {
width: 24px;
height: 24px;
path {
fill: #999;
}
}
}
@include breakpoint(tablet) {
margin-top: -0.85rem;
}
@include breakpoint(mobile) {
render-svg {
svg {
width: 18px;
height: 18px;
}
}
}
}
}
}
}

View File

@@ -11,7 +11,6 @@ $ofn-grey: #808184;
$clr-brick: #c1122b;
$clr-brick-light: #f5e6e7;
$clr-brick-light-trans: rgba(245, 230, 231, 0.9);
$clr-brick-ultra-light: #faf5f6;
$clr-brick-bright: #eb4c46;
$clr-brick-med-bright: #e5a2a0;
$clr-brick-light-bright: #f5c4c9;
@@ -48,6 +47,7 @@ $grey-200: #ddd;
$grey-300: #ccc;
$grey-400: #bbb;
$grey-500: #999;
$grey-550: #888;
$grey-600: #777;
$grey-650: #666;
$grey-700: #555;
@@ -56,6 +56,7 @@ $grey-800: #333;
$teal-300: #80d3df;
$teal-400: #4cb5c5;
$teal-500: #0096ad;
$teal-600: #007a9a;
$orange-400: #ff9466;
$orange-450: #f4704c;

View File

@@ -59,13 +59,6 @@ body.embedded {
line-height: $large-menu-height;
height: $large-menu-height;
vertical-align: top;
&.cart {
div.joyride-tip-guide { // Cart Dropdown
top: 75px;
overflow: visible;
}
}
}
}

View File

@@ -142,57 +142,6 @@
// Background options \\
@mixin darkbg {
background-color: $clr-brick;
&, & * {
color: white;
}
a {
color: $clr-brick-ultra-light;
&:hover {
text-decoration: none;
color: $clr-brick-light;
}
}
}
@mixin lightbg {
background-color: $clr-brick-light;
&, & * {
color: black;
}
a {
color: $clr-brick;
&:hover {
text-decoration: none;
color: $clr-brick-bright;
}
}
}
@mixin turqbg {
background-color: $clr-turquoise-light;
&, & * {
color: $clr-turquoise;
}
a {
color: $clr-turquoise;
&:hover {
text-decoration: none;
color: $clr-turquoise-bright;
}
}
}
@mixin fullbg {
background-position: center center;
background-repeat: no-repeat;
@@ -202,12 +151,6 @@
background-size: cover;
}
@mixin fullwidthbg {
background-position: center top;
background-repeat: no-repeat;
background-size: 100% auto;
}
@mixin gradient($gradient-clr1, $gradient-clr2) {
background: $gradient-clr1;

View File

@@ -8,10 +8,30 @@
@import "shop-inputs";
@import "shop-navigation";
@import "shop-product-rows";
@import "shop-taxon-flag";
@import "shop-popovers";
.darkswarm {
.product-listing {
@include breakpoint(desktop) {
padding-right: 0;
padding-left: 0;
}
.row.full {
width: 100%;
margin: 0;
.columns.full {
padding-right: 0;
padding-left: 0;
}
}
}
.filter-header {
margin-top: 1.1em;
}
products {
display: block;
@@ -51,32 +71,18 @@
product {
@include csstrans;
border-bottom: 1px solid #e5e5e5;
border-top: 1px solid #e5e5e5;
// Avoid margin collapsing which breaks the flush alignment of the first
// image.
overflow: auto;
&:nth-child(n + 2) {
border-top: 1px solid $grey-100;
}
padding-bottom: 1px;
margin-bottom: 20px !important;
position: relative;
display: block;
color: $med-drk-grey;
&:hover, &:focus, &:active {
border-bottom: 1px solid $clr-brick-med-bright;
border-top: 1px solid $clr-brick-med-bright;
}
// BULK
.bulk-buy {
font-size: 0.875rem;
@include breakpoint(tablet) {
font-size: 0.75rem;
}
}
.bulk-buy, .bulk-buy i {
color: #888;
}
.inline {
display: inline;
}
@@ -85,27 +91,6 @@
width: 100px;
margin-bottom: 20px;
}
// ICONS
i {
font-size: 0.75em;
padding-right: 0.9375rem;
@include breakpoint(phablet) {
padding-right: 0.25rem;
}
}
i.ofn-i_056-bulk {
font-size: 1rem;
padding-right: 0rem;
}
i.ofn-i_036-producers {
padding-left: 0.2rem;
padding-right: 0rem;
font-size: 0.8rem;
}
}
}

View File

@@ -6,7 +6,6 @@
background-color: $grey-100;
height: 5em;
padding: 1em 0;
margin-bottom: 1em;
position: relative;
z-index: 5;
@@ -50,7 +49,7 @@
button {
background-color: $grey-600;
margin-left: 1em;
margin: 0 0 0 1em;
height: 3em;
width: 7em;
padding: 0;

View File

@@ -159,11 +159,6 @@ a.button.large {
display: flex;
}
.no-gutter {
padding-right: 0;
padding-left: 0;
}
.disable-scroll {
overflow: hidden;
}

View File

@@ -73,7 +73,7 @@ module Admin
if @enterprise.update(attributes)
flash[:success] = I18n.t(:enterprise_register_success_notice, enterprise: @enterprise.name)
redirect_to admin_dashboard_path
redirect_to spree.admin_dashboard_path
else
flash[:error] = I18n.t(:enterprise_register_error, enterprise: @enterprise.name)
render :welcome, layout: "spree/layouts/bare_admin"

View File

@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'open_food_network/address_finder'
require 'spree/core/gateway_error'
class CheckoutController < Spree::StoreController
layout 'darkswarm'
@@ -47,8 +48,6 @@ class CheckoutController < Spree::StoreController
params_adapter = Checkout::FormDataAdapter.new(permitted_params, @order, spree_current_user)
return action_failed unless @order.update(params_adapter.params[:order])
fire_event('spree.checkout.update')
checkout_workflow(params_adapter.shipping_method_id)
rescue Spree::Core::GatewayError => e
rescue_from_spree_gateway_error(e)
@@ -150,7 +149,7 @@ class CheckoutController < Spree::StoreController
def handle_redirect_from_stripe
if OrderWorkflow.new(@order).next && order_complete?
checkout_succeeded
redirect_to(order_path(@order)) && return
redirect_to(spree.order_path(@order)) && return
else
checkout_failed
end
@@ -210,10 +209,10 @@ class CheckoutController < Spree::StoreController
def update_succeeded_response
respond_to do |format|
format.html do
respond_with(@order, location: order_path(@order))
respond_with(@order, location: spree.order_path(@order))
end
format.json do
render json: { path: order_path(@order) }, status: :ok
render json: { path: spree.order_path(@order) }, status: :ok
end
end
end

View File

@@ -17,7 +17,7 @@ module Spree
end
flash[:success] = Spree.t(:successfully_updated, resource: Spree.t(:general_settings))
redirect_to edit_admin_general_settings_path
redirect_to spree.edit_admin_general_settings_path
end
end
end

View File

@@ -1,79 +0,0 @@
module Spree
module Admin
class ImageSettingsController < Spree::Admin::BaseController
def edit
@styles = ActiveSupport::JSON.decode(Spree::Config[:attachment_styles])
@headers = ActiveSupport::JSON.decode(Spree::Config[:s3_headers])
end
def update
update_styles(params)
update_headers(params) if Spree::Config[:use_s3]
Spree::Config.set(params[:preferences])
update_paperclip_settings
respond_to do |format|
format.html {
flash[:success] = Spree.t(:image_settings_updated)
redirect_to spree.edit_admin_image_settings_path
}
end
end
private
def update_styles(params)
if params[:new_attachment_styles].present?
params[:new_attachment_styles].each do |_index, style|
params[:attachment_styles][style[:name]] = style[:value] if style[:value].present?
end
end
styles = params[:attachment_styles]
Spree::Config[:attachment_styles] = ActiveSupport::JSON.encode(styles) unless styles.nil?
end
def update_headers(params)
if params[:new_s3_headers].present?
params[:new_s3_headers].each do |_index, header|
params[:s3_headers][header[:name]] = header[:value] if header[:value].present?
end
end
headers = params[:s3_headers]
Spree::Config[:s3_headers] = ActiveSupport::JSON.encode(headers) unless headers.nil?
end
def update_paperclip_settings
if Spree::Config[:use_s3]
s3_creds = { access_key_id: Spree::Config[:s3_access_key],
secret_access_key: Spree::Config[:s3_secret],
bucket: Spree::Config[:s3_bucket] }
Spree::Image.attachment_definitions[:attachment][:storage] = :s3
Spree::Image.attachment_definitions[:attachment][:s3_credentials] = s3_creds
Spree::Image.attachment_definitions[:attachment][:s3_headers] =
ActiveSupport::JSON.decode(Spree::Config[:s3_headers])
Spree::Image.attachment_definitions[:attachment][:bucket] = Spree::Config[:s3_bucket]
else
Spree::Image.attachment_definitions[:attachment].delete :storage
end
Spree::Image.attachment_definitions[:attachment][:styles] =
ActiveSupport::JSON.decode(Spree::Config[:attachment_styles]).symbolize_keys!
Spree::Image.attachment_definitions[:attachment][:path] = Spree::Config[:attachment_path]
Spree::Image.attachment_definitions[:attachment][:default_url] =
Spree::Config[:attachment_default_url]
Spree::Image.attachment_definitions[:attachment][:default_style] =
Spree::Config[:attachment_default_style]
# Spree stores attachent definitions in JSON. This converts the style name and format to
# strings. However, when paperclip encounters these, it doesn't recognise the format.
# Here we solve that problem by converting format and style name to symbols.
Spree::Image.reformat_styles
end
end
end
end

View File

@@ -61,7 +61,7 @@ module Spree
private
def location_after_save
admin_product_images_url(@product)
spree.admin_product_images_url(@product)
end
def load_data

View File

@@ -23,7 +23,7 @@ module Spree
rescue StandardError => e
flash[:error] = Spree.t('admin.mail_methods.testmail.error') % { e: e }
ensure
redirect_to edit_admin_mail_methods_url
redirect_to spree.edit_admin_mail_methods_url
end
private

View File

@@ -27,7 +27,7 @@ module Spree
@order.shipments.map(&:refresh_rates)
flash[:success] = Spree.t('customer_details_updated')
redirect_to admin_order_customer_path(@order)
redirect_to spree.admin_order_customer_path(@order)
else
render action: :edit
end

View File

@@ -29,7 +29,7 @@ module Spree
@order = Order.create
@order.created_by = spree_current_user
@order.save
redirect_to edit_admin_order_url(@order)
redirect_to spree.edit_admin_order_url(@order)
end
def edit
@@ -48,16 +48,16 @@ module Spree
if @order.line_items.empty?
@order.errors.add(:line_items, Spree.t('errors.messages.blank'))
end
return redirect_to(edit_admin_order_path(@order),
return redirect_to(spree.edit_admin_order_path(@order),
flash: { error: @order.errors.full_messages.join(', ') })
end
@order.update!
if @order.complete?
redirect_to edit_admin_order_path(@order)
redirect_to spree.edit_admin_order_path(@order)
else
# Jump to next step if order is not complete
redirect_to admin_order_customer_path(@order)
redirect_to spree.admin_order_customer_path(@order)
end
end
@@ -91,7 +91,9 @@ module Spree
Spree::OrderMailer.invoice_email(@order.id, pdf).deliver
flash[:success] = t('admin.orders.invoice_email_sent')
respond_with(@order) { |format| format.html { redirect_to edit_admin_order_path(@order) } }
respond_with(@order) { |format|
format.html { redirect_to spree.edit_admin_order_path(@order) }
}
end
def print
@@ -131,7 +133,9 @@ module Spree
flash[:error] = t(:must_have_valid_business_number,
enterprise_name: @order.distributor.name)
respond_with(@order) { |format| format.html { redirect_to edit_admin_order_path(@order) } }
respond_with(@order) { |format|
format.html { redirect_to spree.edit_admin_order_path(@order) }
}
end
def load_distribution_choices

View File

@@ -22,7 +22,7 @@ module Spree
if @payment_method.save
invoke_callbacks(:create, :after)
flash[:success] = Spree.t(:successfully_created, resource: Spree.t(:payment_method))
redirect_to edit_admin_payment_method_path(@payment_method)
redirect_to spree.edit_admin_payment_method_path(@payment_method)
else
invoke_callbacks(:create, :fails)
respond_with(@payment_method)
@@ -43,7 +43,7 @@ module Spree
if @payment_method.update(params_for_update)
invoke_callbacks(:update, :after)
flash[:success] = Spree.t(:successfully_updated, resource: Spree.t(:payment_method))
redirect_to edit_admin_payment_method_path(@payment_method)
redirect_to spree.edit_admin_payment_method_path(@payment_method)
else
invoke_callbacks(:update, :fails)
respond_with(@payment_method)
@@ -122,7 +122,7 @@ module Spree
return if valid_payment_methods.include?(params[:payment_method][:type])
flash[:error] = Spree.t(:invalid_payment_provider)
redirect_to new_admin_payment_method_path
redirect_to spree.new_admin_payment_method_path
end
def load_hubs

View File

@@ -12,7 +12,7 @@ module Spree
def index
@payments = @order.payments
redirect_to new_admin_order_payment_url(@order) if @payments.empty?
redirect_to spree.new_admin_order_payment_url(@order) if @payments.empty?
end
def new
@@ -25,7 +25,7 @@ module Spree
begin
unless @payment.save
redirect_to admin_order_payments_path(@order)
redirect_to spree.admin_order_payments_path(@order)
return
end
@@ -35,16 +35,16 @@ module Spree
@payment.process!
flash[:success] = flash_message_for(@payment, :successfully_created)
redirect_to admin_order_payments_path(@order)
redirect_to spree.admin_order_payments_path(@order)
else
OrderWorkflow.new(@order).complete!
flash[:success] = Spree.t(:new_order_completed)
redirect_to edit_admin_order_url(@order)
redirect_to spree.edit_admin_order_url(@order)
end
rescue Spree::Core::GatewayError => e
flash[:error] = e.message.to_s
redirect_to new_admin_order_payment_path(@order)
redirect_to spree.new_admin_order_payment_path(@order)
end
end
@@ -118,7 +118,7 @@ module Spree
return if @order.payment? || @order.complete?
flash[:notice] = Spree.t(:fill_in_customer_info)
redirect_to edit_admin_order_customer_url(@order)
redirect_to spree.edit_admin_order_customer_url(@order)
end
def load_order

View File

@@ -29,9 +29,9 @@ module Spree
if @object.save
flash[:success] = flash_message_for(@object, :successfully_created)
if params[:button] == "add_another"
redirect_to new_admin_product_path
redirect_to spree.new_admin_product_path
else
redirect_to admin_products_path
redirect_to spree.admin_products_path
end
else
render :new
@@ -70,7 +70,7 @@ module Spree
flash[:success] = flash_message_for(@object, :successfully_updated)
end
redirect_to edit_admin_product_url(@object, @url_filters)
redirect_to spree.edit_admin_product_url(@object, @url_filters)
end
end
@@ -97,7 +97,7 @@ module Spree
Spree.t('notice_messages.product_not_cloned')
end
redirect_to edit_admin_product_url(@new)
redirect_to spree.edit_admin_product_url(@new)
end
def group_buy_options

View File

@@ -74,7 +74,7 @@ module Spree
end
def location_after_save
edit_admin_shipping_method_path(@shipping_method)
spree.edit_admin_shipping_method_path(@shipping_method)
end
def load_data

View File

@@ -14,7 +14,7 @@ module Spree
protected
def location_after_save
admin_country_states_url(@country)
spree.admin_country_states_url(@country)
end
def collection

View File

@@ -6,7 +6,7 @@ module Spree
respond_to do |format|
format.html {
redirect_to edit_admin_tax_settings_path
redirect_to spree.edit_admin_tax_settings_path
}
end
end

View File

@@ -11,9 +11,9 @@ module Spree
def location_after_save
if @taxonomy.created_at == @taxonomy.updated_at
edit_admin_taxonomy_url(@taxonomy)
spree.edit_admin_taxonomy_url(@taxonomy)
else
admin_taxonomies_url
spree.admin_taxonomies_url
end
end

View File

@@ -15,9 +15,9 @@ module Spree
respond_with(@taxon) do |format|
format.html do
if redirect_to @taxonomy
edit_admin_taxonomy_url(@taxonomy)
spree.edit_admin_taxonomy_url(@taxonomy)
else
admin_taxonomies_url
spree.admin_taxonomies_url
end
end
end
@@ -95,7 +95,7 @@ module Spree
end
respond_with(@taxon) do |format|
format.html { redirect_to edit_admin_taxonomy_url(@taxonomy) }
format.html { redirect_to spree.edit_admin_taxonomy_url(@taxonomy) }
format.json { render json: @taxon.to_json }
end
end

View File

@@ -60,14 +60,14 @@ module Spree
if @user.generate_spree_api_key!
flash[:success] = t('spree.api.key_generated')
end
redirect_to edit_admin_user_path(@user)
redirect_to spree.edit_admin_user_path(@user)
end
def clear_api_key
if @user.clear_spree_api_key!
flash[:success] = t('spree.api.key_cleared')
end
redirect_to edit_admin_user_path(@user)
redirect_to spree.edit_admin_user_path(@user)
end
protected

View File

@@ -61,17 +61,21 @@ module Spree
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
@variant = Spree::Variant.find(params[:id])
flash[:success] = if VariantDeleter.new.delete(@variant)
Spree.t('notice_messages.variant_deleted')
else
Spree.t('notice_messages.variant_not_deleted')
end
flash[:success] = delete_variant
redirect_to admin_product_variants_url(params[:product_id], @url_filters)
redirect_to spree.admin_product_variants_url(params[:product_id], @url_filters)
end
protected
def delete_variant
if VariantDeleter.new.delete(@variant)
Spree.t('notice_messages.variant_deleted')
else
Spree.t('notice_messages.variant_not_deleted')
end
end
def create_before
option_values = params[:new_variant]
option_values.andand.each_value { |id| @object.option_values << OptionValue.find(id) }

View File

@@ -3,8 +3,8 @@
require 'cancan'
require 'spree/core/controller_helpers/auth'
require 'spree/core/controller_helpers/respond_with'
require 'spree/core/controller_helpers/common'
require 'spree/core/controller_helpers/ssl'
require 'spree/core/controller_helpers/common'
module Spree
class BaseController < ApplicationController

View File

@@ -48,10 +48,10 @@ module Spree
else
flash[:error] = I18n.t(:card_could_not_be_removed)
end
redirect_to account_path(anchor: 'cards')
redirect_to spree.account_path(anchor: 'cards')
rescue Stripe::CardError
flash[:error] = I18n.t(:card_could_not_be_removed)
redirect_to account_path(anchor: 'cards')
redirect_to spree.account_path(anchor: 'cards')
end
private

View File

@@ -78,11 +78,7 @@ module Spree
discard_empty_line_items
with_open_adjustments { update_totals_and_taxes }
if @order == current_order
fire_event('spree.order.contents_changed')
else
@order.update_distribution_charge!
end
@order.update_distribution_charge!
respond_with(@order) do |format|
format.html do
@@ -90,7 +86,7 @@ module Spree
@order.next_transition.run_callbacks if @order.cart?
redirect_to checkout_state_path(@order.checkout_steps.first)
elsif @order.complete?
redirect_to order_path(@order)
redirect_to spree.order_path(@order)
else
redirect_to main_app.cart_path
end
@@ -157,7 +153,7 @@ module Spree
else
flash[:error] = I18n.t(:orders_could_not_cancel)
end
redirect_to request.referer || order_path(@order)
redirect_to request.referer || spree.order_path(@order)
end
private
@@ -221,7 +217,7 @@ module Spree
if items.empty?
flash[:error] = I18n.t(:orders_cannot_remove_the_final_item)
redirect_to order_path(order_to_update)
redirect_to spree.order_path(order_to_update)
end
end

View File

@@ -7,7 +7,7 @@ require "spree/core/controller_helpers/ssl"
module Spree
class UserPasswordsController < Devise::PasswordsController
helper 'spree/base', 'spree/store'
helper 'spree/base'
include Spree::Core::ControllerHelpers::Auth
include Spree::Core::ControllerHelpers::Common

View File

@@ -7,7 +7,7 @@ require "spree/core/controller_helpers/ssl"
module Spree
class UserRegistrationsController < Devise::RegistrationsController
helper 'spree/base', 'spree/store'
helper 'spree/base'
include Spree::Core::ControllerHelpers::Auth
include Spree::Core::ControllerHelpers::Common

View File

@@ -7,7 +7,7 @@ require "spree/core/controller_helpers/ssl"
module Spree
class UserSessionsController < Devise::SessionsController
helper 'spree/base', 'spree/store'
helper 'spree/base'
include Spree::Core::ControllerHelpers::Auth
include Spree::Core::ControllerHelpers::Common

View File

@@ -1,21 +0,0 @@
module Admin
module ImageSettingsHelper
def admin_image_settings_format_options
[['Unchanged', ''], ['PNG', 'png'], ['JPEG', 'jpg']]
end
def admin_image_settings_geometry_from_style(style)
geometry, _format = admin_image_settings_split_style style
geometry
end
def admin_image_settings_format_from_style(style)
_geometry, format = admin_image_settings_split_style style
format
end
def admin_image_settings_split_style(style)
[style, nil].flatten[0..1]
end
end
end

View File

@@ -8,10 +8,12 @@ module Spree
def reset_password_instructions(user, token, _opts = {})
@edit_password_reset_url = spree.
edit_spree_user_password_url(reset_password_token: token)
subject = "#{Spree::Config[:site_name]} " \
"#{I18n.t('spree.user_mailer.reset_password_instructions.subject')}"
mail(to: user.email, from: from_address,
subject: Spree::Config[:site_name] + ' ' +
I18n.t(:subject, scope: [:devise, :mailer, :reset_password_instructions]))
I18n.with_locale valid_locale(user) do
mail(to: user.email, from: from_address, subject: subject)
end
end
# This is a OFN specific email, not from Devise::Mailer

View File

@@ -1,5 +1,6 @@
require 'open_food_network/locking'
require 'open_food_network/permalink_generator'
require 'spree/core/s3_support'
class EnterpriseGroup < ActiveRecord::Base
include PermalinkGenerator

View File

@@ -0,0 +1,148 @@
# frozen_string_literal: true
# This is the primary location for defining spree preferences
#
# This file allows us to add global configuration variables, which
# we can allow to be modified in the UI by adding appropriate form
# elements to existing or new configuration pages.
#
# The expectation is that this is created once and stored in
# the spree environment
#
# setters:
# a.color = :blue
# a[:color] = :blue
# a.set :color = :blue
# a.preferred_color = :blue
#
# getters:
# a.color
# a[:color]
# a.get :color
# a.preferred_color
#
module Spree
class AppConfiguration < Preferences::Configuration
# Should state/state_name be required
preference :address_requires_state, :boolean, default: true
preference :admin_interface_logo, :string, default: 'ofn-logo.png'
preference :admin_products_per_page, :integer, default: 10
# Should only be true if you don't need to track inventory
preference :allow_backorder_shipping, :boolean, default: false
preference :allow_checkout_on_gateway_error, :boolean, default: false
preference :allow_guest_checkout, :boolean, default: true
preference :allow_ssl_in_development_and_test, :boolean, default: false
preference :allow_ssl_in_production, :boolean, default: true
preference :allow_ssl_in_staging, :boolean, default: true
# Automatically capture the credit card (as opposed to just authorize and capture later)
preference :auto_capture, :boolean, default: false
# Replace with the name of a zone if you would like to limit the countries
preference :checkout_zone, :string, default: nil
preference :currency, :string, default: "USD"
preference :currency_decimal_mark, :string, default: "."
preference :currency_symbol_position, :string, default: "before"
preference :currency_thousands_separator, :string, default: ","
preference :display_currency, :boolean, default: false
preference :default_country_id, :integer
preference :default_meta_description, :string, default: 'OFN demo site'
preference :default_meta_keywords, :string, default: 'ofn, demo'
preference :default_seo_title, :string, default: ''
preference :hide_cents, :boolean, default: false
preference :layout, :string, default: 'darkswarm'
preference :logo, :string, default: 'ofn-logo.png'
# Maximum nesting level in taxons menu
preference :max_level_in_taxons_menu, :integer, default: 1
preference :orders_per_page, :integer, default: 15
preference :prices_inc_tax, :boolean, default: false
preference :products_per_page, :integer, default: 12
preference :redirect_https_to_http, :boolean, default: false
preference :require_master_price, :boolean, default: true
preference :shipment_inc_vat, :boolean, default: false
# Request instructions/info for shipping
preference :shipping_instructions, :boolean, default: false
# Displays variant full price or difference with product price.
preference :show_variant_full_price, :boolean, default: false
preference :show_products_without_price, :boolean, default: false
preference :show_raw_product_description, :boolean, default: false
preference :site_name, :string, default: 'OFN Demo Site'
preference :site_url, :string, default: 'demo.openfoodnetwork.org'
preference :tax_using_ship_address, :boolean, default: true
# Determines whether to track on_hand values for variants / products.
preference :track_inventory_levels, :boolean, default: true
# Preferences related to image settings
preference :attachment_default_url, :string,
default: '/spree/products/:id/:style/:basename.:extension'
preference :attachment_path, :string,
default: ':rails_root/public/spree/products/:id/:style/:basename.:extension'
preference :attachment_url, :string,
default: '/spree/products/:id/:style/:basename.:extension'
preference :attachment_styles, :string,
default: "{\"mini\":\"48x48>\",\"small\":\"100x100>\",\"product\":\"240x240>\",\"large\":\"600x600>\"}"
preference :attachment_default_style, :string, default: 'product'
preference :s3_access_key, :string
preference :s3_bucket, :string
preference :s3_secret, :string
preference :s3_headers, :string, default: "{\"Cache-Control\":\"max-age=31557600\"}"
preference :use_s3, :boolean, default: false # Use S3 for images rather than the file system
preference :s3_protocol, :string
preference :s3_host_alias, :string
# Default mail headers settings
preference :enable_mail_delivery, :boolean, default: false
preference :mails_from, :string, default: 'ofn@example.com'
preference :mail_bcc, :string, default: 'ofn@example.com'
preference :intercept_email, :string, default: nil
# Default smtp settings
preference :override_actionmailer_config, :boolean, default: true
preference :mail_host, :string, default: 'localhost'
preference :mail_domain, :string, default: 'localhost'
preference :mail_port, :integer, default: 25
preference :secure_connection_type, :string,
default: Core::MailSettings::SECURE_CONNECTION_TYPES[0]
preference :mail_auth_type, :string, default: Core::MailSettings::MAIL_AUTH[0]
preference :smtp_username, :string
preference :smtp_password, :string
# Embedded Shopfronts
preference :enable_embedded_shopfronts, :boolean, default: false
preference :embedded_shopfronts_whitelist, :text, default: nil
# Legal Preferences
preference :footer_tos_url, :string, default: "/Terms-of-service.pdf"
preference :enterprises_require_tos, :boolean, default: false
preference :privacy_policy_url, :string, default: nil
preference :cookies_consent_banner_toggle, :boolean, default: false
preference :cookies_policy_matomo_section, :boolean, default: false
# Tax Preferences
preference :products_require_tax_category, :boolean, default: false
preference :shipping_tax_rate, :decimal, default: 0
# Monitoring
preference :last_job_queue_heartbeat_at, :string, default: nil
# External services
preference :bugherd_api_key, :string, default: nil
preference :matomo_url, :string, default: nil
preference :matomo_site_id, :string, default: nil
preference :matomo_tag_manager_url, :string, default: nil
# Invoices & Receipts
preference :enable_invoices?, :boolean, default: true
preference :invoice_style2?, :boolean, default: false
preference :enable_receipt_printing?, :boolean, default: false
# Stripe Connect
preference :stripe_connect_enabled, :boolean, default: false
# Number localization
preference :enable_localized_number?, :boolean, default: false
# Enable cache
preference :enable_products_cache?, :boolean,
default: (Rails.env.production? || Rails.env.staging?)
end
end

View File

@@ -1,44 +0,0 @@
Spree::AppConfiguration.class_eval do
# This file decorates the existing preferences file defined by Spree.
# It allows us to add our own global configuration variables, which
# we can allow to be modified in the UI by adding appropriate form
# elements to existing or new configuration pages.
# Embedded Shopfronts
preference :enable_embedded_shopfronts, :boolean, default: false
preference :embedded_shopfronts_whitelist, :text, default: nil
# Legal Preferences
preference :footer_tos_url, :string, default: "/Terms-of-service.pdf"
preference :enterprises_require_tos, :boolean, default: false
preference :privacy_policy_url, :string, default: nil
preference :cookies_consent_banner_toggle, :boolean, default: false
preference :cookies_policy_matomo_section, :boolean, default: false
# Tax Preferences
preference :products_require_tax_category, :boolean, default: false
preference :shipping_tax_rate, :decimal, default: 0
# Monitoring
preference :last_job_queue_heartbeat_at, :string, default: nil
# External services
preference :bugherd_api_key, :string, default: nil
preference :matomo_url, :string, default: nil
preference :matomo_site_id, :string, default: nil
preference :matomo_tag_manager_url, :string, default: nil
# Invoices & Receipts
preference :enable_invoices?, :boolean, default: true
preference :invoice_style2?, :boolean, default: false
preference :enable_receipt_printing?, :boolean, default: false
# Stripe Connect
preference :stripe_connect_enabled, :boolean, default: false
# Number localization
preference :enable_localized_number?, :boolean, default: false
# Enable cache
preference :enable_products_cache?, :boolean, default: (Rails.env.production? || Rails.env.staging?)
end

View File

@@ -1,5 +1,8 @@
# frozen_string_literal: true
require 'concerns/payment_method_distributors'
require 'spree/core/delegate_belongs_to'
module Spree
class Gateway < PaymentMethod
include PaymentMethodDistributors

View File

@@ -5,13 +5,19 @@ module Spree
validates_attachment_presence :attachment
validate :no_attachment_errors
# This is where the styles are used in the app:
# - mini: used in the BackOffice: Bulk Product Edit page and Order Cycle edit page
# - small: used in the FrontOffice: Product List page
# - product: used in the BackOffice: Product Image upload modal in the Bulk Product Edit page
# and Product image edit page
# - large: used in the FrontOffice: product modal
has_attached_file :attachment,
styles: { mini: '48x48>', small: '100x100>',
product: '240x240>', large: '600x600>' },
styles: { mini: "48x48#", small: "227x227#",
product: "240x240>", large: "600x600>" },
default_style: :product,
url: '/spree/products/:id/:style/:basename.:extension',
path: ':rails_root/public/spree/products/:id/:style/:basename.:extension',
convert_options: { all: '-strip -auto-orient -colorspace RGB' }
convert_options: { all: '-strip -auto-orient -colorspace sRGB' }
# save the w,h of the original image (from which others can be calculated)
# we need to look at the write-queue for images which have not been saved yet
@@ -20,15 +26,6 @@ module Spree
include Spree::Core::S3Support
supports_s3 :attachment
Spree::Image.attachment_definitions[:attachment][:styles] =
ActiveSupport::JSON.decode(Spree::Config[:attachment_styles]).symbolize_keys!
Spree::Image.attachment_definitions[:attachment][:path] = Spree::Config[:attachment_path]
Spree::Image.attachment_definitions[:attachment][:url] = Spree::Config[:attachment_url]
Spree::Image.attachment_definitions[:attachment][:default_url] =
Spree::Config[:attachment_default_url]
Spree::Image.attachment_definitions[:attachment][:default_style] =
Spree::Config[:attachment_default_style]
# used by admin products autocomplete
def mini_url
attachment.url(:mini, false)
@@ -51,26 +48,26 @@ module Spree
false
end
# Spree stores attachent definitions in JSON. This converts the style name and format to
# strings. However, when paperclip encounters these, it doesn't recognise the format.
# Here we solve that problem by converting format and style name to symbols.
# See also: ImageSettingsController decorator.
#
# eg. {'mini' => ['48x48>', 'png']} is converted to {mini: ['48x48>', :png]}
def self.format_styles(styles)
styles_a = styles.map do |name, style|
style[1] = style[1].to_sym if style.is_a? Array
[name.to_sym, style]
def self.set_attachment_attributes(attribute_name, attribute_value)
attachment_definitions[:attachment][attribute_name] = attribute_value
end
def self.set_s3_attachment_definitions
if Spree::Config[:use_s3]
set_attachment_attributes(:storage, :s3)
set_attachment_attributes(:s3_credentials, s3_credentials)
set_attachment_attributes(:s3_headers,
ActiveSupport::JSON.decode(Spree::Config[:s3_headers]))
set_attachment_attributes(:bucket, Spree::Config[:s3_bucket])
else
attachment_definitions[:attachment].delete :storage
end
Hash[styles_a]
end
def self.reformat_styles
Spree::Image.attachment_definitions[:attachment][:styles] =
format_styles(Spree::Image.attachment_definitions[:attachment][:styles])
def self.s3_credentials
{ access_key_id: Spree::Config[:s3_access_key],
secret_access_key: Spree::Config[:s3_secret],
bucket: Spree::Config[:s3_bucket] }
end
reformat_styles
end
end

View File

@@ -6,11 +6,6 @@ require 'open_food_network/feature_toggle'
require 'open_food_network/tag_rule_applicator'
require 'concerns/order_shipment'
ActiveSupport::Notifications
.subscribe('spree.order.contents_changed') do |_name, _start, _finish, _id, payload|
payload[:order].reload.update_distribution_charge!
end
module Spree
class Order < ActiveRecord::Base
prepend OrderShipment

View File

@@ -1,5 +1,8 @@
# frozen_string_literal: true
require 'concerns/payment_method_distributors'
require 'spree/core/calculated_adjustments'
module Spree
class PaymentMethod < ActiveRecord::Base
include Spree::Core::CalculatedAdjustments
@@ -99,7 +102,7 @@ module Spree
self.class.include Spree::Core::CalculatedAdjustments
end
self.calculator ||= Calculator::FlatRate.new(preferred_amount: 0)
self.calculator ||= ::Calculator::FlatRate.new(preferred_amount: 0)
end
def has_distributor?(distributor)

View File

@@ -0,0 +1,42 @@
# frozen_string_literal: true
module Spree
class Preference < ActiveRecord::Base
serialize :value
validates :key, presence: true
validates :value_type, presence: true
scope :valid, -> {
where(Spree::Preference.arel_table[:key].not_eq(nil)).
where(Spree::Preference.arel_table[:value_type].not_eq(nil))
}
# The type conversions here should match
# the ones in spree::preferences::preferrable#convert_preference_value
def value
if self[:value_type].present?
case self[:value_type].to_sym
when :string, :text
self[:value].to_s
when :password
self[:value].to_s
when :decimal
BigDecimal(self[:value].to_s).round(2, BigDecimal::ROUND_HALF_UP)
when :integer
self[:value].to_i
when :boolean
!(self[:value].to_s =~ /^[t|1]/i).nil?
else
self[:value].is_a?(String) ? YAML.safe_load(self[:value]) : self[:value]
end
else
self[:value]
end
end
def raw_value
self[:value]
end
end
end

View File

@@ -0,0 +1,74 @@
# frozen_string_literal: true
# This takes the preferrable methods and adds some
# syntatic sugar to access the preferences
#
# class App < Configuration
# preference :color, :string
# end
#
# a = App.new
#
# setters:
# a.color = :blue
# a[:color] = :blue
# a.set :color = :blue
# a.preferred_color = :blue
#
# getters:
# a.color
# a[:color]
# a.get :color
# a.preferred_color
#
#
module Spree
module Preferences
class Configuration
include Spree::Preferences::Preferable
def configure
yield(self) if block_given?
end
def preference_cache_key(name)
[ENV['RAILS_CACHE_ID'], self.class.name, name].flatten.join('::').underscore
end
def reset
preferences.each do |name, _value|
set_preference name, preference_default(name)
end
end
alias :[] :get_preference
alias :[]= :set_preference
alias :get :get_preference
def set(*args)
options = args.extract_options!
options.each do |name, value|
set_preference name, value
end
return unless args.size == 2
set_preference args[0], args[1]
end
def method_missing(method, *args)
name = method.to_s.gsub('=', '')
if has_preference? name
if method.to_s =~ /=$/
set_preference(name, args.first)
else
get_preference name
end
else
super
end
end
end
end
end

View File

@@ -0,0 +1,138 @@
# frozen_string_literal: true
# The preference_cache_key is used to determine if the preference
# can be set. The default behavior is to return nil if there is no
# id value. On ActiveRecords, new objects will have their preferences
# saved to a pending hash until it is persisted.
#
# class_attributes are inheritied unless you reassign them in
# the subclass, so when you inherit a Preferable class, the
# inherited hook will assign a new hash for the subclass definitions
# and copy all the definitions allowing the subclass to add
# additional defintions without affecting the base
module Spree
module Preferences
module Preferable
def self.included(base)
base.class_eval do
extend Spree::Preferences::PreferableClassMethods
if respond_to?(:after_create)
after_create do |obj|
obj.save_pending_preferences
end
end
if respond_to?(:after_destroy)
after_destroy do |obj|
obj.clear_preferences
end
end
end
end
def get_preference(name)
has_preference! name
__send__ self.class.preference_getter_method(name)
end
alias :preferred :get_preference
alias :prefers? :get_preference
def set_preference(name, value)
has_preference! name
__send__ self.class.preference_setter_method(name), value
end
def preference_type(name)
has_preference! name
__send__ self.class.preference_type_getter_method(name)
end
def preference_default(name)
has_preference! name
__send__ self.class.preference_default_getter_method(name)
end
def preference_description(name)
has_preference! name
__send__ self.class.preference_description_getter_method(name)
end
def has_preference!(name)
raise NoMethodError, "#{name} preference not defined" unless has_preference? name
end
def has_preference?(name)
respond_to? self.class.preference_getter_method(name)
end
def preferences
prefs = {}
methods.grep(/^prefers_.*\?$/).each do |pref_method|
prefs[pref_method.to_s.gsub(/prefers_|\?/, '').to_sym] = __send__(pref_method)
end
prefs
end
def preference_cache_key(name)
return unless id
[ENV["RAILS_CACHE_ID"], self.class.name, name, id].join('::').underscore
end
def save_pending_preferences
return unless @pending_preferences
@pending_preferences.each do |name, value|
set_preference(name, value)
end
end
def clear_preferences
preferences.keys.each { |pref| preference_store.delete preference_cache_key(pref) }
end
private
def add_pending_preference(name, value)
@pending_preferences ||= {}
@pending_preferences[name] = value
end
def get_pending_preference(name)
return unless @pending_preferences
@pending_preferences[name]
end
def convert_preference_value(value, type)
case type
when :string, :text
value.to_s
when :password
value.to_s
when :decimal
BigDecimal(value.to_s).round(2, BigDecimal::ROUND_HALF_UP)
when :integer
value.to_i
when :boolean
if value.is_a?(FalseClass) ||
value.nil? ||
value == 0 ||
value =~ /^(f|false|0)$/i ||
(value.respond_to?(:empty?) && value.empty?)
false
else
true
end
else
value
end
end
def preference_store
Spree::Preferences::Store.instance
end
end
end
end

View File

@@ -0,0 +1,101 @@
# frozen_string_literal: true
module Spree
module Preferences
module PreferableClassMethods
def preference(name, type, *args)
options = args.extract_options!
options.assert_valid_keys(:default, :description)
default = options[:default]
description = options[:description] || name
# cache_key will be nil for new objects, then if we check if there
# is a pending preference before going to default
define_method preference_getter_method(name) do
# perference_cache_key will only be nil/false for new records
#
if preference_cache_key(name)
preference_store.get(preference_cache_key(name), default)
else
get_pending_preference(name) || default
end
end
alias_method prefers_getter_method(name), preference_getter_method(name)
define_method preference_setter_method(name) do |value|
value = convert_preference_value(value, type)
if preference_cache_key(name)
preference_store.set preference_cache_key(name), value, type
else
add_pending_preference(name, value)
end
end
alias_method prefers_setter_method(name), preference_setter_method(name)
define_method preference_default_getter_method(name) do
default
end
define_method preference_type_getter_method(name) do
type
end
define_method preference_description_getter_method(name) do
description
end
end
def remove_preference(name)
if method_defined? preference_getter_method(name)
remove_method preference_getter_method(name)
end
if method_defined? preference_setter_method(name)
remove_method preference_setter_method(name)
end
if method_defined? prefers_getter_method(name)
remove_method prefers_getter_method(name)
end
if method_defined? prefers_setter_method(name)
remove_method prefers_setter_method(name)
end
if method_defined? preference_default_getter_method(name)
remove_method preference_default_getter_method(name)
end
if method_defined? preference_type_getter_method(name)
remove_method preference_type_getter_method(name)
end
if method_defined? preference_description_getter_method(name)
remove_method preference_description_getter_method(name)
end
end
def preference_getter_method(name)
"preferred_#{name}".to_sym
end
def preference_setter_method(name)
"preferred_#{name}=".to_sym
end
def prefers_getter_method(name)
"prefers_#{name}?".to_sym
end
def prefers_setter_method(name)
"prefers_#{name}=".to_sym
end
def preference_default_getter_method(name)
"preferred_#{name}_default".to_sym
end
def preference_type_getter_method(name)
"preferred_#{name}_type".to_sym
end
def preference_description_getter_method(name)
"preferred_#{name}_description".to_sym
end
end
end
end

View File

@@ -0,0 +1,99 @@
# frozen_string_literal: true
# Use singleton class Spree::Preferences::Store.instance to access
#
# StoreInstance has a persistence flag that is on by default,
# but we disable database persistence in testing to speed up tests
#
require 'singleton'
module Spree
module Preferences
class StoreInstance
attr_accessor :persistence
def initialize
@cache = Rails.cache
@persistence = true
end
def set(key, value, type)
@cache.write(key, value)
persist(key, value, type)
end
def exist?(key)
@cache.exist?(key) ||
should_persist? && Spree::Preference.where(key: key).exists?
end
def get(key, fallback = nil)
# return the retrieved value, if it's in the cache
# use unless nil? incase the value is actually boolean false
#
unless (val = @cache.read(key)).nil?
return val
end
if should_persist?
# If it's not in the cache, maybe it's in the database, but
# has been cleared from the cache
# does it exist in the database?
if Spree::Preference.table_exists? && preference = Spree::Preference.find_by(key: key)
# it does exist, so let's put it back into the cache
@cache.write(preference.key, preference.value)
# and return the value
return preference.value
end
end
unless fallback.nil?
# cache fallback so we won't hit the db above on
# subsequent queries for the same key
#
@cache.write(key, fallback)
end
fallback
end
def delete(key)
@cache.delete(key)
destroy(key)
end
def clear_cache
@cache.clear
end
private
def persist(cache_key, value, type)
return unless should_persist?
preference = Spree::Preference.where(key: cache_key).first_or_initialize
preference.value = value
preference.value_type = type
preference.save
end
def destroy(cache_key)
return unless should_persist?
preference = Spree::Preference.find_by(key: cache_key)
preference&.destroy
end
def should_persist?
@persistence && Spree::Preference.connected? && Spree::Preference.table_exists?
end
end
class Store < StoreInstance
include Singleton
end
end
end

View File

@@ -18,7 +18,7 @@ class Api::ProductSerializer < ActiveModel::Serializer
# return an unformatted descripton
def description
strip_tags object.description
strip_tags object.description&.strip
end
# return a sanitized html description

View File

@@ -4,26 +4,39 @@
= render partial: "shop/products/searchbar"
.row
.small-12.columns
.footer-pad.small-12.columns.no-gutter
.row
.medium-12.large-10.columns
= render partial: "shop/products/search_feedback"
.footer-pad.small-12.columns.product-listing
.row.full
.medium-12.large-9.columns.full
= render partial: "shop/products/search_feedback"
%div.pad-top{ "infinite-scroll" => "loadMore()", "infinite-scroll-distance" => "1", "infinite-scroll-disabled" => 'Products.loading' }
%product.animate-repeat{"ng-controller" => "ProductNodeCtrl", "ng-repeat" => "product in Products.products track by product.id", "id" => "product-{{ product.id }}"}
= render "shop/products/summary"
%div.pad-top{ "infinite-scroll" => "loadMore()", "infinite-scroll-distance" => "1", "infinite-scroll-disabled" => 'Products.loading' }
%product.animate-repeat{"ng-controller" => "ProductNodeCtrl", "ng-repeat" => "product in Products.products track by product.id", "id" => "product-{{ product.id }}"}
= render "shop/products/summary"
.shop-variants
%shop-variant{variant: 'variant', "ng-repeat" => "variant in product.variants | orderBy: ['name_to_display','unit_value'] track by variant.id", "id" => "variant-{{ variant.id }}", "ng-class" => "{'out-of-stock': !variant.on_demand && variant.on_hand == 0}"}
%product{"ng-show" => "Products.loading"}
.row.summary
.small-12.columns.text-center
= t :products_loading
.row
.small-12.columns.text-center
%img.spinner{ src: image_path("spinning-circles.svg") }
%product{"ng-show" => "Products.loading"}
.summary
.small-12.columns.text-center
= t :products_loading
.row.full
.small-12.columns.text-center
%img.spinner{ src: image_path("spinning-circles.svg") }
.hide-for-medium-down.large-2.columns
.hide-for-medium-down.large-1.columns
-# Space between products and filters
&nbsp;
.hide-for-medium-down.large-2.columns
%h5.filter-header
= t(:products_filter_by)
%span{ng: {show: 'filtersCount()' }}
= "({{ filtersCount() }} #{t(:products_filter_selected)})"
= render partial: "shop/products/filters"
.expanding-sidebar.shop-filters-sidebar.hide-for-large-up{ng: {show: 'showFilterSidebar', class: "{'shown': showFilterSidebar}"}}
.background{ng: {click: 'toggleFilterSidebar()'}}
.sidebar
%h5
= t(:products_filter_by)
%span{ng: {show: 'filtersCount()' }}
@@ -31,18 +44,8 @@
= render partial: "shop/products/filters"
.expanding-sidebar.shop-filters-sidebar.hide-for-large-up{ng: {show: 'showFilterSidebar', class: "{'shown': showFilterSidebar}"}}
.background{ng: {click: 'toggleFilterSidebar()'}}
.sidebar
%h5
= t(:products_filter_by)
%span{ng: {show: 'filtersCount()' }}
= "({{ filtersCount() }} #{t(:products_filter_selected)})"
= render partial: "shop/products/filters"
.sidebar-footer
%button.large.dark.left{type: 'button', ng: {click: 'clearFilters()'}}
= t(:products_filter_clear)
%button.large.bright.right{type: 'button', ng: {click: 'toggleFilterSidebar()'}}
= t(:products_filter_done)
.sidebar-footer
%button.large.dark.left{type: 'button', ng: {click: 'clearFilters()'}}
= t(:products_filter_clear)
%button.large.bright.right{type: 'button', ng: {click: 'toggleFilterSidebar()'}}
= t(:products_filter_done)

View File

@@ -1,20 +1,20 @@
.product-thumb
%a{"ng-click" => "triggerProductModal()"}
%i.ofn-i_057-expand
%img{"ng-src" => "{{::product.primaryImageOrMissing}}", "ng-click" => "triggerProductModal()"}
%span.product-thumb__bulk-label{"ng-if" => "::product.group_buy"}
= t(".bulk")
%img{"ng-src" => "{{::product.primaryImageOrMissing}}"}
.row.summary
.small-10.medium-10.large-11.columns.summary-header
.summary
.summary-header
%h3
%a{"ng-click" => "triggerProductModal()", href: 'javascript:void(0)'}
%span{"ng-bind" => "::product.name"}
%i.ofn-i_057-expand
%small
%em
= t :products_from
%p.product-description{ng: {bind: "::product.description", click: "triggerProductModal()", show: "product.description.length"}}
.product-producer
= t :products_from
%span
%enterprise-modal
%i.ofn-i_036-producers
%span{"ng-bind" => "::enterprise.name"}
.small-2.medium-2.large-1.columns.text-center
.taxon-flag
.product-properties.filter-shopfront.property-selectors
%filter-selector{ 'selector-set' => "productPropertySelectors", objects: "[product] | propertiesWithValuesOf" }

View File

@@ -1,81 +0,0 @@
= render :partial => 'spree/admin/shared/configuration_menu'
- content_for :page_title do
= Spree.t(:image_settings)
= form_tag admin_image_settings_path, :method => :put do
- destroy = Spree.t(:destroy)
%fieldset.no-border-top
%fieldset.no-border-bottom
%legend{:align => "center"}= Spree.t(:general_settings)
.field
.warning.note= Spree.t(:image_settings_warning)
.field{"data-hook" => "attachment_path"}
= label_tag 'preferences[attachment_path]', Spree.t(:attachment_path)
= preference_field_tag 'preferences[attachment_path]', Spree::Config[:attachment_path], :type => :string
.alpha.eight.columns
.field{"data-hook" => "attachment_default_url"}
= label_tag 'preferences[attachment_default_url]', Spree.t(:attachment_default_url)
= preference_field_tag 'preferences[attachment_default_url]', Spree::Config[:attachment_default_url], :type => :string
.alpha.eight.columns
.field{"data-hook" => "attachment_url"}
= label_tag 'preferences[attachment_url]', Spree.t(:attachment_url)
= preference_field_tag 'preferences[attachment_url]', Spree::Config[:attachment_url], :type => :string
.omega.four.columns
.field{"data-hook" => "attachment_default_style"}
= label_tag 'preferences[attachment_default_style]', Spree.t(:attachment_default_style)
= collection_select 'preferences', 'attachment_default_style', @styles, :first, :first, {:selected => Spree::Config[:attachment_default_style] }, :class => 'select2 fullwidth'
.clear
.field{"data-hook" => "use_s3"}
= preference_field_tag 'preferences[use_s3]', Spree::Config[:use_s3], :type => :boolean
= label_tag 'preferences[use_s3]', Spree.t(:use_s3)
%fieldset#attachment_styles.no-border-bottom{"data-hook" => "attachment_styles"}
%legend{:align => "center"}= Spree.t(:attachment_styles)
#styles_list.row.frameless
- @styles.each_with_index do |(style_name, style_value), index|
.field.three.columns
= label_tag "attachment_styles[#{style_name}]", style_name
%a.destroy_style{:alt => t(:destroy), :href => "#", :title => t(:destroy)}
%i.icon-trash
= text_field_tag "attachment_styles[#{style_name}][]", admin_image_settings_geometry_from_style(style_value), :class => 'fullwidth'
%br/
- current_format = admin_image_settings_format_from_style(style_value) || ''
= select_tag "attachment_styles[#{style_name}][]", options_for_select(admin_image_settings_format_options, current_format), :class => 'fullwidth', :id => "attachment_styles_format_#{style_name}"
#new-styles.row.frameless
.field
= link_to_with_icon 'icon-plus', Spree.t(:add_new_style), '#', :class => 'add_new_style button'
.row
#s3_settings.alpha.six.columns{"data-hook" => "s3_settings", :style => "display: none"}
%fieldset.no-border-bottom
%legend{:align => "center"}= Spree.t(:configure_s3)
.field{"data-hook" => "s3_access_key"}
= label_tag 'preferences[s3_access_key]', Spree.t(:s3_access_key)
= preference_field_tag 'preferences[s3_access_key]', Spree::Config[:s3_access_key], :type => :string
.field{"data-hook" => "s3_secret"}
= label_tag 'preferences[s3_secret]', Spree.t(:s3_secret)
= preference_field_tag 'preferences[s3_secret]', Spree::Config[:s3_secret], :type => :string
.field{"data-hook" => "s3_bucket"}
= label_tag 'preferences[s3_bucket]', Spree.t(:s3_bucket)
= preference_field_tag 'preferences[s3_bucket]', Spree::Config[:s3_bucket], :type => :string
.field{"data-hook" => "s3_protocol"}
= label_tag 'preferences[s3_protocol]', Spree.t(:s3_protocol)
= preference_field_tag 'preferences[s3_protocol]', Spree::Config[:s3_protocol], :type => :string
#s3_headers.omega.six.columns{"data-hook" => "s3_headers", :style => "display: none"}
%fieldset.no-border-bottom
%legend{:align => "center"}= Spree.t(:s3_headers)
#headers_list
- @headers.each do |header_name, header_value|
.field
= label_tag "s3_headers[#{header_name}]", header_name
%a.destroy_header.with-tip{:alt => destroy, :href => "#", :title => destroy}
%i.icon-trash
= text_field_tag "s3_headers[#{header_name}]", header_value, :class => 'fullwidth'
= link_to_with_icon 'icon-plus', Spree.t(:add_new_header), '#', :class => 'add_header button'
.form-buttons.filter-actions.actions{"data-hook" => "buttons"}
= button Spree.t('actions.update'), 'icon-refresh'

View File

@@ -16,10 +16,6 @@
%div{class: "field"}
= f.label :lastname, Spree.t(:last_name) + ':'
= f.text_field :lastname, class: 'fullwidth'
- if Spree::Config[:company]
%div{class: "field"}
= f.label :company, Spree.t(:company) + ':'
= f.text_field :company, class: 'fullwidth'
%div{class: "field"}
= f.label :address1, Spree.t(:street_address) + ':'
= f.text_field :address1, class: 'fullwidth'

View File

@@ -7,7 +7,6 @@
= configurations_sidebar_menu_item Spree.t(:general_settings), edit_admin_general_settings_path
- if Spree::Config[:override_actionmailer_config]
= configurations_sidebar_menu_item Spree.t(:mail_method_settings), edit_admin_mail_methods_path
= configurations_sidebar_menu_item Spree.t(:image_settings), edit_admin_image_settings_path
= configurations_sidebar_menu_item Spree.t(:tax_categories), admin_tax_categories_path
= configurations_sidebar_menu_item Spree.t(:tax_rates), admin_tax_rates_path
= configurations_sidebar_menu_item Spree.t(:tax_settings), edit_admin_tax_settings_path

View File

@@ -1,4 +1,10 @@
<script>
if (Spree === undefined) {
var Spree = {}
}
if (Spree.routes == undefined) {
Spree.routes = {}
}
Spree.routes = <%== {
:variants_search => spree.admin_search_variants_path(:format => 'json'),
:taxons_search => main_app.api_taxons_path(:format => 'json'),

View File

@@ -3,7 +3,7 @@
= tab :order_cycles, url: main_app.admin_order_cycles_path, icon: 'icon-refresh'
= tab :orders, :subscriptions, :customer_details, :adjustments, :payments, :return_authorizations, url: admin_orders_path('q[s]' => 'completed_at desc'), icon: 'icon-shopping-cart'
= tab :reports, icon: 'icon-file'
= tab :general_settings, :mail_methods, :image_settings, :tax_categories, :tax_rates, :tax_settings, :zones, :countries, :states, :payment_methods, :taxonomies, :shipping_methods, :shipping_categories, :enterprise_fees, :contents, :invoice_settings, :matomo_settings, :stripe_connect_settings, label: 'configuration', icon: 'icon-wrench', url: edit_admin_general_settings_path
= tab :general_settings, :mail_methods, :tax_categories, :tax_rates, :tax_settings, :zones, :countries, :states, :payment_methods, :taxonomies, :shipping_methods, :shipping_categories, :enterprise_fees, :contents, :invoice_settings, :matomo_settings, :stripe_connect_settings, label: 'configuration', icon: 'icon-wrench', url: edit_admin_general_settings_path
= tab :enterprises, :enterprise_relationships, url: main_app.admin_enterprises_path
= tab :customers, url: main_app.admin_customers_path
= tab :enterprise_groups, url: main_app.admin_enterprise_groups_path, label: 'groups'

View File

@@ -20,17 +20,11 @@
:datetime_ui_time_text => I18n.t('datetime_picker_ui.time_text'),
:name => Spree.t(:name),
:next => Spree.t(:next),
:no_results => Spree.t(:no_results),
:option_type_placeholder => Spree.t(:option_type_placeholder),
:paste => Spree.t(:paste),
:previous => Spree.t(:previous),
:remove => Spree.t(:remove),
:rename => Spree.t(:rename),
:searching => Spree.t(:searching),
:sku => Spree.t(:sku),
:type_to_search => Spree.t(:type_to_search),
:taxon_placeholder => Spree.t(:taxon_placeholder),
:variant_placeholder => Spree.t(:variant_placeholder),
:value => Spree.t(:value)
}.to_json
%>

View File

@@ -67,3 +67,5 @@
%script
= raw "Spree.api_key = \"#{spree_current_user.try(:spree_api_key).to_s}\";"
= render "layouts/matomo_tag"

View File

@@ -7,7 +7,6 @@
# config.setting_name = 'new value'
require "spree/core/environment"
require 'spree/product_filters'
# Due to a bug in ActiveRecord we need to load the tagging code in Gateway which
# should have inherited it from its parent PaymentMethod.
@@ -33,9 +32,15 @@ Spree.config do |config|
config.s3_access_key = ENV['S3_ACCESS_KEY'] if ENV['S3_ACCESS_KEY']
config.s3_secret = ENV['S3_SECRET'] if ENV['S3_SECRET']
config.use_s3 = true if ENV['S3_BUCKET']
config.s3_headers = ENV['S3_HEADERS'] if ENV['S3_HEADERS']
config.s3_protocol = ENV.fetch('S3_PROTOCOL', 'https')
end
# Attachments settings
Spree::Image.set_attachment_attributes(:path, ENV['ATTACHMENT_PATH']) if ENV['ATTACHMENT_PATH']
Spree::Image.set_attachment_attributes(:url, ENV['ATTACHMENT_URL']) if ENV['ATTACHMENT_URL']
Spree::Image.set_s3_attachment_definitions
# Spree 2.0 recommends explicitly setting this here when using spree_auth_devise
Spree.user_class = 'Spree::User'

View File

@@ -23,6 +23,10 @@ ar:
variant_unit_name: "اسم وحدة النوع"
spree/credit_card:
base: "بطاقة ائتمان"
number: "رقم "
month: "شهر"
verification_value: "قيمة التحقق"
year: "عام"
order_cycle:
orders_close_at: تاريخ الاغلاق
variant_override:
@@ -1212,6 +1216,9 @@ ar:
require_customer_html: "إذا كنت ترغب في بدء التسوق هنا ، فيرجى %{contact} %{enterprise} أن تسأل عن الانضمام."
select_oc:
select_oc_html: "يرجى <span class='highlighted'>اختيار الوقت الذي تريده لطلبك</span> ، لمعرفة المنتجات المتوفرة."
products:
summary:
bulk: "جملة"
card_could_not_be_updated: لا يمكن تحديث البطاقة
card_could_not_be_saved: لا يمكن حفظ البطاقة
spree_gateway_error_flash_for_checkout: "حدثت مشكلة في معلومات الدفع الخاصة بك: %{error}"
@@ -1606,8 +1613,8 @@ ar:
components_filters_nofilters: "لا يوجد مرشحات"
components_filters_clearfilters: "مسح جميع المرشحات"
groups_title: مجموعات
groups_headline: المجموعات / المناطق
groups_text: "كل منتج فريد من نوعه. كل الأعمال لديها شيء مختلف للعرض. مجموعاتنا هي مجموعات من المنتجين والمحاور والموزعين الذين يشتركون في شيء مثل الموقع أو سوق المزارعين أو الفلسفة. هذا يجعل تجربة التسوق أسهل. لذلك استكشف مجموعاتنا وقمنا بتنظيمها لك."
groups_headline: المجموعات
groups_text: "كل منتج فريد من نوعه. كل الأعمال لديها شيء مختلف للعرض. مجموعاتنا هي مجموعات من المنتجين ومراكز البيع والموزعين الذين يشتركون في خصلة مثل الموقع أو سوق المزارعين أو الفلسفة. هذا يجعل تجربة التسوق أسهل. لذلك استكشف مجموعاتنا التي قمنا بتنظيمها لك."
groups_search: "البحث عن اسم أو كلمة أساسية"
groups_no_groups: "لم يتم العثور على مجموعات"
groups_about: "معلومات عنا"
@@ -1927,7 +1934,6 @@ ar:
shop_for_products_html: "متجر لمنتجات <span class=\"turquoise\">%{enterprise}</span> على:"
change_shop: "تغيير المتجر إلى:"
shop_at: "تسوق الآن عبر:"
price_breakdown: "تفاصيل السعر الكامل"
admin_fee: "رسوم الاشراف"
sales_fee: "رسوم المبيعات"
packing_fee: "رسوم التعبئة"
@@ -2002,6 +2008,7 @@ ar:
calculator: "آلة حاسبة"
calculator_values: "القيم المحوسبة"
calculator_settings_warning: "إذا كنت تقوم بتغيير نوع الحاسبة ، فيجب عليك الحفظ أولاً قبل أن تتمكن من تحرير إعدادات الحاسبة"
calculator_preferred_unit_error: "يجب أن تكون كجم أو رطل"
flat_percent_per_item: "نسبة ثابتة (لكل بند)"
flat_rate_per_item: "سعر ثابت (لكل بند)"
flat_rate_per_order: "تسعيرة ثابته (لكل طلب)"
@@ -2593,6 +2600,15 @@ ar:
إليك ما تغير:
now_out_of_stock: الآن لا يوجد مخزون.
only_n_remainging: "الآن ليس لديه %{num} متبقية."
shopfront:
variant:
add_to_cart: "إضافة"
in_cart: "في السلة"
quantity_in_cart: "%{quantity} في السلة"
bulk_buy_modal:
min_quantity: "اقل كمية "
max_quantity: "اعلى كمية"
price_breakdown: "تفاصيل السعر"
variants:
on_demand:
'yes': "حسب الطلب"
@@ -2996,15 +3012,6 @@ ar:
smtp_send_copy_to_this_addresses: "يرسل نسخة من جميع الرسائل الصادرة إلى هذا العنوان. لعناوين متعددة ، افصل بينها بفواصل."
intercept_email_address: "اعتراض عنوان البريد الإلكتروني"
intercept_email_instructions: "تجاوز مستلم البريد الإلكتروني واستبداله بهذا العنوان."
image_settings: "إعدادات الصورة"
image_settings_warning: "ستحتاج إلى تجديد الصور المصغرة إذا قمت بتحديث أنماط مشبك الورق. استخدم rap paperclip: refresh: الصور المصغرة CLASS = Spree :: Image للقيام بذلك."
attachment_default_style: نمط المرفقات
attachment_default_url: "المرفقات عنوان URL الافتراضي"
attachment_path: "مسار المرفقات"
attachment_styles: "أنماط الورق"
attachment_url: "مرفقات URL"
add_new_style: "إضافة نمط جديد"
image_settings_updated: "تم تحديث إعدادات الصورة بنجاح."
tax_categories: "فئات الضرائب"
listing_tax_categories: "قائمة فئات الضرائب"
back_to_tax_categories_list: "العودة إلى قائمة فئات الضرائب"
@@ -3078,11 +3085,18 @@ ar:
inventory_error_flash_for_insufficient_quantity: "المواد في سلة التسوق غير متاح."
inventory: المخزون
zipcode: الرمز البريدي
weight: الوزن (لكل كجم)
weight: الوزن (لكل كجم أو رطل)
error_user_destroy_with_orders: "لا يمكن حذف المستخدمين الذين لديهم طلبات مكتملة"
cannot_create_payment_without_payment_methods: "لا يمكنك إنشاء دفعة لطلب بدون تحديد طرقة الدفع."
please_define_payment_methods: "يرجى تحديد بعض طرق الدفع أولاً."
options: "خيارات"
has_no_shipped_units: "لا يوجد لديه طلبات مشحونة"
successfully_created: '%{resource} تم إنشاؤه بنجاح!'
successfully_updated: 'تم تحديث %{resource} بنجاح!'
payment_processing_failed: "لا يمكن معالجة الدفع ، يرجى التحقق من التفاصيل التي أدخلتها"
not_available: "غير متاح"
order_populator:
out_of_stock: '%{item} غير متوفر.'
actions:
update: "تحديث"
shared:

View File

@@ -23,6 +23,10 @@ ca:
variant_unit_name: "Nom de la unitat de la variant"
spree/credit_card:
base: "Targeta de crèdit"
number: "Número"
month: "Mes"
verification_value: "Valor de verificació"
year: "Any"
order_cycle:
orders_close_at: Data de tancament
variant_override:
@@ -1216,6 +1220,9 @@ ca:
require_customer_html: "Si vols començar a comprar aquí, si us plau %{contact} %{enterprise} per unir-t'hi."
select_oc:
select_oc_html: "<span class='highlighted'>Trieu quan voleu la vostra comanda</span> per veure quins productes estan disponibles."
products:
summary:
bulk: "A granel"
card_could_not_be_updated: No s'ha pogut actualitzar la targeta
card_could_not_be_saved: no s'ha pogut desar la targeta
spree_gateway_error_flash_for_checkout: "Hi ha hagut un problema amb la vostra informació de pagament: %{error}"
@@ -1923,7 +1930,6 @@ ca:
shop_for_products_html: "Compra productes de <span class = \"turquesa\"> %{enterprise} </ span> a:"
change_shop: "Canvia la botiga a:"
shop_at: "Compra ara a:"
price_breakdown: "Desglossament complet del preu"
admin_fee: "Comissió d'administració"
sales_fee: "Comissió de venda"
packing_fee: "Comissió d'embalatge"
@@ -1998,6 +2004,7 @@ ca:
calculator: "Calculadora"
calculator_values: "Valors de la calculadora"
calculator_settings_warning: "Si canvieu el tipus de calculadora, primer heu de desar abans de poder editar la configuració de la calculadora"
calculator_preferred_unit_error: "ha de ser kg o lliures"
flat_percent_per_item: "Percentatge fixe (per article)"
flat_rate_per_item: "Tarifa fixa (per article)"
flat_rate_per_order: "Tarifa fixa (per comanda)"
@@ -2599,6 +2606,15 @@ ca:
més dels productes de la cistella. Aquí podeu veure el que ha canviat:
now_out_of_stock: ara està fora d'estoc.
only_n_remainging: "ara només n'hi ha %{num}restants."
shopfront:
variant:
add_to_cart: "Afegeix"
in_cart: "a la cistella"
quantity_in_cart: "%{quantity} a la cistella"
bulk_buy_modal:
min_quantity: "Quantitat mínima"
max_quantity: "Quantitat màxima"
price_breakdown: "Desglossament del preu"
variants:
on_demand:
'yes': "Sota demanda"
@@ -2904,15 +2920,6 @@ ca:
smtp_send_copy_to_this_addresses: "Envia una còpia de tots els correus sortints a aquesta adreça. Per a diverses adreces, separeu amb comes."
intercept_email_address: "Intercepta adreça de correu"
intercept_email_instructions: "Invalida el destinatari de correu electrònic i reemplaça amb aquesta adreça."
image_settings: "Configuració de la imatge"
image_settings_warning: "Haureu de regenerar thumbnails si actualitzeu els estils de paperclip. Feu servir rake paperclip:refresh:thumbnails CLASS=Spree::Image per fer-ho."
attachment_default_style: Estil de fitxers adjunts
attachment_default_url: "URL predeterminada de fitxers adjunts"
attachment_path: "Ruta de fitxers adjunts"
attachment_styles: "Estils de paperclip"
attachment_url: "URL dels fitxers adjunts"
add_new_style: "Afegeix un estil nou"
image_settings_updated: "La configuració de la imatge s'ha actualitzat correctament."
tax_categories: "Tipus d'impostos"
listing_tax_categories: "Llista de categories d'impostos"
back_to_tax_categories_list: "Tornar a la llista de categories d'impostos"
@@ -2986,11 +2993,18 @@ ca:
inventory_error_flash_for_insufficient_quantity: "Un article de la teva cistella ha deixat d'estar disponible."
inventory: Inventari
zipcode: Codi postal
weight: Pes (per kg)
weight: Pes (per kg o lliures)
error_user_destroy_with_orders: "No es poden esborrar usuaris amb comandes completades"
cannot_create_payment_without_payment_methods: "No podeu crear un pagament per a una comanda sense que hi hagi definit cap mètode de pagament."
please_define_payment_methods: "Primer definiu alguns mètodes de pagament."
options: "Opcions"
has_no_shipped_units: "no té cap unitat enviada"
successfully_created: '%{resource} s''ha creat correctament.'
successfully_updated: '%{resource} s''ha actualitzat correctament.'
payment_processing_failed: "El pagament no s'ha pogut processar, comproveu les dades que heu introduït"
not_available: "No disponible"
order_populator:
out_of_stock: '%{item} està esgotat.'
actions:
update: "Actualitzar"
shared:

View File

@@ -22,6 +22,7 @@ de_DE:
variant_unit_name: "Name der Varianteneinheit"
spree/credit_card:
base: "Kreditkarte"
number: "Nummer"
order_cycle:
orders_close_at: Schlussdatum
variant_override:
@@ -1874,7 +1875,6 @@ de_DE:
shop_for_products_html: "Suche nach <span class=\"turquoise\">%{enterprise}</span> Produkten unter:"
change_shop: "Laden ändern auf:"
shop_at: "Kaufe jetzt bei:"
price_breakdown: "Vollständige Preisaufschlüsselung"
admin_fee: "Gebühr Administration"
sales_fee: "Gebühr Verkauf"
packing_fee: "Gebühr Umverpackung"
@@ -2537,6 +2537,9 @@ de_DE:
in Ihrem Warenkorb verringert. Das Folgende hat sich geändert:
now_out_of_stock: ist jetzt ausverkauft.
only_n_remainging: "Jetzt hat nur noch %{num} übrig."
shopfront:
variant:
add_to_cart: "Hinzufügen"
variants:
on_demand:
'yes': "Auf Anfrage"
@@ -2827,15 +2830,6 @@ de_DE:
smtp_send_copy_to_this_addresses: "Sendet eine Kopie aller ausgehenden Mails an diese Adresse. Bei mehreren Adressen trennen Sie diese durch Kommas."
intercept_email_address: "E-Mail-Adresse abfangen"
intercept_email_instructions: "Überschreiben Sie den E-Mail-Empfänger und ersetzen Sie ihn mit dieser Adresse."
image_settings: "Bildeinstellungen"
image_settings_warning: "Sie müssen die Miniaturbilder neu erstellen, wenn Sie die Büroklammerformate aktualisieren. Verwenden Sie dazu die Rake-Büroklammer: Refresh: thumbnails CLASS = Spree :: Image."
attachment_default_style: Anhänge-Stil
attachment_default_url: "Anhänge Standard-URL"
attachment_path: "Pfad der Anhänge"
attachment_styles: "Büroklammer-Stile"
attachment_url: "Anhänge-URL"
add_new_style: "Neuen Stil hinzufügen"
image_settings_updated: "Bildeinstellungen erfolgreich aktualisiert."
tax_categories: "Steuerkategorien"
listing_tax_categories: "Steuerkategorien auflisten"
back_to_tax_categories_list: "Zurück zur Liste der Steuerkategorien"
@@ -2909,7 +2903,6 @@ de_DE:
inventory_error_flash_for_insufficient_quantity: "Ein Artikel in Ihrem Warenkorb ist nicht mehr verfügbar."
inventory: Katalog
zipcode: Postleitzahl
weight: Gewicht (pro kg)
error_user_destroy_with_orders: "Benutzer mit abgeschlossenen Bestellungen dürfen nicht gelöscht werden"
cannot_create_payment_without_payment_methods: "Sie können keine Zahlung für eine Bestellung erstellen, ohne dass Zahlungsmethoden definiert sind."
please_define_payment_methods: "Bitte definieren Sie zunächst die Zahlungsmethoden."

View File

@@ -44,6 +44,10 @@ en:
variant_unit_name: "Variant Unit Name"
spree/credit_card:
base: "Credit Card"
number: "Number"
month: "Month"
verification_value: "Verification Value"
year: "Year"
order_cycle:
orders_close_at: Close date
variant_override:
@@ -1282,6 +1286,9 @@ en:
require_customer_html: "If you'd like to start shopping here, please %{contact} %{enterprise} to ask about joining."
select_oc:
select_oc_html: "Please <span class='highlighted'>choose when you want your order</span>, to see what products are available."
products:
summary:
bulk: "Bulk"
# Front-end controller translations
card_could_not_be_updated: Card could not be updated
@@ -2049,7 +2056,6 @@ See the %{link} to find out more about %{sitename}'s features and to start using
shop_for_products_html: "Shop for <span class=\"turquoise\">%{enterprise}</span> products at:"
change_shop: "Change shop to:"
shop_at: "Shop now at:"
price_breakdown: "Full price breakdown"
admin_fee: "Admin fee"
sales_fee: "Sales fee"
packing_fee: "Packing fee"
@@ -2722,6 +2728,15 @@ See the %{link} to find out more about %{sitename}'s features and to start using
in your cart have reduced. Here's what's changed:
now_out_of_stock: is now out of stock.
only_n_remainging: "now only has %{num} remaining."
shopfront:
variant:
add_to_cart: "Add"
in_cart: "in cart"
quantity_in_cart: "%{quantity} in cart"
bulk_buy_modal:
min_quantity: "Min quantity"
max_quantity: "Max quantity"
price_breakdown: "Price breakdown"
variants:
on_demand:
"yes": "On demand"
@@ -3050,16 +3065,6 @@ See the %{link} to find out more about %{sitename}'s features and to start using
intercept_email_address: "Intercept Email Address"
intercept_email_instructions: "Override email recipient and replace with this address."
image_settings: "Image Settings"
image_settings_warning: "You will need to regenerate thumbnails if you update the paperclip styles. Use rake paperclip:refresh:thumbnails CLASS=Spree::Image to do this."
attachment_default_style: Attachments Style
attachment_default_url: "Attachments Default URL"
attachment_path: "Attachments Path"
attachment_styles: "Paperclip Styles"
attachment_url: "Attachments URL"
add_new_style: "Add New Style"
image_settings_updated: "Image Settings successfully updated."
tax_categories: "Tax Categories"
listing_tax_categories: "Listing Tax Categories"
back_to_tax_categories_list: "Back To Tax Categories List"
@@ -3152,6 +3157,13 @@ See the %{link} to find out more about %{sitename}'s features and to start using
cannot_create_payment_without_payment_methods: "You cannot create a payment for an order without any payment methods defined."
please_define_payment_methods: "Please define some payment methods first."
options: "Options"
has_no_shipped_units: "has no shipped units"
successfully_created: ! '%{resource} has been successfully created!'
successfully_updated: ! '%{resource} has been successfully updated!'
payment_processing_failed: "Payment could not be processed, please check the details you entered"
not_available: "N/A"
order_populator:
out_of_stock: ! '%{item} is out of stock.'
actions:
update: "Update"
@@ -3571,6 +3583,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using
issue_text: |
If the above URL does not work try copying and pasting it into your browser.
If you continue to have problems please feel free to contact us.
subject: "Reset password instructions"
confirmation_instructions:
subject: "Please confirm your OFN account"
shipment_mailer:

View File

@@ -22,6 +22,7 @@ en_AU:
variant_unit_name: "Variant Unit Name"
spree/credit_card:
base: "Credit Card"
number: "Number"
order_cycle:
orders_close_at: Close date
variant_override:
@@ -1177,6 +1178,9 @@ en_AU:
contact: "contact"
require_customer_login: "Only approved customers can access this shop."
require_customer_html: "If you'd like to start shopping here, please %{contact} %{enterprise} to ask about joining."
products:
summary:
bulk: "Bulk"
card_could_not_be_updated: Card could not be updated
card_could_not_be_saved: card could not be saved
spree_gateway_error_flash_for_checkout: "There was a problem with your payment information: %{error}"
@@ -1873,7 +1877,6 @@ en_AU:
shop_for_products_html: "Shop for <span class=\"turquoise\">%{enterprise}</span> products at:"
change_shop: "Change shop to:"
shop_at: "Shop now at:"
price_breakdown: "Full price breakdown"
admin_fee: "Admin fee"
sales_fee: "Sales fee"
packing_fee: "Packing fee"
@@ -2525,6 +2528,11 @@ en_AU:
in your cart have reduced. Here's what's changed:
now_out_of_stock: is now out of stock.
only_n_remainging: "now only has %{num} remaining."
shopfront:
variant:
add_to_cart: "Add"
bulk_buy_modal:
max_quantity: "Max quantity"
variants:
on_demand:
'yes': "On demand"
@@ -2746,15 +2754,6 @@ en_AU:
smtp_send_copy_to_this_addresses: "Sends a copy of all outgoing mails to this address. For multiple addresses, separate with commas."
intercept_email_address: "Intercept Email Address"
intercept_email_instructions: "Override email recipient and replace with this address."
image_settings: "Image Settings"
image_settings_warning: "You will need to regenerate thumbnails if you update the paperclip styles. Use rake paperclip:refresh:thumbnails CLASS=Spree::Image to do this."
attachment_default_style: Attachments Style
attachment_default_url: "Attachments Default URL"
attachment_path: "Attachments Path"
attachment_styles: "Paperclip Styles"
attachment_url: "Attachments URL"
add_new_style: "Add New Style"
image_settings_updated: "Image Settings successfully updated."
tax_categories: "Tax Categories"
listing_tax_categories: "Listing Tax Categories"
back_to_tax_categories_list: "Back To Tax Categories List"
@@ -2828,9 +2827,11 @@ en_AU:
inventory_error_flash_for_insufficient_quantity: "An item in your cart has become unavailable."
inventory: Inventory
zipcode: Postcode
weight: Weight (per kg)
error_user_destroy_with_orders: "Users with completed orders may not be deleted"
options: "Options"
successfully_created: '%{resource} has been successfully created!'
successfully_updated: '%{resource} has been successfully updated!'
payment_processing_failed: "Payment could not be processed, please check the details you entered"
actions:
update: "Update"
shared:

View File

@@ -22,6 +22,7 @@ en_BE:
variant_unit_name: "Variant Unit Name"
spree/credit_card:
base: "Credit Card"
number: "Number"
order_cycle:
orders_close_at: Close date
variant_override:
@@ -1138,6 +1139,9 @@ en_BE:
contact: "contact"
require_customer_login: "Only approved customers can access this shop."
require_customer_html: "If you'd like to start shopping here, please %{contact}%{enterprise}to ask about joining."
products:
summary:
bulk: "Bulk"
card_could_not_be_updated: Card could not be updated
card_could_not_be_saved: card could not be saved
spree_gateway_error_flash_for_checkout: "There was a problem with your payment information: %{error}"
@@ -1833,7 +1837,6 @@ en_BE:
shop_for_products_html: "Shop for <span class=\"turquoise\">%{enterprise}</span> products at:"
change_shop: "Change shop to:"
shop_at: "Shop now at:"
price_breakdown: "Full price breakdown"
admin_fee: "Admin fee"
sales_fee: "Sales fee"
packing_fee: "Packing fee"
@@ -2485,6 +2488,11 @@ en_BE:
in your cart have reduced. Here's what's changed:
now_out_of_stock: is now out of stock.
only_n_remainging: "now only has %{num} remaining."
shopfront:
variant:
add_to_cart: "Add"
bulk_buy_modal:
max_quantity: "Max quantity"
variants:
on_demand:
'yes': "On demand"
@@ -2703,15 +2711,6 @@ en_BE:
smtp_send_copy_to_this_addresses: "Sends a copy of all outgoing mails to this address. For multiple addresses, separate with commas."
intercept_email_address: "Intercept Email Address"
intercept_email_instructions: "Override email recipient and replace with this address."
image_settings: "Image Settings"
image_settings_warning: "You will need to regenerate thumbnails if you update the paperclip styles. Use rake paperclip:refresh:thumbnails CLASS=Spree::Image to do this."
attachment_default_style: Attachments Style
attachment_default_url: "Attachments Default URL"
attachment_path: "Attachments Path"
attachment_styles: "Paperclip Styles"
attachment_url: "Attachments URL"
add_new_style: "Add New Style"
image_settings_updated: "Image Settings successfully updated."
tax_categories: "Tax Categories"
listing_tax_categories: "Listing Tax Categories"
back_to_tax_categories_list: "Back To Tax Categories List"
@@ -2778,7 +2777,9 @@ en_BE:
inventory_error_flash_for_insufficient_quantity: "An item in your cart has become unavailable."
inventory: Inventory
zipcode: Postcode
weight: Weight (per kg)
successfully_created: '%{resource} has been successfully created! '
successfully_updated: '%{resource} has been successfully updated!'
payment_processing_failed: "Payment could not be processed, please check the details you entered"
actions:
update: "Update"
shared:

View File

@@ -23,6 +23,10 @@ en_CA:
variant_unit_name: "Variant Unit Name"
spree/credit_card:
base: "Credit Card"
number: "Number"
month: "Month"
verification_value: "Verification Value"
year: "Year"
order_cycle:
orders_close_at: Close date
variant_override:
@@ -1213,6 +1217,9 @@ en_CA:
require_customer_html: "If you'd like to start shopping here, please %{contact}%{enterprise} to ask about joining."
select_oc:
select_oc_html: "Please <span class='highlighted'>choose the store you want</span> from the dropdown box above right."
products:
summary:
bulk: "Bulk"
card_could_not_be_updated: Card could not be updated
card_could_not_be_saved: card could not be saved
spree_gateway_error_flash_for_checkout: "There was a problem with your payment information: %{error}"
@@ -1920,7 +1927,6 @@ en_CA:
shop_for_products_html: "Shop for <span class=\"turquoise\">%{enterprise}</span> products at:"
change_shop: "Change shop to:"
shop_at: "Shop now at:"
price_breakdown: "Full price breakdown"
admin_fee: "Admin fee"
sales_fee: "Sales fee"
packing_fee: "Packing fee"
@@ -1995,6 +2001,7 @@ en_CA:
calculator: "Calculator"
calculator_values: "Calculator values"
calculator_settings_warning: "If you are changing the calculator type, you must save first before you can edit the calculator settings"
calculator_preferred_unit_error: "must be kg or lb"
flat_percent_per_item: "Flat Percent (per item)"
flat_rate_per_item: "Flat Rate (per item)"
flat_rate_per_order: "Flat Rate (per order)"
@@ -2592,6 +2599,15 @@ en_CA:
in your cart have reduced. Here's what's changed:
now_out_of_stock: is now out of stock.
only_n_remainging: "now only has %{num} remaining."
shopfront:
variant:
add_to_cart: "Add"
in_cart: "in cart"
quantity_in_cart: "%{quantity} in cart"
bulk_buy_modal:
min_quantity: "Min quantity"
max_quantity: "Max quantity"
price_breakdown: "Price breakdown"
variants:
on_demand:
'yes': "On demand"
@@ -2899,15 +2915,6 @@ en_CA:
smtp_send_copy_to_this_addresses: "Sends a copy of all outgoing mails to this address. For multiple addresses, separate with commas."
intercept_email_address: "Intercept Email Address"
intercept_email_instructions: "Override email recipient and replace with this address."
image_settings: "Image Settings"
image_settings_warning: "You will need to regenerate thumbnails if you update the paperclip styles. Use rake paperclip:refresh:thumbnails CLASS=Spree::Image to do this."
attachment_default_style: Attachments Style
attachment_default_url: "Attachments Default URL"
attachment_path: "Attachments Path"
attachment_styles: "Paperclip Styles"
attachment_url: "Attachments URL"
add_new_style: "Add New Style"
image_settings_updated: "Image settings successfully updated"
tax_categories: "Tax Categories"
listing_tax_categories: "Listing Tax Categories"
back_to_tax_categories_list: "Back to Tax Categories List"
@@ -2981,11 +2988,18 @@ en_CA:
inventory_error_flash_for_insufficient_quantity: "An item in your cart has become unavailable"
inventory: Inventory
zipcode: Postal Code
weight: Weight (per kg)
weight: Weight (per kg or lb)
error_user_destroy_with_orders: "Users with completed orders may not be deleted"
cannot_create_payment_without_payment_methods: "You cannot create a payment for an order without any payment methods defined."
please_define_payment_methods: "Please define some payment methods first."
options: "Options"
has_no_shipped_units: "has no shipped units"
successfully_created: '%{resource}has been successfully created!'
successfully_updated: '%{resource}has been successfully updated!'
payment_processing_failed: "Payment could not be processed, please check the details you entered."
not_available: "N/A"
order_populator:
out_of_stock: '%{item} is out of stock.'
actions:
update: "Update"
shared:

View File

@@ -22,6 +22,7 @@ en_DE:
variant_unit_name: "Variant Unit Name"
spree/credit_card:
base: "Credit Card"
number: "Number"
order_cycle:
orders_close_at: Close date
variant_override:
@@ -1148,6 +1149,9 @@ en_DE:
contact: "contact"
require_customer_login: "Only approved customers can access this shop."
require_customer_html: "If you'd like to start shopping here, please %{contact} %{enterprise} to ask about joining."
products:
summary:
bulk: "Bulk"
card_could_not_be_updated: Card could not be updated
card_could_not_be_saved: card could not be saved
spree_gateway_error_flash_for_checkout: "There was a problem with your payment information: %{error}"
@@ -1843,7 +1847,6 @@ en_DE:
shop_for_products_html: "Shop for <span class=\"turquoise\">%{enterprise}</span> products at:"
change_shop: "Change shop to:"
shop_at: "Shop now at:"
price_breakdown: "Full price breakdown"
admin_fee: "Admin fee"
sales_fee: "Sales fee"
packing_fee: "Packing fee"
@@ -2495,6 +2498,11 @@ en_DE:
in your cart have reduced. Here's what's changed:
now_out_of_stock: is now out of stock.
only_n_remainging: "now only has %{num} remaining."
shopfront:
variant:
add_to_cart: "Add"
bulk_buy_modal:
max_quantity: "Max quantity"
variants:
on_demand:
'yes': "On demand"
@@ -2716,15 +2724,6 @@ en_DE:
smtp_send_copy_to_this_addresses: "Sends a copy of all outgoing mails to this address. For multiple addresses, separate with commas."
intercept_email_address: "Intercept Email Address"
intercept_email_instructions: "Override email recipient and replace with this address."
image_settings: "Image Settings"
image_settings_warning: "You will need to regenerate thumbnails if you update the paperclip styles. Use rake paperclip:refresh:thumbnails CLASS=Spree::Image to do this."
attachment_default_style: Attachments Style
attachment_default_url: "Attachments Default URL"
attachment_path: "Attachments Path"
attachment_styles: "Paperclip Styles"
attachment_url: "Attachments URL"
add_new_style: "Add New Style"
image_settings_updated: "Image Settings successfully updated."
tax_categories: "Tax Categories"
listing_tax_categories: "Listing Tax Categories"
back_to_tax_categories_list: "Back To Tax Categories List"
@@ -2792,8 +2791,10 @@ en_DE:
inventory_error_flash_for_insufficient_quantity: "An item in your cart has become unavailable."
inventory: Inventory
zipcode: Postcode
weight: Weight (per kg)
error_user_destroy_with_orders: "Users with completed orders may not be deleted"
successfully_created: '%{resource} has been successfully created!'
successfully_updated: '%{resource} has been successfully updated!'
payment_processing_failed: "Payment could not be processed, please check the details you entered"
actions:
update: "Update"
shared:

View File

@@ -23,6 +23,10 @@ en_FR:
variant_unit_name: "Variant Unit Name"
spree/credit_card:
base: "Credit Card"
number: "Number"
month: "Month"
verification_value: "Verification Value"
year: "Year"
order_cycle:
orders_close_at: Close date
variant_override:
@@ -1213,6 +1217,9 @@ en_FR:
require_customer_html: "If you'd like to start shopping here, please %{contact} %{enterprise} to ask about joining."
select_oc:
select_oc_html: "Please <span class='highlighted'>choose an option</span>, to see what products are available."
products:
summary:
bulk: "Bulk"
card_could_not_be_updated: Card could not be updated
card_could_not_be_saved: card could not be saved
spree_gateway_error_flash_for_checkout: "There was a problem with your payment information: %{error}"
@@ -1920,7 +1927,6 @@ en_FR:
shop_for_products_html: "Shop for <span class=\"turquoise\">%{enterprise}</span> products at:"
change_shop: "Change shop to:"
shop_at: "Shop now at:"
price_breakdown: "Full price breakdown"
admin_fee: "Admin fee"
sales_fee: "Sales fee"
packing_fee: "Packing fee"
@@ -1995,6 +2001,7 @@ en_FR:
calculator: "Calculator"
calculator_values: "Calculator values"
calculator_settings_warning: "If you are changing the calculator type, you must save first before you can edit the calculator settings"
calculator_preferred_unit_error: "must be kg or lb"
flat_percent_per_item: "Flat Percent (per item)"
flat_rate_per_item: "Flat Rate (per item)"
flat_rate_per_order: "Flat Rate (per order)"
@@ -2593,6 +2600,15 @@ en_FR:
in your cart have reduced. Here's what's changed:
now_out_of_stock: is now out of stock.
only_n_remainging: "now only has %{num} remaining."
shopfront:
variant:
add_to_cart: "Add"
in_cart: "in cart"
quantity_in_cart: "%{quantity} in cart"
bulk_buy_modal:
min_quantity: "Min quantity"
max_quantity: "Max quantity"
price_breakdown: "Price breakdown"
variants:
on_demand:
'yes': "On demand"
@@ -2900,15 +2916,6 @@ en_FR:
smtp_send_copy_to_this_addresses: "Sends a copy of all outgoing mails to this address. For multiple addresses, separate with commas."
intercept_email_address: "Intercept Email Address"
intercept_email_instructions: "Override email recipient and replace with this address."
image_settings: "Image Settings"
image_settings_warning: "You will need to regenerate thumbnails if you update the paperclip styles. Use rake paperclip:refresh:thumbnails CLASS=Spree::Image to do this."
attachment_default_style: Attachments Style
attachment_default_url: "Attachments Default URL"
attachment_path: "Attachments Path"
attachment_styles: "Paperclip Styles"
attachment_url: "Attachments URL"
add_new_style: "Add New Style"
image_settings_updated: "Image Settings successfully updated."
tax_categories: "Tax Categories"
listing_tax_categories: "Listing Tax Categories"
back_to_tax_categories_list: "Back To Tax Categories List"
@@ -2982,11 +2989,18 @@ en_FR:
inventory_error_flash_for_insufficient_quantity: "An item in your cart has become unavailable."
inventory: Inventory
zipcode: Postcode
weight: Weight (per kg)
weight: Weight (per kg or lb)
error_user_destroy_with_orders: "Users with completed orders may not be deleted"
cannot_create_payment_without_payment_methods: "You cannot create a payment for an order without any payment methods defined."
please_define_payment_methods: "Please define some payment methods first."
options: "Options"
has_no_shipped_units: "has no shipped units"
successfully_created: '%{resource} has been successfully created!'
successfully_updated: '%{resource} has been successfully updated!'
payment_processing_failed: "Payment could not be processed, please check the details you entered"
not_available: "N/A"
order_populator:
out_of_stock: '%{item} is out of stock.'
actions:
update: "Update"
shared:

Some files were not shown because too many files have changed in this diff Show More