mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-21 20:06:54 +00:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd5db396b4 | ||
|
|
315d52961a | ||
|
|
c0bcf177e7 | ||
|
|
8dfede11c6 | ||
|
|
bac123f223 | ||
|
|
fdc775ae6d | ||
|
|
26b39d6626 | ||
|
|
8953e8481d | ||
|
|
1ce76a3166 | ||
|
|
1c703905fe | ||
|
|
feed223ab4 | ||
|
|
90f962a886 | ||
|
|
82f6484031 | ||
|
|
8cd9e94148 | ||
|
|
a934b60f67 | ||
|
|
368da19993 | ||
|
|
419f4490d6 | ||
|
|
39245d55e2 | ||
|
|
fe8200b7e8 | ||
|
|
3676acf244 | ||
|
|
caf6b087c1 | ||
|
|
24d6c1e386 | ||
|
|
a120e390d0 | ||
|
|
98a2bf5d47 | ||
|
|
bb0c1e7a0f | ||
|
|
55a15b914c | ||
|
|
8ce14a55c8 | ||
|
|
d1f47f6956 | ||
|
|
2d50dace20 | ||
|
|
bbbbe71bc4 | ||
|
|
b3dc76b8cf | ||
|
|
ad4b26e86d | ||
|
|
c2a7a89381 | ||
|
|
68e3623861 | ||
|
|
577aa55f98 | ||
|
|
b8e62b3d84 | ||
|
|
dbb8e07b9a | ||
|
|
19550ed4fe | ||
|
|
4d0c710e3b | ||
|
|
fccde70690 |
@@ -1,2 +0,0 @@
|
||||
defaults
|
||||
IE 11
|
||||
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -8,4 +8,3 @@
|
||||
# Same thing for following files, but they don't have an sh extension
|
||||
pre-commit eol=lf
|
||||
webpack-dev-server eol=lf
|
||||
install-bundler eol=lf
|
||||
@@ -1 +1 @@
|
||||
3.3.10
|
||||
3.4.8
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM ruby:3.3.10-alpine3.19 AS base
|
||||
FROM ruby:3.4.8-alpine3.19 AS base
|
||||
ENV LANG=C.UTF-8 \
|
||||
LC_ALL=C.UTF-8 \
|
||||
TZ=Europe/London \
|
||||
|
||||
@@ -83,11 +83,8 @@ RUN wget https://chromedriver.storage.googleapis.com/2.41/chromedriver_linux64.z
|
||||
# Copy code and install app dependencies
|
||||
COPY . /usr/src/app/
|
||||
|
||||
# Install Bundler
|
||||
RUN ./script/install-bundler
|
||||
|
||||
# Install front-end dependencies
|
||||
RUN yarn install
|
||||
|
||||
# Run bundler install in parallel with the amount of available CPUs
|
||||
RUN bundle install --jobs="$(nproc)"
|
||||
RUN bundle install --jobs="$(nproc)"
|
||||
|
||||
4
Gemfile
4
Gemfile
@@ -18,7 +18,7 @@ gem 'activemerchant'
|
||||
gem 'angular-rails-templates'
|
||||
gem 'ransack', '~> 4.1.0'
|
||||
gem 'responders'
|
||||
gem 'webpacker', '~> 5'
|
||||
gem 'shakapacker', '6.6.0'
|
||||
|
||||
# Indirect dependency but we access it directly in JS specs.
|
||||
# It turns out to be hard to upgrade but please do if you can.
|
||||
@@ -126,6 +126,8 @@ gem 'angular_rails_csrf'
|
||||
|
||||
gem 'jquery-rails', '4.4.0'
|
||||
gem 'jquery-ui-rails', '~> 4.2'
|
||||
# TODO move away from sass-rails, master branch will get rid of dependency, so we can move to
|
||||
# https://github.com/sass/embedded-host-node
|
||||
gem "select2-rails", github: "openfoodfoundation/select2-rails", branch: "v349_with_thor_v1"
|
||||
|
||||
gem 'good_migrations'
|
||||
|
||||
20
Gemfile.lock
20
Gemfile.lock
@@ -615,7 +615,7 @@ GEM
|
||||
rack-protection (3.2.0)
|
||||
base64 (>= 0.1.0)
|
||||
rack (~> 2.2, >= 2.2.4)
|
||||
rack-proxy (0.7.6)
|
||||
rack-proxy (0.7.7)
|
||||
rack
|
||||
rack-rewrite (1.5.1)
|
||||
rack-session (1.0.2)
|
||||
@@ -814,7 +814,12 @@ GEM
|
||||
tilt (>= 1.1, < 3)
|
||||
sd_notify (0.1.1)
|
||||
securerandom (0.4.1)
|
||||
semantic_range (3.0.0)
|
||||
semantic_range (3.1.0)
|
||||
shakapacker (6.6.0)
|
||||
activesupport (>= 5.2)
|
||||
rack-proxy (>= 0.6.1)
|
||||
railties (>= 5.2)
|
||||
semantic_range (>= 2.3.0)
|
||||
shoulda-matchers (7.0.1)
|
||||
activesupport (>= 7.1)
|
||||
sidekiq (7.2.4)
|
||||
@@ -942,11 +947,6 @@ GEM
|
||||
addressable (>= 2.8.0)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff (>= 0.4.0, < 2.0.0)
|
||||
webpacker (5.4.4)
|
||||
activesupport (>= 5.2)
|
||||
rack-proxy (>= 0.6.1)
|
||||
railties (>= 5.2)
|
||||
semantic_range (>= 2.3.0)
|
||||
webrick (1.9.2)
|
||||
websocket-driver (0.7.7)
|
||||
base64
|
||||
@@ -1083,6 +1083,7 @@ DEPENDENCIES
|
||||
rubocop-rspec_rails
|
||||
sd_notify
|
||||
select2-rails!
|
||||
shakapacker (= 6.6.0)
|
||||
shoulda-matchers
|
||||
sidekiq
|
||||
sidekiq-scheduler
|
||||
@@ -1108,13 +1109,12 @@ DEPENDENCIES
|
||||
web!
|
||||
web-console
|
||||
webmock
|
||||
webpacker (~> 5)
|
||||
whenever
|
||||
wicked_pdf
|
||||
wkhtmltopdf-binary
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.3.10p183
|
||||
ruby 3.4.8p72
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.22
|
||||
4.0.3
|
||||
|
||||
2
Procfile
2
Procfile
@@ -1,5 +1,5 @@
|
||||
# Foreman Procfile. Start all dev server processes with: `foreman start`
|
||||
|
||||
rails: DEV_CACHING=true bundle exec rails s -p 3000
|
||||
webpack: ./bin/webpack-dev-server
|
||||
webpack: ./bin/webpacker-dev-server
|
||||
sidekiq: DEV_CACHING=true bundle exec sidekiq -q mailers -q default
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Foreman Procfile for Docker env. Start all dev server processes with: `bundle exec foreman start -f Procfile.docker`
|
||||
|
||||
webpack: WEBPACKER_DEV_SERVER_HOST=0.0.0.0 ./bin/webpack-dev-server
|
||||
webpack: WEBPACKER_DEV_SERVER_HOST=0.0.0.0 ./bin/webpacker-dev-server
|
||||
sidekiq: DEV_CACHING=true bundle exec sidekiq -q mailers -q default
|
||||
rails: WEBPACKER_DEV_SERVER_HOST=0.0.0.0 DEV_CACHING=true bundle exec rails s -p 3000 -b 0.0.0.0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
= render ConfirmModalComponent.new(id: dom_id(@order, :ship), confirm_reflexes: "click->Admin::OrdersReflex#ship", controller: "orders", reflex: "Admin::Orders#ship") do
|
||||
= render ConfirmModalComponent.new(id: dom_id(@order, :ship), confirm_actions: "click->modal#close", confirm_reflexes: "click->Admin::OrdersReflex#ship", controller: "orders", reflex: "Admin::Orders#ship") do
|
||||
%div{class: "margin-bottom-30"}
|
||||
%p= t('spree.admin.orders.shipment.mark_as_shipped_message_html')
|
||||
%div{class: "margin-bottom-30"}
|
||||
|
||||
@@ -90,11 +90,13 @@ class VoucherAdjustmentsController < BaseController
|
||||
voucher_code: voucher_params[:voucher_code], enterprise: @order.distributor
|
||||
)
|
||||
voucher = vine_voucher_validator.validate
|
||||
errors = vine_voucher_validator.errors
|
||||
|
||||
return nil if vine_voucher_validator.errors[:not_found_voucher].present?
|
||||
return nil if errors[:not_found_voucher].present?
|
||||
|
||||
if vine_voucher_validator.errors.present?
|
||||
@order.errors.add(:voucher_code, I18n.t('checkout.errors.add_voucher_error'))
|
||||
if errors.present?
|
||||
message = errors[:invalid_voucher] || I18n.t('checkout.errors.add_voucher_error')
|
||||
@order.errors.add(:voucher_code, message)
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
@@ -72,7 +72,8 @@ module ApplicationHelper
|
||||
end
|
||||
end
|
||||
|
||||
# Update "v1" to invalidate existing cache key
|
||||
def cache_key_with_locale(key, locale)
|
||||
Array.wrap(key) + [locale.to_s, I18nDigests.for_locale(locale)]
|
||||
Array.wrap(key) + ["v1", locale.to_s, I18nDigests.for_locale(locale)]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -31,7 +31,6 @@ module Spree
|
||||
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 :currency_decimal_mark, :string, default: "."
|
||||
preference :currency_symbol_position, :string, default: "before"
|
||||
|
||||
@@ -437,18 +437,13 @@ module Spree
|
||||
#
|
||||
# Returns:
|
||||
# - true if all pending_payments processed successfully
|
||||
# - true if a payment failed, ie. raised a GatewayError
|
||||
# which gets rescued and converted to TRUE when
|
||||
# :allow_checkout_gateway_error is set to true
|
||||
# - false if a payment failed, ie. raised a GatewayError
|
||||
# which gets rescued and converted to FALSE when
|
||||
# :allow_checkout_on_gateway_error is set to false
|
||||
# which gets rescued and converted to FALSE
|
||||
#
|
||||
def process_payments!
|
||||
process_each_payment(&:process!)
|
||||
rescue Core::GatewayError => e
|
||||
result = !!Spree::Config[:allow_checkout_on_gateway_error]
|
||||
errors.add(:base, e.message) && (return result)
|
||||
errors.add(:base, e.message) && (return false)
|
||||
end
|
||||
|
||||
def process_payments_offline!
|
||||
|
||||
@@ -93,8 +93,8 @@ module Spree
|
||||
type.demodulize.downcase
|
||||
end
|
||||
|
||||
def self.find_with_destroyed(*args)
|
||||
unscoped { find(*args) }
|
||||
def self.find_with_destroyed(*)
|
||||
unscoped { find(*) }
|
||||
end
|
||||
|
||||
def payment_profiles_supported?
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
module Vine
|
||||
class VoucherValidatorService
|
||||
VINE_ERRORS = {
|
||||
# https://github.com/openfoodfoundation/vine/blob/main/app/Enums/ApiResponse.php
|
||||
"This voucher has expired." => :expired,
|
||||
}.freeze
|
||||
|
||||
attr_reader :voucher_code, :errors
|
||||
|
||||
def initialize(voucher_code:, enterprise:)
|
||||
@@ -42,8 +47,10 @@ module Vine
|
||||
end
|
||||
|
||||
def handle_errors(response)
|
||||
if response[:status] == 400
|
||||
errors[:invalid_voucher] = I18n.t("vine_voucher_validator_service.errors.invalid_voucher")
|
||||
if [400, 409].include?(response[:status])
|
||||
message = response[:body] && JSON.parse(response[:body]).dig("meta", "message")
|
||||
key = VINE_ERRORS.fetch(message, :invalid_voucher)
|
||||
errors[:invalid_voucher] = I18n.t("vine_voucher_validator_service.errors.#{key}")
|
||||
elsif response[:status] == 404
|
||||
errors[:not_found_voucher] =
|
||||
I18n.t("vine_voucher_validator_service.errors.not_found_voucher")
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
- else
|
||||
= favicon_link_tag "/favicon-staging.ico"
|
||||
%link{href: "https://fonts.googleapis.com/css?family=Roboto:400,300italic,400italic,300,700,700italic|Oswald:300,400,700", rel: "stylesheet", type: "text/css"}
|
||||
%link{href: asset_pack_path("media/fonts/OFN-v2.woff"), rel: "preload", as: "font", crossorigin: "anonymous"}
|
||||
%link{href: asset_pack_path("static/OFN-v2.woff"), rel: "preload", as: "font", crossorigin: "anonymous"}
|
||||
= render "layouts/matomo_tag"
|
||||
= language_meta_tags
|
||||
|
||||
= stylesheet_pack_tag "darkswarm", "data-turbo-track": "reload", media: "screen"
|
||||
= javascript_pack_tag "application", "data-turbo-track": "reload"
|
||||
= javascript_pack_tag "application", "data-turbo-track": "reload", defer: false # do not use defer because our javascript currently depend on order of execution of loaded script.
|
||||
|
||||
= render "layouts/shopfront_script" if @shopfront_layout
|
||||
= render "layouts/bugsnag_js"
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
= stylesheet_pack_tag "darkswarm", media: "screen"
|
||||
= javascript_include_tag "darkswarm/all"
|
||||
= javascript_pack_tag "application"
|
||||
= javascript_pack_tag "application", defer: false # do not use defer because our javascript currently depend on order of execution of loaded script.
|
||||
|
||||
= csrf_meta_tags
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
= render "spree/admin/shared/translations"
|
||||
= render "spree/admin/shared/routes"
|
||||
|
||||
= javascript_pack_tag "admin", "data-turbo-track": "reload"
|
||||
= javascript_pack_tag "admin", "data-turbo-track": "reload", defer: false # do not use defer because our javascript currently depend on order of execution of loaded script.
|
||||
|
||||
%script
|
||||
= raw "var AUTH_TOKEN = \"#{form_authenticity_token}\";"
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
// While in feature-toggle, we inherit all files from old admin design.
|
||||
// Individual files may be copied in order to replace the old files.
|
||||
|
||||
@import "vendor/assets/stylesheets/normalize";
|
||||
@import "vendor/assets/stylesheets/responsive-tables";
|
||||
@import "vendor/assets/stylesheets/jquery.powertip";
|
||||
@import "~jquery-ui/themes/base/core";
|
||||
@import "~jquery-ui/themes/base/button";
|
||||
@import "~jquery-ui/themes/base/resizable";
|
||||
@import "vendor/assets/stylesheets/jquery-ui-theme";
|
||||
@import "~jquery-ui/themes/base/dialog";
|
||||
@import "assets/stylesheets/normalize";
|
||||
@import "assets/stylesheets/responsive-tables";
|
||||
@import "assets/stylesheets/jquery.powertip";
|
||||
@import "jquery-ui/themes/base/core";
|
||||
@import "jquery-ui/themes/base/button";
|
||||
@import "jquery-ui/themes/base/resizable";
|
||||
@import "assets/stylesheets/jquery-ui-theme";
|
||||
@import "jquery-ui/themes/base/dialog";
|
||||
@import "../shared/ng-tags-input.min";
|
||||
@import "vendor/assets/stylesheets/select2.css.scss";
|
||||
@import "~flatpickr/dist/flatpickr";
|
||||
@import "~flatpickr/dist/themes/material_blue";
|
||||
@import "~shortcut-buttons-flatpickr/dist/themes/light";
|
||||
@import "assets/stylesheets/select2";
|
||||
@import "flatpickr/dist/flatpickr";
|
||||
@import "flatpickr/dist/themes/material_blue";
|
||||
@import "shortcut-buttons-flatpickr/dist/themes/light";
|
||||
|
||||
@import "../admin/globals/functions";
|
||||
@import "globals/palette"; // admin_v3
|
||||
@@ -123,13 +123,13 @@
|
||||
@import "shared/question-mark-icon";
|
||||
@import "../admin/question-mark-tooltip";
|
||||
|
||||
@import "~tom-select/src/scss/tom-select.default";
|
||||
@import "tom-select/src/scss/tom-select.default";
|
||||
@import "components/tom_select"; // admin_v3
|
||||
|
||||
@import "app/components/modal_component/modal_component";
|
||||
@import "app/components/vertical_ellipsis_menu_component/vertical_ellipsis_menu_component"; // admin_v3 and only V3
|
||||
@import "app/components/tag_list_input_component/tag_list_input_component";
|
||||
@import "app/webpacker/css/admin/trix.scss";
|
||||
@import "modal_component/modal_component";
|
||||
@import "vertical_ellipsis_menu_component/vertical_ellipsis_menu_component"; // admin_v3 and only V3
|
||||
@import "tag_list_input_component/tag_list_input_component";
|
||||
@import "admin/trix";
|
||||
|
||||
@import "terms_of_service_banner"; // admin_v3
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
|
||||
@import 'vendor/assets/stylesheets/autocomplete';
|
||||
@import 'vendor/assets/stylesheets/leaflet';
|
||||
@import 'assets/stylesheets/autocomplete';
|
||||
@import 'assets/stylesheets/leaflet';
|
||||
@import 'variables';
|
||||
@import '../shared/variables/layout';
|
||||
@import '../shared/utilities';
|
||||
@import '~foundation-sites/scss/foundation';
|
||||
@import 'foundation-sites/scss/foundation';
|
||||
|
||||
@import 'big-input';
|
||||
@import 'branding';
|
||||
@@ -77,4 +77,4 @@ ofn-modal {
|
||||
@import "../shared/question-mark-icon";
|
||||
@import '../admin/shared/scroll_bar';
|
||||
|
||||
@import 'app/components/modal_component/modal_component';
|
||||
@import 'modal_component/modal_component';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "~foundation-sites/scss/foundation/components/global";
|
||||
@import "foundation-sites/scss/foundation/components/global";
|
||||
|
||||
// Brand guide colours:
|
||||
// International: #81c26e
|
||||
|
||||
@@ -1,72 +1,6 @@
|
||||
module.exports = function(api) {
|
||||
var validEnv = ['development', 'test', 'production']
|
||||
var currentEnv = api.env()
|
||||
var isDevelopmentEnv = api.env('development')
|
||||
var isProductionEnv = api.env('production')
|
||||
var isTestEnv = api.env('test')
|
||||
module.exports = function (api) {
|
||||
const defaultConfigFunc = require("shakapacker/package/babel/preset.js");
|
||||
const resultConfig = defaultConfigFunc(api);
|
||||
|
||||
if (!validEnv.includes(currentEnv)) {
|
||||
throw new Error(
|
||||
'Please specify a valid `NODE_ENV` or ' +
|
||||
'`BABEL_ENV` environment variables. Valid values are "development", ' +
|
||||
'"test", and "production". Instead, received: ' +
|
||||
JSON.stringify(currentEnv) +
|
||||
'.'
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
presets: [
|
||||
isTestEnv && [
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets: {
|
||||
node: 'current'
|
||||
}
|
||||
}
|
||||
],
|
||||
(isProductionEnv || isDevelopmentEnv) && [
|
||||
'@babel/preset-env',
|
||||
{
|
||||
forceAllTransforms: true,
|
||||
useBuiltIns: 'entry',
|
||||
corejs: 3,
|
||||
modules: false,
|
||||
exclude: ['transform-typeof-symbol']
|
||||
}
|
||||
]
|
||||
].filter(Boolean),
|
||||
plugins: [
|
||||
'babel-plugin-macros',
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
isTestEnv && 'babel-plugin-dynamic-import-node',
|
||||
'@babel/plugin-transform-destructuring',
|
||||
[
|
||||
'@babel/plugin-proposal-class-properties',
|
||||
{
|
||||
loose: true
|
||||
}
|
||||
],
|
||||
[
|
||||
'@babel/plugin-proposal-object-rest-spread',
|
||||
{
|
||||
useBuiltIns: true
|
||||
}
|
||||
],
|
||||
[
|
||||
'@babel/plugin-transform-runtime',
|
||||
{
|
||||
helpers: false
|
||||
}
|
||||
],
|
||||
[
|
||||
'@babel/plugin-transform-regenerator',
|
||||
{
|
||||
async: false
|
||||
}
|
||||
],
|
||||
["@babel/plugin-proposal-private-property-in-object", { "loose": true }],
|
||||
["@babel/plugin-proposal-private-methods", { "loose": true }]
|
||||
].filter(Boolean)
|
||||
}
|
||||
}
|
||||
return resultConfig;
|
||||
};
|
||||
|
||||
@@ -16,7 +16,7 @@ FileUtils.chdir APP_ROOT do
|
||||
# Add necessary setup steps to this file.
|
||||
|
||||
puts "== Installing dependencies =="
|
||||
system! "script/install-bundler"
|
||||
|
||||
# Check first (it's quicker), then install new gems if necessary
|
||||
system("bundle check 2> /dev/null") || system!(BUNDLE_ENV, "bundle install")
|
||||
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
|
||||
ENV["NODE_ENV"] ||= "development"
|
||||
ENV["NODE_OPTIONS"] ||= "--openssl-legacy-provider"
|
||||
|
||||
require "pathname"
|
||||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require "bundler/setup"
|
||||
|
||||
require "webpacker"
|
||||
require "webpacker/webpack_runner"
|
||||
|
||||
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
|
||||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath)
|
||||
|
||||
APP_ROOT = File.expand_path("..", __dir__)
|
||||
Dir.chdir(APP_ROOT) do
|
||||
Webpacker::WebpackRunner.run(ARGV)
|
||||
@@ -1,8 +1,6 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
|
||||
ENV["NODE_ENV"] ||= "development"
|
||||
ENV["NODE_OPTIONS"] ||= "--openssl-legacy-provider"
|
||||
|
||||
require "pathname"
|
||||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
||||
15
bin/yarn
15
bin/yarn
@@ -1,9 +1,16 @@
|
||||
#!/usr/bin/env ruby
|
||||
APP_ROOT = File.expand_path('..', __dir__)
|
||||
|
||||
APP_ROOT = File.expand_path("..", __dir__)
|
||||
Dir.chdir(APP_ROOT) do
|
||||
begin
|
||||
exec "yarnpkg", *ARGV
|
||||
rescue Errno::ENOENT
|
||||
yarn = ENV["PATH"].split(File::PATH_SEPARATOR).
|
||||
select { |dir| File.expand_path(dir) != __dir__ }.
|
||||
product(["yarn", "yarnpkg", "yarn.cmd", "yarn.ps1"]).
|
||||
map { |dir, file| File.expand_path(file, dir) }.
|
||||
find { |file| File.executable?(file) }
|
||||
|
||||
if yarn
|
||||
exec yarn, *ARGV
|
||||
else
|
||||
$stderr.puts "Yarn executable was not detected in the system."
|
||||
$stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
|
||||
exit 1
|
||||
|
||||
@@ -89,7 +89,7 @@ services:
|
||||
build: .
|
||||
command: >
|
||||
sh -lc 'until [ -f /bundles/.Gemfile.lock.sha ] && sha256sum -c /bundles/.Gemfile.lock.sha >/dev/null 2>&1; do sleep 0.5; done;
|
||||
exec ./bin/webpack-dev-server'
|
||||
exec ./bin/webpacker-dev-server'
|
||||
ports:
|
||||
- "3035:3035"
|
||||
volumes:
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
module WebpackImageExtension
|
||||
def image_pack_path(image)
|
||||
# The Webpacker::Helper#resolve_path_to_image method is incredibly useful
|
||||
# for nicely fetching Webpacker image paths, but it's private.
|
||||
resolve_path_to_image(image)
|
||||
end
|
||||
end
|
||||
|
||||
Webpacker::Helper.include WebpackImageExtension
|
||||
@@ -627,6 +627,7 @@ en:
|
||||
errors:
|
||||
vine_api: "There was an error communicating with the API, please try again later."
|
||||
invalid_voucher: "The voucher is not valid"
|
||||
expired: "The voucher has expired"
|
||||
not_found_voucher: "Sorry, we couldn't find that voucher, please check the code."
|
||||
vine_voucher_redeemer_service:
|
||||
errors:
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
|
||||
|
||||
const environment = require('./environment')
|
||||
|
||||
module.exports = environment.toWebpackConfig()
|
||||
@@ -1,35 +0,0 @@
|
||||
const { environment } = require('@rails/webpacker')
|
||||
|
||||
module.exports = environment
|
||||
|
||||
function hotfixPostcssLoaderConfig (subloader) {
|
||||
const subloaderName = subloader.loader
|
||||
if (subloaderName === 'postcss-loader') {
|
||||
if (subloader.options.postcssOptions) {
|
||||
console.log(
|
||||
'\x1b[31m%s\x1b[0m',
|
||||
'Remove postcssOptions workaround in config/webpack/environment.js'
|
||||
)
|
||||
} else {
|
||||
subloader.options.postcssOptions = subloader.options.config;
|
||||
delete subloader.options.config;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addQuietDepsToSassLoader (subloader) {
|
||||
if (subloader.loader === 'sass-loader') {
|
||||
subloader.options.sassOptions = {
|
||||
...subloader.options.sassOptions,
|
||||
quietDeps: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
environment.loaders.keys().forEach(loaderName => {
|
||||
const loader = environment.loaders.get(loaderName);
|
||||
if (loaderName === 'sass') {
|
||||
loader.use.forEach(addQuietDepsToSassLoader);
|
||||
}
|
||||
loader.use.forEach(hotfixPostcssLoaderConfig);
|
||||
});
|
||||
@@ -1,5 +0,0 @@
|
||||
process.env.NODE_ENV = process.env.NODE_ENV || 'production'
|
||||
|
||||
const environment = require('./environment')
|
||||
|
||||
module.exports = environment.toWebpackConfig()
|
||||
@@ -1,5 +0,0 @@
|
||||
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
|
||||
|
||||
const environment = require('./environment')
|
||||
|
||||
module.exports = environment.toWebpackConfig()
|
||||
20
config/webpack/webpack.config.js
Normal file
20
config/webpack/webpack.config.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const { webpackConfig, merge } = require("shakapacker")
|
||||
|
||||
const options = {
|
||||
resolve: {
|
||||
extensions: [".mjs", ".js", ".sass",".scss", ".css", ".module.sass", ".module.scss", ".module.css", ".png", ".svg", ".gif", ".jpeg", ".jpg", ".eot", ".ttf", ".woff"]
|
||||
}
|
||||
}
|
||||
|
||||
const OFNwebpackConfig = merge(webpackConfig, options)
|
||||
|
||||
// quiet deprecations in dependencies, notably foundation-sites
|
||||
const scssRule = OFNwebpackConfig.module.rules.find((rule) => rule.test.test(".scss"))
|
||||
const sassDefaultOptions = scssRule.use[3].options.sassOptions
|
||||
scssRule.use[3].options.sassOptions = {
|
||||
...sassDefaultOptions,
|
||||
quietDeps: true
|
||||
}
|
||||
|
||||
// This results in a new object copied from the mutable global
|
||||
module.exports = OFNwebpackConfig
|
||||
@@ -8,7 +8,7 @@ default: &default
|
||||
cache_path: tmp/cache/webpacker
|
||||
webpack_compile_output: true
|
||||
|
||||
# Additional paths webpack should lookup modules
|
||||
# Additional paths webpack should look up modules
|
||||
# ['app/assets', 'engine/foo/app/assets']
|
||||
additional_paths: [
|
||||
'vendor',
|
||||
@@ -25,37 +25,6 @@ default: &default
|
||||
# Extract and emit a css file
|
||||
extract_css: true
|
||||
|
||||
static_assets_extensions:
|
||||
- .jpg
|
||||
- .jpeg
|
||||
- .png
|
||||
- .gif
|
||||
- .tiff
|
||||
- .ico
|
||||
- .svg
|
||||
- .eot
|
||||
- .otf
|
||||
- .ttf
|
||||
- .woff
|
||||
- .woff2
|
||||
|
||||
extensions:
|
||||
- .mjs
|
||||
- .js
|
||||
- .sass
|
||||
- .scss
|
||||
- .css
|
||||
- .module.sass
|
||||
- .module.scss
|
||||
- .module.css
|
||||
- .png
|
||||
- .svg
|
||||
- .gif
|
||||
- .jpeg
|
||||
- .jpg
|
||||
- .eot
|
||||
- .ttf
|
||||
- .woff
|
||||
|
||||
development:
|
||||
<<: *default
|
||||
@@ -66,22 +35,40 @@ development:
|
||||
https: false
|
||||
host: localhost
|
||||
port: 3035
|
||||
public: localhost:3035
|
||||
# Hot Module Replacement updates modules while the application is running without a full reload
|
||||
hmr: false
|
||||
# Inline should be set to true if using HMR
|
||||
inline: true
|
||||
overlay: true
|
||||
# Defaults to the inverse of hmr. Uncomment to manually set this.
|
||||
# live_reload: true
|
||||
client:
|
||||
# Should we show a full-screen overlay in the browser when there are compiler errors or warnings?
|
||||
overlay: false
|
||||
# May also be a string
|
||||
# webSocketURL:
|
||||
# hostname: "0.0.0.0"
|
||||
# pathname: "/ws"
|
||||
# port: 8080
|
||||
# Should we use gzip compression?
|
||||
compress: true
|
||||
disable_host_check: true
|
||||
use_local_ip: false
|
||||
quiet: false
|
||||
pretty: false
|
||||
# Note that apps that do not check the host are vulnerable to DNS rebinding attacks
|
||||
allowed_hosts: "all"
|
||||
#TODO Old config
|
||||
#pretty: false
|
||||
pretty: true
|
||||
headers:
|
||||
'Access-Control-Allow-Origin': '*'
|
||||
watch_options:
|
||||
ignored:
|
||||
- '**/node_modules/**'
|
||||
- '**/*.swp'
|
||||
static:
|
||||
watch:
|
||||
ignored:
|
||||
- '**/node_modules/**'
|
||||
- '**/*.swp'
|
||||
|
||||
test:
|
||||
<<: *default
|
||||
compile: true
|
||||
compiler_strategy: mtime
|
||||
|
||||
# Compile test packs to a separate directory
|
||||
public_output_path: packs-test
|
||||
|
||||
production: &production
|
||||
<<: *default
|
||||
@@ -91,9 +78,3 @@ production: &production
|
||||
|
||||
# Cache manifest.json for performance
|
||||
cache_manifest: true
|
||||
|
||||
test:
|
||||
<<: *default
|
||||
|
||||
# Compile test packs to a separate directory
|
||||
public_output_path: packs-test
|
||||
|
||||
@@ -179,7 +179,7 @@ module.exports = {
|
||||
// transform: { "\\.[jt]sx?$": "babel-jest" },
|
||||
|
||||
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
|
||||
transformIgnorePatterns: ["/node_modules/(?!(stimulus.+)/)"],
|
||||
transformIgnorePatterns: ["/node_modules/(?!stimulus)/"],
|
||||
|
||||
// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
|
||||
// unmockedModulePathPatterns: undefined,
|
||||
|
||||
@@ -392,9 +392,9 @@ module Reporting
|
||||
end
|
||||
end
|
||||
|
||||
def filter_scope(*args)
|
||||
def filter_scope(*)
|
||||
chain_to_scope do
|
||||
where(*args)
|
||||
where(*)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
36
package.json
36
package.json
@@ -7,12 +7,21 @@
|
||||
},
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.28.5",
|
||||
"@babel/plugin-transform-runtime": "^7.28.5",
|
||||
"@babel/preset-env": "^7.28.5",
|
||||
"@babel/runtime": "^7.28.4",
|
||||
"@floating-ui/dom": "*",
|
||||
"@hotwired/stimulus": "*",
|
||||
"@hotwired/turbo": "*",
|
||||
"@rails/webpacker": "5.4.4",
|
||||
"@stimulus-components/rails-nested-form": "*",
|
||||
"babel-loader": "^8.2.2",
|
||||
"cable_ready": "5.0.6",
|
||||
"coffee-loader": "^5.0.0",
|
||||
"coffeescript": "^2.7.0",
|
||||
"compression-webpack-plugin": "^9.0.0",
|
||||
"css-loader": "^7.1.2",
|
||||
"css-minimizer-webpack-plugin": "^7.0.4",
|
||||
"flatpickr": "*",
|
||||
"foundation-sites": "5.5.3",
|
||||
"hotkeys-js": "*",
|
||||
@@ -21,19 +30,40 @@
|
||||
"leaflet": "1.9.4",
|
||||
"leaflet-geosearch": "4.2.2",
|
||||
"leaflet-providers": "3.0.0",
|
||||
"mini-css-extract-plugin": "^2.9.4",
|
||||
"moment": "*",
|
||||
"mrujs": "*",
|
||||
"pnp-webpack-plugin": "^1.7.0",
|
||||
"postcss": "^8.5.6",
|
||||
"postcss-flexbugs-fixes": "^5.0.2",
|
||||
"postcss-import": "^16.1.1",
|
||||
"postcss-loader": "^8.2.0",
|
||||
"postcss-preset-env": "^10.5.0",
|
||||
"regenerator-transform": "^0.15.2",
|
||||
"sass-embedded": "^1.96.0",
|
||||
"sass-loader": "^16.0.6",
|
||||
"select2": "*",
|
||||
"shakapacker": "6.6.0",
|
||||
"shortcut-buttons-flatpickr": "*",
|
||||
"stimulus": "*",
|
||||
"stimulus-autocomplete": "*",
|
||||
"stimulus-flatpickr": "*",
|
||||
"stimulus_reflex": "3.5.5",
|
||||
"style-loader": "^4.0.0",
|
||||
"terser-webpack-plugin": "^5.3.16",
|
||||
"tom-select": "*",
|
||||
"trix": "*",
|
||||
"turbo_power": "*",
|
||||
"webpack": "~4"
|
||||
"webpack": "^5.104.0",
|
||||
"webpack-assets-manifest": "^5.0.6",
|
||||
"webpack-cli": "^4.9.2",
|
||||
"webpack-merge": "^5.8.0",
|
||||
"webpack-sources": "^3.3.3"
|
||||
},
|
||||
"browserslist": [
|
||||
"defaults",
|
||||
"not IE 11"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@testing-library/dom": "<11.0.0",
|
||||
"jasmine-core": "~5.12.1",
|
||||
@@ -44,6 +74,6 @@
|
||||
"karma-coffee-preprocessor": "~1.0.1",
|
||||
"karma-jasmine": "~0.3.8",
|
||||
"prettier": "*",
|
||||
"webpack-dev-server": "~3"
|
||||
"webpack-dev-server": "^4.9.0"
|
||||
}
|
||||
}
|
||||
|
||||
22
script/bump-ruby.sh
Executable file
22
script/bump-ruby.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
if [ "$#" -lt 1 ]; then
|
||||
echo "Usage: $0 <new-version>"
|
||||
echo "Example: $0 3.4.8"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -ex
|
||||
|
||||
OLD_VERSION=$(cat .ruby-version)
|
||||
NEW_VERSION=$1
|
||||
PATTERN="$(echo "$OLD_VERSION" | sed 's:[]\[^$.*/]:\\&:g')"
|
||||
|
||||
sed -i "s/\<$PATTERN\>/$NEW_VERSION/" .ruby-version Dockerfile
|
||||
|
||||
script/rbenv-install.sh
|
||||
|
||||
# Update bundler to the version shipped with Ruby:
|
||||
bundle update --bundler
|
||||
|
||||
git commit -a -m "Bump Ruby from $OLD_VERSION to $NEW_VERSION"
|
||||
@@ -1,42 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This shell script looks for the last used Bundler version in Gemfile.lock and
|
||||
# installs exactly that version, removing all other versions.
|
||||
|
||||
# Command line arguments are passed on to `gem install`. So you can call this
|
||||
# script with with arguments:
|
||||
#
|
||||
# ./script/install-bundler --no-ri --no-rdoc
|
||||
|
||||
# This script is used by ofn-install and can by handy in your development
|
||||
# environment.
|
||||
|
||||
# Fail if a single command fails.
|
||||
set -e
|
||||
|
||||
# `grep`: find the occurrences of "BUNDLED WITH" (-m is unnecessary and behaves different on macOS)
|
||||
# `-A`: print the next line after "BUNDLED WITH" as well
|
||||
# `-F`: find exactly that string
|
||||
# `tail -n 1`: take the last line, the version line
|
||||
# `tr -d`: delete all spaces, the indent before the version
|
||||
version="$(grep -A 1 -F "BUNDLED WITH" Gemfile.lock | tail -n 1 | tr -d '[:space:]')"
|
||||
|
||||
# if the length of $version is zero
|
||||
if [ -z "$version" ]; then
|
||||
echo >&2 "No bundler version in Gemfile.lock."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the currently used bundler version.
|
||||
# We ignore all errors with `2>/dev/null || true` in case there is no bundler
|
||||
# or only an orphaned shim installed.
|
||||
current="$(bundler --version 2>/dev/null || true)"
|
||||
|
||||
if [ "$current" = "Bundler version $version" ]; then
|
||||
echo >&2 "Already up-to-date: $current"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Passing on all arguments of this script with "$@".
|
||||
gem install bundler -v "$version" "$@"
|
||||
gem uninstall bundler -v "!= $version" 2>/dev/null || true
|
||||
@@ -89,13 +89,13 @@ RSpec.describe ApplicationHelper do
|
||||
it "appends locale and digest to a single key" do
|
||||
expect(
|
||||
helper.cache_key_with_locale("single-key", "en")
|
||||
).to eq(["single-key", "en", en_digest])
|
||||
).to eq(["single-key", "v1", "en", en_digest])
|
||||
end
|
||||
|
||||
it "appends locale and digest to multiple keys" do
|
||||
expect(
|
||||
helper.cache_key_with_locale(["array", "of", "keys"], "es")
|
||||
).to eq(["array", "of", "keys", "es", es_digest])
|
||||
).to eq(["array", "of", "keys", "v1", "es", es_digest])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -299,13 +299,7 @@ RSpec.describe Spree::Order do
|
||||
context "when a payment raises a GatewayError" do
|
||||
before { expect(payment).to receive(:process!).and_raise(Spree::Core::GatewayError) }
|
||||
|
||||
it "returns true when configured to allow checkout on gateway failures" do
|
||||
Spree::Config.set allow_checkout_on_gateway_error: true
|
||||
expect(order.process_payments!).to be_truthy
|
||||
end
|
||||
|
||||
it "returns false when not configured to allow checkout on gateway failures" do
|
||||
Spree::Config.set allow_checkout_on_gateway_error: false
|
||||
it "returns false" do
|
||||
expect(order.process_payments!).to be_falsy
|
||||
end
|
||||
end
|
||||
|
||||
@@ -161,7 +161,19 @@ RSpec.describe VoucherAdjustmentsController do
|
||||
post("/voucher_adjustments", params:)
|
||||
|
||||
expect(response).to be_unprocessable
|
||||
expect(flash[:error]).to match "There was an error while adding the voucher"
|
||||
expect(flash[:error]).to match "The voucher is not valid"
|
||||
end
|
||||
end
|
||||
|
||||
context "when voucher has expired" do
|
||||
it "returns 422 and an error message" do
|
||||
mock_vine_voucher_validator(voucher: nil,
|
||||
errors: { invalid_voucher: "The voucher has expired" })
|
||||
|
||||
post("/voucher_adjustments", params:)
|
||||
|
||||
expect(response).to be_unprocessable
|
||||
expect(flash[:error]).to match "The voucher has expired"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -219,6 +231,20 @@ RSpec.describe VoucherAdjustmentsController do
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when voucher has expired" do
|
||||
it "returns 422 and an error message" do
|
||||
vine_voucher = build(:vine_voucher, code: vine_voucher_code,
|
||||
enterprise: distributor)
|
||||
mock_vine_voucher_validator(voucher: vine_voucher,
|
||||
errors: { invalid_voucher: "The voucher has expired" })
|
||||
|
||||
post("/voucher_adjustments", params:)
|
||||
|
||||
expect(response).to be_unprocessable
|
||||
expect(flash[:error]).to match "The voucher has expired"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -270,11 +270,12 @@ RSpec.describe Vine::VoucherValidatorService, feature: :connected_apps do
|
||||
enterprise: distributor, data: { api_key: "1234568", secret: "my_secret" }
|
||||
)
|
||||
}
|
||||
# Faraday returns un-parsed json
|
||||
let(:data) {
|
||||
{
|
||||
meta: { responseCode: 400, limit: 50, offset: 0, message: "Invalid merchant team." },
|
||||
data: []
|
||||
}.deep_stringify_keys
|
||||
}.to_json
|
||||
}
|
||||
|
||||
before do
|
||||
@@ -285,7 +286,7 @@ RSpec.describe Vine::VoucherValidatorService, feature: :connected_apps do
|
||||
expect_validate_to_be_nil
|
||||
end
|
||||
|
||||
it "adds an error message" do
|
||||
it "adds a general error message" do
|
||||
validate_voucher_service.validate
|
||||
|
||||
expect(validate_voucher_service.errors).to include(
|
||||
@@ -293,6 +294,23 @@ RSpec.describe Vine::VoucherValidatorService, feature: :connected_apps do
|
||||
)
|
||||
end
|
||||
|
||||
context "it is expired" do
|
||||
let(:data) {
|
||||
{
|
||||
meta: { responseCode: 400, limit: 50, offset: 0, message: "This voucher has expired." },
|
||||
data: []
|
||||
}.to_json
|
||||
}
|
||||
|
||||
it "adds a specific error message" do
|
||||
validate_voucher_service.validate
|
||||
|
||||
expect(validate_voucher_service.errors).to include(
|
||||
{ invalid_voucher: "The voucher has expired" }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
it "doesn't creates a new VINE voucher" do
|
||||
expect_voucher_count_not_to_change
|
||||
end
|
||||
@@ -420,6 +438,25 @@ RSpec.describe Vine::VoucherValidatorService, feature: :connected_apps do
|
||||
}.not_to change { voucher.reload.amount }
|
||||
end
|
||||
end
|
||||
|
||||
context "it is expired" do
|
||||
let(:data) {
|
||||
{
|
||||
meta: { responseCode: 400, limit: 50, offset: 0, message: "This voucher has expired." },
|
||||
data: []
|
||||
}.to_json
|
||||
}
|
||||
|
||||
it "adds a specific error message" do
|
||||
mock_api_exception(type: Faraday::BadRequestError, status: 409, body: data)
|
||||
|
||||
validate_voucher_service.validate
|
||||
|
||||
expect(validate_voucher_service.errors).to include(
|
||||
{ invalid_voucher: "The voucher has expired" }
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
module OpenFoodNetwork
|
||||
module PerformanceHelper
|
||||
def multi_benchmark(num_samples, cache_key_patterns: [], &block)
|
||||
def multi_benchmark(num_samples, cache_key_patterns: [], &)
|
||||
results = (0..num_samples).map do |_i|
|
||||
ActiveRecord::Base.connection.query_cache.clear
|
||||
delete_cache_keys(cache_key_patterns)
|
||||
|
||||
result = Benchmark.measure(&block)
|
||||
result = Benchmark.measure(&)
|
||||
|
||||
puts result
|
||||
|
||||
|
||||
@@ -68,9 +68,9 @@ RSpec.describe "DFC Permissions", feature: "cqcm-dev", vcr: true do
|
||||
end
|
||||
end
|
||||
|
||||
def within_platform_list(variant, &block)
|
||||
def within_platform_list(variant, &)
|
||||
retry_expectations(on: Ferrum::JavaScriptError) do
|
||||
within(platform_list(variant), &block)
|
||||
within(platform_list(variant), &)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -555,7 +555,7 @@ RSpec.describe '
|
||||
find_button("Confirm").click
|
||||
end
|
||||
|
||||
expect(page).to have_selector('.reveal-modal', visible: false)
|
||||
expect(page).not_to have_content("This will mark the order as Shipped.")
|
||||
expect(page).to have_content "SHIPPED"
|
||||
click_link('Order Details') unless subpage == 'Order Details'
|
||||
|
||||
@@ -578,7 +578,7 @@ RSpec.describe '
|
||||
find_button("Confirm").click
|
||||
end
|
||||
|
||||
expect(page).to have_selector('.reveal-modal', visible: false)
|
||||
expect(page).not_to have_content("This will mark the order as Shipped.")
|
||||
click_link('Order Details') unless subpage == 'Order Details'
|
||||
|
||||
expect(page).to have_content "SHIPPED"
|
||||
|
||||
@@ -198,7 +198,7 @@ RSpec.describe "As a consumer, I want to checkout my order" do
|
||||
fill_in "Enter voucher code", with: "KM1891"
|
||||
click_button("Apply")
|
||||
|
||||
expect(page).to have_content("There was an error while adding the voucher")
|
||||
expect(page).to have_content("The voucher is not valid")
|
||||
expect(Vouchers::Vine.find_by(code: "KM1891", enterprise: distributor)).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user