mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-13 18:46:49 +00:00
Compare commits
1 Commits
RachL-patc
...
v4.4.46
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f962af786 |
21
.env
21
.env
@@ -10,10 +10,10 @@ TIMEZONE="Melbourne"
|
||||
DEFAULT_COUNTRY_CODE="AU"
|
||||
|
||||
# Locale for translation.
|
||||
LOCALE="en_AU"
|
||||
LOCALE="en"
|
||||
|
||||
# For multilingual - ENV doesn't have array so pass it as string with commas
|
||||
AVAILABLE_LOCALES="en_AU,es"
|
||||
AVAILABLE_LOCALES="en,es"
|
||||
|
||||
# Spree zone.
|
||||
CHECKOUT_ZONE="Australia"
|
||||
@@ -42,6 +42,14 @@ SMTP_PASSWORD="f00d"
|
||||
# Javascript error reporting via Bugsnag.
|
||||
# BUGSNAG_JS_KEY=""
|
||||
|
||||
# SingleSignOn login for Discourse
|
||||
#
|
||||
# DISCOURSE_SSO_SECRET should be a random string. It must be the same as provided to your Discourse instance.
|
||||
# DISCOURSE_SSO_SECRET=""
|
||||
#
|
||||
# DISCOURSE_URL must be the URL of your Discourse instance.
|
||||
# DISCOURSE_URL="https://noticeboard.openfoodnetwork.org.au"
|
||||
|
||||
# see="https://developers.google.com/maps/documentation/javascript/get-api-key
|
||||
# GOOGLE_MAPS_API_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
# see https://developers.google.com/maps/documentation/javascript/localization#Region
|
||||
@@ -61,12 +69,3 @@ SMTP_PASSWORD="f00d"
|
||||
# NEW_RELIC_AGENT_ENABLED=true
|
||||
# NEW_RELIC_APP_NAME="Open Food Network"
|
||||
# NEW_RELIC_LICENSE_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
|
||||
# Database encryption configuration, required for VINE connected app
|
||||
# Generate with bin/rails db:encryption:init
|
||||
# ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
# ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
# ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
|
||||
# VINE API settings
|
||||
# VINE_API_URL="https://vine-staging.openfoodnetwork.org.au/api/v1"
|
||||
|
||||
@@ -5,11 +5,6 @@
|
||||
#
|
||||
# cp .env.development .env.local
|
||||
|
||||
# Locale for translation. Using a locale other than `en` tests the
|
||||
# successful fallback to `en`. You will also see up-to-date text used
|
||||
# in production
|
||||
LOCALE="en_AU"
|
||||
|
||||
VERBOSE_QUERY_LOGS=true
|
||||
|
||||
SECRET_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
@@ -24,8 +19,3 @@ SITE_URL="0.0.0.0:3000"
|
||||
RACK_TIMEOUT_SERVICE_TIMEOUT="0"
|
||||
RACK_TIMEOUT_WAIT_TIMEOUT="0"
|
||||
RACK_TIMEOUT_WAIT_OVERTIME="0"
|
||||
|
||||
# Database encryption configuration, required for VINE connected app
|
||||
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY="dev_primary_key"
|
||||
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY="dev_determinnistic_key"
|
||||
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT="dev_derivation_salt"
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
# ENV vars for the test environment
|
||||
# Override locally with `.env.test.local`
|
||||
|
||||
# Locale for translation.
|
||||
LOCALE="en_TEST"
|
||||
|
||||
OFN_REDIS_JOBS_URL="redis://localhost:6379/2"
|
||||
|
||||
SECRET_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
@@ -16,9 +13,5 @@ STRIPE_PUBLIC_TEST_API_KEY="bogus_stripe_publishable_key"
|
||||
SITE_URL="test.host"
|
||||
|
||||
OPENID_APP_ID="test-provider"
|
||||
OPENID_APP_SECRET="dummy-openid-app-secret-token"
|
||||
OPENID_APP_SECRET="12345"
|
||||
OPENID_REFRESH_TOKEN="dummy-refresh-token"
|
||||
|
||||
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY="test_primary_key"
|
||||
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY="test_deterministic_key"
|
||||
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT="test_derivation_salt"
|
||||
|
||||
11
.github/ISSUE_TEMPLATE/release.md
vendored
11
.github/ISSUE_TEMPLATE/release.md
vendored
@@ -7,11 +7,10 @@ assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## 1. Drafting on Friday
|
||||
## 1. Preparation on Thursday
|
||||
|
||||
- [ ] Merge pull requests in the [Ready To Go] column
|
||||
- [ ] Include translations: `script/release/update_locales`
|
||||
- You need the [Transifex Client] installed on your local dev environement to run the script.
|
||||
- [ ] Increment version number: `git push upstream HEAD:refs/tags/vX.Y.Z`
|
||||
- Major: if server changes are required (eg. provision with ofn-install)
|
||||
- Minor: larger change that is irreversible (eg. migration deleting data)
|
||||
@@ -26,9 +25,8 @@ assignees: ''
|
||||
- [ ] Move this issue to Test Ready.
|
||||
- [ ] Notify `@testers` in [#testing].
|
||||
- [ ] Test build: [Deploy to Staging] with release tag.
|
||||
- [ ] Notify a deployer to deploy it
|
||||
|
||||
## 3. Deployment at beginning of week
|
||||
## 3. Finish on Tuesday
|
||||
|
||||
- [ ] Publish and notify [#global-community] (this is automatically posted with a plugin)
|
||||
- [ ] Deploy the new release to all managed instances.
|
||||
@@ -41,7 +39,7 @@ assignees: ''
|
||||
</details>
|
||||
- [ ] Notify [#instance-managers]:
|
||||
> @instance_managers The new release has been deployed.
|
||||
- [ ] [Create issue] for next release and confirm with next release drafter in [#delivery-circle].
|
||||
- [ ] [Create issue] for next release and confirm with next release manager in [#core-devs].
|
||||
|
||||
The full process is described at https://github.com/openfoodfoundation/openfoodnetwork/wiki/Releasing.
|
||||
|
||||
@@ -54,5 +52,4 @@ The full process is described at https://github.com/openfoodfoundation/openfoodn
|
||||
[Deploy to Staging]: https://github.com/openfoodfoundation/openfoodnetwork/actions/workflows/stage.yml
|
||||
[#global-community]: https://app.slack.com/client/T02G54U79/C59ADD8F2
|
||||
[Create issue]: https://github.com/openfoodfoundation/openfoodnetwork/issues/new?assignees=&labels=&projects=&template=release.md&title=Release
|
||||
[#delivery-circle]: https://openfoodnetwork.slack.com/archives/C01T75H6G0Z
|
||||
[Transifex Client]: https://developers.transifex.com/docs/cli
|
||||
[#core-devs]: https://openfoodnetwork.slack.com/archives/GK2T38QPJ
|
||||
|
||||
14
.github/workflows/auto-author-assign.yml
vendored
14
.github/workflows/auto-author-assign.yml
vendored
@@ -1,14 +0,0 @@
|
||||
name: Auto Author Assign
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, reopened]
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
assign-author:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: toshimaru/auto-author-assign@v2.1.0
|
||||
165
.github/workflows/build.yml
vendored
165
.github/workflows/build.yml
vendored
@@ -3,7 +3,7 @@ name: Build
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches-ignore:
|
||||
branches-ignore:
|
||||
- 'dependabot/**'
|
||||
pull_request:
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
|
||||
- name: Setup redis
|
||||
uses: supercharge/redis-github-action@1.4.0
|
||||
with:
|
||||
with:
|
||||
redis-version: 6
|
||||
|
||||
- name: Set up Ruby
|
||||
@@ -59,14 +59,13 @@ jobs:
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: yarn
|
||||
|
||||
- name: Install JS dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Set up database
|
||||
run: |
|
||||
bin/rake db:create db:schema:load
|
||||
bundle exec rake db:create db:schema:load
|
||||
|
||||
- name: Run tests
|
||||
env:
|
||||
@@ -81,19 +80,10 @@ jobs:
|
||||
# RSpec split test files by test examples feature - it's optional
|
||||
# https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it
|
||||
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/controllers/**/*_spec.rb}"
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/controllers/**/*_spec.rb}"
|
||||
run: |
|
||||
git show --no-patch # the commit being tested (which is often a merge due to actions/checkout@v3)
|
||||
bin/rake knapsack_pro:rspec
|
||||
|
||||
- name: Save SimpleCov file
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: simplecov-chunk-controllers-${{ matrix.ci_node_index }}
|
||||
path: coverage/*.*
|
||||
retention-days: 2 # doesn't need to be long, because it's the combined results that matter
|
||||
if-no-files-found: ignore
|
||||
include-hidden-files: true
|
||||
bundle exec rake knapsack_pro:rspec
|
||||
|
||||
models:
|
||||
runs-on: ubuntu-22.04
|
||||
@@ -116,16 +106,16 @@ jobs:
|
||||
# [n] - where the n is a number of parallel jobs you want to run your tests on.
|
||||
# Use a higher number if you have slow tests to split them between more parallel jobs.
|
||||
# Remember to update the value of the `ci_node_index` below to (0..n-1).
|
||||
ci_node_total: [4]
|
||||
ci_node_total: [5]
|
||||
# Indexes for parallel jobs (starting from zero).
|
||||
# E.g. use [0, 1] for 2 parallel jobs, [0, 1, 2] for 3 parallel jobs, etc.
|
||||
ci_node_index: [0, 1, 2, 3]
|
||||
ci_node_index: [0, 1, 2, 3, 4]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup redis
|
||||
uses: supercharge/redis-github-action@1.4.0
|
||||
with:
|
||||
with:
|
||||
redis-version: 6
|
||||
|
||||
- name: Set up Ruby
|
||||
@@ -135,7 +125,7 @@ jobs:
|
||||
|
||||
- name: Set up database
|
||||
run: |
|
||||
bin/rake db:create db:schema:load
|
||||
bundle exec rake db:create db:schema:load
|
||||
|
||||
- name: Run tests
|
||||
env:
|
||||
@@ -150,18 +140,9 @@ jobs:
|
||||
# RSpec split test files by test examples feature - it's optional
|
||||
# https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it
|
||||
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/models/**/*_spec.rb}"
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/models/**/*_spec.rb}"
|
||||
run: |
|
||||
bin/rake knapsack_pro:rspec
|
||||
|
||||
- name: Save SimpleCov file
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: simplecov-chunk-models-${{ matrix.ci_node_index }}
|
||||
path: coverage/*.*
|
||||
retention-days: 2 # doesn't need to be long, because it's the combined results that matter
|
||||
if-no-files-found: ignore
|
||||
include-hidden-files: true
|
||||
bundle exec rake knapsack_pro:rspec
|
||||
|
||||
system_admin:
|
||||
runs-on: ubuntu-22.04
|
||||
@@ -184,16 +165,16 @@ jobs:
|
||||
# [n] - where the n is a number of parallel jobs you want to run your tests on.
|
||||
# Use a higher number if you have slow tests to split them between more parallel jobs.
|
||||
# Remember to update the value of the `ci_node_index` below to (0..n-1).
|
||||
ci_node_total: [14]
|
||||
ci_node_total: [13]
|
||||
# Indexes for parallel jobs (starting from zero).
|
||||
# E.g. use [0, 1] for 2 parallel jobs, [0, 1, 2] for 3 parallel jobs, etc.
|
||||
ci_node_index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
|
||||
ci_node_index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup redis
|
||||
uses: supercharge/redis-github-action@1.4.0
|
||||
with:
|
||||
with:
|
||||
redis-version: 6
|
||||
|
||||
- name: Set up Ruby
|
||||
@@ -204,14 +185,13 @@ jobs:
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: yarn
|
||||
|
||||
- name: Install JS dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Set up database
|
||||
run: |
|
||||
bin/rake db:create db:schema:load
|
||||
bundle exec rake db:create db:schema:load
|
||||
|
||||
- name: Run tests
|
||||
|
||||
@@ -227,25 +207,16 @@ jobs:
|
||||
# RSpec split test files by test examples feature - it's optional
|
||||
# https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it
|
||||
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/system/admin/**/*_spec.rb}"
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/system/admin/**/*_spec.rb}"
|
||||
|
||||
run: |
|
||||
bin/rake knapsack_pro:queue:rspec
|
||||
|
||||
- name: Save SimpleCov file
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: simplecov-chunk-system-admin-${{ matrix.ci_node_index }}
|
||||
path: coverage/*.*
|
||||
retention-days: 2 # doesn't need to be long, because it's the combined results that matter
|
||||
if-no-files-found: ignore
|
||||
include-hidden-files: true
|
||||
bundle exec rake knapsack_pro:queue:rspec
|
||||
|
||||
- name: Archive failed tests screenshots
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: failed-admin_${{ matrix.ci_node_index }}-tests-screenshots
|
||||
name: failed-tests-screenshots
|
||||
path: tmp/capybara/screenshots/*.png
|
||||
retention-days: 7
|
||||
if-no-files-found: ignore
|
||||
@@ -274,13 +245,13 @@ jobs:
|
||||
ci_node_total: [12]
|
||||
# Indexes for parallel jobs (starting from zero).
|
||||
# E.g. use [0, 1] for 2 parallel jobs, [0, 1, 2] for 3 parallel jobs, etc.
|
||||
ci_node_index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
||||
ci_node_index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup redis
|
||||
uses: supercharge/redis-github-action@1.4.0
|
||||
with:
|
||||
with:
|
||||
redis-version: 6
|
||||
|
||||
- name: Set up Ruby
|
||||
@@ -291,14 +262,13 @@ jobs:
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: yarn
|
||||
|
||||
- name: Install JS dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Set up database
|
||||
run: |
|
||||
bin/rake db:create db:schema:load
|
||||
bundle exec rake db:create db:schema:load
|
||||
|
||||
- name: Run tests
|
||||
|
||||
@@ -314,25 +284,16 @@ jobs:
|
||||
# RSpec split test files by test examples feature - it's optional
|
||||
# https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it
|
||||
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/system/consumer/**/*_spec.rb}"
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/system/consumer/**/*_spec.rb}"
|
||||
|
||||
run: |
|
||||
bin/rake knapsack_pro:queue:rspec
|
||||
|
||||
- name: Save SimpleCov file
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: simplecov-chunk-system-consumer-${{ matrix.ci_node_index }}
|
||||
path: coverage/*.*
|
||||
retention-days: 2 # doesn't need to be long, because it's the combined results that matter
|
||||
if-no-files-found: ignore
|
||||
include-hidden-files: true
|
||||
bundle exec rake knapsack_pro:queue:rspec
|
||||
|
||||
- name: Archive failed tests screenshots
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: failed-consumer_${{ matrix.ci_node_index }}-tests-screenshots
|
||||
name: failed-tests-screenshots
|
||||
path: tmp/capybara/screenshots/*.png
|
||||
retention-days: 7
|
||||
if-no-files-found: ignore
|
||||
@@ -367,7 +328,7 @@ jobs:
|
||||
|
||||
- name: Setup redis
|
||||
uses: supercharge/redis-github-action@1.4.0
|
||||
with:
|
||||
with:
|
||||
redis-version: 6
|
||||
|
||||
- name: Set up Ruby
|
||||
@@ -379,14 +340,13 @@ jobs:
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: yarn
|
||||
|
||||
- name: Install JS dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Set up database
|
||||
run: |
|
||||
bin/rake db:create db:schema:load
|
||||
bundle exec rake db:create db:schema:load
|
||||
|
||||
- name: Run tests
|
||||
|
||||
@@ -405,16 +365,16 @@ jobs:
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/lib/**/*_spec.rb,spec/migrations/**/*_spec.rb,spec/serializers/**/*_spec.rb,engines/**/*_spec.rb}"
|
||||
|
||||
run: |
|
||||
bin/rake knapsack_pro:rspec
|
||||
bundle exec rake knapsack_pro:rspec
|
||||
|
||||
- name: Save SimpleCov file
|
||||
uses: actions/upload-artifact@v4
|
||||
- name: Archive failed tests screenshots
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: simplecov-chunk-engines-${{ matrix.ci_node_index }}
|
||||
path: coverage/*.*
|
||||
retention-days: 2 # doesn't need to be long, because it's the combined results that matter
|
||||
name: failed-tests-screenshots
|
||||
path: tmp/capybara/screenshots/*.png
|
||||
retention-days: 7
|
||||
if-no-files-found: ignore
|
||||
include-hidden-files: true
|
||||
|
||||
test_the_rest:
|
||||
runs-on: ubuntu-22.04
|
||||
@@ -446,7 +406,7 @@ jobs:
|
||||
|
||||
- name: Setup redis
|
||||
uses: supercharge/redis-github-action@1.4.0
|
||||
with:
|
||||
with:
|
||||
redis-version: 6
|
||||
|
||||
- name: Set up Ruby
|
||||
@@ -458,14 +418,13 @@ jobs:
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: yarn
|
||||
|
||||
- name: Install JS dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Set up database
|
||||
run: |
|
||||
bin/rake db:create db:schema:load
|
||||
bundle exec rake db:create db:schema:load
|
||||
|
||||
- name: Run tests
|
||||
env:
|
||||
@@ -482,16 +441,7 @@ jobs:
|
||||
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
|
||||
KNAPSACK_PRO_TEST_FILE_EXCLUDE_PATTERN: "{engines/**/*_spec.rb,spec/models/**/*_spec.rb,spec/controllers/**/*_spec.rb,spec/serializers/**/*_spec.rb,spec/lib/**/*_spec.rb,spec/migrations/**/*_spec.rb,spec/system/**/*_spec.rb}"
|
||||
run: |
|
||||
bin/rake knapsack_pro:rspec
|
||||
|
||||
- name: Save SimpleCov file
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: simplecov-chunk-the-rest-${{ matrix.ci_node_index }}
|
||||
path: coverage/*.*
|
||||
retention-days: 2 # doesn't need to be long, because it's the combined results that matter
|
||||
if-no-files-found: ignore
|
||||
include-hidden-files: true
|
||||
bundle exec rake knapsack_pro:rspec
|
||||
|
||||
non_knapsack_jest_karma:
|
||||
runs-on: ubuntu-22.04
|
||||
@@ -520,49 +470,12 @@ jobs:
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: yarn
|
||||
|
||||
- name: Install JS dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Run JS tests
|
||||
run: bin/rake karma:run
|
||||
run: bundle exec rake karma:run
|
||||
|
||||
- name: Run jest tests
|
||||
run: yarn jest
|
||||
|
||||
collate_simplecov_results:
|
||||
runs-on: ubuntu-22.04
|
||||
needs:
|
||||
- controllers
|
||||
- models
|
||||
- engines
|
||||
- system_admin
|
||||
- system_consumer
|
||||
- test_the_rest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
||||
|
||||
- name: Download individual results from individual runners
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: simplecov-chunk-*
|
||||
path: tmp/simplecov
|
||||
merge-multiple: true
|
||||
|
||||
- name: collate results from each of the workers
|
||||
run: bundle exec rake 'simplecov:collate_results[tmp/simplecov]'
|
||||
|
||||
- name: Upload collated results
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: combined-simplecov-report
|
||||
path: coverage/**/*.*
|
||||
retention-days: 7
|
||||
if-no-files-found: ignore
|
||||
include-hidden-files: true
|
||||
|
||||
8
.github/workflows/mapi.yml
vendored
8
.github/workflows/mapi.yml
vendored
@@ -14,12 +14,12 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: docker/build
|
||||
- run: docker compose up --detach
|
||||
- run: docker-compose up --detach
|
||||
- run: until curl -f -s http://localhost:3000; do echo "waiting for api server"; sleep 1; done
|
||||
- run: docker compose exec -T db psql postgresql://ofn:f00d@localhost:5432/open_food_network_dev --command="update spree_users set spree_api_key='testing' where login='ofn@example.com'"
|
||||
- run: docker-compose exec -T db psql postgresql://ofn:f00d@localhost:5432/open_food_network_dev --command="update spree_users set spree_api_key='testing' where login='ofn@example.com'"
|
||||
# equivalent to Flipper.enable(:api_v1)
|
||||
- run: docker compose exec -T db psql postgresql://ofn:f00d@localhost:5432/open_food_network_dev --command="insert into flipper_features (key, created_at, updated_at) values ('api_v1', localtimestamp, localtimestamp)"
|
||||
- run: docker compose exec -T db psql postgresql://ofn:f00d@localhost:5432/open_food_network_dev --command="insert into flipper_gates (feature_key, key, value, created_at, updated_at) values ('api_v1', 'boolean', 'true', localtimestamp, localtimestamp)"
|
||||
- run: docker-compose exec -T db psql postgresql://ofn:f00d@localhost:5432/open_food_network_dev --command="insert into flipper_features (key, created_at, updated_at) values ('api_v1', localtimestamp, localtimestamp)"
|
||||
- run: docker-compose exec -T db psql postgresql://ofn:f00d@localhost:5432/open_food_network_dev --command="insert into flipper_gates (feature_key, key, value, created_at, updated_at) values ('api_v1', 'boolean', 'true', localtimestamp, localtimestamp)"
|
||||
|
||||
# Run Mayhem for API
|
||||
- name: Run Mayhem for API
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
*.yaml
|
||||
*.json
|
||||
*.html
|
||||
**/*.rb
|
||||
|
||||
# JS
|
||||
# Enabled: app/webpacker/controllers/*.js and app/webpacker/packs/*.js
|
||||
@@ -28,5 +27,6 @@ postcss.config.js
|
||||
/coverage/
|
||||
/engines/
|
||||
/public/
|
||||
/spec/
|
||||
/tmp/
|
||||
/vendor/
|
||||
|
||||
@@ -115,11 +115,6 @@ Rails/OutputSafety:
|
||||
Exclude:
|
||||
- spec/**/*
|
||||
|
||||
Rails/RedundantActiveRecordAllMethod:
|
||||
AllowedReceivers:
|
||||
- ActionMailer::Preview
|
||||
- ActiveSupport::TimeZone
|
||||
|
||||
Rails/SkipsModelValidations:
|
||||
AllowedMethods:
|
||||
- touch
|
||||
@@ -129,13 +124,6 @@ Rails/SkipsModelValidations:
|
||||
- update_column
|
||||
- update_columns
|
||||
|
||||
Rails/UnknownEnv:
|
||||
Environments:
|
||||
- development
|
||||
- production
|
||||
- staging
|
||||
- test
|
||||
|
||||
Rails/WhereExists:
|
||||
EnforcedStyle: where # Cf. conversion https://github.com/openfoodfoundation/openfoodnetwork/pull/12363
|
||||
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 1400 --no-auto-gen-timestamp`
|
||||
# using RuboCop version 1.64.1.
|
||||
# using RuboCop version 1.62.1.
|
||||
# The point is for the user to remove these configuration records
|
||||
# one by one as the offenses are removed from the code base.
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
# versions of RuboCop, may require this file to be generated again.
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Layout/EmptyLines:
|
||||
# Offense count: 2
|
||||
Lint/DuplicateMethods:
|
||||
Exclude:
|
||||
- 'app/services/products_renderer.rb'
|
||||
- 'lib/discourse/single_sign_on.rb'
|
||||
|
||||
# Offense count: 16
|
||||
# Configuration parameters: AllowComments, AllowEmptyLambdas.
|
||||
@@ -28,10 +27,11 @@ Lint/EmptyBlock:
|
||||
- 'spec/jobs/subscription_placement_job_spec.rb'
|
||||
- 'spec/models/product_import/entry_validator_spec.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# Offense count: 6
|
||||
# Configuration parameters: AllowComments.
|
||||
Lint/EmptyClass:
|
||||
Exclude:
|
||||
- 'spec/controllers/spree/admin/base_controller_spec.rb'
|
||||
- 'spec/lib/reports/report_loader_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
@@ -85,7 +85,7 @@ Lint/UselessMethodDefinition:
|
||||
Exclude:
|
||||
- 'app/models/spree/gateway.rb'
|
||||
|
||||
# Offense count: 24
|
||||
# Offense count: 26
|
||||
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
||||
Metrics/AbcSize:
|
||||
Exclude:
|
||||
@@ -104,9 +104,11 @@ Metrics/AbcSize:
|
||||
- 'app/models/spree/order/checkout.rb'
|
||||
- 'app/models/spree/preferences/preferable_class_methods.rb'
|
||||
- 'app/models/spree/return_authorization.rb'
|
||||
- 'lib/discourse/single_sign_on.rb'
|
||||
- 'lib/open_food_network/order_cycle_form_applicator.rb'
|
||||
- 'lib/open_food_network/order_cycle_permissions.rb'
|
||||
- 'lib/spree/core/controller_helpers/order.rb'
|
||||
- 'lib/tasks/enterprises.rake'
|
||||
- 'spec/services/orders/checkout_restart_service_spec.rb'
|
||||
|
||||
# Offense count: 9
|
||||
@@ -163,6 +165,7 @@ Metrics/ClassLength:
|
||||
- 'app/models/spree/variant.rb'
|
||||
- 'app/models/spree/zone.rb'
|
||||
- 'app/reflexes/admin/orders_reflex.rb'
|
||||
- 'app/reflexes/products_reflex.rb'
|
||||
- 'app/serializers/api/cached_enterprise_serializer.rb'
|
||||
- 'app/serializers/api/enterprise_shopfront_serializer.rb'
|
||||
- 'app/services/cart_service.rb'
|
||||
@@ -178,7 +181,7 @@ Metrics/ClassLength:
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/scope.rb'
|
||||
- 'lib/reporting/reports/xero_invoices/base.rb'
|
||||
|
||||
# Offense count: 32
|
||||
# Offense count: 34
|
||||
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
||||
Metrics/CyclomaticComplexity:
|
||||
Exclude:
|
||||
@@ -188,6 +191,7 @@ Metrics/CyclomaticComplexity:
|
||||
- 'app/helpers/checkout_helper.rb'
|
||||
- 'app/helpers/order_cycles_helper.rb'
|
||||
- 'app/helpers/spree/admin/navigation_helper.rb'
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/enterprise_relationship.rb'
|
||||
- 'app/models/product_import/entry_validator.rb'
|
||||
- 'app/models/spree/ability.rb'
|
||||
@@ -201,6 +205,7 @@ Metrics/CyclomaticComplexity:
|
||||
- 'app/models/spree/tax_rate.rb'
|
||||
- 'app/models/spree/variant.rb'
|
||||
- 'app/models/spree/zone.rb'
|
||||
- 'lib/discourse/single_sign_on.rb'
|
||||
- 'lib/open_food_network/enterprise_issue_validator.rb'
|
||||
- 'lib/reporting/reports/xero_invoices/base.rb'
|
||||
- 'lib/spree/core/controller_helpers/order.rb'
|
||||
@@ -208,7 +213,7 @@ Metrics/CyclomaticComplexity:
|
||||
- 'lib/spree/localized_number.rb'
|
||||
- 'spec/models/product_importer_spec.rb'
|
||||
|
||||
# Offense count: 24
|
||||
# Offense count: 25
|
||||
# Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns.
|
||||
Metrics/MethodLength:
|
||||
Exclude:
|
||||
@@ -222,6 +227,7 @@ Metrics/MethodLength:
|
||||
- 'app/models/spree/order/checkout.rb'
|
||||
- 'app/models/spree/payment/processing.rb'
|
||||
- 'app/models/spree/preferences/preferable_class_methods.rb'
|
||||
- 'lib/discourse/single_sign_on.rb'
|
||||
- 'lib/open_food_network/order_cycle_form_applicator.rb'
|
||||
- 'lib/open_food_network/order_cycle_permissions.rb'
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/scope.rb'
|
||||
@@ -229,7 +235,7 @@ Metrics/MethodLength:
|
||||
- 'lib/spree/localized_number.rb'
|
||||
- 'lib/tasks/sample_data/product_factory.rb'
|
||||
|
||||
# Offense count: 49
|
||||
# Offense count: 48
|
||||
# Configuration parameters: CountComments, Max, CountAsOne.
|
||||
Metrics/ModuleLength:
|
||||
Exclude:
|
||||
@@ -259,7 +265,6 @@ Metrics/ModuleLength:
|
||||
- 'spec/controllers/payment_gateways/stripe_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/adjustments_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/payment_methods_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/variants_controller_spec.rb'
|
||||
- 'spec/lib/open_food_network/address_finder_spec.rb'
|
||||
- 'spec/lib/open_food_network/enterprise_fee_calculator_spec.rb'
|
||||
- 'spec/lib/open_food_network/order_cycle_form_applicator_spec.rb'
|
||||
@@ -392,7 +397,9 @@ RSpecRails/HaveHttpStatus:
|
||||
- 'spec/controllers/stripe/webhooks_controller_spec.rb'
|
||||
- 'spec/controllers/user_passwords_controller_spec.rb'
|
||||
- 'spec/controllers/user_registrations_controller_spec.rb'
|
||||
- 'spec/requests/admin/images_spec.rb'
|
||||
- 'spec/requests/api/routes_spec.rb'
|
||||
- 'spec/requests/checkout/failed_checkout_spec.rb'
|
||||
- 'spec/requests/checkout/stripe_sca_spec.rb'
|
||||
- 'spec/requests/home_controller_spec.rb'
|
||||
- 'spec/requests/omniauth_callbacks_controller_spec.rb'
|
||||
@@ -408,7 +415,7 @@ RSpecRails/HttpStatus:
|
||||
- 'spec/controllers/spree/admin/products_controller_spec.rb'
|
||||
- 'spec/requests/api/orders_spec.rb'
|
||||
|
||||
# Offense count: 144
|
||||
# Offense count: 146
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: Inferences.
|
||||
RSpecRails/InferredSpecType:
|
||||
@@ -512,6 +519,7 @@ RSpecRails/InferredSpecType:
|
||||
- 'spec/helpers/navigation_helper_spec.rb'
|
||||
- 'spec/helpers/order_cycles_helper_spec.rb'
|
||||
- 'spec/helpers/serializer_helper_spec.rb'
|
||||
- 'spec/helpers/shared_helper_spec.rb'
|
||||
- 'spec/helpers/shop_helper_spec.rb'
|
||||
- 'spec/helpers/spree/admin/base_helper_spec.rb'
|
||||
- 'spec/helpers/spree/admin/general_settings_helper_spec.rb'
|
||||
@@ -545,6 +553,7 @@ RSpecRails/InferredSpecType:
|
||||
- 'spec/requests/api/routes_spec.rb'
|
||||
- 'spec/requests/api/v1/customers_spec.rb'
|
||||
- 'spec/requests/api_docs_spec.rb'
|
||||
- 'spec/requests/checkout/failed_checkout_spec.rb'
|
||||
- 'spec/requests/checkout/paypal_spec.rb'
|
||||
- 'spec/requests/checkout/routes_spec.rb'
|
||||
- 'spec/requests/checkout/stripe_sca_spec.rb'
|
||||
@@ -601,6 +610,63 @@ Rails/LexicallyScopedActionFilter:
|
||||
- 'app/controllers/spree/admin/zones_controller.rb'
|
||||
- 'app/controllers/spree/users_controller.rb'
|
||||
|
||||
# Offense count: 32
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Rails/Pluck:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/variant_overrides_controller.rb'
|
||||
- 'app/services/cart_service.rb'
|
||||
- 'lib/reporting/report_headers_builder.rb'
|
||||
- 'spec/controllers/admin/bulk_line_items_controller_spec.rb'
|
||||
- 'spec/controllers/admin/subscriptions_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/order_cycles_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/orders_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/products_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/shops_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/states_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/taxons_controller_spec.rb'
|
||||
- 'spec/helpers/spree/admin/orders_helper_spec.rb'
|
||||
- 'spec/lib/reports/lettuce_share_report_spec.rb'
|
||||
- 'spec/lib/reports/users_and_enterprises_report_spec.rb'
|
||||
- 'spec/serializers/api/admin/for_order_cycle/supplied_product_serializer_spec.rb'
|
||||
- 'spec/support/api_helper.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: conservative, aggressive
|
||||
Rails/PluckInWhere:
|
||||
Exclude:
|
||||
- 'app/models/spree/variant.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: AllowedReceivers.
|
||||
# AllowedReceivers: ActionMailer::Preview, ActiveSupport::TimeZone
|
||||
Rails/RedundantActiveRecordAllMethod:
|
||||
Exclude:
|
||||
- 'app/models/spree/tax_rate.rb'
|
||||
- 'app/models/spree/user.rb'
|
||||
- 'app/models/spree/variant.rb'
|
||||
- 'spec/system/admin/product_import_spec.rb'
|
||||
|
||||
# Offense count: 9
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Rails/RedundantPresenceValidationOnBelongsTo:
|
||||
Exclude:
|
||||
- 'app/models/spree/line_item.rb'
|
||||
- 'app/models/spree/order.rb'
|
||||
- 'app/models/spree/tax_rate.rb'
|
||||
- 'app/models/subscription_line_item.rb'
|
||||
- 'app/models/tag_rule.rb'
|
||||
- 'app/models/variant_override.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Rails/RelativeDateConstant:
|
||||
Exclude:
|
||||
- 'lib/tasks/data/remove_transient_data.rb'
|
||||
|
||||
# Offense count: 56
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: Include.
|
||||
@@ -621,6 +687,26 @@ Rails/ResponseParsedBody:
|
||||
- 'spec/controllers/spree/credit_cards_controller_spec.rb'
|
||||
- 'spec/controllers/user_registrations_controller_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Rails/RootPathnameMethods:
|
||||
Exclude:
|
||||
- 'spec/lib/reports/orders_and_fulfillment/order_cycle_customer_totals_report_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Rails/SelectMap:
|
||||
Exclude:
|
||||
- 'app/models/enterprise.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# Configuration parameters: ForbiddenMethods, AllowedMethods.
|
||||
# ForbiddenMethods: decrement!, decrement_counter, increment!, increment_counter, insert, insert!, insert_all, insert_all!, toggle!, touch, touch_all, update_all, update_attribute, update_column, update_columns, update_counters, upsert, upsert_all
|
||||
Rails/SkipsModelValidations:
|
||||
Exclude:
|
||||
- 'app/models/variant_override.rb'
|
||||
- 'spec/models/spree/line_item_spec.rb'
|
||||
|
||||
# Offense count: 7
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
@@ -649,6 +735,24 @@ Rails/UniqueValidationWithoutIndex:
|
||||
- 'app/models/spree/tax_category.rb'
|
||||
- 'app/models/spree/zone.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: Severity, Environments.
|
||||
# Environments: development, test, production
|
||||
Rails/UnknownEnv:
|
||||
Exclude:
|
||||
- 'app/models/spree/app_configuration.rb'
|
||||
|
||||
# Offense count: 7
|
||||
# Configuration parameters: Severity.
|
||||
Rails/UnusedRenderContent:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/bulk_line_items_controller.rb'
|
||||
- 'app/controllers/admin/tag_rules_controller.rb'
|
||||
- 'app/controllers/api/v0/enterprise_fees_controller.rb'
|
||||
- 'app/controllers/api/v0/products_controller.rb'
|
||||
- 'app/controllers/api/v0/taxons_controller.rb'
|
||||
- 'app/controllers/api/v0/variants_controller.rb'
|
||||
|
||||
# Offense count: 1
|
||||
Security/Open:
|
||||
Exclude:
|
||||
@@ -673,7 +777,7 @@ Style/CaseEquality:
|
||||
Exclude:
|
||||
- 'spec/models/spree/payment_spec.rb'
|
||||
|
||||
# Offense count: 23
|
||||
# Offense count: 25
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: nested, compact
|
||||
@@ -700,6 +804,7 @@ Style/ClassAndModuleChildren:
|
||||
- 'app/serializers/api/taxon_serializer.rb'
|
||||
- 'app/serializers/api/variant_serializer.rb'
|
||||
- 'lib/open_food_network/locking.rb'
|
||||
- 'spec/controllers/spree/admin/base_controller_spec.rb'
|
||||
- 'spec/models/spree/payment_method_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
@@ -752,6 +857,12 @@ Style/HashEachMethods:
|
||||
- 'spec/models/product_importer_spec.rb'
|
||||
- 'spec/support/cancan_helper.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: MinBranchesCount.
|
||||
Style/HashLikeCase:
|
||||
Exclude:
|
||||
- 'app/models/enterprise.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Style/MapToHash:
|
||||
@@ -840,6 +951,19 @@ Style/RedundantInitialize:
|
||||
Exclude:
|
||||
- 'spec/models/spree/gateway_spec.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Style/RedundantInterpolation:
|
||||
Exclude:
|
||||
- 'lib/tasks/karma.rake'
|
||||
- 'spec/base_spec_helper.rb'
|
||||
|
||||
# Offense count: 8
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Style/RedundantLineContinuation:
|
||||
Exclude:
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/scope.rb'
|
||||
|
||||
# Offense count: 19
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
||||
@@ -849,10 +973,69 @@ Style/ReturnNilInPredicateMethodDefinition:
|
||||
- 'app/serializers/api/admin/customer_serializer.rb'
|
||||
- 'engines/order_management/app/services/order_management/subscriptions/validator.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Offense count: 204
|
||||
Style/Send:
|
||||
Exclude:
|
||||
- 'spec/controllers/admin/subscriptions_controller_spec.rb'
|
||||
- 'spec/controllers/payment_gateways/paypal_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/base_controller_spec.rb'
|
||||
- 'spec/controllers/spree/orders_controller_spec.rb'
|
||||
- 'spec/helpers/order_cycles_helper_spec.rb'
|
||||
- 'spec/jobs/subscription_confirm_job_spec.rb'
|
||||
- 'spec/jobs/subscription_placement_job_spec.rb'
|
||||
- 'spec/lib/open_food_network/address_finder_spec.rb'
|
||||
- 'spec/lib/open_food_network/enterprise_fee_applicator_spec.rb'
|
||||
- 'spec/lib/open_food_network/enterprise_fee_calculator_spec.rb'
|
||||
- 'spec/lib/open_food_network/order_cycle_form_applicator_spec.rb'
|
||||
- 'spec/lib/open_food_network/permissions_spec.rb'
|
||||
- 'spec/lib/open_food_network/tag_rule_applicator_spec.rb'
|
||||
- 'spec/lib/reports/xero_invoices_report_spec.rb'
|
||||
- 'spec/lib/stripe/webhook_handler_spec.rb'
|
||||
- 'spec/models/calculator/weight_spec.rb'
|
||||
- 'spec/models/enterprise_spec.rb'
|
||||
- 'spec/models/exchange_spec.rb'
|
||||
- 'spec/models/spree/order_inventory_spec.rb'
|
||||
- 'spec/models/spree/payment_spec.rb'
|
||||
- 'spec/models/spree/return_authorization_spec.rb'
|
||||
- 'spec/models/tag_rule/filter_order_cycles_spec.rb'
|
||||
- 'spec/models/tag_rule/filter_payment_methods_spec.rb'
|
||||
- 'spec/models/tag_rule/filter_products_spec.rb'
|
||||
- 'spec/models/tag_rule/filter_shipping_methods_spec.rb'
|
||||
- 'spec/services/cart_service_spec.rb'
|
||||
- 'spec/services/products_renderer_spec.rb'
|
||||
- 'spec/services/variant_units/option_value_namer_spec.rb'
|
||||
- 'spec/support/localized_number_helper.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Style/SlicingWithRange:
|
||||
Exclude:
|
||||
- 'app/helpers/spree/admin/navigation_helper.rb'
|
||||
- 'app/services/embedded_page_service.rb'
|
||||
- 'engines/order_management/app/services/order_management/subscriptions/validator.rb'
|
||||
- 'lib/discourse/single_sign_on.rb'
|
||||
|
||||
# Offense count: 25
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: Mode.
|
||||
Style/StringConcatenation:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/stripe_connect_settings_controller.rb'
|
||||
- 'app/helpers/discourse_helper.rb'
|
||||
- 'app/helpers/enterprises_helper.rb'
|
||||
- 'app/helpers/spree/admin/base_helper.rb'
|
||||
- 'app/mailers/spree/user_mailer.rb'
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/spree/credit_card.rb'
|
||||
- 'app/models/spree/payment_method.rb'
|
||||
- 'app/serializers/api/cached_enterprise_serializer.rb'
|
||||
- 'app/serializers/api/enterprise_shopfront_list_serializer.rb'
|
||||
- 'app/services/embedded_page_service.rb'
|
||||
- 'app/services/products_renderer.rb'
|
||||
- 'lib/spree/api/controller_setup.rb'
|
||||
- 'lib/spree/core/environment_extension.rb'
|
||||
- 'spec/models/spree/line_item_spec.rb'
|
||||
- 'spec/models/spree/product_spec.rb'
|
||||
- 'spec/services/embedded_page_service_spec.rb'
|
||||
- 'spec/support/features/datepicker_helper.rb'
|
||||
- 'spec/system/admin/products_spec.rb'
|
||||
|
||||
@@ -14,6 +14,4 @@ SimpleCov.start 'rails' do
|
||||
add_filter '/log'
|
||||
add_filter '/db'
|
||||
add_filter '/lib/tasks/sample_data/'
|
||||
|
||||
formatter SimpleCov::Formatter::SimpleFormatter
|
||||
end
|
||||
|
||||
@@ -31,7 +31,7 @@ This project needs specific ruby/bundler versions as well as node/yarn specific
|
||||
* Install or change your Ruby version according to the one specified at [.ruby-version](https://github.com/openfoodfoundation/openfoodnetwork/blob/master/.ruby-version) file.
|
||||
- To manage versions, it's recommended to use [rbenv](https://github.com/rbenv/rbenv) or [RVM](https://rvm.io/).
|
||||
* Install [nodenv](https://github.com/nodenv/nodenv) to ensure the correct [.node-version](https://github.com/openfoodfoundation/openfoodnetwork/blob/master/.node-version) is used.
|
||||
- [nodenv](https://github.com/nodenv/nodenv) is recommended as a node version manager.
|
||||
- [nodevn](https://github.com/nodenv/nodenv) is recommended as a node version manager.
|
||||
* PostgreSQL database
|
||||
* Redis (for background jobs)
|
||||
* Chrome (for testing)
|
||||
|
||||
11
Gemfile
11
Gemfile
@@ -16,8 +16,10 @@ gem "image_processing"
|
||||
|
||||
gem 'activemerchant', '>= 1.78.0'
|
||||
gem 'angular-rails-templates', '>= 0.3.0'
|
||||
gem 'awesome_nested_set'
|
||||
gem 'ransack', '~> 4.1.0'
|
||||
gem 'responders'
|
||||
gem 'rexml'
|
||||
gem 'webpacker', '~> 5'
|
||||
|
||||
gem 'i18n'
|
||||
@@ -101,11 +103,8 @@ gem 'redis'
|
||||
gem 'sidekiq'
|
||||
gem 'sidekiq-scheduler'
|
||||
|
||||
gem "cable_ready"
|
||||
gem "stimulus_reflex"
|
||||
|
||||
gem "turbo_power"
|
||||
gem "turbo-rails"
|
||||
gem "cable_ready", "5.0.1"
|
||||
gem "stimulus_reflex", "3.5.0.rc3"
|
||||
|
||||
gem 'combine_pdf'
|
||||
gem 'wicked_pdf'
|
||||
@@ -165,7 +164,7 @@ group :test, :development do
|
||||
gem 'rspec-sql'
|
||||
gem 'rswag'
|
||||
gem 'shoulda-matchers'
|
||||
gem 'stimulus_reflex_testing', github: "podia/stimulus_reflex_testing", branch: :main
|
||||
gem 'stimulus_reflex_testing'
|
||||
gem 'timecop'
|
||||
end
|
||||
|
||||
|
||||
86
Gemfile.lock
86
Gemfile.lock
@@ -17,14 +17,6 @@ GIT
|
||||
sass-rails
|
||||
thor (>= 0.14)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/podia/stimulus_reflex_testing.git
|
||||
revision: abac2ee34de347c589795b4d1a8e83e0baafb201
|
||||
branch: main
|
||||
specs:
|
||||
stimulus_reflex_testing (0.3.1)
|
||||
stimulus_reflex (>= 3.3.0)
|
||||
|
||||
PATH
|
||||
remote: engines/catalog
|
||||
specs:
|
||||
@@ -161,18 +153,20 @@ GEM
|
||||
activerecord (>= 3.1.0, < 8)
|
||||
ast (2.4.2)
|
||||
attr_required (1.0.2)
|
||||
awesome_nested_set (3.6.0)
|
||||
activerecord (>= 4.0.0, < 7.2)
|
||||
aws-eventstream (1.3.0)
|
||||
aws-partitions (1.929.0)
|
||||
aws-sdk-core (3.196.1)
|
||||
aws-partitions (1.914.0)
|
||||
aws-sdk-core (3.192.0)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.651.0)
|
||||
aws-sigv4 (~> 1.8)
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
aws-sdk-kms (1.81.0)
|
||||
aws-sdk-core (~> 3, >= 3.193.0)
|
||||
aws-sdk-kms (1.79.0)
|
||||
aws-sdk-core (~> 3, >= 3.191.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-s3 (1.151.0)
|
||||
aws-sdk-core (~> 3, >= 3.194.0)
|
||||
aws-sdk-s3 (1.147.0)
|
||||
aws-sdk-core (~> 3, >= 3.192.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.8)
|
||||
aws-sigv4 (1.8.0)
|
||||
@@ -191,11 +185,10 @@ GEM
|
||||
bullet (7.1.6)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.11)
|
||||
cable_ready (5.0.5)
|
||||
cable_ready (5.0.1)
|
||||
actionpack (>= 5.2)
|
||||
actionview (>= 5.2)
|
||||
activesupport (>= 5.2)
|
||||
observer (~> 0.1)
|
||||
railties (>= 5.2)
|
||||
thread-local (>= 1.1.0)
|
||||
cancancan (1.15.0)
|
||||
@@ -228,7 +221,7 @@ GEM
|
||||
combine_pdf (1.0.26)
|
||||
matrix
|
||||
ruby-rc4 (>= 0.1.5)
|
||||
concurrent-ruby (1.3.1)
|
||||
concurrent-ruby (1.2.3)
|
||||
connection_pool (2.4.1)
|
||||
crack (1.0.0)
|
||||
bigdecimal
|
||||
@@ -246,7 +239,7 @@ GEM
|
||||
activerecord (>= 5.a)
|
||||
database_cleaner-core (~> 2.0.0)
|
||||
database_cleaner-core (2.0.1)
|
||||
datafoodconsortium-connector (1.0.0.pre.alpha.13)
|
||||
datafoodconsortium-connector (1.0.0.pre.alpha.12)
|
||||
virtual_assembly-semantizer (~> 1.0, >= 1.0.5)
|
||||
date (3.3.4)
|
||||
debug (1.9.2)
|
||||
@@ -261,7 +254,7 @@ GEM
|
||||
warden (~> 1.2.3)
|
||||
devise-encryptable (0.2.0)
|
||||
devise (>= 2.1.0)
|
||||
devise-i18n (1.12.1)
|
||||
devise-i18n (1.12.0)
|
||||
devise (>= 4.9.0)
|
||||
devise-token_authenticatable (1.1.0)
|
||||
devise (>= 4.0.0, < 5.0.0)
|
||||
@@ -356,7 +349,7 @@ GEM
|
||||
ruby-vips (>= 2.0.17, < 3)
|
||||
immigrant (0.3.6)
|
||||
activerecord (>= 3.0)
|
||||
invisible_captcha (2.3.0)
|
||||
invisible_captcha (2.2.0)
|
||||
rails (>= 5.2)
|
||||
io-console (0.7.2)
|
||||
ipaddress (0.8.3)
|
||||
@@ -379,14 +372,13 @@ GEM
|
||||
bindata
|
||||
faraday (~> 2.0)
|
||||
faraday-follow_redirects
|
||||
json-ld (3.3.2)
|
||||
json-ld (3.3.1)
|
||||
htmlentities (~> 4.3)
|
||||
json-canonicalization (~> 1.0)
|
||||
link_header (~> 0.0, >= 0.0.8)
|
||||
multi_json (~> 1.15)
|
||||
rack (>= 2.2, < 4)
|
||||
rdf (~> 3.3)
|
||||
rexml (~> 3.2)
|
||||
json-schema (4.1.1)
|
||||
addressable (>= 2.8)
|
||||
json_spec (1.1.5)
|
||||
@@ -396,7 +388,7 @@ GEM
|
||||
activesupport (>= 4.2)
|
||||
jwt (2.8.1)
|
||||
base64
|
||||
knapsack_pro (7.4.0)
|
||||
knapsack_pro (7.2.0)
|
||||
rake
|
||||
language_server-protocol (3.17.0.3)
|
||||
launchy (3.0.0)
|
||||
@@ -416,7 +408,7 @@ GEM
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
marcel (1.0.4)
|
||||
marcel (1.0.2)
|
||||
matrix (0.4.2)
|
||||
method_source (1.1.0)
|
||||
mime-types (3.5.2)
|
||||
@@ -428,7 +420,7 @@ GEM
|
||||
mini_magick (4.11.0)
|
||||
mini_mime (1.1.5)
|
||||
mini_portile2 (2.8.6)
|
||||
minitest (5.23.1)
|
||||
minitest (5.22.3)
|
||||
monetize (1.13.0)
|
||||
money (~> 6.12)
|
||||
money (6.16.0)
|
||||
@@ -448,19 +440,16 @@ GEM
|
||||
net-smtp (0.5.0)
|
||||
net-protocol
|
||||
newrelic_rpm (9.9.0)
|
||||
nio4r (2.7.1)
|
||||
nio4r (2.7.0)
|
||||
nokogiri (1.16.5)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
nokogiri-html5-inference (0.3.0)
|
||||
nokogiri (~> 1.14)
|
||||
oauth2 (1.4.11)
|
||||
faraday (>= 0.17.3, < 3.0)
|
||||
jwt (>= 1.0, < 3.0)
|
||||
multi_json (~> 1.3)
|
||||
multi_xml (~> 0.5)
|
||||
rack (>= 1.2, < 4)
|
||||
observer (0.1.2)
|
||||
omniauth (2.1.2)
|
||||
hashie (>= 3.4.6)
|
||||
rack (>= 2.2.3)
|
||||
@@ -493,7 +482,7 @@ GEM
|
||||
parallel (1.24.0)
|
||||
paranoia (2.6.3)
|
||||
activerecord (>= 5.1, < 7.2)
|
||||
parser (3.3.2.0)
|
||||
parser (3.3.1.0)
|
||||
ast (~> 2.4.1)
|
||||
racc
|
||||
paypal-sdk-core (0.3.4)
|
||||
@@ -521,7 +510,7 @@ GEM
|
||||
activerecord (>= 4.2)
|
||||
railties (>= 4.2)
|
||||
raabro (1.4.0)
|
||||
racc (1.8.0)
|
||||
racc (1.7.3)
|
||||
rack (2.2.9)
|
||||
rack-mini-profiler (2.3.4)
|
||||
rack (>= 1.2.0)
|
||||
@@ -542,7 +531,7 @@ GEM
|
||||
rack (< 3)
|
||||
rack-test (2.1.0)
|
||||
rack (>= 1.3)
|
||||
rack-timeout (0.7.0)
|
||||
rack-timeout (0.6.3)
|
||||
rails (7.0.8)
|
||||
actioncable (= 7.0.8)
|
||||
actionmailbox (= 7.0.8)
|
||||
@@ -603,7 +592,7 @@ GEM
|
||||
redis-client (>= 0.22.0)
|
||||
redis-client (0.22.1)
|
||||
connection_pool
|
||||
regexp_parser (2.9.2)
|
||||
regexp_parser (2.9.0)
|
||||
reline (0.5.0)
|
||||
io-console (~> 0.5)
|
||||
request_store (1.5.1)
|
||||
@@ -666,7 +655,7 @@ GEM
|
||||
rswag-ui (2.13.0)
|
||||
actionpack (>= 3.1, < 7.2)
|
||||
railties (>= 3.1, < 7.2)
|
||||
rubocop (1.64.1)
|
||||
rubocop (1.63.5)
|
||||
json (~> 2.3)
|
||||
language_server-protocol (>= 3.17.0)
|
||||
parallel (~> 1.10)
|
||||
@@ -755,17 +744,18 @@ GEM
|
||||
state_machines-activerecord (0.9.0)
|
||||
activerecord (>= 6.0)
|
||||
state_machines-activemodel (>= 0.9.0)
|
||||
stimulus_reflex (3.5.1)
|
||||
stimulus_reflex (3.5.0.rc3)
|
||||
actioncable (>= 5.2, < 8)
|
||||
actionpack (>= 5.2, < 8)
|
||||
actionview (>= 5.2, < 8)
|
||||
activesupport (>= 5.2, < 8)
|
||||
cable_ready (~> 5.0)
|
||||
nokogiri (~> 1.0)
|
||||
nokogiri-html5-inference (~> 0.3)
|
||||
rack (>= 2, < 4)
|
||||
railties (>= 5.2, < 8)
|
||||
redis (>= 4.0, < 6.0)
|
||||
stimulus_reflex_testing (0.3.0)
|
||||
stimulus_reflex (>= 3.3.0)
|
||||
stringex (2.8.6)
|
||||
stringio (3.1.0)
|
||||
stripe (11.1.0)
|
||||
@@ -782,12 +772,6 @@ GEM
|
||||
timecop (0.9.8)
|
||||
timeout (0.4.1)
|
||||
ttfunk (1.7.0)
|
||||
turbo-rails (2.0.5)
|
||||
actionpack (>= 6.0.0)
|
||||
activejob (>= 6.0.0)
|
||||
railties (>= 6.0.0)
|
||||
turbo_power (0.6.2)
|
||||
turbo-rails (>= 1.3.0)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
unicode-display_width (2.5.0)
|
||||
@@ -802,7 +786,7 @@ GEM
|
||||
validates_lengths_from_database (0.8.0)
|
||||
activerecord (>= 4)
|
||||
vcr (6.2.0)
|
||||
view_component (3.12.1)
|
||||
view_component (3.12.0)
|
||||
activesupport (>= 5.2.0, < 8.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
method_source (~> 1.0)
|
||||
@@ -823,7 +807,7 @@ GEM
|
||||
activesupport
|
||||
faraday (~> 2.0)
|
||||
faraday-follow_redirects
|
||||
webmock (3.23.1)
|
||||
webmock (3.23.0)
|
||||
addressable (>= 2.8.0)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff (>= 0.4.0, < 2.0.0)
|
||||
@@ -838,13 +822,13 @@ GEM
|
||||
websocket-extensions (0.1.5)
|
||||
whenever (1.0.0)
|
||||
chronic (>= 0.6.3)
|
||||
wicked_pdf (2.8.1)
|
||||
wicked_pdf (2.6.3)
|
||||
activesupport
|
||||
wkhtmltopdf-binary (0.12.6.7)
|
||||
xml-simple (1.1.8)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
zeitwerk (2.6.15)
|
||||
zeitwerk (2.6.14)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
@@ -864,12 +848,13 @@ DEPENDENCIES
|
||||
angularjs-file-upload-rails (~> 2.4.1)
|
||||
angularjs-rails (= 1.8.0)
|
||||
arel-helpers (~> 2.12)
|
||||
awesome_nested_set
|
||||
aws-sdk-s3
|
||||
bigdecimal (= 3.0.2)
|
||||
bootsnap
|
||||
bugsnag
|
||||
bullet
|
||||
cable_ready
|
||||
cable_ready (= 5.0.1)
|
||||
cancancan (~> 1.15.0)
|
||||
capybara
|
||||
catalog!
|
||||
@@ -948,6 +933,7 @@ DEPENDENCIES
|
||||
redcarpet
|
||||
redis
|
||||
responders
|
||||
rexml
|
||||
roadie-rails
|
||||
roo
|
||||
rspec-rails (>= 3.5.2)
|
||||
@@ -970,13 +956,11 @@ DEPENDENCIES
|
||||
spring-commands-rspec
|
||||
spring-commands-rubocop
|
||||
state_machines-activerecord
|
||||
stimulus_reflex
|
||||
stimulus_reflex_testing!
|
||||
stimulus_reflex (= 3.5.0.rc3)
|
||||
stimulus_reflex_testing
|
||||
stringex (~> 2.8.5)
|
||||
stripe
|
||||
timecop
|
||||
turbo-rails
|
||||
turbo_power
|
||||
valid_email2
|
||||
validates_lengths_from_database
|
||||
vcr
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
//= require jquery.ui.all
|
||||
//= require jquery.powertip
|
||||
//= require jquery.cookie
|
||||
//= require jquery.jstree/jquery.jstree
|
||||
//= require jquery.vAlign
|
||||
//= require angular
|
||||
//= require angular-resource
|
||||
//= require angular-animate
|
||||
//= require angular-sanitize
|
||||
//= require angularjs-file-upload
|
||||
//= require ../shared/ng-infinite-scroll.min.js
|
||||
//= require ../shared/ng-tags-input.min.js
|
||||
@@ -61,6 +61,11 @@
|
||||
//= require ./variant_overrides/variant_overrides
|
||||
|
||||
// text, dates and translations
|
||||
//= require textAngular-rangy.min.js
|
||||
// This replaces angular-sanitize. We should include only one.
|
||||
// https://github.com/textAngular/textAngular#where-to-get-it
|
||||
//= require textAngular-sanitize.min.js
|
||||
//= require textAngular.min.js
|
||||
//= require i18n/translations
|
||||
//= require darkswarm/i18n.translate.js
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
removeClearedValues()
|
||||
params = {
|
||||
'q[name_cont]': $scope.q.query,
|
||||
'q[variants_supplier_id_eq]': $scope.q.producerFilter,
|
||||
'q[supplier_id_eq]': $scope.q.producerFilter,
|
||||
'q[variants_primary_taxon_id_eq]': $scope.q.categoryFilter,
|
||||
'q[s]': $scope.sorting,
|
||||
import_date: $scope.q.importDateFilter,
|
||||
@@ -126,11 +126,8 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
DisplayProperties.setShowVariants 0, showVariants
|
||||
|
||||
$scope.addVariant = (product) ->
|
||||
# Set new variant category to same as last product variant category to keep compactibility with deleted variant callback to set new variant category
|
||||
newVariantId = $scope.nextVariantId();
|
||||
newVariantCategoryId = product.variants[product.variants.length - 1]?.category_id
|
||||
product.variants.push
|
||||
id: newVariantId
|
||||
id: $scope.nextVariantId()
|
||||
unit_value: null
|
||||
unit_description: null
|
||||
on_demand: false
|
||||
@@ -139,9 +136,8 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
on_hand: null
|
||||
price: null
|
||||
tax_category_id: null
|
||||
category_id: newVariantCategoryId
|
||||
category_id: null
|
||||
DisplayProperties.setShowVariants product.id, true
|
||||
DirtyProducts.addVariantProperty(product.id, newVariantId, 'category_id', newVariantCategoryId)
|
||||
|
||||
|
||||
$scope.nextVariantId = ->
|
||||
@@ -187,8 +183,9 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
product.variants.length > 0
|
||||
|
||||
|
||||
$scope.hasUnit = (variant) ->
|
||||
variant.variant_unit_with_scale?
|
||||
$scope.hasUnit = (product) ->
|
||||
product.variant_unit_with_scale?
|
||||
|
||||
|
||||
$scope.variantSaved = (variant) ->
|
||||
variant.hasOwnProperty('id') && variant.id > 0
|
||||
@@ -220,7 +217,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
products: productsToSubmit
|
||||
filters:
|
||||
'q[name_cont]': $scope.q.query
|
||||
'q[variants_supplier_id_eq]': $scope.q.producerFilter
|
||||
'q[supplier_id_eq]': $scope.q.producerFilter
|
||||
'q[variants_primary_taxon_id_eq]': $scope.q.categoryFilter
|
||||
'q[s]': $scope.sorting
|
||||
import_date: $scope.q.importDateFilter
|
||||
@@ -241,28 +238,32 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
$window.location = destination
|
||||
|
||||
$scope.packProduct = (product) ->
|
||||
if product.variant_unit_with_scale
|
||||
match = product.variant_unit_with_scale.match(/^([^_]+)_([\d\.]+)$/)
|
||||
if match
|
||||
product.variant_unit = match[1]
|
||||
product.variant_unit_scale = parseFloat(match[2])
|
||||
else
|
||||
product.variant_unit = product.variant_unit_with_scale
|
||||
product.variant_unit_scale = null
|
||||
else
|
||||
product.variant_unit = product.variant_unit_scale = null
|
||||
|
||||
|
||||
if product.variants
|
||||
for id, variant of product.variants
|
||||
$scope.packVariant variant
|
||||
$scope.packVariant product, variant
|
||||
|
||||
|
||||
$scope.packVariant = (variant) ->
|
||||
if variant.variant_unit_with_scale
|
||||
match = variant.variant_unit_with_scale.match(/^([^_]+)_([\d\.]+)$/)
|
||||
if match
|
||||
variant.variant_unit = match[1]
|
||||
variant.variant_unit_scale = parseFloat(match[2])
|
||||
else
|
||||
variant.variant_unit = variant.variant_unit_with_scale
|
||||
variant.variant_unit_scale = null
|
||||
|
||||
$scope.packVariant = (product, variant) ->
|
||||
if variant.hasOwnProperty("unit_value_with_description")
|
||||
match = variant.unit_value_with_description.match(/^([\d\.\,]+(?= |$)|)( |)(.*)$/)
|
||||
if match
|
||||
product = BulkProducts.find product.id
|
||||
variant.unit_value = parseFloat(match[1].replace(",", "."))
|
||||
variant.unit_value = null if isNaN(variant.unit_value)
|
||||
if variant.unit_value && variant.variant_unit_scale
|
||||
variant.unit_value = parseFloat(window.bigDecimal.multiply(variant.unit_value, variant.variant_unit_scale, 2))
|
||||
if variant.unit_value && product.variant_unit_scale
|
||||
variant.unit_value = parseFloat(window.bigDecimal.multiply(variant.unit_value, product.variant_unit_scale, 2))
|
||||
variant.unit_description = match[3]
|
||||
|
||||
$scope.incrementLimit = ->
|
||||
@@ -313,9 +314,19 @@ filterSubmitProducts = (productsToFilter) ->
|
||||
if product.hasOwnProperty("name")
|
||||
filteredProduct.name = product.name
|
||||
hasUpdatableProperty = true
|
||||
if product.hasOwnProperty("producer_id")
|
||||
filteredProduct.supplier_id = product.producer_id
|
||||
hasUpdatableProperty = true
|
||||
if product.hasOwnProperty("price")
|
||||
filteredProduct.price = product.price
|
||||
hasUpdatableProperty = true
|
||||
if product.hasOwnProperty("variant_unit_with_scale")
|
||||
filteredProduct.variant_unit = product.variant_unit
|
||||
filteredProduct.variant_unit_scale = product.variant_unit_scale
|
||||
hasUpdatableProperty = true
|
||||
if product.hasOwnProperty("variant_unit_name")
|
||||
filteredProduct.variant_unit_name = product.variant_unit_name
|
||||
hasUpdatableProperty = true
|
||||
if product.hasOwnProperty("on_hand") and filteredVariants.length == 0 #only update if no variants present
|
||||
filteredProduct.on_hand = product.on_hand
|
||||
hasUpdatableProperty = true
|
||||
@@ -368,17 +379,6 @@ filterSubmitVariant = (variant) ->
|
||||
if variant.hasOwnProperty("display_as")
|
||||
filteredVariant.display_as = variant.display_as
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("producer_id")
|
||||
filteredVariant.supplier_id = variant.producer_id
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("variant_unit_with_scale")
|
||||
filteredVariant.variant_unit = variant.variant_unit
|
||||
filteredVariant.variant_unit_scale = variant.variant_unit_scale
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("variant_unit_name")
|
||||
filteredVariant.variant_unit_name = variant.variant_unit_name
|
||||
hasUpdatableProperty = true
|
||||
|
||||
{filteredVariant: filteredVariant, hasUpdatableProperty: hasUpdatableProperty}
|
||||
|
||||
|
||||
|
||||
@@ -4,30 +4,31 @@ angular.module("ofn.admin").directive "ofnDisplayAs", (OptionValueNamer) ->
|
||||
scope.$watchCollection ->
|
||||
return [
|
||||
scope.$eval(attrs.ofnDisplayAs).unit_value_with_description
|
||||
scope.variant.variant_unit_name
|
||||
scope.variant.variant_unit_with_scale
|
||||
scope.product.variant_unit_name
|
||||
scope.product.variant_unit_with_scale
|
||||
]
|
||||
, ->
|
||||
[variant_unit, variant_unit_scale] = productUnitProperties()
|
||||
[unit_value, unit_description] = variantUnitProperties(variant_unit_scale)
|
||||
variant_object =
|
||||
variant_object =
|
||||
unit_value: unit_value
|
||||
unit_description: unit_description
|
||||
variant_unit_scale: variant_unit_scale
|
||||
variant_unit: variant_unit
|
||||
variant_unit_name: scope.variant.variant_unit_name
|
||||
product:
|
||||
variant_unit_scale: variant_unit_scale
|
||||
variant_unit: variant_unit
|
||||
variant_unit_name: scope.product.variant_unit_name
|
||||
|
||||
scope.placeholder_text = new OptionValueNamer(variant_object).name()
|
||||
|
||||
productUnitProperties = ->
|
||||
# get relevant product properties
|
||||
if scope.variant.variant_unit_with_scale?
|
||||
match = scope.variant.variant_unit_with_scale.match(/^([^_]+)_([\d\.]+)$/)
|
||||
if scope.product.variant_unit_with_scale?
|
||||
match = scope.product.variant_unit_with_scale.match(/^([^_]+)_([\d\.]+)$/)
|
||||
if match
|
||||
variant_unit = match[1]
|
||||
variant_unit_scale = parseFloat(match[2])
|
||||
else
|
||||
variant_unit = scope.variant.variant_unit_with_scale
|
||||
variant_unit = scope.product.variant_unit_with_scale
|
||||
variant_unit_scale = null
|
||||
else
|
||||
variant_unit = variant_unit_scale = null
|
||||
@@ -44,4 +45,4 @@ angular.module("ofn.admin").directive "ofnDisplayAs", (OptionValueNamer) ->
|
||||
unit_value = null if isNaN(unit_value)
|
||||
unit_value *= variant_unit_scale if unit_value && variant_unit_scale
|
||||
unit_description = match[3]
|
||||
[unit_value, unit_description]
|
||||
[unit_value, unit_description]
|
||||
@@ -0,0 +1,8 @@
|
||||
angular.module("ofn.admin").directive "ofnMaintainUnitScale", ->
|
||||
require: "ngModel"
|
||||
link: (scope, element, attrs, ngModel) ->
|
||||
scope.$watch 'product.variant_unit_with_scale', (newValue, oldValue) ->
|
||||
if not (oldValue == newValue)
|
||||
# Triggers track-variant directive to track the unit_value, so that changes to the unit are passed to the server
|
||||
ngModel.$setViewValue ngModel.$viewValue
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
angular.module("ofn.admin").directive "ofnTrackMaster", (DirtyProducts) ->
|
||||
require: "ngModel"
|
||||
link: (scope, element, attrs, ngModel) ->
|
||||
ngModel.$parsers.push (viewValue) ->
|
||||
if ngModel.$dirty
|
||||
DirtyProducts.addMasterProperty scope.product.id, scope.product.master.id, attrs.ofnTrackMaster, viewValue
|
||||
scope.displayDirtyProducts()
|
||||
viewValue
|
||||
@@ -1 +1 @@
|
||||
angular.module("admin.enterprise_groups", ["admin.side_menu", "admin.users", "ngSanitize"])
|
||||
angular.module("admin.enterprise_groups", ["admin.side_menu", "admin.users", "textAngular"])
|
||||
|
||||
@@ -3,6 +3,7 @@ angular.module("admin.enterprises", [
|
||||
"admin.utils",
|
||||
"admin.shippingMethods",
|
||||
"admin.users",
|
||||
"textAngular",
|
||||
"admin.side_menu",
|
||||
"admin.taxons",
|
||||
'admin.indexUtils',
|
||||
@@ -10,3 +11,16 @@ angular.module("admin.enterprises", [
|
||||
'admin.dropdown',
|
||||
'ngSanitize']
|
||||
)
|
||||
# For more options: https://github.com/textAngular/textAngular/blob/master/src/textAngularSetup.js
|
||||
.config [
|
||||
'$provide', ($provide) ->
|
||||
$provide.decorator 'taTranslations', [
|
||||
'$delegate'
|
||||
(taTranslations) ->
|
||||
taTranslations.insertLink = {
|
||||
tooltip: t('admin.enterprises.form.shop_preferences.shopfront_message_link_tooltip'),
|
||||
dialogPrompt: t('admin.enterprises.form.shop_preferences.shopfront_message_link_prompt')
|
||||
}
|
||||
taTranslations
|
||||
]
|
||||
]
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
# Used like a regular angular filter where an object is passed
|
||||
# Adds the additional special case that a value of 0 for the filter
|
||||
# acts as a bypass for that particular attribute
|
||||
|
||||
# NOTE the name doesn't reflect what the filter does, it only fiters on the variant.producer_id
|
||||
angular.module("admin.indexUtils").filter "attrFilter", ($filter) ->
|
||||
return (objects, filters) ->
|
||||
filter = filters["producer_id"]
|
||||
|
||||
return objects if !filter? || filter == 0
|
||||
|
||||
return $filter('filter')(objects, (product) ->
|
||||
for variant in product.variants
|
||||
return true if variant["producer_id"] == filter
|
||||
false
|
||||
, true)
|
||||
Object.keys(filters).reduce (filtered, attr) ->
|
||||
filter = filters[attr]
|
||||
return filtered if !filter? || filter == 0
|
||||
return $filter('filter')(filtered, (object) ->
|
||||
object[attr] == filter
|
||||
)
|
||||
, objects
|
||||
|
||||
@@ -31,7 +31,7 @@ angular.module("admin.indexUtils").factory 'Columns', ($rootScope, $http, $injec
|
||||
savePreferences: (action_name) =>
|
||||
$http
|
||||
method: "PUT"
|
||||
url: "/admin/column_preferences/bulk_update.json"
|
||||
url: "/admin/column_preferences/bulk_update"
|
||||
data:
|
||||
action_name: action_name
|
||||
column_preferences: (preference for column_name, preference of @columns)
|
||||
|
||||
@@ -27,7 +27,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
"order_bill_address_full_name_reversed",
|
||||
"order_bill_address_full_name_with_comma",
|
||||
"order_bill_address_full_name_with_comma_reversed",
|
||||
"variant_supplier_name",
|
||||
"variant_product_supplier_name",
|
||||
"order_email",
|
||||
"order_number",
|
||||
"product_name"].join("_or_") + "_cont"
|
||||
@@ -81,7 +81,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
"q[order_shipment_state_not_eq]": "shipped",
|
||||
"q[order_completed_at_not_null]": "true",
|
||||
"q[order_distributor_id_eq]": $scope.distributorFilter,
|
||||
"q[variant_supplier_id_eq]": $scope.supplierFilter,
|
||||
"q[variant_product_supplier_id_eq]": $scope.supplierFilter,
|
||||
"q[order_order_cycle_id_eq]": $scope.orderCycleFilter,
|
||||
"q[order_completed_at_gteq]": if formattedStartDate then formattedStartDate else undefined,
|
||||
"q[order_completed_at_lt]": if formattedEndDate then formattedEndDate else undefined,
|
||||
@@ -105,7 +105,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
Dereferencer.dereferenceAttr $scope.line_items, "supplier", Enterprises.byID
|
||||
$scope.loadOrders()
|
||||
RequestMonitor.load $q.all([$scope.orders.$promise]).then ->
|
||||
Dereferencer.dereferenceAttr $scope.line_items, "order", Orders.byID
|
||||
Dereferencer.dereferenceAttr $scope.line_items, "order", Orders.byID
|
||||
Dereferencer.dereferenceAttr $scope.orders, "distributor", Enterprises.byID
|
||||
Dereferencer.dereferenceAttr $scope.orders, "order_cycle", OrderCycles.byID
|
||||
$scope.bulk_order_form.$setPristine()
|
||||
@@ -133,7 +133,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
return $http(
|
||||
method: 'GET'
|
||||
url: "/admin/orders/#{order.number}/fire?e=cancel&send_cancellation_email=#{sendEmailCancellation}&restock_items=#{restock_items}")
|
||||
|
||||
|
||||
$scope.deleteLineItem = (lineItem) ->
|
||||
if lineItem.order.item_count == 1
|
||||
ofnCancelOrderAlert((confirm, sendEmailCancellation, restock_items) ->
|
||||
@@ -167,7 +167,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
$scope.cancelOrder(order, sendEmailCancellation, restock_items).then(-> $scope.refreshData())
|
||||
else
|
||||
Promise.all(LineItems.delete(item) for item in items).then(-> $scope.refreshData())
|
||||
, "js.admin.deleting_item_will_cancel_order")
|
||||
, "js.admin.deleting_item_will_cancel_order")
|
||||
else
|
||||
ofnDeleteLineItemsAlert(() ->
|
||||
Promise.all(LineItems.delete(item) for item in lineItemsToDelete).then(-> $scope.refreshData())
|
||||
@@ -199,14 +199,14 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
$scope.refreshData()
|
||||
|
||||
$scope.getLineItemScale = (lineItem) ->
|
||||
if lineItem.units_variant && lineItem.units_variant.variant_unit_scale && (lineItem.units_variant.variant_unit == "weight" || lineItem.units_variant.variant_unit == "volume")
|
||||
lineItem.units_variant.variant_unit_scale
|
||||
if lineItem.units_product && lineItem.units_variant && (lineItem.units_product.variant_unit == "weight" || lineItem.units_product.variant_unit == "volume")
|
||||
lineItem.units_product.variant_unit_scale
|
||||
else
|
||||
1
|
||||
|
||||
$scope.sumUnitValues = ->
|
||||
sum = $scope.filteredLineItems?.reduce (sum, lineItem) ->
|
||||
if lineItem.units_variant.variant_unit == "items"
|
||||
if lineItem.units_product.variant_unit == "items"
|
||||
sum + lineItem.quantity
|
||||
else
|
||||
sum + $scope.roundToThreeDecimals(lineItem.final_weight_volume / $scope.getLineItemScale(lineItem))
|
||||
@@ -214,7 +214,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
|
||||
$scope.sumMaxUnitValues = ->
|
||||
sum = $scope.filteredLineItems?.reduce (sum,lineItem) ->
|
||||
if lineItem.units_variant.variant_unit == "items"
|
||||
if lineItem.units_product.variant_unit == "items"
|
||||
sum + lineItem.max_quantity
|
||||
else
|
||||
sum + lineItem.max_quantity * $scope.roundToThreeDecimals(lineItem.units_variant.unit_value / $scope.getLineItemScale(lineItem))
|
||||
@@ -228,41 +228,39 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
return false if !lineItem.hasOwnProperty('final_weight_volume') || !(lineItem.final_weight_volume > 0)
|
||||
true
|
||||
|
||||
$scope.getScale = (unitsVariant) ->
|
||||
if unitsVariant.hasOwnProperty("variant_unit") && (unitsVariant.variant_unit == "weight" || unitsVariant.variant_unit == "volume")
|
||||
unitsVariant.variant_unit_scale
|
||||
else if unitsVariant.hasOwnProperty("variant_unit") && unitsVariant.variant_unit == "items"
|
||||
$scope.getScale = (unitsProduct, unitsVariant) ->
|
||||
if unitsProduct.hasOwnProperty("variant_unit") && (unitsProduct.variant_unit == "weight" || unitsProduct.variant_unit == "volume")
|
||||
unitsProduct.variant_unit_scale
|
||||
else if unitsProduct.hasOwnProperty("variant_unit") && unitsProduct.variant_unit == "items"
|
||||
1
|
||||
else
|
||||
null
|
||||
|
||||
$scope.getFormattedValueWithUnitName = (value, unitsVariant, scale) ->
|
||||
unit_name = VariantUnitManager.getUnitName(scale, unitsVariant.variant_unit)
|
||||
$scope.getFormattedValueWithUnitName = (value, unitsProduct, unitsVariant, scale) ->
|
||||
unit_name = VariantUnitManager.getUnitName(scale, unitsProduct.variant_unit)
|
||||
$scope.roundToThreeDecimals(value) + " " + unit_name
|
||||
|
||||
$scope.getGroupBySizeFormattedValueWithUnitName = (value, unitsVariant) ->
|
||||
scale = $scope.getScale(unitsVariant)
|
||||
$scope.getGroupBySizeFormattedValueWithUnitName = (value, unitsProduct, unitsVariant) ->
|
||||
scale = $scope.getScale(unitsProduct, unitsVariant)
|
||||
if scale && value
|
||||
value = value / scale if scale != 28.35 && scale != 1 && scale != 453.6 # divide by scale if not smallest unit
|
||||
$scope.getFormattedValueWithUnitName(value, unitsVariant, scale)
|
||||
$scope.getFormattedValueWithUnitName(value, unitsProduct, unitsVariant, scale)
|
||||
else
|
||||
''
|
||||
|
||||
$scope.formattedValueWithUnitName = (value, unitsVariant) ->
|
||||
scale = $scope.getScale(unitsVariant)
|
||||
$scope.formattedValueWithUnitName = (value, unitsProduct, unitsVariant) ->
|
||||
scale = $scope.getScale(unitsProduct, unitsVariant)
|
||||
if scale
|
||||
$scope.getFormattedValueWithUnitName(value, unitsVariant, scale)
|
||||
else
|
||||
$scope.getFormattedValueWithUnitName(value, unitsProduct, unitsVariant, scale)
|
||||
else
|
||||
''
|
||||
|
||||
$scope.fulfilled = (sumOfUnitValues) ->
|
||||
# A Units Variant is an API object which holds unit properies of a variant
|
||||
if $scope.selectedUnitsProduct.hasOwnProperty("group_buy_unit_size") && $scope.selectedUnitsProduct.group_buy_unit_size > 0 &&
|
||||
$scope.selectedUnitsVariant.hasOwnProperty("variant_unit")
|
||||
|
||||
if $scope.selectedUnitsVariant.variant_unit == "weight" || $scope.selectedUnitsVariant.variant_unit == "volume"
|
||||
|
||||
scale = $scope.selectedUnitsVariant.variant_unit_scale
|
||||
if $scope.selectedUnitsProduct.hasOwnProperty("group_buy_unit_size")&& $scope.selectedUnitsProduct.group_buy_unit_size > 0 &&
|
||||
$scope.selectedUnitsProduct.hasOwnProperty("variant_unit")
|
||||
if $scope.selectedUnitsProduct.variant_unit == "weight" || $scope.selectedUnitsProduct.variant_unit == "volume"
|
||||
scale = $scope.selectedUnitsProduct.variant_unit_scale
|
||||
sumOfUnitValues = sumOfUnitValues * scale unless scale == 28.35 || scale == 453.6
|
||||
$scope.roundToThreeDecimals(sumOfUnitValues / $scope.selectedUnitsProduct.group_buy_unit_size)
|
||||
else
|
||||
|
||||
@@ -3,7 +3,6 @@ angular.module('admin.orderCycles')
|
||||
$controller('AdminOrderCycleBasicCtrl', {$scope: $scope, ocInstance: ocInstance})
|
||||
|
||||
order_cycle_id = $location.absUrl().match(/\/admin\/order_cycles\/(\d+)/)[1]
|
||||
$scope.order_cycle_id = order_cycle_id
|
||||
$scope.order_cycle = OrderCycle.load(order_cycle_id)
|
||||
$scope.enterprises = Enterprise.index(order_cycle_id: order_cycle_id)
|
||||
$scope.enterprise_fees = EnterpriseFee.index(order_cycle_id: order_cycle_id)
|
||||
@@ -19,8 +18,6 @@ angular.module('admin.orderCycles')
|
||||
|
||||
$scope.submit = ($event, destination) ->
|
||||
$event.preventDefault()
|
||||
$scope.order_cycle?.trigger_action = $($event.target).data('trigger-action');
|
||||
$scope.order_cycle?.confirm = $($event.target).data('confirm');
|
||||
StatusMessage.display 'progress', t('js.saving')
|
||||
OrderCycle.update(destination, $scope.order_cycle_form)
|
||||
|
||||
@@ -28,4 +25,4 @@ angular.module('admin.orderCycles')
|
||||
if $scope.order_cycle_form?.$dirty
|
||||
t('admin.unsaved_confirm_leave')
|
||||
|
||||
NavigationCheck.register(warnAboutUnsavedChanges)
|
||||
NavigationCheck.register(warnAboutUnsavedChanges)
|
||||
@@ -1,9 +1,8 @@
|
||||
angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($scope, $rootScope, $controller, $location, Enterprise, EnterpriseFee, OrderCycle, ExchangeProduct, ocInstance) ->
|
||||
angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($scope, $rootScope, $controller, $location, Enterprise, OrderCycle, ExchangeProduct, ocInstance) ->
|
||||
$controller('AdminOrderCycleExchangesCtrl', {$scope: $scope, ocInstance: ocInstance, $location: $location})
|
||||
|
||||
$scope.view = 'incoming'
|
||||
# NB: weirdly at this next line $scope.order_cycle.id comes out undefined so we use $scope.order_cycle_id instead
|
||||
$scope.enterprise_fees = EnterpriseFee.index(order_cycle_id: $scope.order_cycle_id, per_item: true)
|
||||
|
||||
$scope.exchangeTotalVariants = (exchange) ->
|
||||
return unless $scope.enterprises? && $scope.enterprises[exchange.enterprise_id]?
|
||||
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
angular.module("admin.orderCycles").controller "OrderCyclesCtrl", ($scope, $q, Columns, StatusMessage, RequestMonitor, OrderCycles, Enterprises, Schedules, Dereferencer) ->
|
||||
$scope.RequestMonitor = RequestMonitor
|
||||
$scope.columns = Columns.columns
|
||||
$scope.saveAll = ($event) ->
|
||||
trigger_action = $($event.target).data('trigger-action')
|
||||
confirm = $($event.target).data('confirm')
|
||||
OrderCycles.saveChanges($scope.order_cycles_form, { trigger_action, confirm })
|
||||
|
||||
$scope.saveAll = -> OrderCycles.saveChanges($scope.order_cycles_form)
|
||||
$scope.ordersCloseAtLimit = -31 # days
|
||||
|
||||
$scope.resetSelectFilters = ->
|
||||
|
||||
@@ -22,8 +22,6 @@ angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl",
|
||||
|
||||
$scope.submit = ($event, destination) ->
|
||||
$event.preventDefault()
|
||||
$scope.order_cycle?.trigger_action = $($event.target).data('trigger-action');
|
||||
$scope.order_cycle?.confirm = $($event.target).data('confirm');
|
||||
StatusMessage.display 'progress', t('js.saving')
|
||||
OrderCycle.mirrorIncomingToOutgoingProducts()
|
||||
OrderCycle.update(destination, $scope.order_cycle_form) if OrderCycle.confirmNoDistributors()
|
||||
|
||||
@@ -6,8 +6,6 @@ angular.module('admin.orderCycles').factory('EnterpriseFee', ($resource) ->
|
||||
params:
|
||||
order_cycle_id: '@order_cycle_id'
|
||||
coordinator_id: '@coordinator_id'
|
||||
per_item: '@per_item'
|
||||
per_order: '@per_order'
|
||||
})
|
||||
|
||||
{
|
||||
|
||||
@@ -161,11 +161,7 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, $
|
||||
StatusMessage.display('failure', t('js.order_cycles.create_failure'))
|
||||
|
||||
update: (destination, form) ->
|
||||
oc = new OrderCycleResource({
|
||||
order_cycle: this.dataForSubmit(),
|
||||
confirm: this.order_cycle.confirm,
|
||||
trigger_action: this.order_cycle.trigger_action
|
||||
})
|
||||
oc = new OrderCycleResource({order_cycle: this.dataForSubmit()})
|
||||
oc.$update {order_cycle_id: this.order_cycle.id, reloading: (if destination? then 1 else 0)}, (data) =>
|
||||
form.$setPristine() if form
|
||||
if destination?
|
||||
@@ -175,8 +171,6 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, $
|
||||
, (response) ->
|
||||
if response.data.errors?
|
||||
StatusMessage.display('failure', response.data.errors[0])
|
||||
else if (response.data.trigger_action)
|
||||
StatusMessage.display('notice', t('js.order_cycles.unsaved_changes'), response.data.trigger_action)
|
||||
else
|
||||
StatusMessage.display('failure', t('js.order_cycles.update_failure'))
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
angular.module("admin.products").controller "editUnitsCtrl", ($scope, VariantUnitManager) ->
|
||||
|
||||
$scope.product =
|
||||
variant_unit: angular.element('#variant_unit').val()
|
||||
variant_unit_scale: angular.element('#variant_unit_scale').val()
|
||||
|
||||
$scope.variant_unit_options = VariantUnitManager.variantUnitOptions()
|
||||
|
||||
if $scope.product.variant_unit == 'items'
|
||||
$scope.variant_unit_with_scale = 'items'
|
||||
else
|
||||
$scope.variant_unit_with_scale = $scope.product.variant_unit + '_' + $scope.product.variant_unit_scale.replace(/\.0$/, '');
|
||||
|
||||
$scope.setFields = ->
|
||||
if $scope.variant_unit_with_scale == 'items'
|
||||
variant_unit = 'items'
|
||||
variant_unit_scale = null
|
||||
else
|
||||
options = $scope.variant_unit_with_scale.split('_')
|
||||
variant_unit = options[0]
|
||||
variant_unit_scale = options[1]
|
||||
|
||||
$scope.product.variant_unit = variant_unit
|
||||
$scope.product.variant_unit_scale = variant_unit_scale
|
||||
@@ -1,14 +1,15 @@
|
||||
# Controller for "New Products" form (spree/admin/products/new)
|
||||
angular.module("admin.products")
|
||||
.controller "unitsCtrl", ($scope, VariantUnitManager, OptionValueNamer, UnitPrices, PriceParser) ->
|
||||
$scope.product = {}
|
||||
$scope.product = { master: {} }
|
||||
$scope.product.master.product = $scope.product
|
||||
$scope.placeholder_text = ""
|
||||
|
||||
$scope.$watchCollection '[product.variant_unit_with_scale, product.unit_value_with_description, product.price, product.variant_unit_name]', ->
|
||||
$scope.$watchCollection '[product.variant_unit_with_scale, product.master.unit_value_with_description, product.price, product.variant_unit_name]', ->
|
||||
$scope.processVariantUnitWithScale()
|
||||
$scope.processUnitValueWithDescription()
|
||||
$scope.processUnitPrice()
|
||||
$scope.placeholder_text = new OptionValueNamer($scope.product).name() if $scope.product.variant_unit_scale
|
||||
$scope.placeholder_text = new OptionValueNamer($scope.product.master).name() if $scope.product.variant_unit_scale
|
||||
|
||||
$scope.variant_unit_options = VariantUnitManager.variantUnitOptions()
|
||||
|
||||
@@ -37,24 +38,24 @@ angular.module("admin.products")
|
||||
# Extract unit_value and unit_description from text field unit_value_with_description,
|
||||
# and update hidden variant fields
|
||||
$scope.processUnitValueWithDescription = ->
|
||||
if $scope.product.hasOwnProperty("unit_value_with_description")
|
||||
match = $scope.product.unit_value_with_description.match(/^([\d\.,]+(?= *|$)|)( *)(.*)$/)
|
||||
if $scope.product.master.hasOwnProperty("unit_value_with_description")
|
||||
match = $scope.product.master.unit_value_with_description.match(/^([\d\.,]+(?= *|$)|)( *)(.*)$/)
|
||||
if match
|
||||
$scope.product.unit_value = PriceParser.parse(match[1])
|
||||
$scope.product.unit_value = null if isNaN($scope.product.unit_value)
|
||||
$scope.product.unit_value = window.bigDecimal.multiply($scope.product.unit_value, $scope.product.variant_unit_scale, 2) if $scope.product.unit_value && $scope.product.variant_unit_scale
|
||||
$scope.product.unit_description = match[3]
|
||||
$scope.product.master.unit_value = PriceParser.parse(match[1])
|
||||
$scope.product.master.unit_value = null if isNaN($scope.product.master.unit_value)
|
||||
$scope.product.master.unit_value = window.bigDecimal.multiply($scope.product.master.unit_value, $scope.product.variant_unit_scale, 2) if $scope.product.master.unit_value && $scope.product.variant_unit_scale
|
||||
$scope.product.master.unit_description = match[3]
|
||||
else
|
||||
value = $scope.product.unit_value
|
||||
value = window.bigDecimal.divide(value, $scope.product.variant_unit_scale, 2) if $scope.product.unit_value && $scope.product.variant_unit_scale
|
||||
$scope.product.unit_value_with_description = value + " " + $scope.product.unit_description
|
||||
value = $scope.product.master.unit_value
|
||||
value = window.bigDecimal.divide(value, $scope.product.variant_unit_scale, 2) if $scope.product.master.unit_value && $scope.product.variant_unit_scale
|
||||
$scope.product.master.unit_value_with_description = value + " " + $scope.product.master.unit_description
|
||||
|
||||
# Calculate unit price based on product price and variant_unit_scale
|
||||
$scope.processUnitPrice = ->
|
||||
price = $scope.product.price
|
||||
scale = $scope.product.variant_unit_scale
|
||||
unit_type = $scope.product.variant_unit
|
||||
unit_value = $scope.product.unit_value
|
||||
unit_value = $scope.product.master.unit_value
|
||||
variant_unit_name = $scope.product.variant_unit_name
|
||||
$scope.unit_price = UnitPrices.displayableUnitPrice(price, scale, unit_type, unit_value, variant_unit_name)
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
angular.module("admin.products").controller "variantUnitsCtrl", ($scope, VariantUnitManager, $timeout, UnitPrices, PriceParser) ->
|
||||
|
||||
$scope.unitName = (scale, type) ->
|
||||
VariantUnitManager.getUnitName(scale, type)
|
||||
|
||||
$scope.$watchCollection "[unit_value_human, variant.price]", ->
|
||||
$scope.processUnitPrice()
|
||||
|
||||
$scope.processUnitPrice = ->
|
||||
if ($scope.variant)
|
||||
price = $scope.variant.price
|
||||
scale = $scope.scale
|
||||
unit_type = angular.element("#product_variant_unit").val()
|
||||
if (unit_type != "items")
|
||||
$scope.updateValue()
|
||||
unit_value = $scope.unit_value
|
||||
else
|
||||
unit_value = 1
|
||||
variant_unit_name = angular.element("#product_variant_unit_name").val()
|
||||
$scope.unit_price = UnitPrices.displayableUnitPrice(price, scale, unit_type, unit_value, variant_unit_name)
|
||||
|
||||
$scope.scale = angular.element('#product_variant_unit_scale').val()
|
||||
|
||||
$scope.updateValue = ->
|
||||
unit_value_human = angular.element('#unit_value_human').val()
|
||||
$scope.unit_value = bigDecimal.multiply(PriceParser.parse(unit_value_human), $scope.scale, 2)
|
||||
|
||||
variant_unit_value = angular.element('#variant_unit_value').val()
|
||||
$scope.unit_value_human = parseFloat(bigDecimal.divide(variant_unit_value, $scope.scale, 2))
|
||||
|
||||
$timeout -> $scope.processUnitPrice()
|
||||
$timeout -> $scope.updateValue()
|
||||
@@ -0,0 +1,19 @@
|
||||
angular.module("admin.products").directive "setOnDemand", ->
|
||||
link: (scope, element, attr) ->
|
||||
onHand = element.context.querySelector("#variant_on_hand")
|
||||
onDemand = element.context.querySelector("#variant_on_demand")
|
||||
|
||||
disableOnHandIfOnDemand = ->
|
||||
if onDemand.checked
|
||||
onHand.disabled = 'disabled'
|
||||
onHand.dataStock = onHand.value
|
||||
onHand.value = t('admin.products.variants.infinity')
|
||||
|
||||
disableOnHandIfOnDemand()
|
||||
|
||||
onDemand.addEventListener 'change', (event) ->
|
||||
disableOnHandIfOnDemand()
|
||||
|
||||
if !onDemand.checked
|
||||
onHand.removeAttribute('disabled')
|
||||
onHand.value = onHand.dataStock
|
||||
@@ -1 +1 @@
|
||||
angular.module("admin.products", ["ngSanitize", "admin.utils", "OFNShared"])
|
||||
angular.module("admin.products", ["textAngular", "admin.utils", "OFNShared"])
|
||||
|
||||
@@ -13,16 +13,16 @@ angular.module("admin.products").factory "OptionValueNamer", (VariantUnitManager
|
||||
name_fields.join ' '
|
||||
|
||||
value_scaled: ->
|
||||
@variant.variant_unit_scale?
|
||||
@variant.product.variant_unit_scale?
|
||||
|
||||
option_value_value_unit: ->
|
||||
if @variant.unit_value?
|
||||
if @variant.variant_unit in ["weight", "volume"]
|
||||
if @variant.product.variant_unit in ["weight", "volume"]
|
||||
[value, unit_name] = @option_value_value_unit_scaled()
|
||||
|
||||
else
|
||||
value = @variant.unit_value
|
||||
unit_name = @pluralize(@variant.variant_unit_name, value)
|
||||
unit_name = @pluralize(@variant.product.variant_unit_name, value)
|
||||
|
||||
value = parseInt(value, 10) if value == parseInt(value, 10)
|
||||
|
||||
@@ -58,13 +58,14 @@ angular.module("admin.products").factory "OptionValueNamer", (VariantUnitManager
|
||||
# to >= 1 when expressed in it.
|
||||
# If there is none available where this is true, use the smallest
|
||||
# available unit.
|
||||
scales = VariantUnitManager.compatibleUnitScales(@variant.variant_unit_scale, @variant.variant_unit)
|
||||
product = @variant.product
|
||||
scales = VariantUnitManager.compatibleUnitScales(product.variant_unit_scale, product.variant_unit)
|
||||
variantUnitValue = @variant.unit_value
|
||||
|
||||
# sets largestScale = last element in filtered scales array
|
||||
[_, ..., largestScale] = (scales.filter (s) -> variantUnitValue / s >= 1)
|
||||
|
||||
if (largestScale)
|
||||
[largestScale, VariantUnitManager.getUnitName(largestScale, @variant.variant_unit)]
|
||||
[largestScale, VariantUnitManager.getUnitName(largestScale, product.variant_unit)]
|
||||
else
|
||||
[scales[0], VariantUnitManager.getUnitName(scales[0], @variant.variant_unit)]
|
||||
[scales[0], VariantUnitManager.getUnitName(scales[0], product.variant_unit)]
|
||||
|
||||
@@ -29,13 +29,13 @@ angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCy
|
||||
deferred.reject(response)
|
||||
deferred.promise
|
||||
|
||||
saveChanges: (form, params = {}) ->
|
||||
saveChanges: (form) ->
|
||||
changed = {}
|
||||
for id, orderCycle of @byID when not @saved(orderCycle)
|
||||
changed[Object.keys(changed).length] = @changesFor(orderCycle)
|
||||
if Object.keys(changed).length > 0
|
||||
StatusMessage.display('progress', "Saving...")
|
||||
OrderCycleResource.bulkUpdate { order_cycle_set: { collection_attributes: changed }, confirm: params['confirm'], trigger_action: params['trigger_action'] }, (data) =>
|
||||
OrderCycleResource.bulkUpdate { order_cycle_set: { collection_attributes: changed } }, (data) =>
|
||||
for orderCycle in data
|
||||
delete orderCycle.coordinator
|
||||
delete orderCycle.producers
|
||||
@@ -47,10 +47,8 @@ angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCy
|
||||
, (response) =>
|
||||
if response.data.errors?
|
||||
StatusMessage.display('failure', response.data.errors[0])
|
||||
else if (response.data.trigger_action)
|
||||
StatusMessage.display('notice', t('js.order_cycles.unsaved_changes'), response.data.trigger_action)
|
||||
else
|
||||
StatusMessage.display('failure', t('js.order_cycles.bulk_save_error'))
|
||||
StatusMessage.display('failure', "Oh no! I was unable to save your changes.")
|
||||
|
||||
saved: (order_cycle) ->
|
||||
@diff(order_cycle).length == 0
|
||||
|
||||
@@ -19,7 +19,7 @@ angular.module("ofn.admin").factory "BulkProducts", (ProductResource, dataFetche
|
||||
for server_product in serverProducts
|
||||
product = @findProductInList(server_product.id, @products)
|
||||
product.variants = server_product.variants
|
||||
@loadVariantUnitValues product.variants
|
||||
@loadVariantUnitValues product
|
||||
|
||||
find: (id) ->
|
||||
@findProductInList id, @products
|
||||
@@ -38,32 +38,34 @@ angular.module("ofn.admin").factory "BulkProducts", (ProductResource, dataFetche
|
||||
@products.splice(index + 1, 0, newProduct)
|
||||
|
||||
unpackProduct: (product) ->
|
||||
#$scope.matchProducer product
|
||||
@loadVariantUnit product
|
||||
|
||||
loadVariantUnit: (product) ->
|
||||
@loadVariantUnitValues product.variants if product.variants
|
||||
|
||||
loadVariantUnitValues: (variants) ->
|
||||
for variant in variants
|
||||
@loadVariantUnitValue variant
|
||||
|
||||
loadVariantUnitValue: (variant) ->
|
||||
variant.variant_unit_with_scale =
|
||||
if variant.variant_unit && variant.variant_unit_scale && variant.variant_unit != 'items'
|
||||
"#{variant.variant_unit}_#{variant.variant_unit_scale}"
|
||||
else if variant.variant_unit
|
||||
variant.variant_unit
|
||||
product.variant_unit_with_scale =
|
||||
if product.variant_unit && product.variant_unit_scale && product.variant_unit != 'items'
|
||||
"#{product.variant_unit}_#{product.variant_unit_scale}"
|
||||
else if product.variant_unit
|
||||
product.variant_unit
|
||||
else
|
||||
null
|
||||
|
||||
unit_value = @variantUnitValue variant
|
||||
@loadVariantUnitValues product if product.variants
|
||||
@loadVariantUnitValue product, product.master if product.master
|
||||
|
||||
loadVariantUnitValues: (product) ->
|
||||
for variant in product.variants
|
||||
@loadVariantUnitValue product, variant
|
||||
|
||||
loadVariantUnitValue: (product, variant) ->
|
||||
unit_value = @variantUnitValue product, variant
|
||||
unit_value = if unit_value? then unit_value else ''
|
||||
variant.unit_value_with_description = "#{unit_value} #{variant.unit_description || ''}".trim()
|
||||
|
||||
variantUnitValue: (variant) ->
|
||||
variantUnitValue: (product, variant) ->
|
||||
if variant.unit_value?
|
||||
if variant.variant_unit_scale
|
||||
variant_unit_value = @divideAsInteger variant.unit_value, variant.variant_unit_scale
|
||||
if product.variant_unit_scale
|
||||
variant_unit_value = @divideAsInteger variant.unit_value, product.variant_unit_scale
|
||||
parseFloat(window.bigDecimal.round(variant_unit_value, 2))
|
||||
else
|
||||
variant.unit_value
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
root = exports ? this
|
||||
|
||||
root.taxon_tree_menu = (obj, context) ->
|
||||
|
||||
base_url = Spree.url(Spree.routes.taxonomy_taxons)
|
||||
admin_base_url = Spree.url(Spree.routes.admin_taxonomy_taxons)
|
||||
edit_url = Spree.url(Spree.routes.admin_taxonomy_taxons + '/' + obj.attr("id") + "/edit");
|
||||
|
||||
create:
|
||||
label: "<i class='icon-plus'></i> " + Spree.translations.add,
|
||||
action: (obj) -> context.create(obj)
|
||||
rename:
|
||||
label: "<i class='icon-pencil'></i> " + Spree.translations.rename,
|
||||
action: (obj) -> context.rename(obj)
|
||||
remove:
|
||||
label: "<i class='icon-trash'></i> " + Spree.translations.remove,
|
||||
action: (obj) -> context.remove(obj)
|
||||
edit:
|
||||
separator_before: true,
|
||||
label: "<i class='icon-edit'></i> " + Spree.translations.edit,
|
||||
action: (obj) -> window.location = edit_url.toString()
|
||||
139
app/assets/javascripts/admin/spree/taxons/taxonomy.js.coffee
Normal file
139
app/assets/javascripts/admin/spree/taxons/taxonomy.js.coffee
Normal file
@@ -0,0 +1,139 @@
|
||||
handle_ajax_error = (XMLHttpRequest, textStatus, errorThrown) ->
|
||||
$.jstree.rollback(last_rollback)
|
||||
$("#ajax_error").show().html("<strong>" + server_error + "</strong><br />" + taxonomy_tree_error)
|
||||
|
||||
handle_move = (e, data) ->
|
||||
last_rollback = data.rlbk
|
||||
position = data.rslt.cp
|
||||
node = data.rslt.o
|
||||
new_parent = data.rslt.np
|
||||
|
||||
url = new URL(Spree.routes.admin_taxonomy_taxons)
|
||||
url.pathname = url.pathname + '/' + node.attr("id")
|
||||
data = {
|
||||
_method: "put",
|
||||
"taxon[position]": position,
|
||||
"taxon[parent_id]": if !isNaN(new_parent.attr("id")) then new_parent.attr("id") else undefined
|
||||
}
|
||||
$.ajax
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
url: url.toString(),
|
||||
data: data,
|
||||
error: handle_ajax_error
|
||||
|
||||
true
|
||||
|
||||
handle_create = (e, data) ->
|
||||
last_rollback = data.rlbk
|
||||
node = data.rslt.obj
|
||||
name = data.rslt.name
|
||||
position = data.rslt.position
|
||||
new_parent = data.rslt.parent
|
||||
|
||||
data = {
|
||||
"taxon[name]": name,
|
||||
"taxon[position]": position
|
||||
"taxon[parent_id]": if !isNaN(new_parent.attr("id")) then new_parent.attr("id") else undefined
|
||||
}
|
||||
$.ajax
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
url: base_url.toString(),
|
||||
data: data,
|
||||
error: handle_ajax_error,
|
||||
success: (data,result) ->
|
||||
node.attr('id', data.id)
|
||||
|
||||
handle_rename = (e, data) ->
|
||||
last_rollback = data.rlbk
|
||||
node = data.rslt.obj
|
||||
name = data.rslt.new_name
|
||||
# change the name inside the main input field as well if taxon is the root one
|
||||
document.getElementById("taxonomy_name").value = name if node.parents("[id]").attr("id") == "taxonomy_tree"
|
||||
|
||||
url = new URL(base_url)
|
||||
url.pathname = url.pathname + '/' + node.attr("id")
|
||||
|
||||
$.ajax
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
url: url.toString(),
|
||||
data: {_method: "put", "taxon[name]": name },
|
||||
error: handle_ajax_error
|
||||
|
||||
handle_delete = (e, data) ->
|
||||
last_rollback = data.rlbk
|
||||
node = data.rslt.obj
|
||||
delete_url = new URL(base_url)
|
||||
delete_url.pathname = delete_url.pathname + '/' + node.attr("id")
|
||||
if confirm(Spree.translations.are_you_sure_delete)
|
||||
$.ajax
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
url: delete_url.toString(),
|
||||
data: {_method: "delete"},
|
||||
error: handle_ajax_error
|
||||
else
|
||||
$.jstree.rollback(last_rollback)
|
||||
last_rollback = null
|
||||
|
||||
root = exports ? this
|
||||
root.setup_taxonomy_tree = (taxonomy_id) ->
|
||||
if taxonomy_id != undefined
|
||||
# this is defined within admin/taxonomies/edit
|
||||
root.base_url = Spree.url(Spree.routes.taxonomy_taxons)
|
||||
|
||||
$.ajax
|
||||
url: base_url.pathname.replace("/taxons", "/jstree"),
|
||||
success: (taxonomy) ->
|
||||
last_rollback = null
|
||||
|
||||
conf =
|
||||
json_data:
|
||||
data: taxonomy,
|
||||
ajax:
|
||||
url: (e) ->
|
||||
base_url.pathname + '/' + e.attr('id') + '/jstree'
|
||||
themes:
|
||||
theme: "apple",
|
||||
url: "/assets/jquery.jstree/themes/apple/style.css"
|
||||
strings:
|
||||
new_node: new_taxon,
|
||||
loading: Spree.translations.loading + "..."
|
||||
crrm:
|
||||
move:
|
||||
check_move: (m) ->
|
||||
position = m.cp
|
||||
node = m.o
|
||||
new_parent = m.np
|
||||
|
||||
# no parent or cant drag and drop
|
||||
if !new_parent || node.attr("rel") == "root"
|
||||
return false
|
||||
|
||||
# can't drop before root
|
||||
if new_parent.attr("id") == "taxonomy_tree" && position == 0
|
||||
return false
|
||||
|
||||
true
|
||||
contextmenu:
|
||||
items: (obj) ->
|
||||
taxon_tree_menu(obj, this)
|
||||
plugins: ["themes", "json_data", "dnd", "crrm", "contextmenu"]
|
||||
|
||||
$("#taxonomy_tree").jstree(conf)
|
||||
.bind("move_node.jstree", handle_move)
|
||||
.bind("remove.jstree", handle_delete)
|
||||
.bind("create.jstree", handle_create)
|
||||
.bind("rename.jstree", handle_rename)
|
||||
.bind "loaded.jstree", ->
|
||||
$(this).jstree("core").toggle_node($('.jstree-icon').first())
|
||||
|
||||
$("#taxonomy_tree a").on "dblclick", (e) ->
|
||||
$("#taxonomy_tree").jstree("rename", this)
|
||||
|
||||
# surpress form submit on enter/return
|
||||
$(document).keypress (e) ->
|
||||
if e.keyCode == 13
|
||||
e.preventDefault()
|
||||
@@ -0,0 +1,6 @@
|
||||
angular.module("admin.utils").directive "textangularLinksTargetBlank", () ->
|
||||
restrict: 'CA'
|
||||
link: (scope, element, attrs) ->
|
||||
setTimeout ->
|
||||
element.find(".ta-editor").scope().defaultTagAttributes.a.target = '_blank'
|
||||
, 500
|
||||
@@ -0,0 +1,11 @@
|
||||
angular.module("admin.utils").directive "textangularStrip", () ->
|
||||
restrict: 'CA'
|
||||
link: (scope, element, attrs) ->
|
||||
scope.stripFormatting = ($html) ->
|
||||
element = document.createElement("div")
|
||||
element.innerHTML = String($html)
|
||||
allTags = element.getElementsByTagName("*")
|
||||
for child in allTags
|
||||
child.removeAttribute("style")
|
||||
child.removeAttribute("class")
|
||||
return element.innerHTML
|
||||
@@ -9,7 +9,6 @@ angular.module("admin.utils")
|
||||
$window.onbeforeunload = @onBeforeUnloadHandler
|
||||
|
||||
$rootScope.$on "$locationChangeStart", @locationChangeStartHandler
|
||||
$window.onBeforeUnloadHandler = @onBeforeUnloadHandler
|
||||
|
||||
# Action for regular browser navigation.
|
||||
onBeforeUnloadHandler: ($event) =>
|
||||
|
||||
@@ -10,9 +10,7 @@ angular.module("admin.utils").factory "StatusMessage", ->
|
||||
|
||||
statusMessage:
|
||||
text: ""
|
||||
style: {},
|
||||
type: null,
|
||||
actionName: null
|
||||
style: {}
|
||||
|
||||
invalidMessage: ""
|
||||
|
||||
@@ -25,15 +23,11 @@ angular.module("admin.utils").factory "StatusMessage", ->
|
||||
active: ->
|
||||
@statusMessage.text != ''
|
||||
|
||||
display: (type, text, actionName = null) ->
|
||||
display: (type, text) ->
|
||||
@statusMessage.text = text
|
||||
@statusMessage.type = type
|
||||
@statusMessage.actionName = actionName
|
||||
@statusMessage.style = @types[type].style
|
||||
null
|
||||
|
||||
clear: ->
|
||||
@statusMessage.text = ''
|
||||
@statusMessage.style = {}
|
||||
@statusMessage.type = null
|
||||
@statusMessage.actionName = null
|
||||
|
||||
@@ -2,10 +2,10 @@ angular.module("admin.variantOverrides").directive "trackInheritance", (VariantO
|
||||
require: "ngModel"
|
||||
link: (scope, element, attrs, ngModel) ->
|
||||
# This is a bit hacky, but it allows us to load the inherit property on the VO, but then not submit it
|
||||
scope.inherit = angular.equals scope.variantOverrides[scope.hub_id][scope.variant.id], VariantOverrides.newFor scope.hub_id, scope.variant
|
||||
scope.inherit = angular.equals scope.variantOverrides[scope.hub_id][scope.variant.id], VariantOverrides.newFor scope.hub_id, scope.variant.id
|
||||
|
||||
ngModel.$parsers.push (viewValue) ->
|
||||
if ngModel.$dirty && viewValue
|
||||
DirtyVariantOverrides.inherit scope.hub_id, scope.variant, scope.variantOverrides[scope.hub_id][scope.variant.id].id
|
||||
DirtyVariantOverrides.inherit scope.hub_id, scope.variant.id, scope.variantOverrides[scope.hub_id][scope.variant.id].id
|
||||
scope.displayDirty()
|
||||
viewValue
|
||||
|
||||
@@ -2,8 +2,4 @@ angular.module("admin.variantOverrides").filter "hubPermissions", ($filter) ->
|
||||
return (products, hubPermissions, hub_id) ->
|
||||
return [] if !hub_id
|
||||
return [] if !hubPermissions[hub_id]
|
||||
|
||||
return $filter('filter')(products, ((product) ->
|
||||
for variant in product.variants
|
||||
return hubPermissions[hub_id].indexOf(variant.producer_id) > -1
|
||||
), true)
|
||||
return $filter('filter')(products, ((product) -> hubPermissions[hub_id].indexOf(product.producer_id) > -1), true)
|
||||
|
||||
@@ -12,11 +12,11 @@ angular.module("admin.variantOverrides").factory "DirtyVariantOverrides", ($http
|
||||
@add(hub_id, variant_id, vo_id)
|
||||
@dirtyVariantOverrides[hub_id][variant_id][attr] = value
|
||||
|
||||
inherit: (hub_id, variant, vo_id) ->
|
||||
@add(hub_id, variant.id, vo_id)
|
||||
blankVo = angular.copy(VariantOverrides.inherit(hub_id, variant))
|
||||
inherit: (hub_id, variant_id, vo_id) ->
|
||||
@add(hub_id, variant_id, vo_id)
|
||||
blankVo = angular.copy(VariantOverrides.inherit(hub_id, variant_id))
|
||||
delete blankVo[attr] for attr, value of blankVo when attr not in @requiredAttrs()
|
||||
@dirtyVariantOverrides[hub_id][variant.id] = blankVo
|
||||
@dirtyVariantOverrides[hub_id][variant_id] = blankVo
|
||||
|
||||
count: ->
|
||||
count = 0
|
||||
|
||||
@@ -13,18 +13,17 @@ angular.module("admin.variantOverrides").factory "VariantOverrides", (variantOve
|
||||
@variantOverrides[hub.id] ||= {}
|
||||
for product in products
|
||||
for variant in product.variants
|
||||
@inherit(hub.id, variant) unless @variantOverrides[hub.id][variant.id]
|
||||
@inherit(hub.id, variant.id) unless @variantOverrides[hub.id][variant.id]
|
||||
|
||||
inherit: (hub_id, variant) ->
|
||||
inherit: (hub_id, variant_id) ->
|
||||
# This method is called from the trackInheritance directive, to reinstate inheritance
|
||||
@variantOverrides[hub_id][variant.id] ||= {}
|
||||
angular.extend @variantOverrides[hub_id][variant.id], @newFor(hub_id, variant)
|
||||
@variantOverrides[hub_id][variant_id] ||= {}
|
||||
angular.extend @variantOverrides[hub_id][variant_id], @newFor hub_id, variant_id
|
||||
|
||||
newFor: (hub_id, variant) ->
|
||||
newFor: (hub_id, variant_id) ->
|
||||
# These properties need to match those checked in VariantOverrideSet.deletable?
|
||||
hub_id: hub_id
|
||||
variant_id: variant.id
|
||||
producer_id: variant.producer_id
|
||||
variant_id: variant_id
|
||||
sku: null
|
||||
price: null
|
||||
count_on_hand: null
|
||||
|
||||
@@ -4,18 +4,15 @@ angular.module('Darkswarm').controller "ProductsCtrl", ($scope, $sce, $filter, $
|
||||
$scope.query = ""
|
||||
$scope.taxonSelectors = FilterSelectorsService.createSelectors()
|
||||
$scope.propertySelectors = FilterSelectorsService.createSelectors()
|
||||
$scope.producerPropertySelectors = FilterSelectorsService.createSelectors()
|
||||
$scope.filtersActive = true
|
||||
$scope.page = 1
|
||||
$scope.per_page = 10
|
||||
$scope.order_cycle = OrderCycle.order_cycle
|
||||
$scope.supplied_taxons = null
|
||||
$scope.supplied_properties = null
|
||||
$scope.supplied_producer_properties = null
|
||||
$scope.showFilterSidebar = false
|
||||
$scope.activeTaxons = []
|
||||
$scope.activeProperties = []
|
||||
$scope.activeProducerProperties = []
|
||||
|
||||
# Update filters after initial load of shop tab
|
||||
$timeout =>
|
||||
@@ -48,12 +45,6 @@ angular.module('Darkswarm').controller "ProductsCtrl", ($scope, $sce, $filter, $
|
||||
$scope.supplied_properties[property.id] = Properties.properties_by_id[property.id]
|
||||
)
|
||||
|
||||
OrderCycleResource.producerProperties params, (data)=>
|
||||
$scope.supplied_producer_properties = {}
|
||||
data.map( (property) ->
|
||||
$scope.supplied_producer_properties[property.id] = Properties.properties_by_id[property.id]
|
||||
)
|
||||
|
||||
$scope.loadMore = ->
|
||||
if ($scope.page * $scope.per_page) <= Products.products.length
|
||||
$scope.loadMoreProducts()
|
||||
@@ -61,7 +52,6 @@ angular.module('Darkswarm').controller "ProductsCtrl", ($scope, $sce, $filter, $
|
||||
$scope.$watch 'query', (newValue, oldValue) -> $scope.loadProducts() if newValue != oldValue
|
||||
$scope.$watchCollection 'activeTaxons', (newValue, oldValue) -> $scope.loadProducts() if newValue != oldValue
|
||||
$scope.$watchCollection 'activeProperties', (newValue, oldValue) -> $scope.loadProducts() if newValue != oldValue
|
||||
$scope.$watchCollection 'activeProducerProperties', (newValue, oldValue) -> $scope.loadProducts() if newValue != oldValue
|
||||
|
||||
$scope.loadProducts = ->
|
||||
$scope.page = 1
|
||||
@@ -76,9 +66,8 @@ angular.module('Darkswarm').controller "ProductsCtrl", ($scope, $sce, $filter, $
|
||||
id: $scope.order_cycle.order_cycle_id,
|
||||
page: page || $scope.page,
|
||||
per_page: $scope.per_page,
|
||||
'q[name_or_meta_keywords_or_variants_display_as_or_variants_display_name_or_variants_supplier_name_cont]': $scope.query,
|
||||
'q[name_or_meta_keywords_or_variants_display_as_or_variants_display_name_or_supplier_name_cont]': $scope.query,
|
||||
'q[with_properties][]': $scope.activeProperties,
|
||||
'q[with_variants_supplier_properties][]': $scope.activeProducerProperties,
|
||||
'q[variants_primary_taxon_id_in_any][]': $scope.activeTaxons
|
||||
}
|
||||
|
||||
@@ -97,12 +86,6 @@ angular.module('Darkswarm').controller "ProductsCtrl", ($scope, $sce, $filter, $
|
||||
Properties.properties_by_id[property_id].name
|
||||
).join($scope.filtersJoinWord()) if $scope.activeProperties?
|
||||
|
||||
$scope.appliedProducerPropertiesList = ->
|
||||
$scope.activeProducerProperties.map( (property_id) ->
|
||||
Properties.properties_by_id[property_id].name
|
||||
).join($scope.filtersJoinWord()) if $scope.activeProducerProperties?
|
||||
|
||||
|
||||
$scope.filtersJoinWord = ->
|
||||
$sce.trustAsHtml(" <span class='join-word'>#{t('products_or')}</span> ")
|
||||
|
||||
@@ -116,7 +99,6 @@ angular.module('Darkswarm').controller "ProductsCtrl", ($scope, $sce, $filter, $
|
||||
$scope.clearFilters = ->
|
||||
$scope.taxonSelectors.clearAll()
|
||||
$scope.propertySelectors.clearAll()
|
||||
$scope.producerPropertySelectors.clearAll()
|
||||
|
||||
$scope.refreshStaleData = ->
|
||||
# If the products template has already been loaded but the controller is being initialized
|
||||
@@ -127,7 +109,7 @@ angular.module('Darkswarm').controller "ProductsCtrl", ($scope, $sce, $filter, $
|
||||
$scope.loadProducts()
|
||||
|
||||
$scope.filtersCount = () ->
|
||||
$scope.taxonSelectors.totalActive() + $scope.propertySelectors.totalActive() + $scope.producerPropertySelectors.totalActive()
|
||||
$scope.taxonSelectors.totalActive() + $scope.propertySelectors.totalActive()
|
||||
|
||||
$scope.toggleFilterSidebar = ->
|
||||
$scope.showFilterSidebar = !$scope.showFilterSidebar
|
||||
|
||||
@@ -42,17 +42,8 @@ angular.module('Darkswarm').controller "RegistrationCtrl", ($scope, Registration
|
||||
$scope.toggleAddressConfirmed = ->
|
||||
$scope.addressConfirmed = !$scope.addressConfirmed
|
||||
if $scope.addressConfirmed
|
||||
$scope.setLatLongIfUsingOpenStreetMap()
|
||||
$scope.enterprise.address.latitude = $scope.latLong.latitude
|
||||
$scope.enterprise.address.longitude = $scope.latLong.longitude
|
||||
else
|
||||
$scope.enterprise.address.latitude = null
|
||||
$scope.enterprise.address.longitude = null
|
||||
|
||||
# When OpenStreetMaps is enabled the latitude and longitude are calculated via a Stimulus
|
||||
# controller, so they need to be read from data properties to be accessible here.
|
||||
$scope.setLatLongIfUsingOpenStreetMap = ->
|
||||
openStreetMap = document.getElementById("open-street-map")
|
||||
if !$scope.latLong && openStreetMap && openStreetMap.dataset.latitude && openStreetMap.dataset.longitude
|
||||
$scope.latLong = { latitude: openStreetMap.dataset.latitude, longitude: openStreetMap.dataset.longitude }
|
||||
|
||||
|
||||
@@ -18,11 +18,4 @@ angular.module('Darkswarm').factory 'OrderCycleResource', ($resource) ->
|
||||
url: '/api/v0/order_cycles/:id/properties.json'
|
||||
params:
|
||||
id: '@id'
|
||||
'producerProperties':
|
||||
method: 'GET'
|
||||
isArray: true
|
||||
url: '/api/v0/order_cycles/:id/producer_properties.json'
|
||||
params:
|
||||
id: '@id'
|
||||
|
||||
})
|
||||
|
||||
@@ -39,7 +39,7 @@ angular.module('Darkswarm').factory 'Products', (OrderCycleResource, OrderCycle,
|
||||
|
||||
dereference: ->
|
||||
for product in @fetched_products
|
||||
product.supplier = Shopfront.producers_by_id[product.variants[0].supplier.id]
|
||||
product.supplier = Shopfront.producers_by_id[product.supplier.id]
|
||||
Dereferencer.dereference product.taxons, Taxons.taxons_by_id
|
||||
|
||||
product.properties = angular.copy(product.properties_with_values)
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
- # NOTE: make sure that any changes in this template are reflected in app/views/admin/products_v3/product_preview.turbo_stream.haml
|
||||
%li{ "ng-class": "{active: selector.active}" }
|
||||
%a{ tooltip: "{{selector.object.value}}", "tooltip-placement": "bottom", "ng-transclude": true, "ng-class": "{active: selector.active, 'has-tip': selector.object.value}" }
|
||||
|
||||
@@ -5,9 +5,8 @@
|
||||
%div.menu{ 'ng-show' => "expanded" }
|
||||
.menu_items
|
||||
.menu_item{ "ng-repeat": "column in columns", "ng-click": "toggle(column);" }
|
||||
%input{ type: "checkbox", "ng-checked": "column.visible" }
|
||||
%span
|
||||
{{ column.name }}
|
||||
%input.redesigned-input{ type: "checkbox", "ng-checked": "column.visible" }
|
||||
{{ column.name }}
|
||||
%hr
|
||||
%div.menu_item.text-center
|
||||
%input.fullwidth.orange{ type: "button", "ng-value": "saved() ? 'Saved': 'Saving'", "ng-show": "saved() || saving", "ng-disabled": "saved()" }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#save-bar.animate-show{ "ng-show": 'dirty || persist || StatusMessage.active()' }
|
||||
.container
|
||||
.seven.columns.alpha
|
||||
%h5#status-message{ "ng-show": "StatusMessage.invalidMessage == ''", "ng-style": 'StatusMessage.statusMessage.style', data: { 'order-cycle-form-target': 'statusMessage' }, "ng-attr-data-type": "{{StatusMessage.statusMessage.type}}", "ng-attr-data-action-name": "{{StatusMessage.statusMessage.actionName}}" }
|
||||
%h5#status-message{ "ng-show": "StatusMessage.invalidMessage == ''", "ng-style": 'StatusMessage.statusMessage.style' }
|
||||
{{ StatusMessage.statusMessage.text || " " }}
|
||||
%h5#status-message{ style: 'color: #C85136', "ng-show": "StatusMessage.invalidMessage !== ''" }
|
||||
{{ StatusMessage.invalidMessage || " " }}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
- # NOTE: make sure that any changes in this template are reflected in app/views/admin/products_v3/product_preview.turbo_stream.haml
|
||||
%ul
|
||||
%active-selector{ "ng-repeat": "selector in allSelectors", "ng-show": "ifDefined(selector.fits, true)" }
|
||||
%span{"ng-bind" => "::selector.object.name"}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
- # NOTE: make sure that any changes in this template are reflected in app/views/admin/products_v3/product_preview.turbo_stream.haml
|
||||
.row
|
||||
.columns.small-12.medium-6.large-6.product-header
|
||||
%h3{"ng-bind" => "::product.name"}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
@import './mail/all.scss';
|
||||
@@ -1,3 +0,0 @@
|
||||
@import '../../../webpacker/css/admin/globals/palette.scss';
|
||||
@import 'email';
|
||||
@import 'payments_list';
|
||||
@@ -1,11 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AdminTooltipComponent < ViewComponent::Base
|
||||
def initialize(text:, link_text:, placement: "top", link: "", link_class: "")
|
||||
@text = text
|
||||
@link_text = link_text
|
||||
@placement = placement
|
||||
@link = link
|
||||
@link_class = link_class
|
||||
end
|
||||
end
|
||||
@@ -1,8 +0,0 @@
|
||||
%div{"data-controller": "tooltip", "data-tooltip-placement-value": @placement }
|
||||
%a{"data-tooltip-target": "element", href: @link, class: @link_class}
|
||||
= @link_text
|
||||
.tooltip-container
|
||||
.tooltip{"data-tooltip-target": "tooltip"}
|
||||
= sanitize @text
|
||||
.arrow{"data-tooltip-target": "arrow"}
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
class HelpModalComponent < ModalComponent
|
||||
def initialize(id:, close_button: true)
|
||||
super
|
||||
super(id:, close_button:)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ModalComponent < ViewComponent::Base
|
||||
def initialize(id:, close_button: true, instant: false, modal_class: :small, **options)
|
||||
def initialize(id:, close_button: true, instant: false, modal_class: :small)
|
||||
@id = id
|
||||
@close_button = close_button
|
||||
@instant = instant
|
||||
@modal_class = modal_class
|
||||
@options = options
|
||||
@data_controller = "modal #{@options.delete(:'data-controller')}".squish
|
||||
@data_action =
|
||||
"keyup@document->modal#closeIfEscapeKey #{@options.delete(:'data-action')}".squish
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
%div{ id: @id, "data-controller": @data_controller, "data-action": @data_action, "data-modal-instant-value": @instant, **@options }
|
||||
%div{ id: @id, "data-controller": "modal", "data-action": "keyup@document->modal#closeIfEscapeKey", "data-modal-instant-value": @instant }
|
||||
.reveal-modal-bg.fade{ "data-modal-target": "background", "data-action": "click->modal#close" }
|
||||
.reveal-modal.fade.modal-component{ "data-modal-target": "modal", class: @modal_class }
|
||||
= content
|
||||
|
||||
@@ -24,19 +24,6 @@
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.flex-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.gap-1 {
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.gap-2 {
|
||||
gap: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* prevent arrow on selected admin menu item appearing above modal */
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
%div.menu_items
|
||||
- @options.each do |option|
|
||||
%label.menu_item{ "data-multiple-checked-select-target": "option", "data-value": option[1], "data-label": option[0] }
|
||||
%input{ type: "checkbox", checked: @selected.include?(option[1]), name: "#{@name}[]", value: option[1] }
|
||||
%span= option[0]
|
||||
%input.redesigned-input{ type: "checkbox", checked: @selected.include?(option[1]), name: "#{@name}[]", value: option[1] }
|
||||
= option[0]
|
||||
|
||||
@@ -11,8 +11,7 @@ class SearchableDropdownComponent < ViewComponent::Base
|
||||
selected_option:,
|
||||
placeholder_value:,
|
||||
include_blank: false,
|
||||
aria_label: '',
|
||||
other_attrs: {}
|
||||
aria_label: ''
|
||||
)
|
||||
@f = form
|
||||
@name = name
|
||||
@@ -21,13 +20,11 @@ class SearchableDropdownComponent < ViewComponent::Base
|
||||
@placeholder_value = placeholder_value
|
||||
@include_blank = include_blank
|
||||
@aria_label = aria_label
|
||||
@other_attrs = other_attrs
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :f, :name, :options, :selected_option, :placeholder_value, :include_blank,
|
||||
:aria_label, :other_attrs
|
||||
attr_reader :f, :name, :options, :selected_option, :placeholder_value, :include_blank, :aria_label
|
||||
|
||||
def classes
|
||||
"fullwidth #{remove_search_plugin? ? 'no-input' : ''}"
|
||||
|
||||
@@ -1 +1 @@
|
||||
= f.select name, options_for_select(options, selected_option), { include_blank: }, class: classes, data:, 'aria-label': aria_label, **other_attrs
|
||||
= f.select name, options_for_select(options, selected_option), { include_blank: }, class: classes, data:, 'aria-label': aria_label
|
||||
|
||||
@@ -8,10 +8,6 @@ export default class extends Controller {
|
||||
window.addEventListener("click", this.#hideIfClickedOutside);
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
window.removeEventListener("click", this.#hideIfClickedOutside);
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.contentTarget.classList.toggle("show");
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ module Admin
|
||||
order.with_lock do
|
||||
if order.contents.update_item(@line_item, line_item_params)
|
||||
# No Content, does not trigger ng resource auto-update
|
||||
head :no_content
|
||||
render body: nil, status: :no_content
|
||||
else
|
||||
render json: { errors: @line_item.errors }, status: :precondition_failed
|
||||
end
|
||||
@@ -49,7 +49,7 @@ module Admin
|
||||
authorize! :update, order
|
||||
|
||||
order.contents.remove(@line_item.variant)
|
||||
head :no_content # No Content, does not trigger ng resource auto-update
|
||||
render body: nil, status: :no_content # No Content, does not trigger ng resource auto-update
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -4,25 +4,17 @@ module Admin
|
||||
class ColumnPreferencesController < Admin::ResourceController
|
||||
before_action :load_collection, only: [:bulk_update]
|
||||
|
||||
respond_to :json
|
||||
|
||||
def bulk_update
|
||||
@cp_set.collection.each { |cp| authorize! :bulk_update, cp }
|
||||
|
||||
respond_to do |format|
|
||||
if @cp_set.save
|
||||
format.json {
|
||||
render json: @cp_set.collection, each_serializer: Api::Admin::ColumnPreferenceSerializer
|
||||
}
|
||||
format.turbo_stream {
|
||||
flash.now[:success] = t('.success')
|
||||
render :bulk_update, locals: { action: permitted_params[:action_name] }
|
||||
}
|
||||
else
|
||||
format.json { render json: { errors: @cp_set.errors }, status: :bad_request }
|
||||
format.turbo_stream {
|
||||
flash.now[:error] = @cp_set.errors.full_messages.to_sentence
|
||||
render :bulk_update, locals: { action: permitted_params[:action_name] }
|
||||
}
|
||||
end
|
||||
if @cp_set.save
|
||||
render json: @cp_set.collection, each_serializer: Api::Admin::ColumnPreferenceSerializer
|
||||
elsif @cp_set.errors.present?
|
||||
render json: { errors: @cp_set.errors }, status: :bad_request
|
||||
else
|
||||
render body: nil, status: :internal_server_error
|
||||
end
|
||||
end
|
||||
|
||||
@@ -36,26 +28,11 @@ module Admin
|
||||
end
|
||||
|
||||
def load_collection
|
||||
collection_attributes = nil
|
||||
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
collection_attributes = Hash[permitted_params[:column_preferences].
|
||||
each_with_index.map { |cp, i| [i, cp] }]
|
||||
collection_attributes.select!{ |_i, cp|
|
||||
cp[:action_name] == permitted_params[:action_name]
|
||||
}
|
||||
end
|
||||
format.all do
|
||||
# Inject action name and user ID for each column_preference
|
||||
collection_attributes = permitted_params[:column_preferences].to_h.each_value { |cp|
|
||||
cp[:action_name] = permitted_params[:action_name]
|
||||
cp[:user_id] = spree_current_user.id
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@cp_set = Sets::ColumnPreferenceSet.new(@column_preferences, collection_attributes:)
|
||||
collection_hash = Hash[permitted_params[:column_preferences].
|
||||
each_with_index.map { |cp, i| [i, cp] }]
|
||||
collection_hash.select!{ |_i, cp| cp[:action_name] == permitted_params[:action_name] }
|
||||
@cp_set = Sets::ColumnPreferenceSet.new(@column_preferences,
|
||||
collection_attributes: collection_hash)
|
||||
end
|
||||
|
||||
def collection
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class ConnectedAppSettingsController < Spree::Admin::BaseController
|
||||
def update
|
||||
Spree::Config.set(connected_apps_enabled:)
|
||||
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
flash[:success] = t(:successfully_updated, resource: t('.resource'))
|
||||
redirect_to main_app.edit_admin_connected_app_settings_path
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def connected_apps_enabled
|
||||
params.require(:preferences).require(:connected_apps_enabled).compact_blank.join(",")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,91 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class ConnectedAppsController < ApplicationController
|
||||
def create
|
||||
authorize! :admin, enterprise
|
||||
|
||||
connect
|
||||
|
||||
render_panel
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize! :admin, enterprise
|
||||
|
||||
app = enterprise.connected_apps.find(params.require(:id))
|
||||
app.destroy
|
||||
|
||||
render_panel
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_connected_app
|
||||
attributes = {}
|
||||
attributes[:type] = connected_app_params[:type] if connected_app_params[:type]
|
||||
|
||||
@app = ConnectedApp.create!(enterprise_id: enterprise.id, **attributes)
|
||||
end
|
||||
|
||||
def connect
|
||||
return connect_vine if connected_app_params[:type] == "ConnectedApps::Vine"
|
||||
|
||||
create_connected_app
|
||||
@app.connect(api_key: spree_current_user.spree_api_key,
|
||||
channel: SessionChannel.for_request(request))
|
||||
end
|
||||
|
||||
def connect_vine
|
||||
if vine_params_empty?
|
||||
return flash[:error] =
|
||||
I18n.t("admin.enterprises.form.connected_apps.vine.api_parameters_empty")
|
||||
end
|
||||
|
||||
create_connected_app
|
||||
|
||||
jwt_service = VineJwtService.new(secret: connected_app_params[:vine_secret])
|
||||
vine_api = VineApiService.new(api_key: connected_app_params[:vine_api_key],
|
||||
jwt_generator: jwt_service)
|
||||
|
||||
if !@app.connect(api_key: connected_app_params[:vine_api_key],
|
||||
secret: connected_app_params[:vine_secret], vine_api:)
|
||||
error_message = "#{@app.errors.full_messages.to_sentence}. \
|
||||
#{I18n.t('admin.enterprises.form.connected_apps.vine.api_parameters_error')}".squish
|
||||
handle_error(error_message)
|
||||
end
|
||||
rescue Faraday::Error => e
|
||||
log_and_notify_exception(e)
|
||||
handle_error(I18n.t("admin.enterprises.form.connected_apps.vine.connection_error"))
|
||||
rescue KeyError => e
|
||||
log_and_notify_exception(e)
|
||||
handle_error(I18n.t("admin.enterprises.form.connected_apps.vine.setup_error"))
|
||||
end
|
||||
|
||||
def enterprise
|
||||
@enterprise ||= Enterprise.find(params.require(:enterprise_id))
|
||||
end
|
||||
|
||||
def render_panel
|
||||
redirect_to "#{edit_admin_enterprise_path(enterprise)}#/connected_apps_panel"
|
||||
end
|
||||
|
||||
def handle_error(message)
|
||||
flash[:error] = message
|
||||
@app.destroy
|
||||
end
|
||||
|
||||
def log_and_notify_exception(exception)
|
||||
Rails.logger.error exception.inspect
|
||||
Bugsnag.notify(exception)
|
||||
end
|
||||
|
||||
def vine_params_empty?
|
||||
connected_app_params[:vine_api_key].empty? || connected_app_params[:vine_secret].empty?
|
||||
end
|
||||
|
||||
def connected_app_params
|
||||
params.permit(:type, :vine_api_key, :vine_secret)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -20,35 +20,31 @@ module Admin
|
||||
|
||||
catalog_url = params.require(:catalog_url)
|
||||
|
||||
json_catalog = fetch_catalog(catalog_url)
|
||||
json_catalog = DfcRequest.new(spree_current_user).get(catalog_url)
|
||||
graph = DfcIo.import(json_catalog)
|
||||
|
||||
# * First step: import all products for given enterprise.
|
||||
# * Second step: render table and let user decide which ones to import.
|
||||
imported = graph.map do |subject|
|
||||
next unless subject.is_a? DataFoodConsortium::Connector::SuppliedProduct
|
||||
|
||||
existing_variant = enterprise.supplied_variants.linked_to(subject.semanticId)
|
||||
|
||||
if existing_variant
|
||||
SuppliedProductBuilder.update_product(subject, existing_variant)
|
||||
else
|
||||
SuppliedProductBuilder.store_product(subject, enterprise)
|
||||
end
|
||||
import_product(subject, enterprise)
|
||||
end
|
||||
|
||||
@count = imported.compact.count
|
||||
rescue Faraday::Error,
|
||||
Addressable::URI::InvalidURIError,
|
||||
ActionController::ParameterMissing => e
|
||||
flash[:error] = e.message
|
||||
redirect_to admin_product_import_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fetch_catalog(url)
|
||||
DfcRequest.new(spree_current_user).call(url)
|
||||
# Most of this code is the same as in the DfcProvider::SuppliedProductsController.
|
||||
def import_product(subject, enterprise)
|
||||
return unless subject.is_a? DataFoodConsortium::Connector::SuppliedProduct
|
||||
|
||||
variant = SuppliedProductBuilder.import_variant(subject, enterprise)
|
||||
product = variant.product
|
||||
|
||||
product.save! if product.new_record?
|
||||
variant.save! if variant.new_record?
|
||||
|
||||
variant
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -65,9 +65,7 @@ module Admin
|
||||
order_cycle ||= OrderCycle.new(coordinator:) if coordinator.present?
|
||||
enterprises = OpenFoodNetwork::OrderCyclePermissions.new(spree_current_user,
|
||||
order_cycle).visible_enterprises
|
||||
|
||||
fees = EnterpriseFee.for_enterprises(enterprises).order('enterprise_id', 'fee_type', 'name')
|
||||
filter_fees(fees)
|
||||
EnterpriseFee.for_enterprises(enterprises).order('enterprise_id', 'fee_type', 'name')
|
||||
else
|
||||
collection = EnterpriseFee.managed_by(spree_current_user).order('enterprise_id',
|
||||
'fee_type', 'name')
|
||||
@@ -76,12 +74,6 @@ module Admin
|
||||
end
|
||||
end
|
||||
|
||||
def filter_fees(fees)
|
||||
fees = fees.per_item if params[:per_item]
|
||||
fees = fees.per_order if params[:per_order]
|
||||
fees
|
||||
end
|
||||
|
||||
def collection_actions
|
||||
[:index, :for_order_cycle, :bulk_update]
|
||||
end
|
||||
|
||||
@@ -189,7 +189,10 @@ module Admin
|
||||
.visible_enterprises
|
||||
|
||||
if enterprises.present?
|
||||
enterprises.includes(supplied_products: [:variants, :image])
|
||||
enterprises.includes(
|
||||
supplied_products:
|
||||
[:supplier, :variants, :image]
|
||||
)
|
||||
end
|
||||
when :index
|
||||
if spree_current_user.admin?
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
module Admin
|
||||
class OrderCyclesController < Admin::ResourceController
|
||||
class DateTimeChangeError < StandardError; end
|
||||
|
||||
include ::OrderCyclesHelper
|
||||
include PaperTrailLogging
|
||||
|
||||
@@ -64,7 +62,9 @@ module Admin
|
||||
end
|
||||
|
||||
def update
|
||||
@order_cycle_form = set_order_cycle_form
|
||||
@order_cycle_form = OrderCycles::FormService.new(@order_cycle, order_cycle_params,
|
||||
spree_current_user)
|
||||
|
||||
if @order_cycle_form.save
|
||||
update_nil_subscription_line_items_price_estimate(@order_cycle)
|
||||
respond_to do |format|
|
||||
@@ -77,9 +77,6 @@ module Admin
|
||||
elsif request.format.json?
|
||||
render json: { errors: @order_cycle.errors.full_messages }, status: :unprocessable_entity
|
||||
end
|
||||
rescue DateTimeChangeError
|
||||
render json: { trigger_action: params[:trigger_action] },
|
||||
status: :unprocessable_entity
|
||||
end
|
||||
|
||||
def bulk_update
|
||||
@@ -93,9 +90,6 @@ module Admin
|
||||
order_cycle = order_cycle_set.collection.find{ |oc| oc.errors.present? }
|
||||
render json: { errors: order_cycle.errors.full_messages }, status: :unprocessable_entity
|
||||
end
|
||||
rescue DateTimeChangeError
|
||||
render json: { trigger_action: params[:trigger_action] },
|
||||
status: :unprocessable_entity
|
||||
end
|
||||
|
||||
def bulk_update_nil_subscription_line_items_price_estimate
|
||||
@@ -241,7 +235,7 @@ module Admin
|
||||
else
|
||||
begin
|
||||
yield
|
||||
rescue ActiveRecord::InvalidForeignKey, ActiveRecord::DeleteRestrictionError
|
||||
rescue ActiveRecord::InvalidForeignKey
|
||||
redirect_to main_app.admin_order_cycles_url
|
||||
flash[:error] = I18n.t('admin.order_cycles.destroy_errors.orders_present')
|
||||
end
|
||||
@@ -276,10 +270,7 @@ module Admin
|
||||
end
|
||||
|
||||
def order_cycle_set
|
||||
@order_cycle_set ||= Sets::OrderCycleSet.new(
|
||||
@order_cycles, { **order_cycle_bulk_params,
|
||||
confirm_datetime_change: params[:confirm], error_class: DateTimeChangeError }
|
||||
)
|
||||
@order_cycle_set ||= Sets::OrderCycleSet.new(@order_cycles, order_cycle_bulk_params)
|
||||
end
|
||||
|
||||
def require_order_cycle_set_params
|
||||
@@ -303,14 +294,5 @@ module Admin
|
||||
collection_attributes: [:id] + PermittedAttributes::OrderCycle.basic_attributes
|
||||
).to_h.with_indifferent_access
|
||||
end
|
||||
|
||||
def set_order_cycle_form
|
||||
OrderCycles::FormService.new(
|
||||
@order_cycle, order_cycle_params.merge(
|
||||
{ confirm_datetime_change: params[:order_cycle][:confirm],
|
||||
error_class: DateTimeChangeError }
|
||||
), spree_current_user
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,8 +4,6 @@ require 'roo'
|
||||
|
||||
module Admin
|
||||
class ProductImportController < Spree::Admin::BaseController
|
||||
TMPDIR_PREFIX = "product_import-"
|
||||
|
||||
before_action :validate_upload_presence, except: %i[index guide validate_data]
|
||||
|
||||
def index
|
||||
@@ -21,7 +19,8 @@ module Admin
|
||||
@importer = ProductImport::ProductImporter.new(File.new(@filepath), spree_current_user,
|
||||
params[:settings])
|
||||
@original_filename = params[:file].try(:original_filename)
|
||||
@non_updatable_fields = ProductImport::EntryValidator.non_updatable_variant_fields
|
||||
@non_updatable_fields = ProductImport::EntryValidator.non_updatable_fields
|
||||
|
||||
return if contains_errors? @importer
|
||||
|
||||
@ams_data = ams_data
|
||||
@@ -102,7 +101,8 @@ module Admin
|
||||
|
||||
def save_uploaded_file(upload)
|
||||
extension = File.extname(upload.original_filename)
|
||||
File.open(File.join(mktmpdir, "import#{extension}"), 'wb') do |f|
|
||||
directory = Dir.mktmpdir 'product_import'
|
||||
File.open(File.join(directory, "import#{extension}"), 'wb') do |f|
|
||||
data = UploadSanitizer.new(upload.read).call
|
||||
f.write(data)
|
||||
f.path
|
||||
@@ -126,14 +126,6 @@ module Admin
|
||||
ProductImport::ProductImporter
|
||||
end
|
||||
|
||||
def mktmpdir
|
||||
Dir::Tmpname.create(TMPDIR_PREFIX, Rails.root.join('tmp') ) { |tmpname| Dir.mkdir(tmpname) }
|
||||
end
|
||||
|
||||
def tmpdir_base
|
||||
Rails.root.join('tmp', TMPDIR_PREFIX).to_s
|
||||
end
|
||||
|
||||
def file_path
|
||||
@file_path ||= validate_file_path(sanitize_file_path(params[:filepath]))
|
||||
end
|
||||
@@ -142,9 +134,8 @@ module Admin
|
||||
FilePathSanitizer.new.sanitize(file_path, on_error: method(:raise_invalid_file_path))
|
||||
end
|
||||
|
||||
# Ensure file is under the safe tmp directory
|
||||
def validate_file_path(file_path)
|
||||
return file_path if file_path.to_s.match?(%r{^#{tmpdir_base}[A-Za-z0-9-]*/import\.csv$})
|
||||
return file_path if file_path.to_s.match?(TEMP_FILE_PATH_REGEX)
|
||||
|
||||
raise_invalid_file_path
|
||||
end
|
||||
@@ -154,5 +145,6 @@ module Admin
|
||||
notice: I18n.t(:product_import_no_data_in_spreadsheet_notice)
|
||||
raise 'Invalid File Path'
|
||||
end
|
||||
TEMP_FILE_PATH_REGEX = %r{^/tmp/product_import[A-Za-z0-9-]*/import\.csv$}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class ProductPreviewController < Spree::Admin::BaseController
|
||||
def show
|
||||
@product = Spree::Product.find(params[:id])
|
||||
authorize! :show, @product
|
||||
|
||||
respond_with do |format|
|
||||
format.turbo_stream {
|
||||
render "admin/products_v3/product_preview", status: :ok
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def model_class
|
||||
Spree::Product
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,18 +1,13 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# rubocop:disable Metrics/ClassLength
|
||||
module Admin
|
||||
class ProductsV3Controller < Spree::Admin::BaseController
|
||||
helper ProductsHelper
|
||||
|
||||
before_action :init_filters_params
|
||||
before_action :init_pagination_params
|
||||
|
||||
def index
|
||||
fetch_products
|
||||
render "index", locals: { producers:, categories:, tax_category_options:, flash: }
|
||||
|
||||
session[:products_return_to_url] = request.url
|
||||
end
|
||||
|
||||
def bulk_update
|
||||
@@ -34,71 +29,6 @@ module Admin
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@record = ProductScopeQuery.new(
|
||||
spree_current_user,
|
||||
{ id: params[:id] }
|
||||
).find_product
|
||||
|
||||
authorize! :delete, @record
|
||||
|
||||
@record.destroyed_by = spree_current_user
|
||||
status = :ok
|
||||
|
||||
if @record.destroy
|
||||
flash.now[:success] = t('.delete_product.success')
|
||||
else
|
||||
flash.now[:error] = t('.delete_product.error')
|
||||
status = :internal_server_error
|
||||
end
|
||||
|
||||
respond_with do |format|
|
||||
format.turbo_stream { render :destroy_product_variant, status: }
|
||||
end
|
||||
end
|
||||
|
||||
def destroy_variant
|
||||
@record = Spree::Variant.active.find(params[:id])
|
||||
authorize! :delete, @record
|
||||
|
||||
status = :ok
|
||||
if VariantDeleter.new.delete(@record)
|
||||
flash.now[:success] = t('.delete_variant.success')
|
||||
else
|
||||
flash.now[:error] = t('.delete_variant.error')
|
||||
status = :internal_server_error
|
||||
end
|
||||
|
||||
respond_with do |format|
|
||||
format.turbo_stream { render :destroy_product_variant, status: }
|
||||
end
|
||||
end
|
||||
|
||||
def clone
|
||||
@product = Spree::Product.find(params[:id])
|
||||
authorize! :clone, @product
|
||||
|
||||
status = :ok
|
||||
|
||||
begin
|
||||
@cloned_product = @product.duplicate
|
||||
flash.now[:success] = t('.success')
|
||||
|
||||
@product_index = "-#{@cloned_product.id}"
|
||||
@producer_options = producers
|
||||
@category_options = categories
|
||||
@tax_category_options = tax_category_options
|
||||
rescue ActiveRecord::ActiveRecordError => e
|
||||
flash.now[:error] = clone_error_message(e)
|
||||
status = :unprocessable_entity
|
||||
@product_index = "-1" # Create a unique enough index
|
||||
end
|
||||
|
||||
respond_with do |format|
|
||||
format.turbo_stream { render :clone, status: }
|
||||
end
|
||||
end
|
||||
|
||||
def index_url(params)
|
||||
"/admin/products?#{params.to_query}" # todo: fix routing so this can be automaticly generated
|
||||
end
|
||||
@@ -155,7 +85,7 @@ module Admin
|
||||
|
||||
def ransack_query
|
||||
query = {}
|
||||
query.merge!(variants_supplier_id_in: @producer_id) if @producer_id.present?
|
||||
query.merge!(supplier_id_in: @producer_id) if @producer_id.present?
|
||||
if @search_term.present?
|
||||
query.merge!(Spree::Variant::SEARCH_KEY => @search_term)
|
||||
end
|
||||
@@ -169,13 +99,13 @@ module Admin
|
||||
def product_query_includes
|
||||
[
|
||||
:image,
|
||||
:supplier,
|
||||
{ variants: [
|
||||
:default_price,
|
||||
:primary_taxon,
|
||||
:product,
|
||||
:stock_items,
|
||||
:tax_category,
|
||||
:supplier,
|
||||
] },
|
||||
]
|
||||
end
|
||||
@@ -213,15 +143,5 @@ module Admin
|
||||
params.permit(products: ::PermittedAttributes::Product.attributes)
|
||||
.to_h.with_indifferent_access
|
||||
end
|
||||
|
||||
def clone_error_message(error)
|
||||
case error
|
||||
when ActiveRecord::RecordInvalid
|
||||
error.record.errors.full_messages.to_sentence
|
||||
else
|
||||
t('.error')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
# rubocop:enable Metrics/ClassLength
|
||||
|
||||
@@ -6,7 +6,7 @@ module Admin
|
||||
include ReportsActions
|
||||
helper ReportsHelper
|
||||
|
||||
before_action :authorize_report, only: [:show, :create]
|
||||
before_action :authorize_report, only: [:show]
|
||||
|
||||
# Define model class for Can? permissions
|
||||
def model_class
|
||||
@@ -20,17 +20,14 @@ module Admin
|
||||
end
|
||||
|
||||
def show
|
||||
@report = report_class.new(spree_current_user, params, render: false)
|
||||
@rendering_options = rendering_options
|
||||
@report = report_class.new(spree_current_user, params, render: render_data?)
|
||||
@rendering_options = rendering_options # also stores user preferences
|
||||
|
||||
show_report
|
||||
end
|
||||
|
||||
def create
|
||||
@report = report_class.new(spree_current_user, params, render: true)
|
||||
update_rendering_options
|
||||
|
||||
render_in_background
|
||||
if render_data?
|
||||
render_in_background
|
||||
else
|
||||
show_report
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
@@ -57,15 +54,28 @@ module Admin
|
||||
@variant_serialized = Api::Admin::VariantSerializer.new(variant)
|
||||
end
|
||||
|
||||
def render_data?
|
||||
request.post?
|
||||
end
|
||||
|
||||
def render_in_background
|
||||
@blob = ReportBlob.create_for_upload_later!(report_filename)
|
||||
cable_ready[ScopedChannel.for_id(params[:uuid])]
|
||||
.inner_html(
|
||||
selector: "#report-table",
|
||||
html: render_to_string(partial: "admin/reports/loading")
|
||||
).scroll_into_view(
|
||||
selector: "#report-table",
|
||||
block: "start"
|
||||
).broadcast
|
||||
|
||||
ReportJob.perform_later(
|
||||
report_class:, user: spree_current_user, params:,
|
||||
format: report_format,
|
||||
blob: @blob,
|
||||
filename: report_filename,
|
||||
channel: ScopedChannel.for_id(params[:uuid]),
|
||||
)
|
||||
|
||||
head :no_content
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -146,7 +146,7 @@ module Admin
|
||||
return nil if parent_data.blank?
|
||||
|
||||
@parent ||= parent_data[:model_class].
|
||||
find_by(parent_data[:find_by] => params["#{model_name}_id"])
|
||||
public_send("find_by", parent_data[:find_by] => params["#{model_name}_id"])
|
||||
instance_variable_set("@#{model_name}", @parent)
|
||||
end
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ module Admin
|
||||
|
||||
def obfuscated_secret_key
|
||||
key = Stripe.api_key
|
||||
"#{key.first(8)}****#{key.last(4)}"
|
||||
key.first(8) + "****" + key.last(4)
|
||||
end
|
||||
|
||||
def settings_params
|
||||
|
||||
@@ -5,7 +5,7 @@ module Admin
|
||||
respond_to :json
|
||||
|
||||
respond_override destroy: { json: {
|
||||
success: lambda { head :no_content }
|
||||
success: lambda { render body: nil, status: :no_content }
|
||||
} }
|
||||
|
||||
def map_by_tag
|
||||
|
||||
@@ -88,7 +88,7 @@ module Admin
|
||||
end
|
||||
|
||||
def modified_variant_overrides_ids
|
||||
variant_overrides_params.pluck(:id)
|
||||
variant_overrides_params.map { |vo| vo[:id] }
|
||||
end
|
||||
|
||||
def collection_actions
|
||||
|
||||
@@ -9,7 +9,7 @@ module Api
|
||||
authorize! :destroy, enterprise_fee
|
||||
|
||||
if enterprise_fee.destroy
|
||||
head :no_content
|
||||
render plain: I18n.t(:successfully_removed), status: :no_content
|
||||
else
|
||||
render plain: enterprise_fee.errors.full_messages.first, status: :forbidden
|
||||
end
|
||||
|
||||
@@ -7,11 +7,9 @@ module Api
|
||||
include ApiActionCaching
|
||||
|
||||
skip_authorization_check
|
||||
skip_before_action :authenticate_user, :ensure_api_key, only: [
|
||||
:taxons, :properties, :producer_properties
|
||||
]
|
||||
skip_before_action :authenticate_user, :ensure_api_key, only: [:taxons, :properties]
|
||||
|
||||
caches_action :taxons, :properties, :producer_properties,
|
||||
caches_action :taxons, :properties,
|
||||
expires_in: CacheService::FILTERS_EXPIRY,
|
||||
cache_path: proc { |controller| controller.request.url }
|
||||
|
||||
@@ -43,13 +41,7 @@ module Api
|
||||
|
||||
def properties
|
||||
render plain: ActiveModel::ArraySerializer.new(
|
||||
product_properties, each_serializer: Api::PropertySerializer
|
||||
).to_json
|
||||
end
|
||||
|
||||
def producer_properties
|
||||
render plain: ActiveModel::ArraySerializer.new(
|
||||
load_producer_properties, each_serializer: Api::PropertySerializer
|
||||
product_properties | producer_properties, each_serializer: Api::PropertySerializer
|
||||
).to_json
|
||||
end
|
||||
|
||||
@@ -66,7 +58,7 @@ module Api
|
||||
select('DISTINCT spree_properties.*')
|
||||
end
|
||||
|
||||
def load_producer_properties
|
||||
def producer_properties
|
||||
producers = Enterprise.
|
||||
joins(:supplied_products).
|
||||
where(spree_products: { id: distributed_products })
|
||||
@@ -94,9 +86,8 @@ module Api
|
||||
end
|
||||
|
||||
def distributed_products
|
||||
OrderCycles::DistributedProductsService.new(
|
||||
distributor, order_cycle, customer
|
||||
).products_relation.pluck(:id)
|
||||
OrderCycles::DistributedProductsService.new(distributor, order_cycle,
|
||||
customer).products_relation
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,7 +21,7 @@ module Api
|
||||
authorize! :create, Spree::Product
|
||||
@product = Spree::Product.new(product_params)
|
||||
|
||||
if @product.save(context: :create_and_create_standard_variant)
|
||||
if @product.save
|
||||
render json: @product, serializer: Api::Admin::ProductSerializer, status: :created
|
||||
else
|
||||
invalid_resource!(@product)
|
||||
@@ -42,9 +42,8 @@ module Api
|
||||
authorize! :delete, Spree::Product
|
||||
@product = product_finder.find_product
|
||||
authorize! :delete, @product
|
||||
@product.destroyed_by = current_api_user
|
||||
@product.destroy
|
||||
head :no_content
|
||||
render json: @product, serializer: Api::Admin::ProductSerializer, status: :no_content
|
||||
end
|
||||
|
||||
def bulk_products
|
||||
@@ -54,7 +53,7 @@ module Api
|
||||
end
|
||||
|
||||
def overridable
|
||||
@products = product_finder.products_for_producers
|
||||
@products = product_finder.paged_products_for_producers
|
||||
|
||||
render_paged_products @products, ::Api::Admin::ProductSimpleSerializer
|
||||
end
|
||||
|
||||
16
app/controllers/api/v0/taxonomies_controller.rb
Normal file
16
app/controllers/api/v0/taxonomies_controller.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class TaxonomiesController < Api::V0::BaseController
|
||||
respond_to :json
|
||||
|
||||
skip_authorization_check only: :jstree
|
||||
|
||||
def jstree
|
||||
@taxonomy = Spree::Taxonomy.find(params[:id])
|
||||
render json: @taxonomy.root, serializer: Api::TaxonJstreeSerializer
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -5,10 +5,12 @@ module Api
|
||||
class TaxonsController < Api::V0::BaseController
|
||||
respond_to :json
|
||||
|
||||
skip_authorization_check only: [:index, :show]
|
||||
skip_authorization_check only: [:index, :show, :jstree]
|
||||
|
||||
def index
|
||||
@taxons = if params[:ids]
|
||||
@taxons = if taxonomy
|
||||
taxonomy.root.children
|
||||
elsif params[:ids]
|
||||
Spree::Taxon.where(id: raw_params[:ids].split(","))
|
||||
else
|
||||
Spree::Taxon.ransack(raw_params[:q]).result
|
||||
@@ -16,9 +18,23 @@ module Api
|
||||
render json: @taxons, each_serializer: Api::TaxonSerializer
|
||||
end
|
||||
|
||||
def jstree
|
||||
@taxon = taxon
|
||||
render json: @taxon.children, each_serializer: Api::TaxonJstreeSerializer
|
||||
end
|
||||
|
||||
def create
|
||||
authorize! :create, Spree::Taxon
|
||||
@taxon = Spree::Taxon.new(taxon_params)
|
||||
@taxon.taxonomy_id = params[:taxonomy_id]
|
||||
taxonomy = Spree::Taxonomy.find_by(id: params[:taxonomy_id])
|
||||
|
||||
if taxonomy.nil?
|
||||
@taxon.errors.add(:taxonomy_id, I18n.t(:invalid_taxonomy_id, scope: 'spree.api'))
|
||||
invalid_resource!(@taxon) && return
|
||||
end
|
||||
|
||||
@taxon.parent_id = taxonomy.root.id unless params.dig(:taxon, :parent_id)
|
||||
|
||||
if @taxon.save
|
||||
render json: @taxon, serializer: Api::TaxonSerializer, status: :created
|
||||
@@ -39,19 +55,25 @@ module Api
|
||||
def destroy
|
||||
authorize! :delete, Spree::Taxon
|
||||
taxon.destroy
|
||||
head :no_content
|
||||
render json: taxon, serializer: Api::TaxonSerializer, status: :no_content
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def taxonomy
|
||||
return if params[:taxonomy_id].blank?
|
||||
|
||||
@taxonomy ||= Spree::Taxonomy.find(params[:taxonomy_id])
|
||||
end
|
||||
|
||||
def taxon
|
||||
@taxon = Spree::Taxon.find(params[:id])
|
||||
@taxon ||= taxonomy.taxons.find(params[:id])
|
||||
end
|
||||
|
||||
def taxon_params
|
||||
return if params[:taxon].blank?
|
||||
|
||||
params.require(:taxon).permit([:name, :position])
|
||||
params.require(:taxon).permit([:name, :parent_id, :position])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -44,7 +44,7 @@ module Api
|
||||
authorize! :delete, @variant
|
||||
|
||||
VariantDeleter.new.delete(@variant)
|
||||
head :no_content
|
||||
render json: @variant, serializer: Api::VariantSerializer, status: :no_content
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -28,6 +28,7 @@ class ApplicationController < ActionController::Base
|
||||
helper 'injection'
|
||||
helper 'markdown'
|
||||
helper 'footer_links'
|
||||
helper 'discourse'
|
||||
helper 'checkout'
|
||||
helper 'link'
|
||||
helper 'terms_and_conditions'
|
||||
@@ -60,7 +61,7 @@ class ApplicationController < ActionController::Base
|
||||
rescue StandardError
|
||||
'unknown'
|
||||
end}")
|
||||
super
|
||||
super(options, response_status)
|
||||
end
|
||||
|
||||
def set_checkout_redirect
|
||||
|
||||
@@ -11,8 +11,6 @@ class CartController < BaseController
|
||||
order.cap_quantity_at_stock!
|
||||
order.recreate_all_fees!
|
||||
|
||||
StockSyncJob.sync_linked_catalogs(order)
|
||||
|
||||
render json: { error: false, stock_levels: stock_levels(order) }, status: :ok
|
||||
else
|
||||
render json: { error: cart_service.errors.full_messages.join(",") },
|
||||
|
||||
@@ -9,12 +9,6 @@ module CheckoutCallbacks
|
||||
# Otherwise we fail on duplicate indexes or end up with negative stock.
|
||||
prepend_around_action CurrentOrderLocker, only: [:edit, :update]
|
||||
|
||||
# We want to download the latest stock data before anything else happens.
|
||||
# We don't want it to be in the same database transaction as the order
|
||||
# locking because this action locks a different set of variants and it
|
||||
# could cause race conditions.
|
||||
prepend_around_action :sync_stock, only: :update
|
||||
|
||||
prepend_before_action :check_hub_ready_for_checkout
|
||||
prepend_before_action :check_order_cycle_expiry
|
||||
prepend_before_action :require_order_cycle
|
||||
@@ -31,14 +25,6 @@ module CheckoutCallbacks
|
||||
|
||||
private
|
||||
|
||||
def sync_stock
|
||||
if current_order&.state == "confirmation"
|
||||
StockSyncJob.sync_linked_catalogs_now(current_order)
|
||||
end
|
||||
|
||||
yield
|
||||
end
|
||||
|
||||
def load_order
|
||||
@order = current_order
|
||||
@order.manual_shipping_selection = true
|
||||
@@ -77,6 +63,12 @@ module CheckoutCallbacks
|
||||
end
|
||||
end
|
||||
|
||||
def valid_order_line_items?
|
||||
@order.insufficient_stock_lines.empty? &&
|
||||
OrderCycles::DistributedVariantsService.new(@order.order_cycle, @order.distributor).
|
||||
distributes_order_variants?(@order)
|
||||
end
|
||||
|
||||
def ensure_order_not_completed
|
||||
redirect_to main_app.cart_path if @order.completed?
|
||||
end
|
||||
|
||||
@@ -51,7 +51,7 @@ module OrderCompletion
|
||||
|
||||
def order_invalid!
|
||||
Bugsnag.notify("Notice: invalid order loaded during checkout") do |payload|
|
||||
payload.add_metadata :order, :order, @order
|
||||
payload.add_metadata :order, @order
|
||||
end
|
||||
|
||||
flash[:error] = t('checkout.order_not_loaded')
|
||||
|
||||
@@ -21,7 +21,7 @@ module OrderStockCheck
|
||||
return unless current_order_cycle&.closed?
|
||||
|
||||
Bugsnag.notify("Notice: order cycle closed during checkout completion") do |payload|
|
||||
payload.add_metadata :order, :order, current_order
|
||||
payload.add_metadata :order, current_order
|
||||
end
|
||||
current_order.empty!
|
||||
current_order.set_order_cycle! nil
|
||||
|
||||
@@ -88,10 +88,14 @@ module ReportsActions
|
||||
display_header_row: false
|
||||
}
|
||||
end
|
||||
update_rendering_options
|
||||
@rendering_options
|
||||
end
|
||||
|
||||
def update_rendering_options
|
||||
rendering_options.update(
|
||||
return unless request.post?
|
||||
|
||||
@rendering_options.update(
|
||||
options: {
|
||||
fields_to_show: params[:fields_to_show],
|
||||
display_summary_row: params[:display_summary_row].present?,
|
||||
|
||||
52
app/controllers/discourse_sso_controller.rb
Normal file
52
app/controllers/discourse_sso_controller.rb
Normal file
@@ -0,0 +1,52 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'discourse/single_sign_on'
|
||||
|
||||
class DiscourseSsoController < ApplicationController
|
||||
include SharedHelper
|
||||
include DiscourseHelper
|
||||
|
||||
before_action :require_config
|
||||
|
||||
def login
|
||||
if require_activation?
|
||||
redirect_to discourse_url
|
||||
else
|
||||
redirect_to discourse_login_url
|
||||
end
|
||||
end
|
||||
|
||||
def sso
|
||||
if spree_current_user
|
||||
begin
|
||||
redirect_to sso_url
|
||||
rescue TypeError
|
||||
render plain: "Bad SingleSignOn request.", status: :bad_request
|
||||
end
|
||||
else
|
||||
redirect_to login_path
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def sso_url
|
||||
secret = discourse_sso_secret!
|
||||
sso = Discourse::SingleSignOn.parse(request.query_string, secret)
|
||||
sso.email = spree_current_user.email
|
||||
sso.username = spree_current_user.login
|
||||
sso.external_id = spree_current_user.id
|
||||
sso.sso_secret = secret
|
||||
sso.admin = admin_user?
|
||||
sso.require_activation = require_activation?
|
||||
sso.to_url(discourse_sso_url)
|
||||
end
|
||||
|
||||
def require_config
|
||||
raise ActionController::RoutingError, 'Not Found' unless discourse_configured?
|
||||
end
|
||||
|
||||
def require_activation?
|
||||
!admin_user? && !spree_current_user.confirmed?
|
||||
end
|
||||
end
|
||||
@@ -7,7 +7,7 @@ class ErrorsController < ApplicationController
|
||||
Bugsnag.notify("404") do |event|
|
||||
event.severity = "info"
|
||||
|
||||
event.add_metadata(:request, :env, request.env)
|
||||
event.add_metadata(:request, request.env)
|
||||
end
|
||||
render status: :not_found, formats: :html
|
||||
end
|
||||
|
||||
@@ -19,18 +19,15 @@ module Spree
|
||||
|
||||
before_action :authorize_admin
|
||||
before_action :set_locale
|
||||
before_action :warn_invalid_order_cycles, if: :page_load_request?
|
||||
before_action :warn_invalid_order_cycles, if: :html_request?
|
||||
|
||||
# Warn the user when they have an active order cycle with hubs that are not ready
|
||||
# for checkout (ie. does not have valid shipping and payment methods).
|
||||
def warn_invalid_order_cycles
|
||||
return if flash[:notice].present? || session[:displayed_order_cycle_warning]
|
||||
return if flash[:notice].present?
|
||||
|
||||
warning = OrderCycles::WarningService.new(spree_current_user).call
|
||||
return if warning.blank?
|
||||
|
||||
flash.now[:notice] = warning
|
||||
session[:displayed_order_cycle_warning] = true
|
||||
flash[:notice] = warning if warning.present?
|
||||
end
|
||||
|
||||
protected
|
||||
@@ -84,12 +81,6 @@ module Spree
|
||||
|
||||
private
|
||||
|
||||
def page_load_request?
|
||||
return false if request.format.include?('turbo')
|
||||
|
||||
html_request?
|
||||
end
|
||||
|
||||
def html_request?
|
||||
request.format.html?
|
||||
end
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user