Merge pull request #5548 from luisramos0/3-0-stable-jun-2

[Spree 2.1] Merge master into 3-0-stable
This commit is contained in:
Pau Pérez Fabregat
2020-06-12 11:27:29 +02:00
committed by GitHub
160 changed files with 4445 additions and 3701 deletions

View File

@@ -142,7 +142,6 @@ Layout/LineLength:
- spec/controllers/api/product_images_controller_spec.rb
- spec/controllers/api/products_controller_spec.rb
- spec/controllers/api/promo_images_controller_spec.rb
- spec/controllers/api/shipments_controller_spec.rb
- spec/controllers/api/variants_controller_spec.rb
- spec/controllers/cart_controller_spec.rb
- spec/controllers/checkout_controller_spec.rb

View File

@@ -1,9 +1,9 @@
# Contributing
We love pull requests from everyone. Any contribution is valuable, but there are two issue streams that we especially love people to work on:
We love pull requests from everyone. Any contribution is valuable!
1) Our delivery backlog, is managed via a ZenHub board (ZenHub extensions are available for most major browsers). We use a Kanban-style approach, whereby devs pick issues from the top of the backlog which has been organised according to current priorities. If you have some time and are interested in working on some issues from the backlog, please make yourself known on the [#dev][slack-dev] channel on Slack and we can direct you to the most appropriate issue to pick up.
If you have some time and are interested in working on some issues please make yourself known on the [#dev][slack-dev] channel on Slack.
2) Our list of bugs and other self-contained issues that we consider to be a good starting point for new contributors, or devs who arent able to commit to seeing a whole feature through. These issues are marked with the `# good first issue` label.
We have curated all issues we consider to be a good starting point for new members of the community within the [Welcome New Developers project board][welcome-dev]. Have a look and pick the one you would prefer working on!
## Set up
@@ -19,10 +19,6 @@ If you want to run the whole test suite, we recommend using a free CI service to
bundle exec rspec spec
## Which issue to pick first?
We have curated all issues interesting for new members of the community within the [Welcome New Developers project board][welcome-dev]. Have a look and pick the one you would prefer working on!
## Internationalisation (i18n)
The locale `en` is maintained in the source code, but other locales are managed at [Transifex][ofn-transifex]. Read more about [internationalisation][i18n] in the developer wiki.

View File

@@ -13,8 +13,8 @@ WORKDIR /usr/src/app
COPY .ruby-version .
# Install Rbenv & Ruby
RUN git clone https://github.com/rbenv/rbenv.git ${RBENV_ROOT} && \
git clone https://github.com/rbenv/ruby-build.git ${RBENV_ROOT}/plugins/ruby-build && \
RUN git clone --depth 1 --branch v1.1.2 https://github.com/rbenv/rbenv.git ${RBENV_ROOT} && \
git clone --depth 1 --branch v20200520 https://github.com/rbenv/ruby-build.git ${RBENV_ROOT}/plugins/ruby-build && \
${RBENV_ROOT}/plugins/ruby-build/install.sh && \
echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh && \
rbenv install $(cat .ruby-version) && \
@@ -43,4 +43,5 @@ RUN wget https://chromedriver.storage.googleapis.com/2.41/chromedriver_linux64.z
# Copy code and install app dependencies
COPY . /usr/src/app/
RUN bundle install
# Run bundler install in parallel with the amount of available CPUs
RUN bundle install --jobs="$(nproc)"

View File

@@ -2,21 +2,17 @@
This is a general guide to setting up an Open Food Network development environment on your local machine.
The fastest way to make it work locally is to use Docker, see the [Docker setup guide](DOCKER.md).
### Requirements
The following guides are located in the wiki and provide more OS-specific step-by-step instructions:
- [Ubuntu Setup Guide][ubuntu]
- [macOS Sierra Setup Guide][sierra]
- [OSX El Capitan Setup Guide][el-capitan]
### Dependencies
* Rails 3.2.x
* Ruby 2.3.7
The fastest way to make it work locally is to use Docker, you only need to setup git, see the [Docker setup guide](DOCKER.md).
Otherwise, for a local setup you will need:
* Ruby 2.3.7 and bundler
* PostgreSQL database
* PhantomJS (for testing)
* See Gemfile for a list of gems required
* Chrome (for testing)
The following guides will provide OS-specific step-by-step instructions to get these requirements installed:
- [Ubuntu Setup Guide][ubuntu]
- [OSX Setup Guide][osx]
If you are likely to need to manage multiple version of ruby on your local machine, we recommend version managers such as [rbenv](https://github.com/rbenv/rbenv) or [RVM](https://rvm.io/).
@@ -52,14 +48,12 @@ This will create the "ofn" user as superuser and allowing it to create databases
Once done, run `script/setup`. If the script succeeds you're ready to start developing. If not, take a look at the output as it should be informative enough to help you troubleshoot.
If you run into any other issues getting your local environment up and running please consult [the wiki][wiki].
If still you get stuck do not hesitate to open an issue reporting the full output of the script.
Now, your dreams of spinning up a development server can be realised:
bundle exec rails server
Go to [http://localhost:3000](http://localhost:3000) to play around!
To login as the default user, use:
email: ofn@example.com
@@ -79,7 +73,7 @@ The tests of all custom engines can be run with:
bundle exec rake ofn:specs:engines:rspec
Note: If your OS is not explicitly supported in the setup guides then not all tests may pass. However, you may still be able to develop. Get in touch with the [#dev][slack-dev] channel on Slack to troubleshoot issues and determine if they will preclude you from contributing to OFN.
Note: If your OS is not explicitly supported in the setup guides then not all tests may pass. However, you may still be able to develop.
Note: The time zone on your machine should match the one defined in `config/application.yml`.
@@ -120,8 +114,7 @@ $ createdb open_food_network_test --owner=ofn
If these commands succeed, you should be able to [continue the setup process](#get-it-running).
[developer-wiki]: https://github.com/openfoodfoundation/openfoodnetwork/wiki
[sierra]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup%3A-macOS-%28Sierra%2C-HighSierra%2C-Mojave-and-Catalina%29
[el-capitan]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup:-OS-X-(El-Capitan)
[osx]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup:-OS-X
[ubuntu]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup:-Ubuntu
[wiki]: https://github.com/openfoodfoundation/openfoodnetwork/wiki
[zeus]: https://github.com/burke/zeus

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.6.0'
gem 'i18n-js', '~> 3.7.0'
gem 'rails', '~> 4.0.13'
gem 'rails-i18n', '~> 4.0'
gem 'rails_safe_tasks', '~> 1.0'
@@ -161,11 +161,11 @@ group :test do
end
group :development do
gem 'byebug', '~> 11.0' # 11.1 requires ruby 2.4
gem 'byebug', '~> 11.0.0' # 11.1 requires ruby 2.4
gem 'debugger-linecache'
gem "newrelic_rpm", "~> 3.0"
gem "pry", "~> 0.12.0" # pry 0.13 is not compatible with pry-byebug 3.7
gem 'pry-byebug', '~> 3.7' # 3.8 requires ruby 2.4
gem 'pry-byebug', '~> 3.7.0' # 3.8 requires ruby 2.4
gem 'rubocop'
gem 'rubocop-rails'
gem 'spring'

View File

@@ -207,7 +207,7 @@ GEM
activerecord (>= 3.2.0, < 5.0)
fog (~> 1.0)
rails (>= 3.2.0, < 5.0)
ddtrace (0.35.2)
ddtrace (0.36.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.6.0)
i18n-js (3.7.0)
i18n (>= 0.6.6)
immigrant (0.3.6)
activerecord (>= 3.0)
@@ -502,6 +502,7 @@ GEM
pg (0.21.0)
polyamorous (0.6.4)
activerecord (>= 3.0)
power_assert (1.2.0)
pry (0.12.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
@@ -510,7 +511,7 @@ GEM
pry (~> 0.10)
public_suffix (4.0.3)
rack (1.5.5)
rack-mini-profiler (2.0.1)
rack-mini-profiler (2.0.2)
rack (>= 1.2.0)
rack-protection (1.5.5)
rack
@@ -643,9 +644,10 @@ GEM
sprockets (>= 2.8, < 4.0)
state_machine (1.2.0)
stringex (1.5.1)
stripe (5.15.0)
stripe (5.22.0)
temple (0.8.2)
test-unit (3.3.5)
test-unit (3.3.6)
power_assert
thor (0.20.3)
thread_safe (0.3.6)
tilt (1.4.1)
@@ -707,7 +709,7 @@ DEPENDENCIES
aws-sdk (= 1.11.1)
blockenspiel
bugsnag
byebug (~> 11.0)
byebug (~> 11.0.0)
cancan (~> 1.6.10)
capybara (>= 2.18.0)
catalog!
@@ -741,7 +743,7 @@ DEPENDENCIES
highline (= 1.6.18)
httparty (~> 0.11)
i18n (~> 0.6.11)
i18n-js (~> 3.6.0)
i18n-js (~> 3.7.0)
immigrant
jquery-migrate-rails
jquery-rails (= 3.1.5)
@@ -765,7 +767,7 @@ DEPENDENCIES
paranoia (~> 2.0)
pg (~> 0.21.0)
pry (~> 0.12.0)
pry-byebug (~> 3.7)
pry-byebug (~> 3.7.0)
rack-mini-profiler (< 3.0.0)
rack-rewrite
rack-ssl

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 570 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 123 KiB

View File

@@ -1,72 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="386.638px" height="320px" viewBox="-31.319 2 386.638 320" enable-background="new -31.319 2 386.638 320"
xml:space="preserve">
<g>
<path fill="#ABDBD0" d="M331.518,159.254c-13.147,0-23.805,26.723-23.805,59.69c0,32.96,10.658,59.685,23.805,59.685
c13.142,0,23.801-26.725,23.801-59.685C355.319,185.977,344.66,159.254,331.518,159.254z M332.114,255.185
c-8.06,0-14.593-15.746-14.593-35.167s6.533-35.165,14.593-35.165c8.059,0,14.594,15.743,14.594,35.165
S340.173,255.185,332.114,255.185z"/>
<path fill="#ABDBD0" d="M304.557,219.468c0-36.244,11.718-65.623,26.171-65.623c2.107,0,4.154,0.642,6.116,1.823
c-10.469-8.709-35.108-4.515-46.498-2.514c-2.139,3.216-3.572,6.079-4.237,7.624c-3.91,9.023-7.063,22.001-7.063,22.001
l-11.863-0.291l11.689,55.666h-17.909c2.54,25.911,10.809,43.072,25.314,46.94c0,0,30.567,4.944,45.693-0.081
c-0.414,0.046-0.828,0.081-1.243,0.081C316.273,285.091,304.557,255.707,304.557,219.468z"/>
<path fill="#ABDBD0" d="M64.393,237.666c0-46.574,34.058-84.332,76.072-84.332c1.812,0,3.605,0.095,5.386,0.234
c-5.466-1.08-11.117-1.655-16.903-1.655c-47.453,0-85.919,38.074-85.919,85.044c0,46.967,38.467,85.042,85.919,85.042
c2.052,0,4.08-0.097,6.096-0.238C95.562,318.679,64.393,282.219,64.393,237.666z"/>
<path fill="#ABDBD0" d="M122.02,149.109c44.188-2.104,67.371,17.402,79.829,34.057l3.027-2.314l4.452-5.008l28.39,7.793
l10.02,52.325h27.275l-11.689-55.667l11.861,0.291c0,0,3.157-12.974,7.066-22c1.977-4.57,10.576-20.597,24.492-23.378
c13.917-2.784,26.31,15.218,26.31,15.218l-6.824-19.114l-25.606-9.464l-7.794-42.304l11.689-7.236l-1.114-11.69l-64.57-23.38
l-82.387,19.483V66.74l13.361,3.341l-8.908,25.608c0,0-23.709-3.198-47.031-1.02c-27.244,2.543-54.707,10.521-54.707,10.521
l-7.365,14.434l-5.009,66.242l2.983,0.565l5.182-59.414l70.49-6.662L122.02,149.109L122.02,149.109z M65.958,118.276
c-3.541,0.556-6.775-1.29-7.219-4.123c-0.446-2.835,2.065-5.583,5.606-6.139c3.543-0.556,6.776,1.288,7.22,4.124
C72.011,114.972,69.5,117.719,65.958,118.276z M107.793,115.428c-4.711,0.741-9.011-1.713-9.603-5.483
c-0.592-3.77,2.748-7.425,7.458-8.167c4.713-0.741,9.014,1.717,9.604,5.484C115.845,111.034,112.505,114.689,107.793,115.428z
M225.388,109.481h-19.989L166.472,98.96l7.715-25.25l57.162-10.17L225.388,109.481z M252.39,181.723l-17.886-0.702l7.015-117.482
l30.508,9.469l5.612,49.447L252.39,181.723z M282.025,122.017l-6.135-47.956l14.378,7.715l7.015,43.925L282.025,122.017z"/>
<path fill="#ABDBD0" d="M147.008,91.476V57.053h-6.84V41.534c-0.001-8.57-6.945-15.515-15.517-15.519v6.314
c5.083,0.008,9.198,4.123,9.206,9.204v15.519h-6.312v33.7C134.962,90.733,141.75,91.082,147.008,91.476z"/>
<path fill="#ABDBD0" d="M-22.811,227.408c0-33.523,28.628-60.694,63.942-60.694c1.17,0,2.333,0.034,3.487,0.094l0.406-5.338
c-2.084-0.176-4.193-0.274-6.325-0.274c-38.67-0.001-70.018,29.602-70.018,66.12c0,36.522,31.348,66.125,70.018,66.125
c6.585,0,12.95-0.877,18.994-2.483c-1.019-1.387-1.98-2.814-2.918-4.26c-4.397,0.909-8.959,1.4-13.642,1.4
C5.817,288.099-22.811,260.925-22.811,227.408z"/>
<path fill="#ABDBD0" d="M10.539,226.003c0-18.358,16.222-33.24,36.233-33.24c2.119,0,4.189,0.176,6.207,0.497
c0.214-0.435,0.437-0.864,0.675-1.295l-10.952-2.055l1.408-18.469c-1.078-0.059-2.159-0.087-3.249-0.087
c-32.898,0-59.568,25.249-59.568,56.395c0,31.139,26.67,56.388,59.568,56.388c4.363,0,8.614-0.457,12.71-1.299
c-4.71-7.248-8.31-15.242-10.552-23.764C24.771,257.346,10.539,243.2,10.539,226.003z"/>
<g>
<polygon fill="#ABDBD0" points="121.189,130.962 56.135,136.089 56.662,129.208 122.02,123.859 "/>
<polygon fill="#ABDBD0" points="120.531,141.218 55.478,146.347 56.004,139.465 121.364,134.116 "/>
<path fill="#ABDBD0" d="M120.311,143.455l-65.36,5.348l-0.526,6.882l50.139-3.953c4.875-1.368,9.922-2.336,15.109-2.83
L120.311,143.455z"/>
<path fill="#ABDBD0" d="M54.293,159.059l-0.527,6.883l24.851-1.96c4.491-3.131,9.296-5.842,14.364-8.088L54.293,159.059z"/>
<path fill="#ABDBD0" d="M72.954,168.275l-19.187,1.571l-0.526,6.882l11.721-0.926C67.461,173.128,70.129,170.612,72.954,168.275z"
/>
<path fill="#ABDBD0" d="M52.847,179.313l-0.526,6.882l4.571-0.362c1.745-2.542,3.636-4.978,5.641-7.313L52.847,179.313z"/>
</g>
<circle fill="#ABDBD0" cx="140.958" cy="239.852" r="19.726"/>
<ellipse fill="#ABDBD0" cx="328.491" cy="218.807" rx="4.487" ry="12.775"/>
<g>
<circle fill="#ABDBD0" cx="162.134" cy="223.81" r="2.781"/>
<circle fill="#ABDBD0" cx="133.371" cy="215.827" r="2.781"/>
<circle fill="#ABDBD0" cx="115.492" cy="239.462" r="2.781"/>
<circle fill="#ABDBD0" cx="131.915" cy="265.616" r="2.781"/>
<circle fill="#ABDBD0" cx="161.682" cy="255.915" r="2.783"/>
</g>
<path fill="#ABDBD0" d="M126.341,6.21c-9.103,0-16.483,7.379-16.483,16.482c0,2.76,0.686,5.357,1.886,7.641
c-2.135-2.062-3.7-4.699-4.48-7.655l0,0c-0.538,0.587-1.051,1.203-1.509,1.884c-5.088,7.548-3.096,17.791,4.454,22.881
c2.287,1.542,4.825,2.424,7.39,2.708c-4.22,0.898-8.783,0.158-12.644-2.444c-7.548-5.088-9.542-15.333-4.452-22.881
c1.634-2.423,3.81-4.247,6.245-5.472c-0.014-0.289-0.046-0.574-0.046-0.869c0-3.665,1.211-7.038,3.233-9.775l-0.001,0.001
c-0.855-0.185-1.731-0.312-2.642-0.312c-7.101,0-12.857,5.756-12.857,12.858c0,2.152,0.535,4.177,1.472,5.959
c-2.421-2.337-3.933-5.611-3.933-9.241c0-7.101,5.756-12.857,12.856-12.857c2.414,0,4.663,0.675,6.591,1.833
c-0.004,0.002-0.004,0.004-0.006,0.005C114.405,3.9,118.571,2,123.185,2c6.343,0,11.841,3.588,14.598,8.842
C134.817,7.98,130.789,6.21,126.341,6.21z"/>
<path fill="#ABDBD0" d="M188.32,300.982c-0.004,0-0.006,0.002-0.008,0.004c19.094-15.154,31.275-38.079,31.275-63.757
c0-40.085-29.659-73.5-69.016-81.055c-1.782-0.134-3.574-0.227-5.385-0.227c-42.013,0-76.072,36.7-76.072,81.97
c0,43.31,31.169,78.747,70.65,81.743c7.991-0.539,15.673-2.145,22.914-4.642L188.32,300.982z M144.663,286.068
c-23.696,0-42.907-20.166-42.907-45.041c0-24.878,19.211-45.042,42.907-45.042c23.697,0,42.908,20.166,42.908,45.042
C187.571,265.902,168.359,286.068,144.663,286.068z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.3 KiB

View File

@@ -105,6 +105,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$scope.producerFilter = "0"
$scope.categoryFilter = "0"
$scope.importDateFilter = "0"
$scope.fetchProducts()
$scope.$watch 'sortOptions', (sort) ->
return unless sort && sort.predicate != ""

View File

@@ -37,6 +37,7 @@ angular.module("admin.orders").controller "ordersCtrl", ($scope, $timeout, Reque
'q[distributor_id_in][]': $scope['q']['distributor_id_in'],
'q[order_cycle_id_in][]': $scope['q']['order_cycle_id_in'],
'q[s]': $scope.sorting || 'completed_at desc',
shipping_method_id: $scope.shipping_method_id,
per_page: $scope.per_page,
page: page
}

View File

@@ -4,7 +4,6 @@ angular.module("admin.side_menu")
items: []
selected: null
# Checks for path and uses it to set the view
# If no path, loads first view
init: =>
@@ -31,11 +30,3 @@ angular.module("admin.side_menu")
for item in @items when item.name is name
return item
null
hide_item_by_name: (name) =>
item = @find_by_name(name)
item.visible = false if item
show_item_by_name: (name) =>
item = @find_by_name(name)
item.visible = true if item

View File

@@ -8,6 +8,9 @@
#= require angular-sanitize
#= require angular-animate
#= require angular-resource
#= require autocomplete.min.js
#= require leaflet-1.6.0.js
#= require leaflet-providers.js
#= require lodash.underscore.js
# bluebird.js is a dependency of angular-google-maps.js 2.0.0
#= require bluebird.js

View File

@@ -1,6 +1,3 @@
Darkswarm.controller "GroupPageCtrl", ($scope, enterprises, Enterprises, MapConfiguration, OfnMap) ->
Darkswarm.controller "GroupPageCtrl", ($scope, enterprises, Enterprises) ->
$scope.Enterprises = Enterprises
$scope.map = angular.copy MapConfiguration.options
$scope.mapMarkers = OfnMap.enterprise_markers enterprises
$scope.embedded_layout = window.location.search.indexOf("embedded_shopfront=true") != -1

View File

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

View File

@@ -0,0 +1,100 @@
Darkswarm.directive 'ofnOpenStreetMap', ($window, Enterprises, EnterpriseModal, availableCountries, openStreetMapConfig) ->
restrict: 'E'
replace: true
scope: true
template: "<div></div>"
link: (scope, element, attrs, ctrl, transclude)->
map = null
markers = []
enterpriseNames = []
openStreetMapProviderName = openStreetMapConfig.open_street_map_provider_name
openStreetMapProviderOptions = JSON.parse(openStreetMapConfig.open_street_map_provider_options)
average = (values) ->
total = values.reduce (sum, value) ->
sum = sum + value
, 0
total / values.length
averageAngle = (angleName) ->
positiveAngles = []
negativeAngles = []
for enterprise in Enterprises.enterprises
if enterprise.latitude? && enterprise.longitude?
if enterprise[angleName] > 0
positiveAngles.push(enterprise[angleName])
else
negativeAngles.push(enterprise[angleName])
averageNegativeAngle = average(negativeAngles)
averagePositiveAngle = average(positiveAngles)
if negativeAngles.length == 0
averagePositiveAngle
else if positiveAngles.length == 0
averageNegativeAngle
else if averagePositiveAngle > averageNegativeAngle
averagePositiveAngle - averageNegativeAngle
else
averageNegativeAngle - averagePositiveAngle
buildMarker = (enterprise, latlng, title) ->
icon = L.icon
iconUrl: enterprise.icon
marker = L.marker latlng,
draggable: true,
icon: icon,
riseOnHover: true,
title: title
marker.on "click", ->
EnterpriseModal.open enterprise
marker
enterpriseName = (enterprise) ->
return enterprise.name + " (" + enterprise.address.address1 + ", " + enterprise.address.city + ", " + enterprise.address.state_name + ")";
goToEnterprise = (selectedEnterpriseName) ->
enterprise = Enterprises.enterprises.find (enterprise) ->
enterpriseName(enterprise) == selectedEnterpriseName
map.setView([enterprise.latitude, enterprise.longitude], 12)
displayMap = ->
setMapDimensions()
averageLatitude = averageAngle("latitude")
averageLongitude = averageAngle("longitude")
zoomLevel = 6
map = L.map('open-street-map')
L.tileLayer.provider(openStreetMapProviderName, openStreetMapProviderOptions).addTo(map)
map.setView([averageLatitude, averageLongitude], zoomLevel)
displayEnterprises = ->
for enterprise in Enterprises.enterprises
if enterprise.latitude? && enterprise.longitude?
marker = buildMarker(enterprise, { lat: enterprise.latitude, lng: enterprise.longitude }, enterprise.name).addTo(map)
enterpriseNames.push(enterpriseName(enterprise))
markers.push(marker)
displaySearchField = () ->
new Autocomplete('#open-street-map--search',
onSubmit: goToEnterprise
search: searchEnterprises
)
overwriteInlinePositionRelativeToPositionSearchField = ->
$('#open-street-map--search').css("position", "absolute")
overwriteInlinePositionRelativeToPositionSearchField()
searchEnterprises = (input) ->
if input.length < 1
return []
enterpriseNames.filter (country) ->
country.toLowerCase().includes input.toLowerCase()
setMapDimensions = ->
height = $window.innerHeight - element.offset().top
element.css "width", "100%"
element.css "height", (height + "px")
displayMap()
displayEnterprises()
displaySearchField()

View File

@@ -21,8 +21,10 @@ Darkswarm.factory 'Checkout', ($injector, CurrentOrder, ShippingMethods, StripeE
try
@handle_checkout_error_response(response)
catch error
@loadFlash(error: t("checkout.failed")) # inform the user about the unexpected error
throw error # generate a BugsnagJS alert
try
@loadFlash(error: t("checkout.failed")) # inform the user about the unexpected error
finally
throw error # generate a BugsnagJS alert
handle_checkout_error_response: (response) =>
if response.data.path

View File

@@ -1,4 +1,4 @@
Darkswarm.factory 'Enterprises', (enterprises, ShopsResource, CurrentHub, Taxons, Dereferencer, Matcher, Geo, $rootScope) ->
Darkswarm.factory 'Enterprises', (enterprises, ShopsResource, CurrentHub, Taxons, Dereferencer, Matcher, GmapsGeo, $rootScope) ->
new class Enterprises
enterprises: []
enterprises_by_id: {}
@@ -59,7 +59,7 @@ Darkswarm.factory 'Enterprises', (enterprises, ShopsResource, CurrentHub, Taxons
false
calculateDistance: (query, firstMatching) ->
if query?.length > 0 and Geo.OK
if query?.length > 0 and GmapsGeo.OK
if firstMatching?
@setDistanceFrom firstMatching
else
@@ -68,9 +68,9 @@ Darkswarm.factory 'Enterprises', (enterprises, ShopsResource, CurrentHub, Taxons
@resetDistance()
calculateDistanceGeo: (query) ->
Geo.geocode query, (results, status) =>
GmapsGeo.geocode query, (results, status) =>
$rootScope.$apply =>
if status == Geo.OK
if status == GmapsGeo.OK
#console.log "Geocoded #{query} -> #{results[0].geometry.location}."
@setDistanceFrom results[0].geometry.location
else
@@ -79,7 +79,7 @@ Darkswarm.factory 'Enterprises', (enterprises, ShopsResource, CurrentHub, Taxons
setDistanceFrom: (locatable) ->
for enterprise in @enterprises
enterprise.distance = Geo.distanceBetween enterprise, locatable
enterprise.distance = GmapsGeo.distanceBetween enterprise, locatable
$rootScope.$broadcast 'enterprisesChanged'
resetDistance: ->

View File

@@ -1,5 +1,5 @@
Darkswarm.service "Geo", ->
new class Geo
Darkswarm.service "GmapsGeo", ->
new class GmapsGeo
OK: google?.maps?.GeocoderStatus?.OK
# Usage:

View File

@@ -1,6 +1,5 @@
.row
.columns.small-12.large-6.product-header
.columns.small-12.medium-6.large-6.product-header
%h3{"ng-bind" => "::product.name"}
%span
%em {{'products_from' | t}}
@@ -8,19 +7,14 @@
%br
.filter-shopfront.taxon-selectors.inline-block
%filter-selector{ 'selector-set' => "productTaxonSelectors", objects: "[product] | taxonsOf" }
.filter-shopfront.property-selectors.inline-block
%filter-selector{ 'selector-set' => "productPropertySelectors", objects: "[product] | propertiesWithValuesOf" }
%div{"ng-if" => "product.description_html"}
%hr
.product-description{"ng-if" => "product.description_html"}
%p.text-small{"ng-bind-html" => "::product.description_html"}
%hr
.columns.small-12.large-6
%img.product-img{"ng-src" => "{{::product.largeImage}}", "ng-if" => "::product.largeImage"}
%img.product-img.placeholder{ src: "/assets/noimage/large.png", "ng-if" => "::!product.largeImage"}
.columns.small-12.medium-6.large-6.product-img
%img{"ng-src" => "{{::product.largeImage}}", "ng-if" => "::product.largeImage"}
%img.placeholder{ src: "/assets/noimage/large.png", "ng-if" => "::!product.largeImage"}
%ng-include{src: "'partials/close.html'"}

View File

@@ -27,13 +27,11 @@
a, a.button {
display: block;
padding-top: 0.5rem;
@include border-radius(0.5em);
border: 1px solid $border-clr;
padding: 0.5em 0.625em;
font-size: 0.875em;
color: $base-clr;
font-size: 0.75em;
background: white;

View File

@@ -1,9 +1,30 @@
.product-header {
padding-left: 1.5rem;
h1, h2, h3, h4, h5, h6 {
margin: 0;
margin: 0.2rem 1.5rem 0 0;
}
hr {
margin: 0.5em 0;
span {
color: $grey-500;
}
.product-description {
margin: 1rem 0.25rem 0.25rem 0;
}
.property-selectors li {
margin: 0 0.25rem 0.25rem 0;
padding: 0.4rem 0 0;
a {
border: 1px solid $grey-300;
font-weight: normal;
padding: 0.15rem 0.5rem;
}
span {
color: $grey-600;
}
}
}

View File

@@ -63,6 +63,8 @@ ordercycle {
select {
background-image: url('/assets/white-caret.svg');
background-size: 30px auto;
background-position-x: 102%;
}
p {
@@ -71,24 +73,27 @@ ordercycle {
select,
p {
width: inherit;
display: inline-block;
color: $white;
background-color: transparent;
border: 0;
border-radius: 0 $radius-small $radius-small 0;
margin-bottom: 0;
padding: 0.5em 1.25em 0.5em 0.75em;
font-size: 1em;
line-height: 1.3em;
padding: 0.5em 1.25em 0.5em 0.75em;
height: 2.35em;
background-size: 30px auto;
border-radius: 0 $radius-small $radius-small 0;
min-width: 13em;
width: 200px;
@include breakpoint(mobile) {
width: 100%;
min-width: 0;
}
@media all and (min-width: 640px) and (max-width: 1024px), (min-width: 1200px) {
width: 250px;
}
}
option {
@@ -107,6 +112,7 @@ ordercycle {
@include breakpoint(mobile) {
display: flex;
margin-right: 0;
}
}
@@ -162,7 +168,7 @@ shop ordercycle {
@include breakpoint(tablet) {
float: none;
padding: 0 0 10px;
padding: 0;
}
}

View File

@@ -3,6 +3,9 @@
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
* the top of the compiled file, but it's generally better to create a new file per style scope.
*= require autocomplete
*= require leaflet
*= require_self
*/
@import 'variables';

View File

@@ -143,8 +143,8 @@
}
.reveal-modal-bg.in {
filter: alpha(opacity = 50);
opacity: 0.5;
filter: alpha(opacity = 75);
opacity: 0.75;
}
.animate-repeat {

View File

@@ -11,7 +11,7 @@ section {
display: block;
background: $white;
position: relative;
z-index: 2;
z-index: 20;
.details {
box-sizing: border-box;
@@ -20,10 +20,6 @@ section {
padding: 30px 0 0;
position: relative;
select {
width: 200px;
}
img {
display: block;
height: 100px;

View File

@@ -3,18 +3,22 @@
@import "branding";
.product-img {
padding: 5px;
margin-bottom: 10px;
outline: 1px solid #ccc;
text-align: center;
@include box-shadow(0 1px 2px 1px rgba(0, 0, 0, 0.15));
img {
padding: 0.3rem;
// placeholder for when no product images
&.placeholder {
opacity: 0.35;
// placeholder for when no product images
&.placeholder {
opacity: 0.35;
@include breakpoint(desktop) {
display: none;
@include breakpoint(desktop) {
display: none;
}
}
@media only screen and (max-width: 1024px) {
margin: 0 0 0.5rem;
}
}
}
@@ -49,10 +53,3 @@
.producer-logo {
max-width: 220px;
}
@media only screen and (max-width: 1024px) {
.product-img {
margin-top: 2em;
margin-bottom: 1em;
}
}

View File

@@ -6,6 +6,7 @@
.map-container {
width: 100%;
position: relative;
map, .angular-google-map-container, google-map, .angular-google-map {
display: block;
@@ -38,6 +39,30 @@
background: rgba(255, 255, 255, 1);
}
}
#open-street-map {
z-index: 1;
}
#open-street-map--search {
top: 16px;
left: 54px;
width: 50%;
z-index: 1000;
.autocomplete-input,
.autocomplete-result-list {
border: 2px solid $grey-500;
&:hover, &:active, &:focus {
border-color: $clr-brick;
}
}
.autocomplete-result-list {
border-top: 1px dotted $grey-500;
}
}
}
.map-footer {
@@ -63,3 +88,8 @@
left: 0px;
}
}
.tabs-content .map-footer {
position: relative;
bottom: 30px;
}

View File

@@ -5,8 +5,6 @@ dialog
, .reveal-modal {
border: none;
outline: none;
padding: 30px 20px 0 20px;
border-bottom: 30px solid white;
overflow-y: scroll;
overflow-x: hidden;
min-height: 260px;
@@ -18,23 +16,26 @@ dialog
// Reveal.js break point:
// @media only screen and (max-width: 40.063em)
// Small - when modal IS full screen
// Small - smaller outside area
@media only screen and (max-width: 640px) {
left: 0;
max-height: 100%;
position: absolute !important;
top: 0;
left: 4%;
max-height: 92%;
max-width: 92%;
padding: 15px 0 0;
top: 4%;
}
// Medium and up - when modal IS NOT full screen
// Medium and up - larger outside area
@media only screen and (min-width: 641px) {
border-bottom: 30px solid $white;
max-height: 90%;
padding: 30px 20px 0 20px;
top: 5%;
}
}
.reveal-modal-bg {
background-color: rgba(0, 0, 0, 0.85);
background-color: $black;
position: fixed;
}
@@ -58,6 +59,10 @@ dialog
dialog .close-reveal-modal
, .reveal-modal .close-reveal-modal {
@include close-button(0.25rem);
background-color: $grey-500;
color: $white;
font-size: 1.5rem;
right: 0.25rem;
}

View File

@@ -23,6 +23,12 @@
text-decoration: underline;
}
}
@media only screen and (max-width: 640px) {
.tabbable {
margin: 0 15px;
}
}
}
@media only screen and (min-width: 1025px) {

View File

@@ -2,6 +2,10 @@
@import "mixins";
#registration-modal {
@media only screen and (max-width: 640px) {
margin: 0 15px;
}
header {
text-align: center;

View File

@@ -234,6 +234,7 @@ $sidebar-footer-height: 5em;
.warning-sign {
margin: 0 10px 0 5px;
display: inline-block;
line-height: 1.9rem;
strong {
color: $grey-650;

View File

@@ -9,6 +9,7 @@
color: $dark-grey;
box-shadow: $distributor-header-shadow;
position: relative;
z-index: 10;
.columns {
display: flex;

View File

@@ -68,6 +68,10 @@ table.social {
background-color: white !important;
border: 1px solid #ebebeb;
}
&.fullwidth {
width: 100%;
}
}
table.order-summary {

View File

@@ -32,7 +32,8 @@ module Admin
PreferenceSections::GroupSignupPageSection.new,
PreferenceSections::MainLinksSection.new,
PreferenceSections::FooterAndExternalLinksSection.new,
PreferenceSections::UserGuideSection.new
PreferenceSections::UserGuideSection.new,
PreferenceSections::MapSection.new
]
end
end

View File

@@ -145,7 +145,7 @@ module Admin
preload(:schedules).
ransack(params[:q]).
result.
accessible_by(spree_current_user)
visible_by(spree_current_user)
end
def load_data_for_index

View File

@@ -65,7 +65,10 @@ class EnterprisesController < BaseController
def reset_order
order = current_order(true)
OrderCartReset.new(order, params[:id], try_spree_current_user, current_customer).call
# reset_distributor must be called before any call to current_customer or current_distributor
order_cart_reset = OrderCartReset.new(order, params[:id])
order_cart_reset.reset_distributor
order_cart_reset.reset_other!(try_spree_current_user, current_customer)
rescue ActiveRecord::RecordNotFound
flash[:error] = I18n.t(:enterprise_shop_show_error)
redirect_to shops_path

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_method_url
redirect_to edit_admin_mail_methods_url
end
private

View File

@@ -247,15 +247,17 @@ module Spree
end
def suppliers_of_products_distributed_by(distributors)
distributors.map { |d| Spree::Product.in_distributor(d).includes(:supplier).to_a }.
flatten.map(&:supplier).uniq
supplier_ids = Spree::Product.in_distributors(distributors).
select('spree_products.supplier_id')
Enterprise.where(id: supplier_ids)
end
# Load order cycles the current user has access to
def my_order_cycles
OrderCycle.
active_or_complete.
accessible_by(spree_current_user).
visible_by(spree_current_user).
order('orders_close_at DESC')
end

View File

@@ -100,6 +100,10 @@ module InjectionHelper
inject_json_ams "currencyConfig", {}, Api::CurrencyConfigSerializer
end
def inject_open_street_map_config
inject_json_ams "openStreetMapConfig", {}, Api::OpenStreetMapConfigSerializer
end
def inject_spree_api_key
render partial: "json/injection_ams", locals: { name: 'spreeApiKey', json: "'#{@spree_api_key}'" }
end

View File

@@ -17,6 +17,11 @@ class ContentConfiguration < Spree::Preferences::FileConfiguration
preference :home_show_stats, :boolean, default: true
has_attached_file :home_hero, default_url: "/assets/home/home.jpg"
# Map
preference :open_street_map_enabled, :boolean, default: false
preference :open_street_map_provider_name, :string, default: "OpenStreetMap.Mapnik"
preference :open_street_map_provider_options, :text, default: "{}"
# Producer sign-up page
# All the following defaults using I18n don't work.
# https://github.com/openfoodfoundation/openfoodnetwork/issues/3816

View File

@@ -70,7 +70,7 @@ class OrderCycle < ActiveRecord::Base
}
# Return order cycles that user coordinates, sends to or receives from
scope :accessible_by, lambda { |user|
scope :visible_by, lambda { |user|
if user.has_spree_role?('admin')
where(nil)
else

View File

@@ -0,0 +1,17 @@
# frozen_string_literal: true
module PreferenceSections
class MapSection
def name
I18n.t('admin.contents.edit.map')
end
def preferences
[
:open_street_map_enabled,
:open_street_map_provider_name,
:open_street_map_provider_options
]
end
end
end

View File

@@ -39,7 +39,7 @@ class AbilityDecorator
# OR if they manage a producer which is included in any order cycles
def can_manage_order_cycles?(user)
can_manage_orders?(user) ||
OrderCycle.accessible_by(user).any?
OrderCycle.visible_by(user).any?
end
# Users can manage orders if they have a sells own/any enterprise.
@@ -193,7 +193,7 @@ class AbilityDecorator
def add_order_cycle_management_abilities(user)
can [:admin, :index, :read, :edit, :update, :incoming, :outgoing], OrderCycle do |order_cycle|
OrderCycle.accessible_by(user).include? order_cycle
OrderCycle.visible_by(user).include? order_cycle
end
can [:admin, :index, :create], Schedule
can [:admin, :update, :destroy], Schedule do |schedule|

View File

@@ -26,6 +26,7 @@ Spree::AppConfiguration.class_eval do
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

View File

@@ -13,7 +13,7 @@ module Spree
end
def compute(object)
min = preferred_minimal_amount.to_i
min = preferred_minimal_amount.to_f
order_amount = line_items_for(object).map { |x| x.price * x.quantity }.sum
if order_amount < min

View File

@@ -79,6 +79,12 @@ Spree::Product.class_eval do
select('distinct spree_products.*')
}
scope :in_distributors, lambda { |distributors|
with_order_cycles_outer.
where('(o_exchanges.incoming = ? AND o_exchanges.receiver_id IN (?))', false, distributors).
uniq
}
# Products supplied by a given enterprise or distributed via that enterprise through an OC
scope :in_supplier_or_distributor, lambda { |enterprise|
enterprise = enterprise.respond_to?(:id) ? enterprise.id : enterprise.to_i
@@ -153,18 +159,6 @@ Spree::Product.class_eval do
self.class.in_order_cycle(order_cycle).include? self
end
# overriding to check self.on_demand as well
def has_stock?
has_variants? ? variants.any?(&:in_stock?) : (on_demand || master.in_stock?)
end
def has_stock_for_distribution?(order_cycle, distributor)
# This product has stock for a distribution if it is available on-demand
# or if one of its variants in the distribution is in stock
(!has_variants? && on_demand) ||
variants_distributed_by(order_cycle, distributor).any?(&:in_stock?)
end
def variants_distributed_by(order_cycle, distributor)
order_cycle.variants_distributed_by(distributor).where(product_id: self)
end

View File

@@ -0,0 +1,21 @@
# frozen_string_literal: true
module Api
class OpenStreetMapConfigSerializer < ActiveModel::Serializer
attributes :open_street_map_enabled,
:open_street_map_provider_name,
:open_street_map_provider_options
def open_street_map_enabled
ContentConfig.open_street_map_enabled
end
def open_street_map_provider_name
ContentConfig.open_street_map_provider_name
end
def open_street_map_provider_options
ContentConfig.open_street_map_provider_options.to_json
end
end
end

View File

@@ -7,9 +7,8 @@ class BulkInvoiceService
def start_pdf_job(order_ids)
pdf = CombinePDF.new
orders = Spree::Order.where(id: order_ids)
orders.each do |order|
orders_from(order_ids).each do |order|
invoice = renderer.render_to_string(order)
pdf << CombinePDF.parse(invoice)
@@ -29,6 +28,10 @@ class BulkInvoiceService
private
def orders_from(order_ids)
Spree::Order.where(id: order_ids).order("completed_at DESC")
end
def new_invoice_id
Time.zone.now.to_i.to_s
end

View File

@@ -2,25 +2,12 @@
# Resets an order by verifying it's state and fixing any issues
class OrderCartReset
def initialize(order, distributor_id, current_user, current_customer)
def initialize(order, distributor_id)
@order = order
@distributor ||= Enterprise.is_distributor.find_by(permalink: distributor_id) ||
Enterprise.is_distributor.find(distributor_id)
@current_user = current_user
@current_customer = current_customer
end
def call
reset_distributor
reset_user_and_customer if current_user
reset_order_cycle
order.save!
end
private
attr_reader :order, :distributor, :current_user, :current_customer
def reset_distributor
if order.distributor && order.distributor != distributor
order.empty!
@@ -29,12 +16,24 @@ class OrderCartReset
order.distributor = distributor
end
def reset_user_and_customer
def reset_other!(current_user, current_customer)
reset_user_and_customer(current_user)
reset_order_cycle(current_customer)
order.save!
end
private
attr_reader :order, :distributor, :current_user
def reset_user_and_customer(current_user)
return unless current_user
order.associate_user!(current_user) if order.user.blank? || order.email.blank?
order.__send__(:associate_customer) if order.customer.nil? # Only associates existing customers
end
def reset_order_cycle
def reset_order_cycle(current_customer)
listed_order_cycles = Shop::OrderCyclesList.new(distributor, current_customer).call
if order_cycle_not_listed?(order.order_cycle, listed_order_cycles)

View File

@@ -24,13 +24,25 @@ class SearchOrders
attr_reader :params, :current_user
def fetch_orders
@search = ::Permissions::Order.new(current_user).editable_orders.ransack(params[:q])
@search = search_query.ransack(params[:q])
return paginated_results if using_pagination?
@search.result(distinct: true)
end
def search_query
base_query = ::Permissions::Order.new(current_user).editable_orders
return base_query unless params[:shipping_method_id]
base_query
.joins(shipments: :shipping_rates)
.where(spree_shipping_rates: {
selected: true,
shipping_method_id: params[:shipping_method_id]
})
end
def paginated_results
@search.result(distinct: true)
.page(params[:page])

View File

@@ -18,6 +18,10 @@
= label_tag(:matomo_site_id, t('.matomo_site_id')) + tag(:br)
= preference_field_tag("preferences[#{:matomo_site_id}]", Spree::Config[:matomo_site_id], type: Spree::Config.preference_type(:matomo_site_id))
.field
= label_tag(:matomo_tag_manager_url, t('.matomo_tag_manager_url')) + tag(:br)
= preference_field_tag("preferences[#{:matomo_tag_manager_url}]", Spree::Config[:matomo_tag_manager_url], type: Spree::Config.preference_type(:matomo_tag_manager_url))
.warning.note= t('.config_instructions_tag_manager_html')
.form-buttons{"data-hook" => "buttons"}
= button t(:update), 'icon-refresh'

View File

@@ -6,7 +6,9 @@
= @group.logo.url
- content_for :injection_data do
= inject_available_countries
= inject_group_enterprises
= inject_open_street_map_config
#group-page.row.pad-top.footer-pad{"ng-controller" => "GroupPageCtrl"}
.small-12.columns.pad-top
@@ -32,13 +34,8 @@
%tab{heading: t(:label_map),
active: "tabs.map.active",
select: "select(\'map\')"}
.map-container
%map{"ng-if" => "(isActive(\'/map\') && (mapShowed = true)) || mapShowed"}
%ui-gmap-google-map{options: "map.additional_options", center: "map.center", zoom: "map.zoom", styles: "map.styles", draggable: "true"}
%map-osm-tiles
%map-search
%ui-gmap-markers{models: "mapMarkers", fit: "true",
coords: "'self'", icon: "'icon'", click: "'reveal'"}
%div{"ng-if" => "(isActive(\'/map\') && (mapShowed = true)) || mapShowed"}
= render partial: "shared/map"
%tab{heading: t(:groups_about),
active: "tabs.about.active",
@@ -122,4 +119,4 @@
%span
= t 'title'
= render "shared/footer"
= render "shared/footer"

View File

@@ -1,6 +1,15 @@
- if Spree::Config.matomo_tag_manager_url.present?
:javascript
var _mtm = _mtm || [];
_mtm.push({'mtm.startTime': (new Date().getTime()), 'event': 'mtm.Start'});
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
var u="#{Spree::Config.matomo_tag_manager_url}";
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u; s.parentNode.insertBefore(g,s);
- if Spree::Config.matomo_url.present?
:javascript
var _paq = _paq || [];
var _paq = window._paq || [];
_paq.push(["setDocumentTitle", document.domain + "/" + document.title]);
_paq.push(["setCookieDomain", "*.#{Spree::Config.site_url}"]);
_paq.push(["setDomains", ["*.#{Spree::Config.site_url}"]]);
@@ -8,8 +17,8 @@
_paq.push(['enableLinkTracking']);
(function() {
var u="#{Spree::Config.matomo_url}";
_paq.push(['setTrackerUrl', u+'piwik.php']);
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '#{Spree::Config.matomo_site_id}']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();

View File

@@ -39,7 +39,8 @@
= render "layouts/bugsnag_js"
%script{:src => "https://js.stripe.com/v3/", :type => "text/javascript"}
%script{src: "//maps.googleapis.com/maps/api/js?libraries=places,geometry#{ ENV['GOOGLE_MAPS_API_KEY'] ? '&key=' + ENV['GOOGLE_MAPS_API_KEY'] : ''} "}
- if !ContentConfig.open_street_map_enabled
%script{src: "//maps.googleapis.com/maps/api/js?libraries=places,geometry#{ ENV['GOOGLE_MAPS_API_KEY'] ? '&key=' + ENV['GOOGLE_MAPS_API_KEY'] : ''} "}
= javascript_include_tag "darkswarm/all"
= javascript_include_tag "web/all"
= render "layouts/i18n_script"

View File

@@ -2,15 +2,8 @@
= t :label_map
- content_for :injection_data do
= inject_available_countries
= inject_enterprise_shopfront_list
= inject_open_street_map_config
.map-container{"fill-vertical" => true}
%map{"ng-controller" => "MapCtrl"}
%ui-gmap-google-map{options: "map.additional_options", center: "map.center", zoom: "map.zoom", styles: "map.styles", draggable: "true"}
%map-osm-tiles
%map-search
%ui-gmap-markers{models: "OfnMap.enterprises", fit: "true",
coords: "'self'", icon: "'icon'", click: "'reveal'"}
.map-footer
%a{:href => "http://www.openstreetmap.org/copyright"} &copy; OpenStreetMap contributors
= render partial: "shared/map"

View File

@@ -0,0 +1,19 @@
- if ContentConfig.open_street_map_enabled
.map-container
%ofn-open-street-map#open-street-map
%div#open-street-map--search
%input.autocomplete-input
%ul.autocomplete-result-list
- else
.map-container
%map{"ng-controller" => "MapCtrl"}
%ui-gmap-google-map{options: "map.additional_options", center: "map.center", zoom: "map.zoom",
styles: "map.styles", draggable: "true"}
%map-osm-tiles
%map-search
%ui-gmap-markers{models: "OfnMap.enterprises", fit: "true",
coords: "'self'", icon: "'icon'", click: "'reveal'"}
.map-footer
%a{:href => "http://www.openstreetmap.org/copyright"} &copy; OpenStreetMap contributors

View File

@@ -1,3 +1,5 @@
.content.footer-pad{ "darker-background" => true, "ng-controller" => "ProductsCtrl", "ng-show" => "order_cycle.order_cycle_id == null" }
.select-oc-message
= t '.select_oc_html'
.row
.small-12.columns
.select-oc-message
= t '.select_oc_html'

View File

@@ -1,4 +1,5 @@
= render :partial => 'spree/admin/shared/order_tabs', :locals => { :current => 'Adjustments' }
= render :partial => 'spree/admin/shared/order_page_title'
= render :partial => 'spree/admin/shared/order_tabs', locals: { current: 'Adjustments' }
- content_for :page_title do
%i.icon-arrow-right

View File

@@ -1,4 +1,5 @@
= render :partial => 'spree/admin/shared/order_tabs', :locals => { :current => 'Adjustments' }
= render partial: 'spree/admin/shared/order_page_title'
= render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Adjustments' }
- content_for :page_title do
%i.icon-arrow-right

View File

@@ -1,4 +1,5 @@
= render :partial => 'spree/admin/shared/order_tabs', :locals => { :current => 'Adjustments' }
= render partial: 'spree/admin/shared/order_page_title'
= render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Adjustments' }
- content_for :page_title do
%i.icon-arrow-right

View File

@@ -15,15 +15,13 @@
%colgroup
%col{ style: "width: 5%" }/
%col{ style: "width: 10%" }/
- if @product.has_variants?
%col{ style: "width: 25%" }/
%col{ style: "width: 25%" }/
%col{ style: "width: 45%" }/
%col{ style: "width: 15%" }/
%thead
%tr
%th{:colspan => "2"}= t('spree.thumbnail')
- if @product.has_variants?
%th= Spree::Variant.model_name.human
%th= Spree::Variant.model_name.human
%th= t('spree.alt_text')
%th.actions
%tbody
@@ -35,8 +33,7 @@
%span.handle
%td
= link_to image_tag(image.attachment.url(:mini)), image.attachment.url(:product)
- if @product.has_variants?
%td= options_text_for(image)
%td= options_text_for(image)
%td= image.alt
%td.actions
= link_to_with_icon 'icon-edit', t('spree.edit'), edit_admin_product_image_url(@product, image), no_text: true, data: { action: 'edit'}

View File

@@ -5,11 +5,11 @@
- content_for :page_actions do
%li
= link_to_with_icon 'icon-envelope-alt', t("spree.admin.mail_methods.send_testmail"), testmail_admin_mail_method_path, method: :post, title: t("spree.admin.mail_methods.send_testmail"), class: 'send_mail button no-text'
= link_to_with_icon 'icon-envelope-alt', t("spree.admin.mail_methods.send_testmail"), testmail_admin_mail_methods_path, method: :post, title: t("spree.admin.mail_methods.send_testmail"), class: 'send_mail button no-text'
= render partial: 'spree/shared/error_messages', locals: { target: @mail_method }
= form_tag admin_mail_method_path, method: :put do |f|
= form_tag admin_mail_methods_path, method: :put do |f|
%fieldset.no-border-top
= render partial: 'form', locals: { f: f }
.form-buttons.filter-actions.actions= button t("spree.actions.update"), 'icon-refresh'

View File

@@ -32,6 +32,11 @@
%label
= check_box_tag "q[completed_at_not_null]", 1, true, {'ng-model' => 'q.completed_at_not_null'}
= t(:show_only_complete_orders)
.field
= label_tag nil, t(:shipping_method)
= select_tag("shipping_method_id",
options_for_select(Spree::ShippingMethod.managed_by(spree_current_user).collect {|s| [t("spree.shipping_method.#{s.name}"), s.id]}),
{include_blank: true, class: 'select2', 'ng-model' => 'shipping_method_id'})
.field-block.alpha.eight.columns
= label_tag nil, t(:distributors)
= select_tag("q[distributor_id_in]",

View File

@@ -1,4 +1,5 @@
= render :partial => 'spree/admin/shared/order_tabs', :locals => { :current => 'Customer Details' }
= render partial: 'spree/admin/shared/order_page_title'
= render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Customer Details' }
= csrf_meta_tags

View File

@@ -8,7 +8,8 @@
- if can?(:admin, Spree::Order)
%li= button_link_to t(:back_to_orders_list), admin_orders_path, :icon => 'icon-arrow-left'
= render :partial => 'spree/admin/shared/order_tabs', :locals => { :current => 'Order Details' }
= render partial: "spree/admin/shared/order_page_title"
= render partial: "spree/admin/shared/order_tabs", locals: { current: 'Order Details' }
%div{"data-hook" => "admin_order_edit_header"}
-# Suppress errors when manually creating a new order - needs to proceed to edit page

View File

@@ -1,5 +1,7 @@
- content_for :page_title do
= t(:new)
= t(:new_order)
\#
= @order.number
- content_for :page_actions do
%li= button_link_to t(:back_to_orders_list), spree.admin_orders_path, :icon => 'icon-arrow-left'

View File

@@ -1,12 +1,14 @@
- content_for :page_title do
= t(:new)
- content_for :page_actions do
%li= button_link_to t(:back_to_orders_list), spree.admin_orders_path, :icon => 'icon-arrow-left'
= admin_inject_shops(module: 'admin.orders')
= admin_inject_order_cycles
- content_for :page_title do
= t(:new_order)
\#
= @order.number
= render 'spree/admin/shared/order_tabs', :current => 'Order Details'
= csrf_meta_tags

View File

@@ -1,42 +1,44 @@
= admin_inject_payment_method
= admin_inject_json_ams_array "admin.paymentMethods", "shops", @hubs, Api::Admin::BasicEnterpriseSerializer
%div.alpha.eleven.columns{ "ng-app" => "admin.paymentMethods", "ng-controller" => "paymentMethodCtrl" }
.alpha.eleven.columns{ "ng-app" => "admin.paymentMethods", "ng-controller" => "paymentMethodCtrl" }
.row
= t '.deactivation_warning'
.row
.alpha.three.columns
= label_tag nil, t(:name)
= label_tag nil, t('.name')
.omega.eight.columns
= text_field :payment_method, :name, class: 'fullwidth'
.row
.alpha.three.columns
= label_tag nil, t(:description)
= label_tag nil, t('.description')
.omega.eight.columns
= text_area :payment_method, :description, {cols: 60, rows: 6, class: 'fullwidth'}
- if spree_current_user.admin?
.row
.alpha.three.columns
= label_tag nil, t(:environment)
= label_tag nil, t('.environment')
.omega.eight.columns
= collection_select(:payment_method, :environment, Rails.configuration.database_configuration.keys.sort, :to_s, :titleize, {}, {id: 'gtwy-env', class: 'select2 fullwidth'})
.row
.alpha.three.columns
= label_tag nil, t(:display)
.omega.eight.columns
= select(:payment_method, :display_on, Spree::PaymentMethod::DISPLAY.collect { |display| [t(display), display == :both ? nil : display.to_s] }, {}, {class: 'select2 fullwidth'})
.row
.alpha.three.columns
= label_tag nil, t(:active)
= label_tag nil, t('.display')
.omega.eight.columns
= select(:payment_method, :display_on, Spree::PaymentMethod::DISPLAY.collect { |display| [t('.' + display.to_s), display == :both ? nil : display.to_s] }, {}, {class: 'select2 fullwidth'})
.row
.alpha.three.columns
= label_tag nil, t('.active')
.two.columns
= radio_button :payment_method, :active, true
&nbsp;
= label_tag nil, t(:say_yes)
= label_tag nil, t('.active_yes')
.omega.six.columns
= radio_button :payment_method, :active, false
&nbsp;
= label_tag nil, t(:say_no)
= label_tag nil, t('.active_no')
.row
.alpha.three.columns
= label(:payment_method, :tags, t(:tags))
= label(:payment_method, :tags, t('.tags'))
.omega.eight.columns
= hidden_field(:payment_method, :tag_list, "ng-value" => "paymentMethod.tag_list")
%tags-with-translation#something{ object: "paymentMethod" }

View File

@@ -1,7 +1,7 @@
#provider-settings{ ng: { controller: "ProvidersCtrl" } }
.row
.alpha.three.columns
= label :payment_method, :type, t(:provider)
= label :payment_method, :type, t('.provider')
.omega.eight.columns
= collection_select(:payment_method, :type, @providers, :to_s, :clean_name, (!@object.persisted? ? { :selected => "Spree::PaymentMethod::Check"} : {}), { class: 'select2 fullwidth', 'provider-prefs-for' => "#{@object.id}"})

View File

@@ -4,7 +4,7 @@
= @payment_method.name
- content_for :page_actions do
%li
= button_link_to t(:new), spree.new_admin_payment_method_path, icon: 'icon-plus'
= button_link_to t('.new'), spree.new_admin_payment_method_path, icon: 'icon-plus'
%li
= button_link_to t('.back_to_payment_methods_list'), spree.admin_payment_methods_path, icon: 'icon-arrow-left'
= render partial: 'spree/shared/error_messages', locals: { target: @payment_method }

View File

@@ -1,9 +1,9 @@
- content_for :page_title do
= Spree.t(:payment_methods)
= t('.payment_methods')
- content_for :page_actions do
%li
= button_link_to Spree.t(:new_payment_method), new_object_url, icon: 'icon-plus', id: 'admin_new_payment_methods_link'
= button_link_to t('.new_payment_method'), new_object_url, icon: 'icon-plus', id: 'admin_new_payment_methods_link'
- if @payment_methods.any?
%table#listing_payment_methods.index
@@ -17,12 +17,12 @@
%col{style: "width: 11%"}
%thead
%tr
%th= Spree.t(:name)
%th= t(:products_distributor)
%th= Spree.t(:provider)
%th= Spree.t(:environment)
%th= Spree.t(:display)
%th= Spree.t(:active)
%th= t('.name')
%th= t('.products_distributor')
%th= t('.provider')
%th= t('.environment')
%th= t('.display')
%th= t('.active')
%th.actions
%tbody
- @payment_methods.each do |method|
@@ -34,10 +34,10 @@
%br/
%td= method.type
%td.align-center= method.environment.to_s.titleize
%td.align-center= method.display_on.blank? ? Spree.t(:both) : Spree.t(method.display_on)
%td.align-center= method.active ? Spree.t(:say_yes) : Spree.t(:say_no)
%td.align-center= method.display_on.blank? ? t('.both') : t('.' + method.display_on.to_s)
%td.align-center= method.active ? t('.active_yes') : t('.active_no')
%td.actions
= link_to_edit method, no_text: true
= link_to_delete method, no_text: true
- else
.alpha.twelve.columns.no-objects-found= Spree.t(:no_payment_methods_found)
.alpha.twelve.columns.no-objects-found= t('.no_payment_methods_found')

View File

@@ -1,3 +1,4 @@
= render partial: 'spree/admin/shared/order_page_title'
= render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Payments' }
- content_for :page_actions do

View File

@@ -1,3 +1,4 @@
= render partial: 'spree/admin/shared/order_page_title'
= render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Payments' }
- content_for :page_title do

View File

@@ -1,3 +1,4 @@
= render partial: 'spree/admin/shared/order_page_title'
= render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Payments' }
- content_for :page_title do

View File

@@ -43,37 +43,6 @@
.clear
- unless @product.has_variants?
= f.field_container :sku do
= f.label :sku, t(:sku)
= f.text_field :sku, :size => 16
.alpha.two.columns
= f.field_container :on_hand do
= f.label :on_hand, t(:on_hand)
= f.number_field :on_hand, :min => 0
.omega.two.columns
= f.field_container :on_demand, :class => ['checkbox'] do
%label
= f.check_box :on_demand
= t(:on_demand)
.clear
%ul#shipping_specs
%li#shipping_specs_weight_field.field.alpha.two.columns
= f.label :weight, t(:weight)
= f.text_field :weight, :size => 4
%li#shipping_specs_height_field.field.omega.two.columns
= f.label :height, t(:height)
= f.text_field :height, :size => 4
%li#shipping_specs_width_field.field.alpha.two.columns
= f.label :width, t(:width)
= f.text_field :width, :size => 4
%li#shipping_specs_depth_field.field.omega.two.columns
= f.label :depth, t(:depth)
= f.text_field :depth, :size => 4
= f.field_container :shipping_categories do
= f.label :shipping_category_id, t(:shipping_categories)
= f.collection_select(:shipping_category_id, @shipping_categories, :id, :name, { :include_blank => 'None' }, { :class => 'select2' })

View File

@@ -6,6 +6,7 @@
- if @return_authorization.can_cancel?
= button_link_to t('actions.cancel'), fire_admin_order_return_authorization_url(@order, @return_authorization, e: 'cancel'), method: :put, data: { confirm: t('.are_you_sure') }, icon: 'icon-remove'
= render partial: 'spree/admin/shared/order_page_title'
= render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Return Authorizations' }
- content_for :page_title do

View File

@@ -1,3 +1,4 @@
= render partial: 'spree/admin/shared/order_page_title'
= render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Return Authorizations' }
- content_for :page_actions do

View File

@@ -1,3 +1,4 @@
= render partial: 'spree/admin/shared/order_page_title'
= render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Return Authorizations' }
- content_for :page_title do

View File

@@ -6,7 +6,7 @@
%ul.sidebar
= 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_method_path
= 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

View File

@@ -0,0 +1,4 @@
- content_for :page_title do
= t(:order)
\#
= @order.number

View File

@@ -1,8 +1,3 @@
- content_for :page_title do
= t(:order)
\#
= @order.number
- if @order.bill_address.present?
= @order.bill_address.firstname
= @order.bill_address.lastname

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_method, :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, :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 :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

@@ -15,13 +15,12 @@
.omega.eight.columns
= f.text_area :description, class: 'fullwidth', rows: 2, placeholder: t(:spree_admin_eg_collect_your_order)
= error_message_on :shipping_method, :description
- if spree_current_user.admin?
.row
.alpha.three.columns
= f.label :display_on, t(:display)
.omega.eight.columns
= select(:shipping_method, :display_on, [[t(".both"), nil], [t(".back_end"), "back_end"]], {}, {class: 'select2 fullwidth'})
= error_message_on :shipping_method, :display_on
.row
.alpha.three.columns
= f.label :display_on, t(:display)
.omega.eight.columns
= select(:shipping_method, :display_on, [[t(".both"), nil], [t(".back_end"), "back_end"]], {}, {class: 'select2 fullwidth'})
= error_message_on :shipping_method, :display_on
.row
.alpha.three.columns

View File

@@ -57,7 +57,7 @@
<button class="add_variant no-text icon-plus icon_link with-tip" data-stock-location-id="{{variant.stock_location_id}}" title="Add" data-action="add"></button>
</td>
{{else}}
<td><%= Spree.t(:out_of_stock) %></td>
<td><%= t('.out_of_stock') %></td>
<td>0</td>
{{/if}}
</tr>

View File

@@ -3,40 +3,32 @@
= render partial: 'spree/admin/shared/product_tabs', locals: {current: 'Variants'}
#new_variant
- if @variants.any?
%table.index.sortable{"data-sortable-link" => update_positions_admin_product_variants_path(@product)}
%colgroup
%col{style: "width: 5%"}/
%col{style: "width: 25%"}/
%col{style: "width: 20%"}/
%col{style: "width: 20%"}/
%col{style: "width: 15%"}/
%col{style: "width: 15%"}/
%thead
%tr
%th{colspan: "2"}= t('.options')
%th= t('.price')
%th= t('.sku')
%th.actions
%tbody
- @variants.each do |variant|
%tr{id: spree_dom_id(variant), class: cycle('odd', 'even'), style: "#{"color:red;" if variant.deleted? }" }
%td.no-border
%span.handle
%td= variant.full_name
%td.align-center= variant.display_price.to_html
%td.align-center= variant.sku
%td.actions
= link_to_edit(variant, no_text: true) unless variant.deleted?
= link_to_delete(variant, no_text: true) unless variant.deleted?
- unless @product.has_variants?
%tr
%td{colspan: "5"}= t(:none)
- else
.alpha.twelve.columns.no-objects-found
= t('.no_results')
\.
%table.index.sortable{"data-sortable-link" => update_positions_admin_product_variants_path(@product)}
%colgroup
%col{style: "width: 5%"}/
%col{style: "width: 25%"}/
%col{style: "width: 20%"}/
%col{style: "width: 20%"}/
%col{style: "width: 15%"}/
%col{style: "width: 15%"}/
%thead
%tr
%th{colspan: "2"}= t('.options')
%th= t('.price')
%th= t('.sku')
%th.actions
%tbody
- @variants.each do |variant|
%tr{id: spree_dom_id(variant), class: cycle('odd', 'even'), style: "#{"color:red;" if variant.deleted? }" }
%td.no-border
%span.handle
%td= variant.full_name
%td.align-center= variant.display_price.to_html
%td.align-center= variant.sku
%td.actions
= link_to_edit(variant, no_text: true) unless variant.deleted?
= link_to_delete(variant, no_text: true) unless variant.deleted?
- if @product.empty_option_values?
%p.first_add_option_types.no-objects-found

View File

@@ -1,11 +1,29 @@
%h3
= t(".customer_greeting", name: @order.bill_address.firstname)
%h4
= t(".instructions")
%span.clear
%table.social.white-bg.fullwidth
%table.column
%tr
%td
%h3
= t(".customer_greeting", name: @order.bill_address.firstname)
%h4
= t(".instructions_html", distributor: @order.distributor.name )
%img{src: "#{@order.distributor.logo.url(:medium)}"}
%p.callout
= t(".dont_cancel", email: @order.distributor.contact.email)
%p &nbsp;
%h4
= t(".order_summary_canceled_html", number: @order.number)
%p
= t(".details")
= t(".order_summary_canceled")
= render 'order_summary'
%p
- if @order.paid?
= t(".paid_order", distributor: @order.distributor.name)
- else
= t(".unpaid_order")
= render 'signoff'
= render 'shared/mailers/social_and_contact'

View File

@@ -1,10 +1,9 @@
- if target && target.errors.any?
#errorExplanation.errorExplanation
%h2
= Spree.t(:errors_prohibited_this_record_from_being_saved, count: target.errors.count)
\:
= t(".errors_prohibited_this_record_from_being_saved", count: target.errors.count)
%p
= Spree.t(:there_were_problems_with_the_following_fields)
= t(".there_were_problems_with_the_following_fields")
\:
%ul
- target.errors.full_messages.each do |msg|

View File

@@ -7,8 +7,8 @@
%th.order3.show-for-large-up= t('.changes_allowed_until')
%th.order4.show-for-large-up= t('.items')
%th.order5.text-right= t('.total')
%th.order6.text-right.show-for-large-up= t('.edit')
%th.order7.text-right= t('.cancel')
%th.order6.text-right= t('.edit')
%th.order7.show-for-large-up.text-right= t('.cancel')
%tbody.transaction-group{"ng-repeat" => "order in Orders.changeable", "ng-class-odd"=>"'odd'", "ng-class-even"=>"'even'"}
%tr.order-row
%td.order1
@@ -18,7 +18,7 @@
%td.order3.show-for-large-up{"ng-bind" => "::order.changes_allowed_until"}
%td.order4.show-for-large-up{"ng-bind" => "::order.item_count"}
%td.order5.text-right{"ng-class" => "{'credit' : order.total < 0, 'debit' : order.total > 0, 'paid' : order.total == 0}","ng-bind" => "::order.total | localizeCurrency"}
%td.order6.text-right.show-for-large-up.brick
%td.order6.text-right.brick
%a{"ng-href" => "{{::order.path}}" }= t('.edit')
%td.order7.text-right
%td.order7.show-for-large-up.text-right
= link_to t('.cancel'), "", method: :put, "ng-href" => "{{::order.cancel_path}}", "confirm-link-click" => t('orders_confirm_cancel')

View File

@@ -5,6 +5,7 @@ defaults: &defaults
host: <%= ENV.fetch('OFN_DB_HOST', 'localhost') %>
username: <%= ENV.fetch('OFN_DB_USERNAME', 'ofn') %>
password: <%= ENV.fetch('OFN_DB_PASSWORD', 'f00d') %>
port: <%= ENV.fetch('OFN_DB_PORT', 5432) %>
development:
<<: *defaults

View File

@@ -363,7 +363,6 @@ ar:
title: "إعدادات Matomo"
matomo_url: "العنوان الالكتروني ل Matomo "
matomo_site_id: "معرف موقع Matomo"
info_html: "Matomo هو تحليلات الويب والجوال. يمكنك إما تنصيب Matomo محليًا أو استخدام خدمة استضافة سحابية. انظر <a href='http://matomo.org' target='_blank'>matomo.org</a> لمزيد من المعلومات."
config_instructions_html: "هنا يمكنك تهيئة تكامل Matomo لشبكة الغذاء المفتوح. يجب أن يشير عنوان الالكتروني URL الخاص بـ Matomo أدناه إلى مثيل Matomo حيث سيتم إرسال معلومات تتبع المستخدم إلى ؛ إذا تم تركه فارغًا ، فسيتم تعطيل تتبع مستخدم Matomo. حقل معرف الموقع ليس إلزاميًا ولكنه مفيد إذا كنت تتعقب أكثر من موقع ويب على مثيل Matomo ؛ يمكن العثور عليه على وحدة تحكم مثيل Matomo."
customers:
index:
@@ -398,6 +397,7 @@ ar:
footer_and_external_links: تذييل والروابط الخارجية
your_content: المحتوى الخاص بك
user_guide: دليل المستخدم
map: خريطة
enterprise_fees:
index:
title: "رسوم الشركة"
@@ -2752,6 +2752,8 @@ ar:
new_payment: "دفعة جديد"
capture: "إلتقاط"
void: "فارغ"
login: "تسجيل الدخول"
password: "كلمه السر"
configurations: "تهيئة"
general_settings: "الاعدادات العامة"
site_name: "اسم الموقع"
@@ -2816,8 +2818,6 @@ ar:
abbreviation: "الاختصار"
new_state: "محافظة جديدة"
payment_methods: "طرق الدفع"
new_payment_method: "طريقة الدفع الجديدة"
provider: "مزود"
taxonomies: "التصنيفات"
new_taxonomy: "تصنيف جديد"
back_to_taxonomies_list: "العودة إلى قائمة التصنيفات"
@@ -3024,10 +3024,23 @@ ar:
categories: "التصنيفات"
zones: "مناطق"
payment_methods:
index:
payment_methods: "طريقة الدفع"
new_payment_method: "طريقة الدفع الجديدة"
name: "الاسم"
products_distributor: "الموزع"
provider: "مزود"
environment: "بيئة"
display: "عرض"
active: "نشط"
both: "على حد سواء"
active_yes: "نعم"
active_no: "لا"
new:
new_payment_method: "طريقة الدفع الجديدة"
back_to_payment_methods_list: "العودة إلى قائمة طرق الدفع"
edit:
new: "جديد"
editing_payment_method: "تحرير طريقة الدفع"
back_to_payment_methods_list: "العودة إلى قائمة طرق الدفع"
stripe_connect:
@@ -3043,6 +3056,17 @@ ar:
account_id: معرف الحساب
business_name: الاسم التجاري
charges_enabled: تم تمكين الدفع
form:
name: "الاسم"
description: "وصف"
environment: "بيئة"
display: "عرض"
active: "نشط"
active_yes: "نعم"
active_no: "لا"
tags: "الاوسمة"
providers:
provider: "مزود"
payments:
source_forms:
stripe:
@@ -3143,6 +3167,7 @@ ar:
display_as: "عرض ب"
display_name: "اسم العرض"
autocomplete:
out_of_stock: "غير متوفر"
producer_name: "المنتج"
unit: "وحدة"
shared:
@@ -3207,9 +3232,6 @@ ar:
invalid: غير صالحة
order_mailer:
cancel_email:
customer_greeting: "مرحبًا %{name}!"
instructions: "تم إلغاء طلبك. يرجى الاحتفاظ بمعلومات الإلغاء هذه بسجلاتك."
order_summary_canceled: "ملخص الطلب [ملغى]"
subject: "إلغاء الطلب"
confirm_email:
subject: "تأكيد الطلب"

View File

@@ -368,8 +368,10 @@ ca:
title: "Configuració de Matomo"
matomo_url: "URL de Matomo"
matomo_site_id: "Identificador de Matomo"
info_html: "Matomo és un analitzador de webs i mòbils. Podeu allotjar Matomo de manera local o utilitzar un servei al núvol. Vegeu <a href='http://matomo.org' target='_blank'> matomo.org </a> per obtenir més informació."
matomo_tag_manager_url: "URL de Matomo Tag Manager"
info_html: "Matomo és una aplicació d'analytics web i mòbil. Podeu allotjar Matomo en local o bé utilitzar un servei allotjat al núvol. Consulteu <a href='http://matomo.org' target='_blank'>matomo.org</a> per obtenir més informació."
config_instructions_html: "Aquí podeu configurar la integració Matomo OFN. L'URL de Matomo que us apareix a continuació ha d'indicar la instància de Matomo en la qual s'enviarà la informació de seguiment de l'usuari; si es deixa buit, el seguiment de l'usuari de Matomo estarà desactivat. El camp d'identificació del lloc no és obligatori, però és útil si fa un seguiment de més d'un lloc web en una sola instància de Matomo; es pot trobar a la consola d'instància de Matomo."
config_instructions_tag_manager_html: "En configurar l'URL de Matomo Tag Manager s'activa Matomo Tag Manager. Aquesta eina us permet configurar esdeveniments danalítica. LURL de Matomo Tag Manager es copia de la secció Instal·lar codi de Matomo Tag Manager. Assegureu-vos de seleccionar el contenidor i lentorn adequats ja que aquestes opcions canvien lURL."
customers:
index:
new_customer: "Nova consumidora"
@@ -403,6 +405,7 @@ ca:
footer_and_external_links: Peu de pàgina i enllaços externs
your_content: El vostre contingut
user_guide: Guia de l'usuari
map: Mapa
enterprise_fees:
index:
title: "Comissions de l'organització"
@@ -687,6 +690,7 @@ ca:
ofn_uid_tip: L'identificador únic que sutilitza per identificar l'organització a Open Food Network.
shipping_methods:
name: "Nom"
applies: "Actiu?"
manage: "Gestiona els mètodes d'enviament"
create_button: "Crea un nou mètode d'enviament"
create_one_button: "Crea'n un ara"
@@ -2811,6 +2815,14 @@ ca:
new_payment: "Nou pagament"
capture: "Captura"
void: "Buit"
login: "Inicia sessió"
password: "Contrasenya"
signature: "Signatura"
solution: "Solució"
landing_page: "Pàgina d'inici"
server: "Servidor"
test_mode: "Mode de prova"
logourl: "URL del logo"
configurations: "Configuracions"
general_settings: "Configuració general"
site_name: "Nom del lloc"
@@ -2875,8 +2887,6 @@ ca:
abbreviation: "Abreviatura"
new_state: "Nou estat"
payment_methods: "Mètodes de Pagament"
new_payment_method: "Nou mètode de pagament"
provider: "Proveïdor"
taxonomies: "Taxonomies"
new_taxonomy: "Nova taxonomia"
back_to_taxonomies_list: "Torna a la llista de taxonomies"
@@ -2929,6 +2939,12 @@ ca:
options: "Opcions"
actions:
update: "Actualitzar"
shared:
error_messages:
errors_prohibited_this_record_from_being_saved:
one: "Un error va prohibir guardar aquest registre:"
other: "%{count} errors han impedit guardar aquest registre:"
there_were_problems_with_the_following_fields: "Hi ha hagut problemes amb els camps següents"
errors:
messages:
blank: "no es pot deixar en blanc"
@@ -3071,6 +3087,8 @@ ca:
zone: "Zona"
calculator: "Calculadora"
display: "Mostra"
both: "Ambdues, validació de comanda i administració"
back_end: "Només pàgina administració (back office) "
no_shipping_methods_found: "No shan trobat mètodes denviament"
new:
new_shipping_method: "Nou mètode d'enviament"
@@ -3083,11 +3101,29 @@ ca:
categories: "Categories"
zones: "Zones"
both: "Comandes com administració"
back_end: "Només pàgina administració (back office) "
deactivation_warning: "Desactivar un mètode d'enviament pot fer que desaparegui de la teva llista. Pots ocultar-lo de la pàgina de validació de comanda configurant l'opció \"Mostrar\" a \"només a la pàgina d'administració\" (back end)."
payment_methods:
index:
payment_methods: "Mètodes de Pagament"
new_payment_method: "Nou mètode de pagament"
name: "Nom"
products_distributor: "Distribuïdora"
provider: "Proveïdor"
environment: "Ambient"
display: "Mostra"
active: "Actiu"
both: "Ambdós"
front_end: "Visible només per al comprador"
back_end: "Només pàgina administració (back office) "
active_yes: "Sí"
active_no: "No"
no_payment_methods_found: "No s'han trobat mètodes de pagament"
new:
new_payment_method: "Nou mètode de pagament"
back_to_payment_methods_list: "Tornar a la llista de mètodes de pagament"
edit:
new: "Nou"
editing_payment_method: "Edició del mètode de pagament"
back_to_payment_methods_list: "Tornar a la llista de mètodes de pagament"
stripe_connect:
@@ -3103,6 +3139,21 @@ ca:
account_id: Identificador del compte
business_name: Nom de l'empresa
charges_enabled: Càrrecs habilitats
form:
name: "Nom"
description: "Descripció"
environment: "Ambient"
display: "Mostra"
active: "Actiu"
active_yes: "Sí"
active_no: "No"
both: "Ambdues, validació de comanda i administració"
front_end: "Visible només per al comprador"
back_end: "Només pàgina administració (back office) "
tags: "Etiquetes"
deactivation_warning: "Desactivar un mètode de pagament pot fer que el mètode de pagament desapareixi de la vostra llista. De forma alternativa, podeu amagar un mètode de pagament a la pàgina de compra configurant l'opció \"Mostrar\" a \"només a la pàgina d'administració\" (back end)."
providers:
provider: "Proveïdor"
payments:
source_forms:
stripe:
@@ -3205,6 +3256,7 @@ ca:
display_as_placeholder: 'per exemple. 2 kg'
display_name_placeholder: 'per exemple. Tomàquets'
autocomplete:
out_of_stock: "Fora d'existència"
producer_name: "Productor"
unit: "Unitat"
shared:
@@ -3242,6 +3294,7 @@ ca:
format: '%d-% m-% Y'
js_format: 'dd-mm-yy'
orders:
error_flash_for_unavailable_items: "Un ítem del teu carret ja no està disponible. Sis plau actualitza les quantitats seleccionades."
edit:
login_to_view_order: "Si us plau inicia sessió per veure la teva comanda."
bought:
@@ -3269,9 +3322,14 @@ ca:
invalid: invàlid
order_mailer:
cancel_email:
customer_greeting: "Hola %{name}!"
instructions: "La teva comanda ha estat anul·lada. Conserva aquesta informació de cancel·lació per als teus registres."
order_summary_canceled: "Resum de comanda [CANCEL·LADA]"
customer_greeting: "Benvolgut/da,%{name}"
instructions_html: "La teva comanda<strong> %{distributor}</strong> ha estat CANCEL·LADA"
dont_cancel: "Si heu canviat d'opinió o no voleu cancel·lar aquesta comanda, poseu-vos en contacte amb %{email}"
order_summary_canceled_html: "<strong>Resum de comanda # %{number} [CANCELAT]</strong>"
details: "Aquí teniu els detalls del que vau demanar:"
unpaid_order: "La vostra comanda no s'havia pagat, per la qual cosa no s'ha realitzat cap reemborsament"
paid_order: "La vostra comanda s'havia pagat per la qual cosa %{distributor} ha reemborsat l'import complet"
credit_order: "La vostra comanda s'havia pagat i per tant, s'ha abonat l'import al vostre compte"
subject: "Cancel·lació de la comanda"
confirm_email:
subject: "Confirmació de la comanda"

View File

@@ -367,7 +367,6 @@ de_DE:
title: "Matomo-Einstellungen"
matomo_url: "Matomo-URL"
matomo_site_id: "Matomo-Site-ID"
info_html: "Matomo ist eine Web- und Mobile Analytics. Sie können Matomo entweder lokal hosten oder einen von der Cloud gehosteten Dienst verwenden. Weitere Informationen finden Sie unter <a href='http://matomo.org' target='_blank'> matomo.org </a>."
config_instructions_html: "Hier können Sie die OFN Matomo Integration konfigurieren. Die unten angegebene Matomo-URL sollte auf die Matomo-Instanz verweisen, an die die Benutzerverfolgungsinformationen gesendet werden. Wenn es leer bleibt, wird das Matomo-Benutzer-Tracking deaktiviert. Das Feld Site-ID ist nicht obligatorisch, aber nützlich, wenn Sie mehr als eine Website in einer einzelnen Matomo-Instanz verfolgen. Es kann auf der Matomo-Instanzkonsole gefunden werden."
customers:
index:
@@ -402,6 +401,7 @@ de_DE:
footer_and_external_links: Fußzeile und externe Links
your_content: Ihr Inhalt
user_guide: Benutzerhandbuch
map: Karte
enterprise_fees:
index:
title: "Unternehmensgebühren"
@@ -2785,6 +2785,8 @@ de_DE:
new_payment: "Neue Zahlung"
capture: "Erfassung"
void: "Leere"
login: "Anmeldung"
password: "Passwort"
configurations: "Konfigurationen"
general_settings: "Allgemeine Einstellungen"
site_name: "Site-Name"
@@ -2849,8 +2851,6 @@ de_DE:
abbreviation: "Abkürzung"
new_state: "Neuer Staat"
payment_methods: "Zahlungsarten"
new_payment_method: "Neue Zahlungsart"
provider: "Anbieter"
taxonomies: "Taxonomien"
new_taxonomy: "Neue Taxonomie"
back_to_taxonomies_list: "Zurück zur Taxonomieliste"
@@ -3057,6 +3057,13 @@ de_DE:
categories: "Kategorien"
zones: "Zonen"
payment_methods:
index:
payment_methods: "Zahlungsarten"
name: "Name"
products_distributor: "Verteiler"
both: "Beide"
active_yes: "Ja"
active_no: "Nein"
new:
new_payment_method: "Neue Zahlungsart"
back_to_payment_methods_list: "Zurück zur Liste der Zahlungsmethoden"
@@ -3076,6 +3083,12 @@ de_DE:
account_id: Konto-ID
business_name: Geschäftsname
charges_enabled: Gebühren aktiviert
form:
name: "Name"
description: "Beschreibung"
active_yes: "Ja"
active_no: "Nein"
tags: "Stichwörter"
payments:
source_forms:
stripe:
@@ -3236,9 +3249,6 @@ de_DE:
invalid: ungültig
order_mailer:
cancel_email:
customer_greeting: "Hallo %{name}!"
instructions: "Ihre Bestellung wurde storniert. Bitte bewahren Sie diese Stornierungsinformationen für Ihre Unterlagen auf."
order_summary_canceled: "Bestellübersicht [STORNIERT]"
subject: "Stornierung der Bestellung"
confirm_email:
subject: "Bestellbestätigung"

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